From e1721012d8dfabcd96aa1fc17bd10d68c2fa5de4 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Fri, 3 Jul 2026 01:49:56 -0400 Subject: [PATCH] [vulkan] Set actual dynamic state handling for topology --- .../renderer_vulkan/fixed_pipeline_state.cpp | 24 ++++++++++++++++++- .../renderer_vulkan/vk_graphics_pipeline.cpp | 1 + .../renderer_vulkan/vk_rasterizer.cpp | 16 ++++++------- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index c6aa28fa23..3c041a48cb 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -39,6 +39,24 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = { POLYGON, // Patches }; +constexpr std::array TOPOLOGY_CLASS_REPRESENTATIVE_LUT = { + Maxwell::PrimitiveTopology::Points, // Points + Maxwell::PrimitiveTopology::Lines, // Lines + Maxwell::PrimitiveTopology::LineLoop, // LineLoop + Maxwell::PrimitiveTopology::LineStrip, // LineStrip + Maxwell::PrimitiveTopology::Triangles, // Triangles + Maxwell::PrimitiveTopology::Triangles, // TriangleStrip + Maxwell::PrimitiveTopology::Triangles, // TriangleFan + Maxwell::PrimitiveTopology::Triangles, // Quads + Maxwell::PrimitiveTopology::Triangles, // QuadStrip + Maxwell::PrimitiveTopology::Triangles, // Polygon + Maxwell::PrimitiveTopology::LinesAdjacency, // LinesAdjacency + Maxwell::PrimitiveTopology::LinesAdjacency, // LineStripAdjacency + Maxwell::PrimitiveTopology::TrianglesAdjacency, // TrianglesAdjacency + Maxwell::PrimitiveTopology::TrianglesAdjacency, // TriangleStripAdjacency + Maxwell::PrimitiveTopology::Patches, // Patches +}; + void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) { std::ranges::transform(regs.transform_feedback.controls, state.layouts.begin(), [](const auto& layout) { @@ -71,7 +89,11 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe tessellation_clockwise.Assign(regs.tessellation.params.output_primitives.Value() == Maxwell::Tessellation::OutputPrimitives::Triangles_CW); patch_control_points_minus_one.Assign(regs.patch_vertices - 1); - topology.Assign(topology_); + const bool can_collapse_topology_class = + features.has_extended_dynamic_state && features.has_extended_dynamic_state_2; + topology.Assign(can_collapse_topology_class + ? TOPOLOGY_CLASS_REPRESENTATIVE_LUT[static_cast(topology_)] + : topology_); msaa_mode.Assign(regs.anti_alias_samples_mode); raw2 = 0; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 0c0174391c..6f1c07f84b 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -865,6 +865,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT, VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT, VK_DYNAMIC_STATE_STENCIL_OP_EXT, + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT, }; dynamic_states.insert(dynamic_states.end(), extended.begin(), extended.end()); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 863ebb72ec..c4ac861927 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1011,12 +1011,12 @@ void RasterizerVulkan::UpdateDynamicStates() { auto& regs = maxwell3d->regs; auto& flags = maxwell3d->dirty.flags; const auto topology = maxwell3d->draw_manager.draw_state.topology; - if (state_tracker.ChangePrimitiveTopology(topology)) { + const bool topology_changed = state_tracker.ChangePrimitiveTopology(topology); + if (topology_changed) { flags[Dirty::DepthBiasEnable] = true; flags[Dirty::PrimitiveRestartEnable] = true; } - // Core Dynamic States (Vulkan 1.0) - Always active regardless of dyna_state setting UpdateViewportsState(regs); UpdateScissorsState(regs); UpdateDepthBias(regs); @@ -1025,7 +1025,6 @@ void RasterizerVulkan::UpdateDynamicStates() { UpdateStencilFaces(regs); UpdateLineWidth(regs); - // EDS1: CullMode, DepthCompare, FrontFace, StencilOp, DepthBoundsTest, DepthTest, DepthWrite, StencilTest if (device.IsExtExtendedDynamicStateSupported()) { UpdateCullMode(regs); UpdateDepthCompareOp(regs); @@ -1037,21 +1036,24 @@ void RasterizerVulkan::UpdateDynamicStates() { UpdateDepthWriteEnable(regs); UpdateStencilTestEnable(regs); } + if (topology_changed) { + scheduler.Record([topology_vk = MaxwellToVK::PrimitiveTopology(device, topology)]( + vk::CommandBuffer cmdbuf) { + cmdbuf.SetPrimitiveTopologyEXT(topology_vk); + }); + } } - // EDS2: PrimitiveRestart, RasterizerDiscard, DepthBias enable/disable if (device.IsExtExtendedDynamicState2Supported()) { UpdatePrimitiveRestartEnable(regs); UpdateRasterizerDiscardEnable(regs); UpdateDepthBiasEnable(regs); } - // EDS2 Extras: LogicOp operation selection if (device.IsExtExtendedDynamicState2ExtrasSupported()) { UpdateLogicOp(regs); } - // EDS3 Enables: LogicOpEnable, DepthClamp, LineStipple, ConservativeRaster if (device.IsExtExtendedDynamicState3EnablesSupported()) { using namespace Tegra::Engines; // AMD Workaround: LogicOp incompatible with float render targets @@ -1076,12 +1078,10 @@ void RasterizerVulkan::UpdateDynamicStates() { UpdateAlphaToOneEnable(regs); } - // EDS3 Blending: ColorBlendEnable, ColorBlendEquation, ColorWriteMask if (device.IsExtExtendedDynamicState3BlendingSupported()) { UpdateBlending(regs); } - // Vertex Input Dynamic State: Independent from EDS levels if (device.IsExtVertexInputDynamicStateSupported()) { if (auto* gp = pipeline_cache.CurrentGraphicsPipeline(); gp && gp->HasDynamicVertexInput()) { UpdateVertexInput(regs);