Jelajahi Sumber

Add support for void-returning fragment functions.

Eric Mellino 8 tahun lalu
induk
melakukan
7682e68810

+ 1 - 1
src/ShaderGen.Build/ShaderGen.Build.csproj

@@ -9,7 +9,7 @@
     <PackageId>ShaderGen.Build</PackageId>
     <Description>Build-time plugin which generates shader code during a post-build event.</Description>
     <PackageTags>Shader GLSL HLSL SPIR-V Graphics OpenGL Vulkan Direct3D Game</PackageTags>
-    <PackageVersion>1.0.8</PackageVersion>
+    <PackageVersion>1.0.9</PackageVersion>
   </PropertyGroup>
 
   <ItemGroup>

+ 1 - 0
src/ShaderGen.Tests/ShaderGeneratorTests.cs

@@ -22,6 +22,7 @@ namespace ShaderGen.Tests
             yield return new object[] { "TestShaders.CustomStructResource.VS", null };
             yield return new object[] { "TestShaders.Swizzles.VS", null };
             yield return new object[] { "TestShaders.CustomMethodCalls.VS", null };
+            yield return new object[] { "TestShaders.VeldridShaders.ShadowDepth.VS", "TestShaders.VeldridShaders.ShadowDepth.FS" };
         }
 
         [Theory]

+ 37 - 0
src/ShaderGen.Tests/TestAssets/VeldridShaders/ShadowDepth.cs

@@ -0,0 +1,37 @@
+using System.Numerics;
+using ShaderGen;
+using static ShaderGen.ShaderBuiltins;
+
+namespace TestShaders.VeldridShaders
+{
+    public class ShadowDepth
+    {
+        public Matrix4x4 Projection;
+        public Matrix4x4 View;
+        public Matrix4x4 World;
+
+        [VertexShader]
+        public FragmentInput VS(VertexInput input)
+        {
+            FragmentInput output;
+            output.Position = Mul(Projection, Mul(View, Mul(World, new Vector4(input.Position, 1))));
+            return output;
+        }
+
+        [FragmentShader]
+        public void FS(FragmentInput input) { }
+
+        public struct VertexInput
+        {
+            [PositionSemantic] public Vector3 Position;
+            [NormalSemantic] public Vector3 Normal;
+            [TextureCoordinateSemantic] public Vector2 TexCoord;
+        }
+
+        public struct FragmentInput
+        {
+            [PositionSemantic]
+            public Vector4 Position;
+        }
+    }
+}

+ 20 - 7
src/ShaderGen/GlslBackendBase.cs

@@ -149,6 +149,8 @@ namespace ShaderGen
                 }
             }
 
+            string mappedReturnType = CSharpToShaderType(entryFunction.ReturnType.Name);
+
             // Declare "out" variables
             if (entryFunction.Type == ShaderFunctionType.VertexEntryPoint)
             {
@@ -177,19 +179,20 @@ namespace ShaderGen
             else
             {
                 Debug.Assert(entryFunction.Type == ShaderFunctionType.FragmentEntryPoint);
-                string mappedReturnType = CSharpToShaderType(entryFunction.ReturnType.Name);
-                if (mappedReturnType != "vec4")
+                if (mappedReturnType != "vec4" && mappedReturnType != "void")
                 {
-                    throw new ShaderGenerationException("Fragment shader must return a System.Numerics.Vector4 value.");
+                    throw new ShaderGenerationException("Fragment shader must return a System.Numerics.Vector4 value, or no value.");
                 }
 
-                WriteInOutVariable(sb, false, false, "vec4", "_outputColor_", 0);
+                if (mappedReturnType == "vec4")
+                {
+                    WriteInOutVariable(sb, false, false, "vec4", "_outputColor_", 0);
+                }
             }
 
             sb.AppendLine();
 
             string inTypeName = CSharpToShaderType(inputType.Name);
-            string outTypeName = CSharpToShaderType(entryFunction.ReturnType.Name);
 
             sb.AppendLine($"void main()");
             sb.AppendLine("{");
@@ -220,7 +223,14 @@ namespace ShaderGen
             }
 
             // Call actual function.
-            sb.AppendLine($"    {outTypeName} {CorrectIdentifier("output")} = {entryFunction.Name}({CorrectIdentifier("input")});");
+            if (mappedReturnType != "void")
+            {
+                sb.AppendLine($"    {mappedReturnType} {CorrectIdentifier("output")} = {entryFunction.Name}({CorrectIdentifier("input")});");
+            }
+            else
+            {
+                sb.Append($"    {entryFunction.Name}({CorrectIdentifier("input")});");
+            }
 
             // Assign output fields to synthetic "out" variables with normalized "fsin_#" names.
             if (entryFunction.Type == ShaderFunctionType.VertexEntryPoint)
@@ -251,7 +261,10 @@ namespace ShaderGen
             else
             {
                 Debug.Assert(entryFunction.Type == ShaderFunctionType.FragmentEntryPoint);
-                sb.AppendLine($"    _outputColor_ = {CorrectIdentifier("output")};");
+                if (mappedReturnType == "vec4")
+                {
+                    sb.AppendLine($"    _outputColor_ = {CorrectIdentifier("output")};");
+                }
             }
             sb.AppendLine("}");
         }

+ 1 - 0
src/ShaderGen/GlslKnownTypes.cs

@@ -12,6 +12,7 @@ namespace ShaderGen
             { "System.Numerics.Vector3", "vec3" },
             { "System.Numerics.Vector4", "vec4" },
             { "System.Numerics.Matrix4x4", "mat4" },
+            { "System.Void", "void" },
         };
 
         public static string GetMappedName(string name)

+ 1 - 0
src/ShaderGen/HlslKnownTypes.cs

@@ -12,6 +12,7 @@ namespace ShaderGen
             { "System.Numerics.Vector3", "float3" },
             { "System.Numerics.Vector4", "float4" },
             { "System.Numerics.Matrix4x4", "float4x4" },
+            { "System.Void", "void" },
         };
 
         public static string GetMappedName(string name)

+ 12 - 1
src/ShaderGen/HlslMethodVisitor.cs

@@ -12,7 +12,18 @@ namespace ShaderGen
         protected override string GetFunctionDeclStr()
         {
             string returnType = _backend.CSharpToShaderType(_shaderFunction.ReturnType.Name);
-            string suffix = _shaderFunction.Type == ShaderFunctionType.FragmentEntryPoint ? " : SV_Target" : string.Empty;
+            string suffix = string.Empty;
+            if (_shaderFunction.Type == ShaderFunctionType.FragmentEntryPoint)
+            {
+                if (_shaderFunction.ReturnType.Name == "System.Numerics.Vector4")
+                {
+                    suffix = " : SV_Target";
+                }
+                else if (_shaderFunction.ReturnType.Name != "System.Void")
+                {
+                    throw new ShaderGenerationException("Unsupported fragment return type: " + _shaderFunction.ReturnType.Name);
+                }
+            }
             string fullDeclType = _backend.CSharpToShaderType(_shaderFunction.DeclaringType);
             string funcName = _shaderFunction.IsEntryPoint
                 ? _shaderFunction.Name

+ 1 - 1
src/ShaderGen/ShaderGen.csproj

@@ -2,7 +2,7 @@
 
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <AssemblyVersion>1.0.3</AssemblyVersion>
+    <AssemblyVersion>1.0.4</AssemblyVersion>
 
     <!-- Package stuff -->
     <PackageId>ShaderGen</PackageId>