Просмотр исходного кода

Vulkan: Skip draws when patches topology is used without a tessellation shader (#6508)

gdkchan 2 лет назад
Родитель
Сommit
791bf22109

+ 1 - 0
src/Ryujinx.Graphics.Vulkan/PipelineBase.cs

@@ -981,6 +981,7 @@ namespace Ryujinx.Graphics.Vulkan
             _bindingBarriersDirty = true;
 
             _newState.PipelineLayout = internalProgram.PipelineLayout;
+            _newState.HasTessellationControlShader = internalProgram.HasTessellationControlShader;
             _newState.StagesCount = (uint)stages.Length;
 
             stages.CopyTo(_newState.Stages.AsSpan()[..stages.Length]);

+ 11 - 0
src/Ryujinx.Graphics.Vulkan/PipelineState.cs

@@ -311,6 +311,7 @@ namespace Ryujinx.Graphics.Vulkan
             set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
         }
 
+        public bool HasTessellationControlShader;
         public NativeArray<PipelineShaderStageCreateInfo> Stages;
         public PipelineLayout PipelineLayout;
         public SpecData SpecializationData;
@@ -319,6 +320,7 @@ namespace Ryujinx.Graphics.Vulkan
 
         public void Initialize()
         {
+            HasTessellationControlShader = false;
             Stages = new NativeArray<PipelineShaderStageCreateInfo>(Constants.MaxShaderStages);
 
             AdvancedBlendSrcPreMultiplied = true;
@@ -419,6 +421,15 @@ namespace Ryujinx.Graphics.Vulkan
                     PVertexBindingDescriptions = pVertexBindingDescriptions,
                 };
 
+                // Using patches topology without a tessellation shader is invalid.
+                // If we find such a case, return null pipeline to skip the draw.
+                if (Topology == PrimitiveTopology.PatchList && !HasTessellationControlShader)
+                {
+                    program.AddGraphicsPipeline(ref Internal, null);
+
+                    return null;
+                }
+
                 bool primitiveRestartEnable = PrimitiveRestartEnable;
 
                 bool topologySupportsRestart;

+ 2 - 0
src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs

@@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
         public bool HasMinimalLayout { get; }
         public bool UsePushDescriptors { get; }
         public bool IsCompute { get; }
+        public bool HasTessellationControlShader => (Stages & (1u << 3)) != 0;
 
         public uint Stages { get; }
 
@@ -461,6 +462,7 @@ namespace Ryujinx.Graphics.Vulkan
                 stages[i] = _shaders[i].GetInfo();
             }
 
+            pipeline.HasTessellationControlShader = HasTessellationControlShader;
             pipeline.StagesCount = (uint)_shaders.Length;
             pipeline.PipelineLayout = PipelineLayout;