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); }
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); } }
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); }
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); } }
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()); }
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); } } } } }
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()); } }
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); }
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()); }
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()); }
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)); }
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); }
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)); }
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 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"); }
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); } }
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()); }
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); }
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); }
/// <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); }
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); }