[vulkan] Rework line rasterization handle
This commit is contained in:
parent
7fdbc33aaf
commit
57aab352b4
|
|
@ -127,6 +127,13 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
|
|||
depth_bounds_min = static_cast<u32>(regs.depth_bounds[0]);
|
||||
depth_bounds_max = static_cast<u32>(regs.depth_bounds[1]);
|
||||
|
||||
depth_bias = std::bit_cast<u32>(regs.depth_bias);
|
||||
depth_bias_clamp = std::bit_cast<u32>(regs.depth_bias_clamp);
|
||||
slope_scale_depth_bias = std::bit_cast<u32>(regs.slope_scale_depth_bias);
|
||||
|
||||
line_width_smooth = std::bit_cast<u32>(regs.line_width_smooth);
|
||||
line_width_aliased = std::bit_cast<u32>(regs.line_width_aliased);
|
||||
|
||||
line_stipple_factor = regs.line_stipple_params.factor;
|
||||
line_stipple_pattern = regs.line_stipple_params.pattern;
|
||||
|
||||
|
|
|
|||
|
|
@ -236,6 +236,13 @@ struct FixedPipelineState {
|
|||
u32 depth_bounds_min;
|
||||
u32 depth_bounds_max;
|
||||
|
||||
u32 depth_bias;
|
||||
u32 depth_bias_clamp;
|
||||
u32 slope_scale_depth_bias;
|
||||
|
||||
u32 line_width_smooth;
|
||||
u32 line_width_aliased;
|
||||
|
||||
u32 line_stipple_factor;
|
||||
u32 line_stipple_pattern;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <iostream>
|
||||
#include <span>
|
||||
|
||||
|
|
@ -707,24 +708,68 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
|||
dynamic.cull_enable ? MaxwellToVK::CullFace(dynamic.CullFace()) : VK_CULL_MODE_NONE),
|
||||
.frontFace = MaxwellToVK::FrontFace(dynamic.FrontFace()),
|
||||
.depthBiasEnable = (dynamic.depth_bias_enable != 0 ? VK_TRUE : VK_FALSE),
|
||||
.depthBiasConstantFactor = 0.0f,
|
||||
.depthBiasClamp = 0.0f,
|
||||
.depthBiasSlopeFactor = 0.0f,
|
||||
.lineWidth = 1.0f,
|
||||
// TODO(alekpop): Transfer from regs
|
||||
.depthBiasConstantFactor = std::bit_cast<float>(key.state.depth_bias) / 2.0f,
|
||||
.depthBiasClamp = std::bit_cast<float>(key.state.depth_bias_clamp),
|
||||
.depthBiasSlopeFactor = std::bit_cast<float>(key.state.slope_scale_depth_bias),
|
||||
.lineWidth = key.state.smooth_lines != 0
|
||||
? std::bit_cast<float>(key.state.line_width_smooth)
|
||||
: std::bit_cast<float>(key.state.line_width_aliased),
|
||||
};
|
||||
const bool smooth_lines_supported =
|
||||
device.IsExtLineRasterizationSupported() && device.SupportsSmoothLines();
|
||||
const bool stippled_lines_supported =
|
||||
device.IsExtLineRasterizationSupported() && device.SupportsStippledRectangularLines();
|
||||
const bool line_rasterization_supported = device.IsExtLineRasterizationSupported();
|
||||
const bool any_stippled_lines_supported =
|
||||
line_rasterization_supported &&
|
||||
(device.SupportsStippledRectangularLines() || device.SupportsStippledBresenhamLines() ||
|
||||
device.SupportsStippledSmoothLines());
|
||||
const bool line_stipple_dynamic_state_supported =
|
||||
IsLine(input_assembly_topology) && any_stippled_lines_supported;
|
||||
const bool supports_rectangular_lines =
|
||||
line_rasterization_supported && device.SupportsRectangularLines();
|
||||
const bool supports_bresenham_lines =
|
||||
line_rasterization_supported && device.SupportsBresenhamLines();
|
||||
const bool supports_smooth_lines = line_rasterization_supported && device.SupportsSmoothLines();
|
||||
|
||||
VkLineRasterizationModeEXT line_rasterization_mode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
|
||||
if (line_rasterization_supported) {
|
||||
if (key.state.smooth_lines != 0) {
|
||||
if (supports_smooth_lines) {
|
||||
line_rasterization_mode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
|
||||
} else if (supports_rectangular_lines) {
|
||||
line_rasterization_mode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
|
||||
} else if (supports_bresenham_lines) {
|
||||
line_rasterization_mode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
|
||||
}
|
||||
} else {
|
||||
if (supports_rectangular_lines) {
|
||||
line_rasterization_mode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
|
||||
} else if (supports_bresenham_lines) {
|
||||
line_rasterization_mode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
|
||||
} else if (supports_smooth_lines) {
|
||||
line_rasterization_mode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool stippled_lines_supported = [&]() {
|
||||
if (!line_rasterization_supported || !dynamic.line_stipple_enable) {
|
||||
return false;
|
||||
}
|
||||
switch (line_rasterization_mode) {
|
||||
case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT:
|
||||
return device.SupportsStippledRectangularLines();
|
||||
case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT:
|
||||
return device.SupportsStippledBresenhamLines();
|
||||
case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT:
|
||||
return device.SupportsStippledSmoothLines();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}();
|
||||
|
||||
VkPipelineRasterizationLineStateCreateInfoEXT line_state{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.lineRasterizationMode = key.state.smooth_lines != 0 && smooth_lines_supported
|
||||
? VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT
|
||||
: VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT,
|
||||
.stippledLineEnable =
|
||||
(dynamic.line_stipple_enable && stippled_lines_supported) ? VK_TRUE : VK_FALSE,
|
||||
.lineRasterizationMode = line_rasterization_mode,
|
||||
.stippledLineEnable = stippled_lines_supported ? VK_TRUE : VK_FALSE,
|
||||
.lineStippleFactor = key.state.line_stipple_factor,
|
||||
.lineStipplePattern = static_cast<uint16_t>(key.state.line_stipple_pattern),
|
||||
};
|
||||
|
|
@ -840,12 +885,15 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
|||
.pAttachments = cb_attachments.data(),
|
||||
.blendConstants = {}
|
||||
};
|
||||
static_vector<VkDynamicState, 34> dynamic_states{
|
||||
static_vector<VkDynamicState, 35> dynamic_states{
|
||||
VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS,
|
||||
VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
|
||||
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE,
|
||||
VK_DYNAMIC_STATE_LINE_WIDTH,
|
||||
};
|
||||
if (line_stipple_dynamic_state_supported) {
|
||||
dynamic_states.push_back(VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
|
||||
}
|
||||
if (key.state.extended_dynamic_state) {
|
||||
static constexpr std::array extended{
|
||||
VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT,
|
||||
|
|
|
|||
|
|
@ -173,6 +173,55 @@ DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances,
|
|||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
bool IsLineRasterizationTopology(const Device& device, Maxwell::PrimitiveTopology topology) {
|
||||
const VkPrimitiveTopology vk_topology = MaxwellToVK::PrimitiveTopology(device, topology);
|
||||
return vk_topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST ||
|
||||
vk_topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
|
||||
}
|
||||
|
||||
VkLineRasterizationModeEXT SelectLineRasterizationMode(const Device& device, bool smooth_lines) {
|
||||
const bool supports_rectangular_lines = device.SupportsRectangularLines();
|
||||
const bool supports_bresenham_lines = device.SupportsBresenhamLines();
|
||||
const bool supports_smooth_lines = device.SupportsSmoothLines();
|
||||
|
||||
if (smooth_lines) {
|
||||
if (supports_smooth_lines) {
|
||||
return VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
|
||||
}
|
||||
if (supports_rectangular_lines) {
|
||||
return VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
|
||||
}
|
||||
if (supports_bresenham_lines) {
|
||||
return VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
|
||||
}
|
||||
} else {
|
||||
if (supports_rectangular_lines) {
|
||||
return VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
|
||||
}
|
||||
if (supports_bresenham_lines) {
|
||||
return VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
|
||||
}
|
||||
if (supports_smooth_lines) {
|
||||
return VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
|
||||
}
|
||||
}
|
||||
|
||||
return VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
|
||||
}
|
||||
|
||||
bool SupportsStippleForMode(const Device& device, VkLineRasterizationModeEXT mode) {
|
||||
switch (mode) {
|
||||
case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT:
|
||||
return device.SupportsStippledRectangularLines();
|
||||
case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT:
|
||||
return device.SupportsStippledBresenhamLines();
|
||||
case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT:
|
||||
return device.SupportsStippledSmoothLines();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
||||
|
|
@ -1026,6 +1075,7 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
|||
UpdateDepthBounds(regs);
|
||||
UpdateStencilFaces(regs);
|
||||
UpdateLineWidth(regs);
|
||||
UpdateLineStipple(regs);
|
||||
|
||||
// EDS1: CullMode, DepthCompare, FrontFace, StencilOp, DepthBoundsTest, DepthTest, DepthWrite, StencilTest
|
||||
if (device.IsExtExtendedDynamicStateSupported()) {
|
||||
|
|
@ -1370,6 +1420,33 @@ void RasterizerVulkan::UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs) {
|
|||
scheduler.Record([width](vk::CommandBuffer cmdbuf) { cmdbuf.SetLineWidth(width); });
|
||||
}
|
||||
|
||||
void RasterizerVulkan::UpdateLineStipple(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
if (!state_tracker.TouchLineStipple()) {
|
||||
return;
|
||||
}
|
||||
if (!device.IsExtLineRasterizationSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto topology = maxwell3d->draw_manager->GetDrawState().topology;
|
||||
if (!IsLineRasterizationTopology(device, topology)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const VkLineRasterizationModeEXT mode =
|
||||
SelectLineRasterizationMode(device, regs.line_anti_alias_enable != 0);
|
||||
|
||||
if (regs.line_stipple_enable == 0 || !SupportsStippleForMode(device, mode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler.Record(
|
||||
[factor = regs.line_stipple_params.factor,
|
||||
pattern = static_cast<u16>(regs.line_stipple_params.pattern)](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetLineStippleEXT(factor, pattern);
|
||||
});
|
||||
}
|
||||
|
||||
void RasterizerVulkan::UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
if (!state_tracker.TouchCullMode()) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ private:
|
|||
void UpdateDepthBounds(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateLineStipple(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
|
||||
void UpdateCullMode(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateDepthBoundsTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ Flags MakeInvalidationFlags() {
|
|||
StencilWriteMask,
|
||||
StencilCompare,
|
||||
LineWidth,
|
||||
LineStipple,
|
||||
CullMode,
|
||||
DepthBoundsEnable,
|
||||
DepthTestEnable,
|
||||
|
|
@ -119,6 +120,13 @@ void SetupDirtyStencilProperties(Tables& tables) {
|
|||
void SetupDirtyLineWidth(Tables& tables) {
|
||||
tables[0][OFF(line_width_smooth)] = LineWidth;
|
||||
tables[0][OFF(line_width_aliased)] = LineWidth;
|
||||
tables[0][OFF(line_anti_alias_enable)] = LineWidth;
|
||||
}
|
||||
|
||||
void SetupDirtyLineStipple(Tables& tables) {
|
||||
tables[0][OFF(line_stipple_enable)] = LineStipple;
|
||||
FillBlock(tables[0], OFF(line_stipple_params), NUM(line_stipple_params), LineStipple);
|
||||
tables[1][OFF(line_anti_alias_enable)] = LineStipple;
|
||||
}
|
||||
|
||||
void SetupDirtyCullMode(Tables& tables) {
|
||||
|
|
@ -226,6 +234,7 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) {
|
|||
SetupDirtyDepthBounds(tables);
|
||||
SetupDirtyStencilProperties(tables);
|
||||
SetupDirtyLineWidth(tables);
|
||||
SetupDirtyLineStipple(tables);
|
||||
SetupDirtyCullMode(tables);
|
||||
SetupDirtyStateEnable(tables);
|
||||
SetupDirtyDepthCompareOp(tables);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ enum : u8 {
|
|||
StencilWriteMask,
|
||||
StencilCompare,
|
||||
LineWidth,
|
||||
LineStipple,
|
||||
|
||||
CullMode,
|
||||
DepthBoundsEnable,
|
||||
|
|
@ -177,6 +178,10 @@ public:
|
|||
return Exchange(Dirty::LineWidth, false);
|
||||
}
|
||||
|
||||
bool TouchLineStipple() const {
|
||||
return Exchange(Dirty::LineStipple, false);
|
||||
}
|
||||
|
||||
bool TouchCullMode() {
|
||||
return Exchange(Dirty::CullMode, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1229,6 +1229,14 @@ void Device::RemoveUnsuitableExtensions() {
|
|||
features.provoking_vertex,
|
||||
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_line_rasterization
|
||||
extensions.line_rasterization = features.line_rasterization.rectangularLines ||
|
||||
features.line_rasterization.bresenhamLines ||
|
||||
features.line_rasterization.smoothLines;
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.line_rasterization,
|
||||
features.line_rasterization,
|
||||
VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_conditional_rendering
|
||||
extensions.conditional_rendering = features.conditional_rendering.conditionalRendering;
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.conditional_rendering,
|
||||
|
|
|
|||
|
|
@ -435,7 +435,7 @@ public:
|
|||
return extensions.viewport_array2;
|
||||
}
|
||||
|
||||
/// Returns true if the device supporst VK_EXT_DESCRIPTOR_INDEXING.
|
||||
/// Returns true if the device supporst VK_EXT_descriptor_indexing.
|
||||
bool isExtDescriptorIndexingSupported() const {
|
||||
return extensions.descriptor_indexing;
|
||||
}
|
||||
|
|
@ -631,19 +631,32 @@ public:
|
|||
}
|
||||
|
||||
bool SupportsRectangularLines() const {
|
||||
return features.line_rasterization.rectangularLines != VK_FALSE;
|
||||
return features.line_rasterization.rectangularLines;
|
||||
}
|
||||
|
||||
bool SupportsBresenhamLines() const {
|
||||
return features.line_rasterization.bresenhamLines;
|
||||
}
|
||||
|
||||
bool SupportsSmoothLines() const {
|
||||
return features.line_rasterization.smoothLines != VK_FALSE;
|
||||
return features.line_rasterization.smoothLines;
|
||||
}
|
||||
|
||||
bool SupportsStippledRectangularLines() const {
|
||||
return features.line_rasterization.stippledRectangularLines != VK_FALSE;
|
||||
return features.line_rasterization.stippledRectangularLines;
|
||||
}
|
||||
|
||||
bool SupportsStippledBresenhamLines() const {
|
||||
return features.line_rasterization.stippledBresenhamLines;
|
||||
}
|
||||
|
||||
bool SupportsStippledSmoothLines() const {
|
||||
return features.line_rasterization.stippledSmoothLines;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports AlphaToOne.
|
||||
bool SupportsAlphaToOne() const {
|
||||
return features.features.alphaToOne != VK_FALSE;
|
||||
return features.features.alphaToOne;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
|||
X(vkCmdSetFrontFaceEXT);
|
||||
X(vkCmdSetLogicOpEXT);
|
||||
X(vkCmdSetPatchControlPointsEXT);
|
||||
X(vkCmdSetLineStippleEXT);
|
||||
X(vkCmdSetLineWidth);
|
||||
X(vkCmdSetPrimitiveTopologyEXT);
|
||||
X(vkCmdSetStencilOpEXT);
|
||||
|
|
|
|||
Loading…
Reference in New Issue