Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
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);
            }
        }
Ejemplo n.º 3
0
        public void TestVertexShader_VertexSemantics()
        {
            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;

            StructureDefinition vsInput = shaderModel.GetStructureDefinition(nameof(TestShaders) + "." + nameof(PositionTexture));

            Assert.Equal(SemanticType.Position, vsInput.Fields[0].SemanticType);
            Assert.Equal(SemanticType.TextureCoordinate, vsInput.Fields[1].SemanticType);

            StructureDefinition fsInput = shaderModel.GetStructureDefinition(
                nameof(TestShaders) + "." + nameof(TestVertexShader) + "+" + nameof(TestVertexShader.VertexOutput));

            Assert.Equal(SemanticType.SystemPosition, fsInput.Fields[0].SemanticType);
            Assert.Equal(SemanticType.TextureCoordinate, fsInput.Fields[1].SemanticType);
        }
Ejemplo n.º 4
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);
            }
        }
Ejemplo n.º 5
0
        public void ResourcesUsedInStages()
        {
            Compilation     compilation = TestUtil.GetCompilation();
            HlslBackend     backend     = new HlslBackend(compilation);
            ShaderGenerator sg          = new ShaderGenerator(
                compilation, backend, "TestShaders.UsedResourcesShaders.VS", "TestShaders.UsedResourcesShaders.FS");

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

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

            Assert.Equal(4, shaderModel.VertexResources.Length);
            Assert.Contains(shaderModel.VertexResources, rd => rd.Name == "VS_M0");
            Assert.Contains(shaderModel.VertexResources, rd => rd.Name == "VS_M1");
            Assert.Contains(shaderModel.VertexResources, rd => rd.Name == "VS_T0");
            Assert.Contains(shaderModel.VertexResources, rd => rd.Name == "VS_S0");

            Assert.Equal(5, shaderModel.FragmentResources.Length);
            Assert.Contains(shaderModel.FragmentResources, rd => rd.Name == "FS_M0");
            Assert.Contains(shaderModel.FragmentResources, rd => rd.Name == "FS_M1");
            Assert.Contains(shaderModel.FragmentResources, rd => rd.Name == "FS_T0");
            Assert.Contains(shaderModel.FragmentResources, rd => rd.Name == "FS_S0");
            Assert.Contains(shaderModel.FragmentResources, rd => rd.Name == "FS_M2_Indirect");
        }
        public static void ShaderSetAutoDiscovery()
        {
            ToolChain toolChain = ToolChain.Get(ToolFeatures.ToCompiled);

            if (toolChain == null)
            {
                throw new RequiredToolFeatureMissingException("No tool chain supporting compilation was found!");
            }

            Compilation                        compilation      = TestUtil.GetCompilation();
            LanguageBackend                    backend          = toolChain.CreateBackend(compilation);
            ShaderGenerator                    sg               = new ShaderGenerator(compilation, backend);
            ShaderGenerationResult             generationResult = sg.GenerateShaders();
            IReadOnlyList <GeneratedShaderSet> hlslSets         = generationResult.GetOutput(backend);

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

            Assert.Equal("VertexAndFragment", set.Name);

            CompileResult result = toolChain.Compile(set.VertexShaderCode, Stage.Vertex, "VS");

            Assert.False(result.HasError, result.ToString());

            result = toolChain.Compile(set.FragmentShaderCode, Stage.Fragment, "FS");
            Assert.False(result.HasError, result.ToString());
        }
Ejemplo n.º 7
0
        public void ExpectedException(string vsName, string fsName)
        {
            Compilation     compilation = TestUtil.GetCompilation();
            Glsl330Backend  backend     = new Glsl330Backend(compilation);
            ShaderGenerator sg          = new ShaderGenerator(compilation, backend, vsName, fsName);

            Assert.Throws <ShaderGenerationException>(() => sg.GenerateShaders());
        }
        public void AllSetsAllLanguagesEndToEnd()
        {
            Compilation compilation = TestUtil.GetTestProjectCompilation();

            LanguageBackend[] backends = new LanguageBackend[]
            {
                new HlslBackend(compilation),
                new Glsl330Backend(compilation),
                new Glsl450Backend(compilation),
            };
            ShaderGenerator sg = new ShaderGenerator(compilation, backends);

            ShaderGenerationResult result = sg.GenerateShaders();

            foreach (LanguageBackend backend in backends)
            {
                IReadOnlyList <GeneratedShaderSet> sets = result.GetOutput(backend);
                foreach (GeneratedShaderSet set in sets)
                {
                    if (set.VertexShaderCode != null)
                    {
                        if (backend is HlslBackend)
                        {
                            FxcTool.AssertCompilesCode(set.VertexShaderCode, "vs_5_0", set.VertexFunction.Name);
                        }
                        else
                        {
                            bool is450 = backend is Glsl450Backend;
                            GlsLangValidatorTool.AssertCompilesCode(set.VertexShaderCode, "vert", is450);
                        }
                    }
                    if (set.FragmentFunction != null)
                    {
                        if (backend is HlslBackend)
                        {
                            FxcTool.AssertCompilesCode(set.FragmentShaderCode, "ps_5_0", set.FragmentFunction.Name);
                        }
                        else
                        {
                            bool is450 = backend is Glsl450Backend;
                            GlsLangValidatorTool.AssertCompilesCode(set.FragmentShaderCode, "frag", is450);
                        }
                    }
                    if (set.ComputeFunction != null)
                    {
                        if (backend is HlslBackend)
                        {
                            FxcTool.AssertCompilesCode(set.ComputeShaderCode, "cs_5_0", set.ComputeFunction.Name);
                        }
                        else
                        {
                            bool is450 = backend is Glsl450Backend;
                            GlsLangValidatorTool.AssertCompilesCode(set.ComputeShaderCode, "comp", is450);
                        }
                    }
                }
            }
        }
Ejemplo n.º 9
0
        public void MissingSemantic_ThrowsShaderGenerationException()
        {
            Compilation compilation = TestUtil.GetCompilation();

            foreach (LanguageBackend backend in TestUtil.GetAllBackends(compilation))
            {
                ShaderGenerator sg = new ShaderGenerator(compilation, backend, "TestShaders.MissingInputSemantics.VS");

                Assert.Throws <ShaderGenerationException>(() => sg.GenerateShaders());
            }
        }
        public static void ReferenceTypeField_ThrowsShaderGenerationException()
        {
            Compilation compilation = TestUtil.GetCompilation();

            foreach (LanguageBackend backend in TestUtil.GetAllBackends(compilation))
            {
                ShaderGenerator sg = new ShaderGenerator(compilation, backend, "ShaderGen.Tests.ReferenceTypeField.VS");

                Assert.Throws <ShaderGenerationException>(() => sg.GenerateShaders());
            }
        }
Ejemplo n.º 11
0
        private void TestProcessor_UsersArgs()
        {
            Compilation     compilation = TestUtil.GetCompilation();
            HlslBackend     backend     = new HlslBackend(compilation);
            TestProcessor   processor   = new TestProcessor();
            ShaderGenerator sg          = new ShaderGenerator(
                compilation,
                backend,
                "TestShaders.ProcessorTestShaders.VS", "TestShaders.ProcessorTestShaders.FS", null, processor);

            sg.GenerateShaders();
            Assert.Equal("This Sentence Should Be Printed By_Enumerating All Resources In Order", processor.Result);
        }
Ejemplo n.º 12
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());
        }
Ejemplo n.º 13
0
        public void MissingFunctionAttribute_Throws()
        {
            string vsName = "TestShaders.MissingFunctionAttribute.VS";

            Compilation     compilation = TestUtil.GetTestProjectCompilation();
            Glsl330Backend  backend     = new Glsl330Backend(compilation);
            ShaderGenerator sg          = new ShaderGenerator(
                compilation,
                vsName,
                null,
                backend);

            Assert.Throws <ShaderGenerationException>(() => sg.GenerateShaders());
        }
Ejemplo n.º 14
0
        public void StructureSizes()
        {
            Compilation     compilation = TestUtil.GetTestProjectCompilation();
            HlslBackend     backend     = new HlslBackend(compilation);
            ShaderGenerator sg          = new ShaderGenerator(
                compilation,
                "TestShaders.StructureSizeTests.VS",
                null,
                backend);

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

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

            StructureDefinition test0 = shaderModel.GetStructureDefinition(
                nameof(TestShaders) + "." + nameof(StructureSizeTests) + "+" + nameof(StructureSizeTests.SizeTest_0));

            Assert.Equal(48, test0.Alignment.CSharpSize);
            Assert.True(test0.CSharpMatchesShaderAlignment);

            StructureDefinition test1 = shaderModel.GetStructureDefinition(
                nameof(TestShaders) + "." + nameof(StructureSizeTests) + "+" + nameof(StructureSizeTests.SizeTest_1));

            Assert.Equal(52, test1.Alignment.CSharpSize);
            Assert.True(test1.CSharpMatchesShaderAlignment);

            StructureDefinition test2 = shaderModel.GetStructureDefinition(
                nameof(TestShaders) + "." + nameof(StructureSizeTests) + "+" + nameof(StructureSizeTests.SizeTest_2));

            Assert.Equal(48, test2.Alignment.CSharpSize);
            Assert.False(test2.CSharpMatchesShaderAlignment);

            StructureDefinition test3 = shaderModel.GetStructureDefinition(
                nameof(TestShaders) + "." + nameof(StructureSizeTests) + "+" + nameof(StructureSizeTests.SizeTest_3));

            Assert.Equal(64, test3.Alignment.CSharpSize);
            Assert.False(test3.CSharpMatchesShaderAlignment);

            Assert.Equal(4, shaderModel.GetTypeSize(test3.Fields[0].Type));
            Assert.Equal(12, shaderModel.GetTypeSize(test3.Fields[1].Type));
            Assert.Equal(12, shaderModel.GetTypeSize(test3.Fields[2].Type));
            Assert.Equal(16, shaderModel.GetTypeSize(test3.Fields[3].Type));
            Assert.Equal(4, shaderModel.GetTypeSize(test3.Fields[4].Type));
            Assert.Equal(16, shaderModel.GetTypeSize(test3.Fields[5].Type));
        }
Ejemplo n.º 15
0
        public void MultipleResourceSets_CorrectlyParsed()
        {
            Compilation     compilation = TestUtil.GetTestProjectCompilation();
            HlslBackend     backend     = new HlslBackend(compilation);
            ShaderGenerator sg          = new ShaderGenerator(
                compilation,
                "TestShaders.MultipleResourceSets.VS",
                null,
                backend);

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

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

            Assert.Equal(13, shaderModel.AllResources.Length);

            Assert.Equal(0, shaderModel.AllResources[0].Set);
            Assert.Equal(0, shaderModel.AllResources[0].Binding);
            Assert.Equal(0, shaderModel.AllResources[1].Set);
            Assert.Equal(1, shaderModel.AllResources[1].Binding);
            Assert.Equal(1, shaderModel.AllResources[2].Set);
            Assert.Equal(0, shaderModel.AllResources[2].Binding);
            Assert.Equal(2, shaderModel.AllResources[3].Set);
            Assert.Equal(0, shaderModel.AllResources[3].Binding);
            Assert.Equal(3, shaderModel.AllResources[4].Set);
            Assert.Equal(0, shaderModel.AllResources[4].Binding);
            Assert.Equal(4, shaderModel.AllResources[5].Set);
            Assert.Equal(0, shaderModel.AllResources[5].Binding);
            Assert.Equal(0, shaderModel.AllResources[6].Set);
            Assert.Equal(2, shaderModel.AllResources[6].Binding);

            Assert.Equal(0, shaderModel.AllResources[7].Set);
            Assert.Equal(3, shaderModel.AllResources[7].Binding);
            Assert.Equal(4, shaderModel.AllResources[8].Set);
            Assert.Equal(1, shaderModel.AllResources[8].Binding);
            Assert.Equal(0, shaderModel.AllResources[9].Set);
            Assert.Equal(4, shaderModel.AllResources[9].Binding);

            Assert.Equal(2, shaderModel.AllResources[10].Set);
            Assert.Equal(1, shaderModel.AllResources[10].Binding);
            Assert.Equal(0, shaderModel.AllResources[11].Set);
            Assert.Equal(5, shaderModel.AllResources[11].Binding);
            Assert.Equal(1, shaderModel.AllResources[12].Set);
            Assert.Equal(1, shaderModel.AllResources[12].Binding);
        }
Ejemplo n.º 16
0
        public void PointLightsInfo_CorrectSize()
        {
            Compilation     compilation = TestUtil.GetCompilation();
            HlslBackend     backend     = new HlslBackend(compilation);
            ShaderGenerator sg          = new ShaderGenerator(compilation, backend, "TestShaders.PointLightTestShaders.VS");

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

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

            Assert.Single(shaderModel.AllResources);
            Assert.Equal(208, shaderModel.GetTypeSize(shaderModel.AllResources[0].ValueType));
        }
Ejemplo n.º 17
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");
        }
Ejemplo n.º 18
0
        public void PartialFiles()
        {
            Compilation     compilation = TestUtil.GetTestProjectCompilation();
            HlslBackend     backend     = new HlslBackend(compilation);
            ShaderGenerator sg          = new ShaderGenerator(
                compilation,
                "TestShaders.PartialVertex.VertexShaderFunc",
                null,
                backend);

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

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

            FxcTool.AssertCompilesCode(vsCode, "vs_5_0", "VertexShaderFunc");
        }
Ejemplo n.º 19
0
        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);
            }
        }
Ejemplo n.º 20
0
        public void PartialFiles()
        {
            ToolChain toolChain = ToolChain.Get(ToolFeatures.ToCompiled);

            if (toolChain == null)
            {
                throw new RequiredToolFeatureMissingException("No tool chain supporting compilation was found!");
            }

            Compilation     compilation = TestUtil.GetCompilation();
            LanguageBackend backend     = toolChain.CreateBackend(compilation);
            ShaderGenerator sg          = new ShaderGenerator(compilation, backend, "TestShaders.PartialVertex.VertexShaderFunc");

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

            Assert.Equal(1, sets.Count);
            GeneratedShaderSet set         = sets[0];
            ShaderModel        shaderModel = set.Model;
            string             vsCode      = set.VertexShaderCode;
            CompileResult      result      = toolChain.Compile(vsCode, Stage.Vertex, "VertexShaderFunc");

            Assert.False(result.HasError, result.ToString());
        }
Ejemplo n.º 21
0
        private void TestBuiltins()
        {
            // Find all backends that can create a headless graphics device on this system.
            IReadOnlyList <ToolChain> toolChains = ToolChain.Requires(ToolFeatures.HeadlessGraphicsDevice, false);

            if (toolChains.Count < 1)
            {
                throw new RequiredToolFeatureMissingException(
                          $"At least one tool chain capable of creating headless graphics devices is required for this test!");
            }

            /*
             * Auto-generate C# code for testing methods.
             */
            IReadOnlyList <MethodInfo> methods = null;
            Mappings    mappings;
            Compilation compilation;

            using (new TestTimer(_output, () => $"Generating C# shader code to test {methods.Count} methods"))
            {
                // Get all the methods we wish to test
                methods  = MethodsToTest.ToArray();
                mappings = CreateMethodTestCompilation(methods, out compilation);

                // Note, you could use compilation.Emit(...) at this point to compile the auto-generated code!
                // however, for now we'll invoke methods directly rather than executing the C# code that has been
                // generated, as loading emitted code into a test is currently much more difficult.
            }

            // Allocate enough space to store the result sets for each backend!
            TestSets testSets = null;

            using (new TestTimer(
                       _output,
                       () =>
                       $"Generating random test data ({(mappings.BufferSize * testSets.TestLoops).ToMemorySize()}) for {testSets.TestLoops} iterations of {mappings.Methods} methods")
                   )
            {
                testSets = new TestSets(toolChains, compilation, mappings, TestLoops, MinMantissa, MaxMantissa);
            }

            /*
             * Transpile shaders
             */

            ShaderGenerationResult generationResult;

            using (new TestTimer(
                       _output,
                       t =>
                       $"Generated shader sets for {string.Join(", ", toolChains.Select(tc => tc.Name))} backends in {t * 1000:#.##}ms.")
                   )
            {
                ShaderGenerator sg = new ShaderGenerator(
                    compilation,
                    testSets.Select(t => t.Backend).Where(b => b != null).ToArray(),
                    null,
                    null,
                    "ComputeShader.CS");

                generationResult = sg.GenerateShaders();
            }

            /*
             * Loop through each backend to run tests.
             */
            bool first = true;

            using (new TestTimer(_output, "Executing all tests on all backends"))
            {
                foreach (TestSet testSet in testSets)
                {
                    _output.WriteLine(string.Empty);
                    if (first)
                    {
                        // This is the first test set, so we use Space1 instead of Spacer 2.
                        first = false;
                        _output.WriteLine(TestUtil.Spacer1);
                    }
                    else
                    {
                        _output.WriteLine(TestUtil.Spacer2);
                    }

                    _output.WriteLine(String.Empty);

                    testSet.Execute(generationResult, "CS", _output);
                }

                _output.WriteLine(string.Empty);
            }

            _output.WriteLine(string.Empty);
            _output.WriteLine(TestUtil.Spacer1);
            _output.WriteLine(string.Empty);

            Assert.True(testSets.Count(t => t.Executed) > 1,
                        "At least 2 test sets are required for comparison.");

            /*
             * Finally, evaluate differences between results
             */
            IReadOnlyList <(MethodMap MethodMap, IReadOnlyList <Failure> Failures)> failures;

            using (new TestTimer(_output, "Analysing results for failures"))
            {
                failures = testSets.GetFailures(FloatEpsilon)
                           .Select(kvp => (MethodMap: kvp.Key, Failures: kvp.Value))
                           .OrderByDescending(kvp => kvp.Failures.Count)
                           .ToArray();
            }

            if (!failures.Any())
            {
                _output.WriteLine("No failures detected!");
                return;
            }

            _output.WriteLine(
                $"{failures.Count} methods had failures out of {mappings.Methods} ({100.0 * failures.Count / mappings.Methods:#.##}%).");

            _output.WriteLine(string.Empty);

            // Get pointer array
            string lastMethodName = null;

            foreach ((MethodMap methodMap, IReadOnlyList <Failure> methodFailures) in failures)
            {
                if (lastMethodName != methodMap.Method.Name)
                {
                    if (lastMethodName != null)
                    {
                        // Seperate methods of different names with spacer 1
                        _output.WriteLine(string.Empty);
                        _output.WriteLine(TestUtil.Spacer1);
                        _output.WriteLine(string.Empty);
                    }

                    lastMethodName = methodMap.Method.Name;
                }
                else
                {
                    _output.WriteLine(string.Empty);
                    _output.WriteLine(TestUtil.Spacer2);
                    _output.WriteLine(string.Empty);
                }

                int failureCount = methodFailures.Count;
                _output.WriteLine(
                    $"{TestUtil.GetUnicodePieChart((double)failureCount / testSets.TestLoops)} {methodMap.Signature} failed {failureCount}/{testSets.TestLoops} ({failureCount * 100.0 / testSets.TestLoops:#.##}%).");

                // Output examples!
                int example = 0;
                foreach (Failure failure in methodFailures)
                {
                    _output.WriteLine(string.Empty);
                    if (example++ >= FailureExamples)
                    {
                        _output.WriteLine("…");
                        break;
                    }

                    _output.WriteLine(failure.ToString());
                }
            }

            _output.WriteLine(string.Empty);
            _output.WriteLine(TestUtil.Spacer2);
            _output.WriteLine(string.Empty);
        }
Ejemplo n.º 22
0
        public void AllSetsCompile()
        {
            Compilation compilation = TestUtil.GetCompilation();

            // Get all available tool chains.
            LanguageBackend[] backends = TestUtil.GetAllBackends(compilation, ToolFeatures.ToCompiled);

            ShaderGenerator        sg = new ShaderGenerator(compilation, backends);
            ShaderGenerationResult generationResult = sg.GenerateShaders();

            string spacer1 = new string('=', 80);
            string spacer2 = new string('-', 80);

            bool failed = false;

            foreach (LanguageBackend backend in backends)
            {
                ToolChain toolChain = ToolChain.Get(backend);
                IReadOnlyList <GeneratedShaderSet> sets = generationResult.GetOutput(backend);
                _output.WriteLine(spacer1);
                _output.WriteLine($"Generated shader sets for {toolChain.Name} backend.");

                foreach (GeneratedShaderSet set in sets)
                {
                    _output.WriteLine(string.Empty);
                    _output.WriteLine(spacer2);
                    _output.WriteLine(string.Empty);
                    CompileResult result;

                    if (set.VertexShaderCode != null)
                    {
                        result = toolChain.Compile(set.VertexShaderCode, Stage.Vertex, set.VertexFunction.Name);
                        if (result.HasError)
                        {
                            _output.WriteLine($"Failed to compile Vertex Shader from set \"{set.Name}\"!");
                            _output.WriteLine(result.ToString());
                            failed = true;
                        }
                        else
                        {
                            _output.WriteLine($"Compiled Vertex Shader from set \"{set.Name}\"!");
                        }
                    }

                    if (set.FragmentFunction != null)
                    {
                        result = toolChain.Compile(set.FragmentShaderCode, Stage.Fragment, set.FragmentFunction.Name);
                        if (result.HasError)
                        {
                            _output.WriteLine($"Failed to compile Fragment Shader from set \"{set.Name}\"!");
                            _output.WriteLine(result.ToString());
                            failed = true;
                        }
                        else
                        {
                            _output.WriteLine($"Compiled Fragment Shader from set \"{set.Name}\"!");
                        }
                    }

                    if (set.ComputeFunction != null)
                    {
                        // TODO The skipped shaders are not included in the auto discovered shaders, leaving this here for completeness.
                        if (backend is GlslEs300Backend)
                        {
                            string fullname = set.ComputeFunction.DeclaringType + "." + set.ComputeFunction.Name + "_";
                            if (s_glslesSkippedShaders.Contains(fullname))
                            {
                                continue;
                            }
                        }

                        result = toolChain.Compile(set.ComputeShaderCode, Stage.Compute, set.ComputeFunction.Name);
                        if (result.HasError)
                        {
                            _output.WriteLine($"Failed to compile Compute Shader from set \"{set.Name}\"!");
                            _output.WriteLine(result.ToString());
                            failed = true;
                        }
                        else
                        {
                            _output.WriteLine($"Compiled Compute Shader from set \"{set.Name}\"!");
                        }
                    }
                }

                _output.WriteLine(string.Empty);
            }

            Assert.False(failed);
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Compilation function (must be overrided for a specific graphic library implementation).
        /// </summary>
        /// <param name="shader">Shader to compile.</param>
        /// <returns>Shader instance with compiled binary.</returns>
        protected override ShaderInstance CompileShader(ShaderInstance shader)
        {
            var outShader = new VKShaderInstance(base.CompileShader(shader));

            // - Gets all shader referenced assemblies
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            var mathAsm    = typeof(System.Numerics.Vector4).Assembly.GetReferencedAssemblies();

            assemblies = assemblies.Concat(mathAsm.Select(x => Assembly.Load(x.FullName))).ToArray();
            var assemblyMeta = assemblies.Select(x => MetadataReference.CreateFromFile(x.Location));

            // - Compile the shader code obtaining an IL version
            CSharpCompilation compilation = CSharpCompilation.Create
                                            (
                "pEngine",
                syntaxTrees: new[] { CSharpSyntaxTree.ParseText(outShader.CSourceCode) },
                references: assemblyMeta,
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                                            );

            // - Get the assembly class path
            string fullName = outShader.Type.FullName;

            // - We want to compile targetting GLSL450 compatible for Vulkan
            var backend = new Glsl450Backend(compilation);

            // - Prepare a GLSL compiler providing the C# IL binary
            var generator = new ShaderGenerator
                            (
                compilation, backend,
                outShader.HasVertexShader ? $"{fullName}.{shader.VertexFunctionName}" : null,
                outShader.HasFragmentShader ? $"{fullName}.{shader.FragmentFunctionName}" : null,
                outShader.HasComputeShader ? $"{fullName}.{shader.ComputeFunctionName}" : null
                            );

            // - Compile to the GLSL code
            var shaders = generator.GenerateShaders().GetOutput(backend);

            // - Stores all shader sources
            outShader.VertexSource   = outShader.HasVertexShader ? shaders.Where(x => x.VertexShaderCode != null).First().VertexShaderCode : "";
            outShader.FragmentSource = outShader.HasFragmentShader ? shaders.Where(x => x.FragmentShaderCode != null).First().FragmentShaderCode : "";
            outShader.ComputeSource  = outShader.HasComputeShader ? shaders.Where(x => x.ComputeShaderCode != null).First().ComputeShaderCode : "";

            // - This class will compile the GLSL code to the SPIR-V binary
            ShaderCompiler compiler = new ShaderCompiler();

            if (outShader.HasVertexShader)
            {
                var res = compiler.CompileToSpirV(outShader.VertexSource, ShaderCompiler.ShaderKind.VertexShader, "main");

                if (res.ErrorCount > 0)
                {
                    throw new InvalidProgramException(res.Errors);
                }

                outShader.VertexBinary = res.Binary;
            }

            if (outShader.HasFragmentShader)
            {
                var res = compiler.CompileToSpirV(outShader.FragmentSource, ShaderCompiler.ShaderKind.FragmentShader, "main");

                if (res.ErrorCount > 0)
                {
                    throw new InvalidProgramException(res.Errors);
                }

                outShader.FragmentBinary = res.Binary;
            }

            if (outShader.HasComputeShader)
            {
                var res = compiler.CompileToSpirV(outShader.ComputeSource, ShaderCompiler.ShaderKind.ComputeShader, "main");

                if (res.ErrorCount > 0)
                {
                    throw new InvalidProgramException(res.Errors);
                }

                outShader.ComputeBinary = res.Binary;
            }

            return(outShader);
        }
Ejemplo n.º 24
0
        public static int Main(string[] args)
        {
            string referenceItemsResponsePath = null;
            string compileItemsResponsePath   = null;
            string outputPath      = null;
            string genListFilePath = null;
            bool   listAllFiles    = false;
            string processorPath   = null;
            string processorArgs   = null;

            for (int i = 0; i < args.Length; i++)
            {
                args[i] = args[i].Replace("\\\\", "\\");
            }

            ArgumentSyntax.Parse(args, syntax =>
            {
                syntax.DefineOption("ref", ref referenceItemsResponsePath, true, "The semicolon-separated list of references to compile against.");
                syntax.DefineOption("src", ref compileItemsResponsePath, true, "The semicolon-separated list of source files to compile.");
                syntax.DefineOption("out", ref outputPath, true, "The output path for the generated shaders.");
                syntax.DefineOption("genlist", ref genListFilePath, true, "The output file to store the list of generated files.");
                syntax.DefineOption("listall", ref listAllFiles, false, "Forces all generated files to be listed in the list file. By default, only bytecode files will be listed and not the original shader code.");
                syntax.DefineOption("processor", ref processorPath, false, "The path of an assembly containing IShaderSetProcessor types to be used to post-process GeneratedShaderSet objects.");
                syntax.DefineOption("processorargs", ref processorArgs, false, "Custom information passed to IShaderSetProcessor.");
            });

            referenceItemsResponsePath = NormalizePath(referenceItemsResponsePath);
            compileItemsResponsePath   = NormalizePath(compileItemsResponsePath);
            outputPath      = NormalizePath(outputPath);
            genListFilePath = NormalizePath(genListFilePath);
            processorPath   = NormalizePath(processorPath);

            if (!File.Exists(referenceItemsResponsePath))
            {
                Console.Error.WriteLine("Reference items response file does not exist: " + referenceItemsResponsePath);
                return(-1);
            }
            if (!File.Exists(compileItemsResponsePath))
            {
                Console.Error.WriteLine("Compile items response file does not exist: " + compileItemsResponsePath);
                return(-1);
            }
            if (!Directory.Exists(outputPath))
            {
                try
                {
                    Directory.CreateDirectory(outputPath);
                }
                catch
                {
                    Console.Error.WriteLine($"Unable to create the output directory \"{outputPath}\".");
                    return(-1);
                }
            }

            string[] referenceItems = File.ReadAllLines(referenceItemsResponsePath);
            string[] compileItems   = File.ReadAllLines(compileItemsResponsePath);

            List <MetadataReference> references = new List <MetadataReference>();

            foreach (string referencePath in referenceItems)
            {
                if (!File.Exists(referencePath))
                {
                    Console.Error.WriteLine("Error: reference does not exist: " + referencePath);
                    return(1);
                }

                using (FileStream fs = File.OpenRead(referencePath))
                {
                    references.Add(MetadataReference.CreateFromStream(fs, filePath: referencePath));
                }
            }

            List <SyntaxTree> syntaxTrees = new List <SyntaxTree>();

            foreach (string sourcePath in compileItems)
            {
                string fullSourcePath = Path.Combine(Environment.CurrentDirectory, sourcePath);
                if (!File.Exists(fullSourcePath))
                {
                    Console.Error.WriteLine("Error: source file does not exist: " + fullSourcePath);
                    return(1);
                }

                using (FileStream fs = File.OpenRead(fullSourcePath))
                {
                    SourceText text = SourceText.From(fs);
                    syntaxTrees.Add(CSharpSyntaxTree.ParseText(text, path: fullSourcePath));
                }
            }

            Compilation compilation = CSharpCompilation.Create(
                "ShaderGen.App.GenerateShaders",
                syntaxTrees,
                references,
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            HlslBackend      hlsl      = new HlslBackend(compilation);
            Glsl330Backend   glsl330   = new Glsl330Backend(compilation);
            GlslEs300Backend glsles300 = new GlslEs300Backend(compilation);
            Glsl450Backend   glsl450   = new Glsl450Backend(compilation);
            MetalBackend     metal     = new MetalBackend(compilation);

            LanguageBackend[] languages = new LanguageBackend[]
            {
                hlsl,
                glsl330,
                glsles300,
                glsl450,
                metal,
            };

            List <IShaderSetProcessor> processors = new List <IShaderSetProcessor>();

            if (processorPath != null)
            {
                try
                {
                    Assembly           assm           = Assembly.LoadFrom(processorPath);
                    IEnumerable <Type> processorTypes = assm.GetTypes().Where(
                        t => t.GetInterface(nameof(ShaderGen) + "." + nameof(IShaderSetProcessor)) != null);
                    foreach (Type type in processorTypes)
                    {
                        IShaderSetProcessor processor = (IShaderSetProcessor)Activator.CreateInstance(type);
                        processor.UserArgs = processorArgs;
                        processors.Add(processor);
                    }
                }
                catch (ReflectionTypeLoadException rtle)
                {
                    string msg = string.Join(Environment.NewLine, rtle.LoaderExceptions.Select(e => e.ToString()));
                    Console.WriteLine("FAIL: " + msg);
                    throw new Exception(msg);
                }
            }

            ShaderGenerator        sg = new ShaderGenerator(compilation, languages, processors.ToArray());
            ShaderGenerationResult shaderGenResult;

            try
            {
                shaderGenResult = sg.GenerateShaders();
            }
            catch (Exception e) when(!Debugger.IsAttached)
            {
                StringBuilder sb = new StringBuilder();

                sb.AppendLine("An error was encountered while generating shader code:");
                sb.AppendLine(e.ToString());
                Console.Error.WriteLine(sb.ToString());
                return(-1);
            }

            Encoding      outputEncoding     = new UTF8Encoding(false);
            List <string> generatedFilePaths = new List <string>();

            foreach (LanguageBackend lang in languages)
            {
                string extension = BackendExtension(lang);
                IReadOnlyList <GeneratedShaderSet> sets = shaderGenResult.GetOutput(lang);
                foreach (GeneratedShaderSet set in sets)
                {
                    string name = set.Name;
                    if (set.VertexShaderCode != null)
                    {
                        string vsOutName = name + "-vertex." + extension;
                        string vsOutPath = Path.Combine(outputPath, vsOutName);
                        File.WriteAllText(vsOutPath, set.VertexShaderCode, outputEncoding);
                        bool succeeded = CompileCode(
                            lang,
                            vsOutPath,
                            set.VertexFunction.Name,
                            ShaderFunctionType.VertexEntryPoint,
                            out string[] genPaths);
                        if (succeeded)
                        {
                            generatedFilePaths.AddRange(genPaths);
                        }
                        if (!succeeded || listAllFiles)
                        {
                            generatedFilePaths.Add(vsOutPath);
                        }
                    }
                    if (set.FragmentShaderCode != null)
                    {
                        string fsOutName = name + "-fragment." + extension;
                        string fsOutPath = Path.Combine(outputPath, fsOutName);
                        File.WriteAllText(fsOutPath, set.FragmentShaderCode, outputEncoding);
                        bool succeeded = CompileCode(
                            lang,
                            fsOutPath,
                            set.FragmentFunction.Name,
                            ShaderFunctionType.FragmentEntryPoint,
                            out string[] genPaths);
                        if (succeeded)
                        {
                            generatedFilePaths.AddRange(genPaths);
                        }
                        if (!succeeded || listAllFiles)
                        {
                            generatedFilePaths.Add(fsOutPath);
                        }
                    }
                    if (set.ComputeShaderCode != null)
                    {
                        string csOutName = name + "-compute." + extension;
                        string csOutPath = Path.Combine(outputPath, csOutName);
                        File.WriteAllText(csOutPath, set.ComputeShaderCode, outputEncoding);
                        bool succeeded = CompileCode(
                            lang,
                            csOutPath,
                            set.ComputeFunction.Name,
                            ShaderFunctionType.ComputeEntryPoint,
                            out string[] genPaths);
                        if (succeeded)
                        {
                            generatedFilePaths.AddRange(genPaths);
                        }
                        if (!succeeded || listAllFiles)
                        {
                            generatedFilePaths.Add(csOutPath);
                        }
                    }
                }
            }

            File.WriteAllLines(genListFilePath, generatedFilePaths);

            return(0);
        }