From dbcbce57b004046d9bc0e1acf6c45a7f2713c97b Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sun, 1 Feb 2026 23:21:24 -0400 Subject: [PATCH] [vulkan] Adjusting provoking vertex last. --- .../renderer_vulkan/fixed_pipeline_state.cpp | 1 - .../renderer_vulkan/fixed_pipeline_state.h | 5 ++--- .../renderer_vulkan/vk_graphics_pipeline.cpp | 8 +++++--- .../renderer_vulkan/vk_rasterizer.cpp | 18 ++++++++++++++++++ src/video_core/renderer_vulkan/vk_rasterizer.h | 1 + .../renderer_vulkan/vk_state_tracker.cpp | 5 +++++ .../renderer_vulkan/vk_state_tracker.h | 4 ++++ .../vulkan_common/vulkan_wrapper.cpp | 1 + src/video_core/vulkan_common/vulkan_wrapper.h | 5 +++++ 9 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index cae8f0f88d..591cd0c653 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -84,7 +84,6 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe depth_enabled.Assign(regs.zeta_enable != 0 ? 1 : 0); depth_format.Assign(static_cast(regs.zeta.format)); y_negate.Assign(regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft ? 1 : 0); - provoking_vertex_last.Assign(regs.provoking_vertex == Maxwell::ProvokingVertex::Last ? 1 : 0); conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0); smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0); alpha_to_coverage_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_coverage != 0 ? 1 : 0); diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index eeb9d2df95..234a563697 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h @@ -214,9 +214,8 @@ struct FixedPipelineState { BitField<5, 1, u32> depth_enabled; BitField<6, 5, u32> depth_format; BitField<11, 1, u32> y_negate; - BitField<12, 1, u32> provoking_vertex_last; - BitField<13, 1, u32> conservative_raster_enable; - BitField<14, 1, u32> smooth_lines; + BitField<12, 1, u32> conservative_raster_enable; + BitField<13, 1, u32> smooth_lines; BitField<15, 1, u32> alpha_to_coverage_enabled; BitField<16, 1, u32> alpha_to_one_enabled; BitField<17, 3, Tegra::Engines::Maxwell3D::EngineHint> app_stage; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 06ea1c5b22..c836c64029 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -741,9 +741,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provoking_vertex{ .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT, .pNext = nullptr, - .provokingVertexMode = key.state.provoking_vertex_last != 0 - ? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT - : VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, + .provokingVertexMode = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, }; if (IsLine(input_assembly_topology) && device.IsExtLineRasterizationSupported()) { @@ -918,6 +916,10 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { } } + if (device.IsExtProvokingVertexSupported()) { + dynamic_states.push_back(VK_DYNAMIC_STATE_PROVOKING_VERTEX_EXT); + } + const VkPipelineDynamicStateCreateInfo dynamic_state_ci{ .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, .pNext = nullptr, diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 4c4b994003..83d560e8b8 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1042,6 +1042,10 @@ void RasterizerVulkan::UpdateDynamicStates() { UpdateLogicOp(regs); } + if (device.IsExtProvokingVertexSupported()) { + UpdateProvokingVertex(regs); + } + if (device.IsExtExtendedDynamicState3EnablesSupported()) { using namespace Tegra::Engines; if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE || @@ -1617,6 +1621,20 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) { [front_face](vk::CommandBuffer cmdbuf) { cmdbuf.SetFrontFaceEXT(front_face); }); } +void RasterizerVulkan::UpdateProvokingVertex(Tegra::Engines::Maxwell3D::Regs& regs) { + if (!device.IsExtProvokingVertexSupported()) { + return; + } + if (!state_tracker.TouchProvokingVertex()) { + return; + } + + const auto mode = regs.provoking_vertex == Maxwell::ProvokingVertex::Last + ? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT + : VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT; + scheduler.Record([mode](vk::CommandBuffer cmdbuf) { cmdbuf.SetProvokingVertexEXT(mode); }); +} + void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) { if (!state_tracker.TouchStencilOp()) { return; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index b689c6b660..69bf654dc7 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -186,6 +186,7 @@ private: void UpdateAlphaToCoverageEnable(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateAlphaToOneEnable(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs); + void UpdateProvokingVertex(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs); void UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs); diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp index 79967d540a..7c93a4d595 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp @@ -166,6 +166,10 @@ void SetupDirtyFrontFace(Tables& tables) { table[OFF(window_origin)] = FrontFace; } +void SetupDirtyProvokingVertex(Tables& tables) { + tables[0][OFF(provoking_vertex)] = ProvokingVertex; +} + void SetupDirtyStencilOp(Tables& tables) { auto& table = tables[0]; table[OFF(stencil_front_op.fail)] = StencilOp; @@ -250,6 +254,7 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) { SetupDirtyStateEnable(tables); SetupDirtyDepthCompareOp(tables); SetupDirtyFrontFace(tables); + SetupDirtyProvokingVertex(tables); SetupDirtyStencilOp(tables); SetupDirtyBlending(tables); SetupDirtyViewportSwizzles(tables); diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index 74bae9e181..162d68ee16 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h @@ -248,6 +248,10 @@ public: return Exchange(Dirty::FrontFace, false); } + bool TouchProvokingVertex() { + return Exchange(Dirty::ProvokingVertex, false); + } + bool TouchStencilOp() { return Exchange(Dirty::StencilOp, false); } diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 8fc5e8e063..f1a17d4197 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -159,6 +159,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkCmdSetPatchControlPointsEXT); X(vkCmdSetLineWidth); X(vkCmdSetPrimitiveTopologyEXT); + X(vkCmdSetProvokingVertexEXT); X(vkCmdSetStencilOpEXT); X(vkCmdSetStencilTestEnableEXT); X(vkCmdSetVertexInputEXT); diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 4177359f2d..bedf0a85b5 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -254,6 +254,7 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT{}; PFN_vkCmdSetLineWidth vkCmdSetLineWidth{}; PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT{}; + PFN_vkCmdSetProvokingVertexEXT vkCmdSetProvokingVertexEXT{}; PFN_vkCmdSetScissor vkCmdSetScissor{}; PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask{}; PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT{}; @@ -1529,6 +1530,10 @@ public: dld->vkCmdSetPrimitiveTopologyEXT(handle, primitive_topology); } + void SetProvokingVertexEXT(VkProvokingVertexModeEXT provoking_vertex_mode) const noexcept { + dld->vkCmdSetProvokingVertexEXT(handle, provoking_vertex_mode); + } + void SetStencilOpEXT(VkStencilFaceFlags face_mask, VkStencilOp fail_op, VkStencilOp pass_op, VkStencilOp depth_fail_op, VkCompareOp compare_op) const noexcept { dld->vkCmdSetStencilOpEXT(handle, face_mask, fail_op, pass_op, depth_fail_op, compare_op);