private byte[] CompileToSpirv( ShaderVariantDescription variant, string fileName, ShaderStages stage) { GlslCompileOptions glslOptions = GetOptions(variant); string glsl = LoadGlsl(fileName); SpirvCompilationResult result = SpirvCompilation.CompileGlslToSpirv( glsl, fileName, stage, glslOptions); return(result.SpirvBytes); }
private string[] CompileCompute(ShaderVariantDescription variant) { List <string> generatedFiles = new List <string>(); byte[] csBytes = CompileToSpirv(variant, variant.Shaders[0].FileName, ShaderStages.Compute); string spvPath = Path.Combine(_outputPath, $"{variant.Name}_{ShaderStages.Compute.ToString()}.spv"); File.WriteAllBytes(spvPath, csBytes); generatedFiles.Add(spvPath); List <Exception> compilationExceptions = new List <Exception>(); foreach (CrossCompileTarget target in variant.Targets) { try { ComputeCompilationResult result = SpirvCompilation.CompileCompute(csBytes, target, variant.CrossCompileOptions); string csPath = Path.Combine(_outputPath, $"{variant.Name}_Compute.{GetExtension(target)}"); File.WriteAllText(csPath, result.ComputeShader); generatedFiles.Add(csPath); string reflectionPath = Path.Combine(_outputPath, $"{variant.Name}_ReflectionInfo.json"); JsonSerializer serializer = new JsonSerializer(); serializer.Formatting = Formatting.Indented; StringEnumConverter enumConverter = new StringEnumConverter(); serializer.Converters.Add(enumConverter); using (StreamWriter sw = File.CreateText(reflectionPath)) using (JsonTextWriter jtw = new JsonTextWriter(sw)) { serializer.Serialize(jtw, result.Reflection); } generatedFiles.Add(reflectionPath); } catch (Exception e) { compilationExceptions.Add(e); } } if (compilationExceptions.Count > 0) { throw new AggregateException($"Errors were encountered when compiling shader variant(s).", compilationExceptions); } return(generatedFiles.ToArray()); }
public string[] Compile(ShaderVariantDescription variant) { if (variant.Shaders.Length == 1) { if (variant.Shaders[0].Stage == ShaderStages.Vertex) { return(CompileVertexFragment(variant)); } if (variant.Shaders[0].Stage == ShaderStages.Compute) { return(CompileCompute(variant)); } } if (variant.Shaders.Length == 2) { bool hasVertex = false; bool hasFragment = false; foreach (var shader in variant.Shaders) { hasVertex |= shader.Stage == ShaderStages.Vertex; hasFragment |= shader.Stage == ShaderStages.Fragment; } if (!hasVertex) { throw new SpirvCompilationException($"Variant \"{variant.Name}\" is missing a vertex shader."); } if (!hasFragment) { throw new SpirvCompilationException($"Variant \"{variant.Name}\" is missing a fragment shader."); } return(CompileVertexFragment(variant)); } else { throw new SpirvCompilationException( $"Variant \"{variant.Name}\" has an unsupported combination of shader stages."); } }
private GlslCompileOptions GetOptions(ShaderVariantDescription variant) { return(new GlslCompileOptions(true, variant.Macros)); }
private string[] CompileVertexFragment(ShaderVariantDescription variant) { List <string> generatedFiles = new List <string>(); List <Exception> compilationExceptions = new List <Exception>(); byte[] vsBytes = null; byte[] fsBytes = null; string vertexFileName = variant.Shaders.FirstOrDefault(vsd => vsd.Stage == ShaderStages.Vertex)?.FileName; if (vertexFileName != null) { try { vsBytes = CompileToSpirv(variant, vertexFileName, ShaderStages.Vertex); //string spvPath = Path.Combine(_outputPath, $"{variant.Name}_{ShaderStages.Vertex.ToString()}.spv"); string spvPath = Path.Combine(_outputPath, $"{variant.Name}.vert.spv"); File.WriteAllBytes(spvPath, vsBytes); generatedFiles.Add(spvPath); } catch (Exception e) { compilationExceptions.Add(e); } } string fragmentFileName = variant.Shaders.FirstOrDefault(vsd => vsd.Stage == ShaderStages.Fragment)?.FileName; if (fragmentFileName != null) { try { fsBytes = CompileToSpirv(variant, fragmentFileName, ShaderStages.Fragment); //string spvPath = Path.Combine(_outputPath, $"{variant.Name}_{ShaderStages.Fragment.ToString()}.spv"); string spvPath = Path.Combine(_outputPath, $"{variant.Name}.frag.spv"); File.WriteAllBytes(spvPath, fsBytes); generatedFiles.Add(spvPath); } catch (Exception e) { compilationExceptions.Add(e); } } if (compilationExceptions.Count > 0) { throw new AggregateException( $"Errors were encountered when compiling from GLSL to SPIR-V.", compilationExceptions); } foreach (CrossCompileTarget target in variant.Targets) { try { bool writeReflectionFile = true; VertexFragmentCompilationResult result = SpirvCompilation.CompileVertexFragment( vsBytes, fsBytes, target, variant.CrossCompileOptions); if (result.VertexShader != null) { string vsPath = Path.Combine(_outputPath, $"{variant.Name}_Vertex.{GetExtension(target)}"); File.WriteAllText(vsPath, result.VertexShader); generatedFiles.Add(vsPath); } if (result.FragmentShader != null) { string fsPath = Path.Combine(_outputPath, $"{variant.Name}_Fragment.{GetExtension(target)}"); File.WriteAllText(fsPath, result.FragmentShader); generatedFiles.Add(fsPath); } if (writeReflectionFile) { writeReflectionFile = false; string reflectionPath = Path.Combine(_outputPath, $"{variant.Name}_ReflectionInfo.json"); JsonSerializer serializer = new JsonSerializer(); serializer.Formatting = Formatting.Indented; StringEnumConverter enumConverter = new StringEnumConverter(); serializer.Converters.Add(enumConverter); using (StreamWriter sw = File.CreateText(reflectionPath)) using (JsonTextWriter jtw = new JsonTextWriter(sw)) { serializer.Serialize(jtw, result.Reflection); } generatedFiles.Add(reflectionPath); } } catch (Exception e) { compilationExceptions.Add(e); } } if (compilationExceptions.Count > 0) { throw new AggregateException($"Errors were encountered when compiling shader variant(s).", compilationExceptions); } return(generatedFiles.ToArray()); }