From 24e6105e6fda830ce9753c724d0b96ce1ca80560 Mon Sep 17 00:00:00 2001
From: sunshineinabox <aqemail@gmail.com>
Date: Mon, 13 May 2024 00:18:20 -0700
Subject: [PATCH] Primitive Topolgy DynamicState maybe causing performance
 degredation.

---
 src/Ryujinx.Graphics.Vulkan/PipelineBase.cs   | 18 ++++++++++-----
 .../PipelineConverter.cs                      | 19 ++++++++--------
 .../PipelineDynamicState.cs                   | 22 +++++++++++++++++--
 src/Ryujinx.Graphics.Vulkan/PipelineState.cs  |  9 ++++++--
 4 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
index 096627e0b..3c67d952a 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
@@ -693,7 +693,7 @@ namespace Ryujinx.Graphics.Vulkan
                 var oldStencilTestEnable = _supportExtDynamic ? DynamicState._stencilTestEnable : _newState.StencilTestEnable;
                 var oldDepthTestEnable = _supportExtDynamic ? DynamicState._depthtestEnable : _newState.DepthTestEnable;
                 var oldDepthWriteEnable = _supportExtDynamic ? DynamicState._depthwriteEnable : _newState.DepthWriteEnable;
-                var oldTopology = _newState.Topology;
+                var oldTopology = _supportExtDynamic ? DynamicState. Topology : _newState.Topology;
                 var oldViewports = DynamicState.Viewports;
                 var oldViewportsCount = _newState.ViewportsCount;
 
@@ -726,6 +726,7 @@ namespace Ryujinx.Graphics.Vulkan
                     DynamicState.SetCullMode(oldCullMode);
                     DynamicState.SetStencilTest(oldStencilTestEnable);
                     DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable);
+                    DynamicState.SetPrimitiveTopology(ref oldTopology);
                 }
                 else
                 {
@@ -733,9 +734,8 @@ namespace Ryujinx.Graphics.Vulkan
                     _newState.StencilTestEnable = oldStencilTestEnable;
                     _newState.DepthTestEnable = oldDepthTestEnable;
                     _newState.DepthWriteEnable = oldDepthWriteEnable;
+                    _newState.Topology = oldTopology;
                 }
-                
-                _newState.Topology = oldTopology;
 
                 DynamicState.SetViewports(ref oldViewports, oldViewportsCount);
 
@@ -1019,9 +1019,15 @@ namespace Ryujinx.Graphics.Vulkan
             _topology = topology;
 
             var vkTopology = Gd.TopologyRemap(topology).Convert();
-
-            _newState.Topology = vkTopology;
-
+            if (_supportExtDynamic)
+            {
+                DynamicState.SetPrimitiveTopology(ref vkTopology);
+            }
+            else
+            {
+                _newState.Topology = vkTopology;
+            }
+            
             SignalStateChange();
         }
 
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs
index 1a7cba1e5..d0344ee4b 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs
@@ -164,10 +164,7 @@ namespace Ryujinx.Graphics.Vulkan
             pipeline.DepthBoundsTestEnable = false; // Not implemented.
 
             pipeline.DepthClampEnable = state.DepthClampEnable;
-
-            pipeline.DepthTestEnable = state.DepthTest.TestEnable;
-            pipeline.DepthWriteEnable = state.DepthTest.WriteEnable;
-            pipeline.DepthCompareOp = state.DepthTest.Func.Convert();
+            
             pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne;
             
             pipeline.HasDepthStencil = state.DepthStencilEnable;
@@ -200,6 +197,10 @@ namespace Ryujinx.Graphics.Vulkan
             // Stencil masks and ref are dynamic, so are 0 in the Vulkan pipeline.
             if (!gd.Capabilities.SupportsExtendedDynamicState)
             {
+                pipeline.DepthTestEnable = state.DepthTest.TestEnable;
+                pipeline.DepthWriteEnable = state.DepthTest.WriteEnable;
+                pipeline.DepthCompareOp = state.DepthTest.Func.Convert();
+                
                 pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None;
                 
                 pipeline.FrontFace = state.FrontFace.Convert();
@@ -213,12 +214,12 @@ namespace Ryujinx.Graphics.Vulkan
                 pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert();
                 pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert();
                 pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert();
+                
+                pipeline.StencilTestEnable = state.StencilTest.TestEnable;
+                
+                pipeline.Topology = gd.TopologyRemap(state.Topology).Convert();
             }
-
-            pipeline.StencilTestEnable = state.StencilTest.TestEnable;
-
-            pipeline.Topology = gd.TopologyRemap(state.Topology).Convert();
-
+            
             int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount);
             int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount);
 
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs
index 7a1c39b04..916b065bd 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs
@@ -36,6 +36,8 @@ namespace Ryujinx.Graphics.Vulkan
         public bool _depthwriteEnable;
         private CompareOp _depthCompareOp;
 
+        public PrimitiveTopology Topology;
+
         private Array4<float> _blendConstants;
 
         public uint ViewportsCount;
@@ -58,7 +60,8 @@ namespace Ryujinx.Graphics.Vulkan
             DepthTestBool = 1 << 7, 
             DepthTestCompareOp = 1 << 8,
             StencilTestEnable = 1 << 9,
-            All = Blend | DepthBias | Scissor | Stencil | Viewport | CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable,
+            Toplogy = 1 << 10,
+            All = Blend | DepthBias | Scissor | Stencil | Viewport | CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable | Toplogy,
         }
 
         private DirtyFlags _dirty;
@@ -103,8 +106,13 @@ namespace Ryujinx.Graphics.Vulkan
 
             _dirty |= DirtyFlags.DepthTestCompareOp;
         }
+        
+        public void SetPrimitiveTopology(ref PrimitiveTopology topology)
+        {
+            Topology = topology;
 
-
+            _dirty |= DirtyFlags.Toplogy;
+        }
         
         public void SetStencilOp(StencilOp backFailOp,
             StencilOp backPassOp,
@@ -242,6 +250,11 @@ namespace Ryujinx.Graphics.Vulkan
             {
                 RecordStencilTestEnable(api, commandBuffer);
             }
+            
+            if (_dirty.HasFlag(DirtyFlags.Toplogy))
+            {
+                RecordPrimitiveTopology(api, commandBuffer);
+            }
 
             _dirty = DirtyFlags.None;
         }
@@ -315,5 +328,10 @@ namespace Ryujinx.Graphics.Vulkan
         {
             api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp);
         }
+        
+        private void RecordPrimitiveTopology(Vk api, CommandBuffer commandBuffer)
+        {
+            api.CmdSetPrimitiveTopology(commandBuffer, Topology);
+        }
     }
 }
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
index 6182ccaa0..3dbc01f2d 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
@@ -453,9 +453,13 @@ namespace Ryujinx.Graphics.Vulkan
                 {
                     SType = StructureType.PipelineInputAssemblyStateCreateInfo,
                     PrimitiveRestartEnable = primitiveRestartEnable,
-                    Topology = Topology,
                 };
 
+                if (!supportsExtDynamicState)
+                {
+                    inputAssemblyState.Topology = Topology;
+                }
+
                 var tessellationState = new PipelineTessellationStateCreateInfo
                 {
                     SType = StructureType.PipelineTessellationStateCreateInfo,
@@ -593,7 +597,7 @@ namespace Ryujinx.Graphics.Vulkan
                     colorBlendState.PNext = &colorBlendAdvancedState;
                 }
                 
-                int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 14 : 15) : 7;
+                int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 15 : 16) : 7;
 
                 DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
 
@@ -617,6 +621,7 @@ namespace Ryujinx.Graphics.Vulkan
                     dynamicStates[index++] = DynamicState.DepthWriteEnable;
                     dynamicStates[index++] = DynamicState.DepthCompareOp;
                     dynamicStates[index++] = DynamicState.StencilTestEnable;
+                    dynamicStates[index++] = DynamicState.PrimitiveTopology;
                     dynamicStates[index] = DynamicState.StencilOp;
                 }