Beispiel #1
0
        public GeneratedShaderSet(
            string name,
            string vsCode,
            string gsCode,
            string fsCode,
            string csCode,
            ShaderFunction vertexfunction,
            ShaderFunction geometryFunction,
            ShaderFunction fragmentFunction,
            ShaderFunction computeFunction,
            ShaderModel model)
        {
            if (string.IsNullOrEmpty(vsCode) && string.IsNullOrEmpty(gsCode) && string.IsNullOrEmpty(fsCode) && string.IsNullOrEmpty(csCode))
            {
                throw new ShaderGenerationException("At least one of vsCode, fsCode, or csCode must be non-empty");
            }

            Name               = name;
            VertexShaderCode   = vsCode;
            GeometryShaderCode = gsCode;
            FragmentShaderCode = fsCode;
            ComputeShaderCode  = csCode;
            VertexFunction     = vertexfunction;
            GeometryFunction   = geometryFunction;
            FragmentFunction   = fragmentFunction;
            ComputeFunction    = computeFunction;
            Model              = model;
        }
Beispiel #2
0
        protected override void WriteVersionHeader(ShaderFunction function, StringBuilder sb)
        {
            string version = function.Type == ShaderFunctionType.ComputeEntryPoint ? "430" : "330 core";

            sb.AppendLine($"#version {version}");
            sb.AppendLine();
        }
Beispiel #3
0
        public void HlslEndToEnd(string vsName, string fsName)
        {
            Compilation     compilation = TestUtil.GetTestProjectCompilation();
            HlslBackend     backend     = new HlslBackend(compilation);
            ShaderGenerator sg          = new ShaderGenerator(
                compilation,
                vsName,
                fsName,
                backend);

            ShaderGenerationResult             result = sg.GenerateShaders();
            IReadOnlyList <GeneratedShaderSet> sets   = result.GetOutput(backend);

            Assert.Equal(1, sets.Count);
            GeneratedShaderSet set         = sets[0];
            ShaderModel        shaderModel = set.Model;

            if (vsName != null)
            {
                ShaderFunction vsFunction = shaderModel.GetFunction(vsName);
                string         vsCode     = set.VertexShaderCode;
                FxcTool.AssertCompilesCode(vsCode, "vs_5_0", vsFunction.Name);
            }
            if (fsName != null)
            {
                ShaderFunction fsFunction = shaderModel.GetFunction(fsName);
                string         fsCode     = set.FragmentShaderCode;
                FxcTool.AssertCompilesCode(fsCode, "ps_5_0", fsFunction.Name);
            }
        }
Beispiel #4
0
        protected override void WriteVersionHeader(ShaderFunction function, StringBuilder sb)
        {
            bool   useVersion320 = function.UsesTexture2DMS;
            bool   useVersion310 = function.UsesStructuredBuffer;
            string versionNumber = useVersion320 ? "320" :
                                   useVersion310 ? "310" : "300";
            string version = $"{versionNumber} es";

            sb.AppendLine($"#version {version}");
            sb.AppendLine($"precision mediump float;");
            sb.AppendLine($"precision mediump int;");
            sb.AppendLine($"precision mediump sampler2D;");
            sb.AppendLine($"precision mediump sampler2DShadow;");
            sb.AppendLine($"precision mediump sampler2DArray;");
            sb.AppendLine($"precision mediump sampler2DArrayShadow;");
            if (useVersion320)
            {
                sb.AppendLine($"precision mediump sampler2DMS;");
            }
            sb.AppendLine();

            sb.AppendLine($"struct SamplerDummy {{ int _dummyValue; }};");
            sb.AppendLine($"struct SamplerComparisonDummy {{ int _dummyValue; }};");
            sb.AppendLine();
        }
Beispiel #5
0
        protected override void WriteVersionHeader(
            ShaderFunction function,
            ShaderFunctionAndMethodDeclarationSyntax[] orderedFunctions,
            StringBuilder sb)
        {
            bool anyUsesStructuredBuffer = function.UsesStructuredBuffer ||
                                           orderedFunctions.Any(i => i.Function.UsesStructuredBuffer);

            bool   useVersion320 = function.UsesTexture2DMS;
            bool   useVersion310 = anyUsesStructuredBuffer;
            string versionNumber = useVersion320 ? "320" :
                                   useVersion310 ? "310" : "300";
            string version = $"{versionNumber} es";

            sb.AppendLine($"#version {version}");
            sb.AppendLine($"precision mediump float;");
            sb.AppendLine($"precision mediump int;");
            sb.AppendLine($"precision mediump sampler2D;");
            sb.AppendLine($"precision mediump sampler2DShadow;");
            sb.AppendLine($"precision mediump sampler2DArray;");
            sb.AppendLine($"precision mediump sampler2DArrayShadow;");
            if (useVersion320)
            {
                sb.AppendLine($"precision mediump sampler2DMS;");
            }
            if (function.UsesRWTexture2D)
            {
                sb.AppendLine($"precision mediump image2D;");
            }
            sb.AppendLine();

            sb.AppendLine($"struct SamplerDummy {{ int _dummyValue; }};");
            sb.AppendLine($"struct SamplerComparisonDummy {{ int _dummyValue; }};");
            sb.AppendLine();
        }
Beispiel #6
0
        public void Glsl450EndToEnd(string vsName, string fsName)
        {
            Compilation     compilation = TestUtil.GetTestProjectCompilation();
            LanguageBackend backend     = new Glsl450Backend(compilation);
            ShaderGenerator sg          = new ShaderGenerator(
                compilation,
                vsName,
                fsName,
                backend);

            ShaderGenerationResult             result = sg.GenerateShaders();
            IReadOnlyList <GeneratedShaderSet> sets   = result.GetOutput(backend);

            Assert.Equal(1, sets.Count);
            GeneratedShaderSet set         = sets[0];
            ShaderModel        shaderModel = set.Model;

            if (vsName != null)
            {
                ShaderFunction vsFunction = shaderModel.GetFunction(vsName);
                string         vsCode     = set.VertexShaderCode;
                GlsLangValidatorTool.AssertCompilesCode(vsCode, "vert", true);
            }
            if (fsName != null)
            {
                ShaderFunction fsFunction = shaderModel.GetFunction(fsName);
                string         fsCode     = set.FragmentShaderCode;
                GlsLangValidatorTool.AssertCompilesCode(fsCode, "frag", true);
            }
        }
Beispiel #7
0
        public void TestVertexShader_ShaderModel()
        {
            string          functionName = "TestShaders.TestVertexShader.VS";
            Compilation     compilation  = TestUtil.GetTestProjectCompilation();
            HlslBackend     backend      = new HlslBackend(compilation);
            ShaderGenerator sg           = new ShaderGenerator(
                compilation,
                functionName,
                null,
                backend);
            ShaderGenerationResult             genResult = sg.GenerateShaders();
            IReadOnlyList <GeneratedShaderSet> sets      = genResult.GetOutput(backend);

            Assert.Equal(1, sets.Count);
            ShaderModel shaderModel = sets[0].Model;

            Assert.Equal(2, shaderModel.Structures.Length);
            Assert.Equal(3, shaderModel.AllResources.Length);
            ShaderFunction vsEntry = shaderModel.GetFunction(functionName);

            Assert.Equal("VS", vsEntry.Name);
            Assert.Single(vsEntry.Parameters);
            Assert.True(vsEntry.IsEntryPoint);
            Assert.Equal(ShaderFunctionType.VertexEntryPoint, vsEntry.Type);
        }
Beispiel #8
0
        protected void WriteStructure(ShaderFunction function, StringBuilder sb, StructureDefinition sd, ResourceDefinition resource)
        {
            if (resource != null)
            {
                if (resource.ResourceKind == ShaderResourceKind.Emit)
                {
                    sb.Append("out ");
                }
                else
                {
                    sb.Append("in ");
                }
                if (resource.ResourceKind == ShaderResourceKind.BuiltIn)
                {
                    sb.AppendLine(SemanticIdentifier(new ShaderBuiltin(function.Type.Stage(), resource.Semantic)));
                }
                else
                {
                    sb.AppendLine(CSharpToShaderType(sd.Name));
                }
            }
            else
            {
                sb.AppendLine($"struct {CSharpToShaderType(sd.Name)}");
            }
            sb.AppendLine("{");
            StringBuilder fb = new StringBuilder();

            foreach (FieldDefinition field in sd.Fields)
            {
                string fieldTypeStr = GetStructureFieldType(field);
                fb.Append(fieldTypeStr);
                fb.Append(' ');
                fb.Append(CorrectIdentifier(field.Name.Trim()));
                int arrayCount = field.ArrayElementCount;
                if (arrayCount > 0)
                {
                    fb.Append('['); fb.Append(arrayCount); fb.Append(']');
                }
                fb.Append(';');
                sb.Append("    ");
                sb.AppendLine(fb.ToString());
                fb.Clear();
            }
            sb.Append("}");
            if (resource != null)
            {
                sb.Append(" ");
                sb.Append(CorrectIdentifierName(resource.Name.Trim()));
                if (resource.ValueType.FixedSize > 0)
                {
                    sb.Append('[');
                    sb.Append(resource.ValueType.FixedSize);
                    sb.Append(']');
                }
            }
            sb.AppendLine(";");
            sb.AppendLine();
        }
Beispiel #9
0
 public void WriteFunction(ShaderFunction f)
 {
     BeginLine();
     WriteType(f.Source, f.ReturnType);
     Write(" " + f.Name);
     WriteParameters(f, true);
     WriteFunctionBody(f);
 }
Beispiel #10
0
 public ShaderSetProcessorInput(
     string name,
     ShaderFunction vertexFunction,
     ShaderFunction fragmentFunction,
     ShaderModel model)
     : this(name, vertexFunction, null, fragmentFunction, model)
 {
 }
Beispiel #11
0
 protected override void WriteVersionHeader(
     ShaderFunction function,
     ShaderFunctionAndMethodDeclarationSyntax[] orderedFunctions,
     StringBuilder sb)
 {
     sb.AppendLine("#version 450");
     sb.AppendLine("#extension GL_ARB_separate_shader_objects : enable");
     sb.AppendLine("#extension GL_ARB_shading_language_420pack : enable");
 }
Beispiel #12
0
        protected override void WriteVersionHeader(ShaderFunction function, StringBuilder sb)
        {
            string version = (function.Type == ShaderFunctionType.ComputeEntryPoint ||
                              function.UsesStructuredBuffer) ? "430" : "330 core";

            sb.AppendLine($"#version {version}");
            sb.AppendLine();
            sb.AppendLine($"struct SamplerDummy {{ int _dummyValue; }};");
            sb.AppendLine();
        }
 public ShaderSetProcessorInput(
     string name,
     ShaderFunction vertexFunction,
     ShaderFunction fragmentFunction,
     ShaderModel model)
 {
     SetName          = name;
     VertexFunction   = vertexFunction;
     FragmentFunction = fragmentFunction;
     Model            = model;
 }
Beispiel #14
0
 static void VerifyShaderFunction(ShaderGenerator g, ShaderFunction f)
 {
     for (int i = 0; i < f.Parameters.Length; i++)
     {
         var fat = f.Parameters[i].Type as FixedArrayType;
         if (fat != null && fat.OptionalSize == null)
         {
             g.Log.Error(f.Parameters[i].Source, ErrorCode.E0000, "Unable to detect length of 'fixed' array (in " + g.Path.Quote() + ")");
         }
     }
 }
Beispiel #15
0
        private void TestCompile(GraphicsBackend graphicsBackend, string vsName, string fsName, string csName = null)
        {
            Compilation compilation = TestUtil.GetCompilation();
            ToolChain   toolChain   = ToolChain.Require(ToolFeatures.ToCompiled, graphicsBackend);

            LanguageBackend backend = toolChain.CreateBackend(compilation);
            ShaderGenerator sg      = new ShaderGenerator(compilation, backend, vsName, fsName, csName);

            ShaderGenerationResult generationResult = sg.GenerateShaders();

            IReadOnlyList <GeneratedShaderSet> sets = generationResult.GetOutput(backend);

            Assert.Equal(1, sets.Count);
            GeneratedShaderSet set         = sets[0];
            ShaderModel        shaderModel = set.Model;

            List <CompileResult> results = new List <CompileResult>();

            if (!string.IsNullOrWhiteSpace(vsName))
            {
                ShaderFunction vsFunction = shaderModel.GetFunction(vsName);
                string         vsCode     = set.VertexShaderCode;

                results.Add(toolChain.Compile(vsCode, Stage.Vertex, vsFunction.Name));
            }
            if (!string.IsNullOrWhiteSpace(fsName))
            {
                ShaderFunction fsFunction = shaderModel.GetFunction(fsName);
                string         fsCode     = set.FragmentShaderCode;
                results.Add(toolChain.Compile(fsCode, Stage.Fragment, fsFunction.Name));
            }
            if (!string.IsNullOrWhiteSpace(csName))
            {
                ShaderFunction csFunction = shaderModel.GetFunction(csName);
                string         csCode     = set.ComputeShaderCode;
                results.Add(toolChain.Compile(csCode, Stage.Compute, csFunction.Name));
            }

            // Collate results
            StringBuilder builder = new StringBuilder();

            foreach (CompileResult result in results)
            {
                if (result.HasError)
                {
                    builder.AppendLine(result.ToString());
                }
            }

            Assert.True(builder.Length < 1, builder.ToString());
        }
Beispiel #16
0
        /// <summary>
        /// Calls intrinsic function.
        /// </summary>
        /// <param name="function"></param>
        /// <param name="operand"></param>
        /// <returns></returns>
        public Operand Call(ShaderFunction function, [NotNull] Operand operand)
        {
            Operand tmp;

            if (function == ShaderFunction.Length)
            {
                tmp = CreateTemporary(PinFormat.Float, operand.ArraySize);
            }
            else
            {
                tmp = CreateTemporary(operand.Format, operand.ArraySize);
            }

            Call(function, operand, tmp);
            return(tmp);
        }
Beispiel #17
0
        protected override void WriteVersionHeader(ShaderFunction function, StringBuilder sb)
        {
            bool   useVersion320 = function.UsesTexture2DMS;
            string versionNumber = useVersion320 ? "320" : "300";
            string version       = $"{versionNumber} es";

            sb.AppendLine($"#version {version}");
            sb.AppendLine($"precision mediump float;");
            sb.AppendLine($"precision mediump int;");
            sb.AppendLine($"precision mediump sampler2D;");
            if (useVersion320)
            {
                sb.AppendLine($"precision mediump sampler2DMS;");
            }
            sb.AppendLine();
        }
        private static float Noise(Vector2 st)
        {
            var i = ShaderFunction.Floor(st);
            var f = ShaderFunction.Fract(st);

            var a = Random(i);
            var b = Random(i + new Vector2(1, 0));
            var c = Random(i + new Vector2(0, 1));
            var d = Random(i + new Vector2(1, 1));

            var u = f * f * Subtract(2.0f * f, 3.0f);

            return(Mathf.Lerp(a, b, u.x) + (c - a) * u.y * (1.0f - u.x) + (d - b) * u.x * u.y);

            float Random(Vector2 vec) => ShaderFunction.Fract(Mathf.Sin(Vector2.Dot(vec, new Vector2(12.9898f, 78.233f)) * 43758.5453123f));
            Vector2 Subtract(Vector2 vec, float v) => new Vector2(vec.x - v, vec.y - v);
        }
Beispiel #19
0
        protected override void WriteVersionHeader(
            ShaderFunction function,
            ShaderFunctionAndMethodDeclarationSyntax[] orderedFunctions,
            StringBuilder sb)
        {
            bool anyUsesStructuredBuffer = function.UsesStructuredBuffer ||
                                           orderedFunctions.Any(i => i.Function.UsesStructuredBuffer);

            string version = (function.Type == ShaderFunctionType.ComputeEntryPoint ||
                              anyUsesStructuredBuffer) ? "430" : "330 core";

            sb.AppendLine($"#version {version}");
            sb.AppendLine();
            sb.AppendLine($"struct SamplerDummy {{ int _dummyValue; }};");
            sb.AppendLine($"struct SamplerComparisonDummy {{ int _dummyValue; }};");
            sb.AppendLine();
        }
Beispiel #20
0
        public static void ShaderSetAutoDiscovery()
        {
            Compilation                        compilation = TestUtil.GetTestProjectCompilation();
            HlslBackend                        backend     = new HlslBackend(compilation);
            ShaderGenerator                    sg          = new ShaderGenerator(compilation, new[] { backend });
            ShaderGenerationResult             result      = sg.GenerateShaders();
            IReadOnlyList <GeneratedShaderSet> hlslSets    = result.GetOutput(backend);

            Assert.Equal(3, hlslSets.Count);
            GeneratedShaderSet set = hlslSets[0];

            Assert.Equal("VertexAndFragment", set.Name);
            ShaderModel    shaderModel = set.Model;
            ShaderFunction func        = shaderModel.Functions[0];

            FxcTool.AssertCompilesCode(set.VertexShaderCode, "vs_5_0", "VS");
            FxcTool.AssertCompilesCode(set.FragmentShaderCode, "ps_5_0", "FS");
        }
        public void DummyTest()
        {
            string      vsName      = "TestShaders.VeldridShaders.VertexAndFragment.VS";
            string      fsName      = "TestShaders.VeldridShaders.VertexAndFragment.FS";
            Compilation compilation = TestUtil.GetTestProjectCompilation();

            using (TempFile fp = new TempFile())
            {
                Microsoft.CodeAnalysis.Emit.EmitResult emitResult = compilation.Emit(fp);
                Assert.True(emitResult.Success);
            }

            LanguageBackend backend = new Glsl450Backend(compilation);
            ShaderGenerator sg      = new ShaderGenerator(
                compilation,
                vsName,
                fsName,
                backend);

            ShaderGenerationResult             result = sg.GenerateShaders();
            IReadOnlyList <GeneratedShaderSet> sets   = result.GetOutput(backend);

            Assert.Equal(1, sets.Count);
            GeneratedShaderSet set         = sets[0];
            ShaderModel        shaderModel = set.Model;

            if (vsName != null)
            {
                ShaderFunction vsFunction = shaderModel.GetFunction(vsName);
                string         vsCode     = set.VertexShaderCode;
                File.WriteAllText(@"C:\Users\raver\Documents\forward-vertex.glsl", vsCode);
                GlsLangValidatorTool.AssertCompilesCode(vsCode, "vert", true);
            }
            if (fsName != null)
            {
                ShaderFunction fsFunction = shaderModel.GetFunction(fsName);
                string         fsCode     = set.FragmentShaderCode;
                File.WriteAllText(@"C:\Users\raver\Documents\forward-frag.glsl", fsCode);
                GlsLangValidatorTool.AssertCompilesCode(fsCode, "frag", true);
            }
        }
        private static float Voronoi(int x, int y, float u, float v)
        {
            var vec = new Vector2(x, y);
            var p   = ShaderFunction.Floor(vec);
            var f   = ShaderFunction.Fract(vec);
            var k   = 1f + 63f * Mathf.Pow(1f - v, 6f);
            var a   = Vector2.zero;

            for (var i = -2; i <= 2; i++)
            {
                for (var j = -2; j <= 2; j++)
                {
                    var g = new Vector2(i, j);
                    var o = Vector3.Scale(ShaderFunction.Hash3(p + g), new Vector3(u, u, 1f));
                    var d = g - f + new Vector2(o.x, o.y);
                    var w = Mathf.Pow(1f - Mathf.SmoothStep(0f, 1.414f, ShaderFunction.Length(d)), k);
                    a += new Vector2(o.z * w, w);
                }
            }

            return(a.x / a.y);
        }
Beispiel #23
0
 public MetalMethodVisitor(Compilation compilation, string setName, ShaderFunction shaderFunction, LanguageBackend backend)
     : base(compilation, setName, shaderFunction, backend)
 {
 }
        internal string GetResourceParameterList(ShaderFunction function, string setName, HashSet <ResourceDefinition> resourcesUsed)
        {
            BackendContext setContext = GetContext(setName);

            List <ResourceDefinition[]> resourcesBySet = setContext.Resources.GroupBy(rd => rd.Set)
                                                         .Select(g => g.ToArray()).ToList();

            List <string> resourceArgList = new List <string>();
            int           bufferBinding   = 0;
            int           textureBinding  = 0;
            int           samplerBinding  = 0;
            int           setIndex        = 0;

            foreach (ResourceDefinition[] set in resourcesBySet)
            {
                Debug.Assert(set[0].Set == setIndex);
                setIndex += 1;

                foreach (ResourceDefinition rd in set)
                {
                    switch (rd.ResourceKind)
                    {
                    case ShaderResourceKind.Uniform:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteUniform(rd, bufferBinding));
                        }
                        bufferBinding++;
                        break;

                    case ShaderResourceKind.Texture2D:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteTexture2D(rd, textureBinding));
                        }
                        textureBinding++;
                        break;

                    case ShaderResourceKind.Texture2DArray:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteTexture2DArray(rd, textureBinding));
                        }
                        textureBinding++;
                        break;

                    case ShaderResourceKind.TextureCube:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteTextureCube(rd, textureBinding));
                        }
                        textureBinding++;
                        break;

                    case ShaderResourceKind.Texture2DMS:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteTexture2DMS(rd, textureBinding));
                        }
                        textureBinding++;
                        break;

                    case ShaderResourceKind.Sampler:
                    case ShaderResourceKind.SamplerComparison:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteSampler(rd, samplerBinding));
                        }
                        samplerBinding++;
                        break;

                    case ShaderResourceKind.StructuredBuffer:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteStructuredBuffer(rd, bufferBinding));
                        }
                        bufferBinding++;
                        break;

                    case ShaderResourceKind.RWStructuredBuffer:
                    case ShaderResourceKind.AtomicBuffer:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteRWStructuredBuffer(rd, bufferBinding));
                        }
                        bufferBinding++;
                        break;

                    case ShaderResourceKind.RWTexture2D:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteRWTexture2D(rd, textureBinding));
                        }
                        textureBinding++;
                        break;

                    case ShaderResourceKind.DepthTexture2D:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteDepthTexture2D(rd, textureBinding));
                        }
                        textureBinding++;
                        break;

                    case ShaderResourceKind.DepthTexture2DArray:
                        if (resourcesUsed.Contains(rd))
                        {
                            resourceArgList.Add(WriteDepthTexture2DArray(rd, textureBinding));
                        }
                        textureBinding++;
                        break;

                    default: throw new ShaderGenerationException("Illegal resource kind: " + rd.ResourceKind);
                    }
                }
            }

            return(string.Join(", ", resourceArgList));
        }
 protected override ShaderMethodVisitor VisitShaderMethod(string setName, ShaderFunction func)
 {
     return(new MetalMethodVisitor(Compilation, setName, func, this));
 }
        public static List <(string Type, string Name, string Attribute)> GetBuiltinParameterList(ShaderFunction function)
        {
            List <(string, string, string)> values = new List <(string, string, string)>();

            if (function.UsesVertexID)
            {
                values.Add(("uint", "_builtins_VertexID", "[[ vertex_id ]]"));
            }
            if (function.UsesInstanceID)
            {
                values.Add(("uint", "_builtins_InstanceID", "[[ instance_id ]]"));
            }
            if (function.UsesDispatchThreadID)
            {
                values.Add(("uint3", "_builtins_DispatchThreadID", "[[ thread_position_in_grid ]]"));
            }
            if (function.UsesGroupThreadID)
            {
                values.Add(("uint3", "_builtins_GroupThreadID", "[[ thread_position_in_threadgroup ]]"));
            }
            if (function.UsesFrontFace)
            {
                values.Add(("bool", "_builtins_IsFrontFace", "[[ front_facing ]]"));
            }

            return(values);
        }
        protected override MethodProcessResult GenerateFullTextCore(string setName, ShaderFunction function)
        {
            Debug.Assert(function.IsEntryPoint);

            StringBuilder  sb         = new StringBuilder();
            BackendContext setContext = GetContext(setName);
            ShaderFunctionAndMethodDeclarationSyntax entryPoint = setContext.Functions.SingleOrDefault(
                sfabs => sfabs.Function.Name == function.Name);

            if (entryPoint == null)
            {
                throw new ShaderGenerationException("Couldn't find given function: " + function.Name);
            }

            ValidateRequiredSemantics(setName, entryPoint.Function, function.Type);

            // Write header
            sb.AppendLine("#include <metal_stdlib>");
            sb.AppendLine("using namespace metal;");

            // TODO: Necessary for Metal?
            StructureDefinition[] orderedStructures
                = StructureDependencyGraph.GetOrderedStructureList(Compilation, setContext.Structures);
            foreach (StructureDefinition sd in orderedStructures)
            {
                WriteStructure(sb, sd);
            }

            HashSet <ResourceDefinition> resourcesUsed
                = ProcessFunctions(setName, entryPoint, out string funcsStr, out string entryStr);

            ValidateResourcesUsed(setName, resourcesUsed);

            StringBuilder containerSB = new StringBuilder();

            containerSB.AppendLine("struct ShaderContainer {");

            List <string> structFields    = new List <string>();
            List <string> ctorParams      = new List <string>();
            List <string> ctorAssignments = new List <string>();

            foreach (ResourceDefinition resource in resourcesUsed)
            {
                structFields.Add(GetResourceField(resource));
                ctorParams.Add(GetResourceCtorParam(resource));
                ctorAssignments.Add($"{resource.Name}({resource.Name}_param)");
            }

            foreach (string sf in structFields)
            {
                containerSB.AppendLine(sf);
            }

            containerSB.AppendLine(funcsStr);

            // Emit the ctor definition
            containerSB.AppendLine($"ShaderContainer(");
            string ctorParamsStr = string.Join(", ", ctorParams);

            containerSB.AppendLine(ctorParamsStr);
            containerSB.AppendLine($")");
            string allCtorAssignments = string.Join(", ", ctorAssignments);

            if (!string.IsNullOrEmpty(allCtorAssignments))
            {
                containerSB.AppendLine(":");
                containerSB.AppendLine(allCtorAssignments);
            }
            containerSB.AppendLine("{}");

            containerSB.AppendLine(entryStr);

            containerSB.AppendLine("};"); // Close the global containing struct.
            sb.AppendLine(containerSB.ToString());

            // Emit the out function call which creates the container struct and calls the real shader function.
            string type = entryPoint.Function.Type == ShaderFunctionType.VertexEntryPoint
                ? "vertex"
                : entryPoint.Function.Type == ShaderFunctionType.FragmentEntryPoint
                    ? "fragment"
                    : "kernel";

            ShaderFunction entryFunction         = entryPoint.Function;
            string         returnType            = CSharpToShaderType(entryFunction.ReturnType.Name);
            string         fullDeclType          = CSharpToShaderType(entryFunction.DeclaringType);
            string         funcName              = entryFunction.Name;
            string         baseParameterList     = string.Join(", ", entryFunction.Parameters.Select(FormatParameter));
            string         resourceParameterList = GetResourceParameterList(entryFunction, setName, resourcesUsed);
            string         builtinParameterList  = string.Join(
                ", ",
                GetBuiltinParameterList(entryFunction).Select(b => $"{b.Type} {b.Name} {b.Attribute}"));
            string fullParameterList = string.Join(
                ", ",
                new string[]
            {
                baseParameterList, resourceParameterList, builtinParameterList
            }.Where(s => !string.IsNullOrEmpty(s)));

            string functionDeclStr = $"{type} {returnType} {funcName}({fullParameterList})";

            string containerArgs = string.Join(", ", resourcesUsed.Select(
                                                   rd => rd.Name));

            string entryFuncArgs = string.Join(
                ", ",
                MetalBackend.GetBuiltinParameterList(entryFunction).Select(b => $"{b.Name}"));

            if (entryFunction.Parameters.Length > 0)
            {
                Debug.Assert(entryFunction.Parameters.Length == 1);
                entryFuncArgs = Utilities.JoinIgnoreNull(
                    ", ",
                    new string[] { $"{entryFunction.Parameters[0].Name}", entryFuncArgs });
            }

            sb.AppendLine(functionDeclStr);
            sb.AppendLine("{");
            sb.AppendLine($"return ShaderContainer({containerArgs}).{entryFunction.Name}({entryFuncArgs});");
            sb.AppendLine("}");

            return(new MethodProcessResult(sb.ToString(), resourcesUsed));
        }
Beispiel #28
0
        bool TryProcessFunctionCall(ref Expression e, Function f, Expression[] args, Expression optionalValueOrObject = null, Expression optionalObject = null)
        {
            // Special case for T[].get_Length()
            if (f.DeclaringType.IsRefArray &&
                optionalValueOrObject != null && optionalValueOrObject.ReturnType.IsFixedArray &&
                f.Name == "get_Length" && f.Parameters.Length == 0)
            {
                var fat = (FixedArrayType)optionalValueOrObject.ReturnType;
                e = fat.OptionalSize ?? Expression.Invalid;
                return(true);
            }

            if (Backend.ShaderBackend.IsIntrinsic(f))
            {
                return(false);
            }

            var processedArgs = ProcessArguments(args, optionalValueOrObject, optionalObject);

            ShaderFunction result;

            if (!ProcessedFunctions.TryGetValue(f, out result))
            {
                // TODO: This code doesn't handle:
                // - Recursion
                // - Multiple uses of function with array in parameterlist

                if (!f.HasBody)
                {
                    Log.Error(e.Source, ErrorCode.E5010, f.Quote() + " is pure intrinsic and is not supported by current shader backend (in " + Generator.Path.Quote() + ")");
                    return(false);
                }

                result = new ShaderFunction(f.Source, Shader, f.UnoName.ToIdentifier() + "_" + Generator.ShaderGlobalCounter++, f.ReturnType, null);

                var state         = new CopyState(result);
                var parameterList = TryProcessParameterList(f, processedArgs, state);

                if (parameterList == null)
                {
                    return(false);
                }

                result.SetParameters(parameterList);
                result.SetBody(f.Body.CopyNullable(state));

                if (!f.IsStatic)
                {
                    if (f.IsConstructor)
                    {
                        result.ReturnType = f.DeclaringType;
                        var var = new Variable(f.Source, f, "__this", f.DeclaringType);
                        result.Body.Statements.Insert(0, new VariableDeclaration(var));
                        result.Body.Statements.Add(new Return(f.Source, new This(f.Source, f.DeclaringType)));
                        result.Body.Visit(new ThisSwapper(this, new LoadLocal(f.Source, var)));
                    }
                    else
                    {
                        result.Body.Visit(new ThisSwapper(this, new LoadArgument(f.Source, result, f.Parameters.Length)));
                    }
                }

                ProcessedFunctions.Add(f, result);
                result.Visit(this);
                Shader.Functions.Add(result); // add after process
            }

            e = new CallShader(e.Source, result, processedArgs);
            return(true);
        }
Beispiel #29
0
        protected override MethodProcessResult GenerateFullTextCore(string setName, ShaderFunction function)
        {
            BackendContext context = GetContext(setName);
            StringBuilder  sb      = new StringBuilder();

            ShaderFunctionAndMethodDeclarationSyntax entryPoint = context.Functions.SingleOrDefault(
                sfabs => sfabs.Function.Name == function.Name);

            if (entryPoint == null)
            {
                throw new ShaderGenerationException("Couldn't find given function: " + function.Name);
            }

            ValidateRequiredSemantics(setName, entryPoint.Function, function.Type);

            StructureDefinition[] orderedStructures
                = StructureDependencyGraph.GetOrderedStructureList(Compilation, context.Structures);

            foreach (StructureDefinition sd in orderedStructures)
            {
                WriteStructure(sb, sd);
            }

            HashSet <ResourceDefinition> resourcesUsed
                = ProcessFunctions(setName, entryPoint, out string funcStr, out string entryStr);

            foreach (ResourceDefinition rd in context.Resources)
            {
                if (!resourcesUsed.Contains(rd))
                {
                    continue;
                }

                switch (rd.ResourceKind)
                {
                case ShaderResourceKind.Uniform:
                    WriteUniform(sb, rd);
                    break;

                case ShaderResourceKind.Texture2D:
                    WriteTexture2D(sb, rd);
                    break;

                case ShaderResourceKind.Texture2DArray:
                    WriteTexture2DArray(sb, rd);
                    break;

                case ShaderResourceKind.TextureCube:
                    WriteTextureCube(sb, rd);
                    break;

                case ShaderResourceKind.Texture2DMS:
                    WriteTexture2DMS(sb, rd);
                    break;

                case ShaderResourceKind.Sampler:
                    WriteSampler(sb, rd);
                    break;

                case ShaderResourceKind.StructuredBuffer:
                case ShaderResourceKind.RWStructuredBuffer:
                    WriteStructuredBuffer(sb, rd, rd.ResourceKind == ShaderResourceKind.StructuredBuffer);
                    break;

                default: throw new ShaderGenerationException("Illegal resource kind: " + rd.ResourceKind);
                }
            }

            sb.AppendLine(funcStr);
            sb.AppendLine(entryStr);

            WriteMainFunction(setName, sb, entryPoint.Function);

            // Append version last because it relies on information from parsing the shader.
            StringBuilder versionSB = new StringBuilder();

            WriteVersionHeader(function, versionSB);

            sb.Insert(0, versionSB.ToString());

            return(new MethodProcessResult(sb.ToString(), resourcesUsed));
        }
Beispiel #30
0
 protected abstract void WriteVersionHeader(ShaderFunction function, StringBuilder sb);