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

Implement geometry shader passthrough (#1961)

* Implement geometry shader passthrough

* Cache version change
gdkchan 5 лет назад
Родитель
Сommit
f93089a64f

+ 1 - 1
Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs

@@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
         /// <summary>
         /// Version of the codegen (to be changed when codegen or guest format change).
         /// </summary>
-        private const ulong ShaderCodeGenVersion = 1964;
+        private const ulong ShaderCodeGenVersion = 1961;
 
         /// <summary>
         /// Creates a new instance of the shader cache.

+ 36 - 16
Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs

@@ -26,6 +26,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
                 context.AppendLine("#extension GL_ARB_compute_shader : enable");
             }
 
+            if (context.Config.GpPassthrough)
+            {
+                context.AppendLine("#extension GL_NV_geometry_shader_passthrough : enable");
+            }
+
             context.AppendLine("#pragma optionNV(fastmath off)");
 
             context.AppendLine();
@@ -33,20 +38,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
             context.AppendLine($"const int {DefaultNames.UndefinedName} = 0;");
             context.AppendLine();
 
-            if (context.Config.Stage == ShaderStage.Geometry)
-            {
-                string inPrimitive = context.Config.GpuAccessor.QueryPrimitiveTopology().ToGlslString();
-
-                context.AppendLine($"layout ({inPrimitive}) in;");
-
-                string outPrimitive = context.Config.OutputTopology.ToGlslString();
-
-                int maxOutputVertices = context.Config.MaxOutputVertices;
-
-                context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;");
-                context.AppendLine();
-            }
-
             if (context.Config.Stage == ShaderStage.Compute)
             {
                 int localMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeLocalMemorySize(), 4);
@@ -109,6 +100,33 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
 
             if (context.Config.Stage != ShaderStage.Compute)
             {
+                if (context.Config.Stage == ShaderStage.Geometry)
+                {
+                    string inPrimitive = context.Config.GpuAccessor.QueryPrimitiveTopology().ToGlslString();
+
+                    context.AppendLine($"layout ({inPrimitive}) in;");
+
+                    if (context.Config.GpPassthrough)
+                    {
+                        context.AppendLine($"layout (passthrough) in gl_PerVertex");
+                        context.EnterScope();
+                        context.AppendLine("vec4 gl_Position;");
+                        context.AppendLine("float gl_PointSize;");
+                        context.AppendLine("float gl_ClipDistance[];");
+                        context.LeaveScope(";");
+                    }
+                    else
+                    {
+                        string outPrimitive = context.Config.OutputTopology.ToGlslString();
+
+                        int maxOutputVertices = context.Config.MaxOutputVertices;
+
+                        context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;");
+                    }
+
+                    context.AppendLine();
+                }
+
                 if (info.IAttributes.Count != 0)
                 {
                     DeclareInputAttributes(context, info);
@@ -432,6 +450,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
                     };
                 }
 
+                string pass = context.Config.GpPassthrough ? "passthrough, " : string.Empty;
+
                 string name = $"{DefaultNames.IAttributePrefix}{attr}";
 
                 if ((context.Config.Flags & TranslationFlags.Feedback) != 0)
@@ -440,12 +460,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
                     {
                         char swzMask = "xyzw"[c];
 
-                        context.AppendLine($"layout (location = {attr}, component = {c}) {iq}in float {name}_{swzMask}{suffix};");
+                        context.AppendLine($"layout ({pass}location = {attr}, component = {c}) {iq}in float {name}_{swzMask}{suffix};");
                     }
                 }
                 else
                 {
-                    context.AppendLine($"layout (location = {attr}) {iq}in vec4 {name}{suffix};");
+                    context.AppendLine($"layout ({pass}location = {attr}) {iq}in vec4 {name}{suffix};");
                 }
             }
         }

+ 2 - 1
Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs

@@ -69,7 +69,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
                 // compiler may eliminate them.
                 // (Not needed for fragment shader as it is the last stage).
                 if (context.Config.Stage != ShaderStage.Compute &&
-                    context.Config.Stage != ShaderStage.Fragment)
+                    context.Config.Stage != ShaderStage.Fragment &&
+                    !context.Config.GpPassthrough)
                 {
                     for (int attr = 0; attr < Declarations.MaxAttributes; attr++)
                     {

+ 4 - 0
Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs

@@ -6,6 +6,8 @@ namespace Ryujinx.Graphics.Shader.Translation
     {
         public ShaderStage Stage { get; }
 
+        public bool GpPassthrough { get; }
+
         public OutputTopology OutputTopology { get; }
 
         public int MaxOutputVertices { get; }
@@ -33,6 +35,7 @@ namespace Ryujinx.Graphics.Shader.Translation
         public ShaderConfig(IGpuAccessor gpuAccessor, TranslationFlags flags, TranslationCounts counts)
         {
             Stage                  = ShaderStage.Compute;
+            GpPassthrough          = false;
             OutputTopology         = OutputTopology.PointList;
             MaxOutputVertices      = 0;
             LocalMemorySize        = 0;
@@ -51,6 +54,7 @@ namespace Ryujinx.Graphics.Shader.Translation
         public ShaderConfig(ShaderHeader header, IGpuAccessor gpuAccessor, TranslationFlags flags, TranslationCounts counts)
         {
             Stage                  = header.Stage;
+            GpPassthrough          = header.Stage == ShaderStage.Geometry && header.GpPassthrough;
             OutputTopology         = header.OutputTopology;
             MaxOutputVertices      = header.MaxOutputVertexCount;
             LocalMemorySize        = header.ShaderLocalMemoryLowSize + header.ShaderLocalMemoryHighSize;

+ 4 - 0
Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs

@@ -81,6 +81,8 @@ namespace Ryujinx.Graphics.Shader.Translation
 
         public int SassVersion { get; }
 
+        public bool GpPassthrough { get; }
+
         public bool DoesLoadOrStore { get; }
         public bool DoesFp64        { get; }
 
@@ -136,6 +138,8 @@ namespace Ryujinx.Graphics.Shader.Translation
 
             SassVersion = commonWord0.Extract(17, 4);
 
+            GpPassthrough = commonWord0.Extract(24);
+
             DoesLoadOrStore = commonWord0.Extract(26);
             DoesFp64        = commonWord0.Extract(27);