private System.Tuple <Shader, System.Exception> LoadShader(string shaderFile, params InputElement[] inputElements) { var result = new Shader() { vertexShader = null, pixelShader = null, geometryShader = null, layout = null, validState = false }; ShaderBytecode vertexShaderByteCode = null; ShaderBytecode pixelShaderByteCode = null; ShaderBytecode geometryShaderByteCode = null; ShaderSignature signature = null; VertexShader vertexShader = null; PixelShader pixelShader = null; GeometryShader geometryShader = null; InputLayout layout = null; System.Exception error = null; try { var shaderFileBytecode = File.ReadAllBytes(shaderFile); vertexShaderByteCode = ShaderBytecode.Compile(shaderFileBytecode, "VS", "vs_4_0", ShaderFlags.OptimizationLevel0); vertexShader = new VertexShader(device, vertexShaderByteCode); var reflection = new ShaderReflection(vertexShaderByteCode); /* Iterate through constant buffers */ for (int i = 0; i < reflection.Description.ConstantBuffers; ++i) { var cb = reflection.GetConstantBuffer(i); if (cb.Description.Name == "worldViewProj") { result.vertexShaderSlot.worldViewProj = i; } } reflection.Dispose(); pixelShaderByteCode = ShaderBytecode.Compile(shaderFileBytecode, "PS", "ps_4_0", ShaderFlags.OptimizationLevel0); pixelShader = new PixelShader(device, pixelShaderByteCode); try { geometryShaderByteCode = ShaderBytecode.Compile(shaderFileBytecode, "GS", "gs_4_0", ShaderFlags.OptimizationLevel0); geometryShader = new GeometryShader(device, geometryShaderByteCode); } catch (CompilationException e) { if (!e.Message.Contains("'GS': entrypoint")) { throw e; } } signature = ShaderSignature.GetInputSignature(vertexShaderByteCode); layout = new InputLayout(device, signature, inputElements); signature.Dispose(); result.vertexShader = vertexShader; result.pixelShader = pixelShader; result.geometryShader = geometryShader; result.layout = layout; } catch (System.Exception e) { System.Console.WriteLine("Error while compiling shader {0}:\n{1}", shaderFile, e); error = e; } finally { if (geometryShaderByteCode != null) { geometryShaderByteCode.Dispose(); } if (vertexShaderByteCode != null) { vertexShaderByteCode.Dispose(); } if (pixelShaderByteCode != null) { pixelShaderByteCode.Dispose(); } if (geometryShaderByteCode != null) { geometryShaderByteCode.Dispose(); } if (signature != null) { signature.Dispose(); } if (error != null && vertexShader != null) { vertexShader.Dispose(); } if (error != null && pixelShader != null) { pixelShader.Dispose(); } if (error != null && geometryShader != null) { geometryShader.Dispose(); } if (error != null && layout != null) { signature.Dispose(); } } result.validState = error == null; return(System.Tuple.Create(result, error)); }
public static void CompileD3D12Shader(H1ShaderCompileInput input, H1ShaderCompileOutput output) { // process shared/single environments String includeContent = ""; List <SharpDX.Direct3D.ShaderMacro> macros = new List <SharpDX.Direct3D.ShaderMacro>(); // 1. shared environment ProcessShaderCompilerEnvironment(input.SharedEnvironment, ref includeContent, macros); // 2. single environment ProcessShaderCompilerEnvironment(input.Environment, ref includeContent, macros); // load shader file content String sourceContent = includeContent + "\n" + LoadShaderFile(input.SourceFileName); // preprocess the shader file sourceContent = ShaderBytecode.Preprocess(sourceContent, macros.ToArray(), new H1SharpDXCompileInclude()); #if DEBUG var shader = ShaderBytecode.Compile(sourceContent, input.EntryPointName, input.Target.ToFormat, SharpDX.D3DCompiler.ShaderFlags.Debug | SharpDX.D3DCompiler.ShaderFlags.SkipOptimization); #else var shader = ShaderBytecode.Compile(sourceContent, input.EntryPointName, input.Target.ToFormat); #endif if (shader.Message != null) // failed to compile the shader { // @TODO - should log the error for failing compiling shader output.IsSucceed = false; return; } // assign the resultant byte code output.Code = shader; // create shader parameter map output.ParameterMap = new H1ShaderParameterMap(); // reflection for the compiled shader ShaderReflection shaderReflect = new ShaderReflection(shader); ShaderDescription shaderDesc = shaderReflect.Description; int bindResCounts = shaderDesc.BoundResources; for (int resIdx = 0; resIdx < bindResCounts; ++resIdx) { InputBindingDescription bindDesc = shaderReflect.GetResourceBindingDescription(resIdx); // for constant buffers if (bindDesc.Type == ShaderInputType.ConstantBuffer) { int cbIndex = bindDesc.BindPoint; ConstantBuffer cb = shaderReflect.GetConstantBuffer(cbIndex); ConstantBufferDescription cbDesc; cbDesc = cb.Description; // track all variables in this constant buffer for (int varIdx = 0; varIdx < cbDesc.VariableCount; varIdx++) { ShaderReflectionVariable variable = cb.GetVariable(varIdx); ShaderVariableDescription variableDesc = variable.Description; output.ParameterMap.ParameterMap.Add(variableDesc.Name, new H1ParameterAllocation(H1ParameterType.Variable, cbIndex, variableDesc.StartOffset, variableDesc.Size)); } // add constant buffer parameter output.ParameterMap.ParameterMap.Add(cbDesc.Name, new H1ParameterAllocation(H1ParameterType.ConstantBuffer, cbIndex, -1, cbDesc.Size)); } // texture, samplers .... other various GDI data } // release shader reflection shaderReflect.Dispose(); output.IsSucceed = true; // successfully compiled }