private void CreateShaders() { foreach (var shaderBytecode in effectBytecode.Stages) { var bytecodeRaw = shaderBytecode.Data; var reflection = effectBytecode.Reflection; // TODO CACHE Shaders with a bytecode hash switch (shaderBytecode.Stage) { case ShaderStage.Vertex: vertexShader = new VertexShader(GraphicsDevice.NativeDevice, bytecodeRaw); // Note: input signature can be reused when reseting device since it only stores non-GPU data, // so just keep it if it has already been created before. if (inputSignature == null) { inputSignature = EffectInputSignature.GetOrCreateLayout(new EffectInputSignature(shaderBytecode.Id, bytecodeRaw)); } break; case ShaderStage.Domain: domainShader = new DomainShader(GraphicsDevice.NativeDevice, bytecodeRaw); break; case ShaderStage.Hull: hullShader = new HullShader(GraphicsDevice.NativeDevice, bytecodeRaw); break; case ShaderStage.Geometry: if (reflection.ShaderStreamOutputDeclarations != null && reflection.ShaderStreamOutputDeclarations.Count > 0) { // Calculate the strides var soStrides = new List <int>(); foreach (var streamOutputElement in reflection.ShaderStreamOutputDeclarations) { for (int i = soStrides.Count; i < (streamOutputElement.Stream + 1); i++) { soStrides.Add(0); } soStrides[streamOutputElement.Stream] += streamOutputElement.ComponentCount * sizeof(float); } var soElements = new StreamOutputElement[0]; // TODO CREATE StreamOutputElement from bytecode.Reflection.ShaderStreamOutputDeclarations geometryShader = new GeometryShader(GraphicsDevice.NativeDevice, bytecodeRaw, soElements, soStrides.ToArray(), reflection.StreamOutputRasterizedStream); } else { geometryShader = new GeometryShader(GraphicsDevice.NativeDevice, bytecodeRaw); } break; case ShaderStage.Pixel: pixelShader = new PixelShader(GraphicsDevice.NativeDevice, bytecodeRaw); break; case ShaderStage.Compute: computeShader = new ComputeShader(GraphicsDevice.NativeDevice, bytecodeRaw); break; } } }
private void CreateShaders() { using (GraphicsDevice.UseOpenGLCreationContext()) { resourceId = GL.CreateProgram(); // Attach shaders foreach (var shader in effectBytecode.Stages) { ShaderType shaderStage; switch (shader.Stage) { case ShaderStage.Vertex: shaderStage = ShaderType.VertexShader; inputSignature = EffectInputSignature.GetOrCreateLayout(new EffectInputSignature(shader.Id, shader.Data)); break; case ShaderStage.Pixel: shaderStage = ShaderType.FragmentShader; break; default: throw new Exception("Unsupported shader stage"); break; } #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES var shaderSources = BinarySerialization.Read <ShaderLevelBytecode>(shader.Data); var shaderSource = GraphicsDevice.IsOpenGLES2 ? shaderSources.DataES2 : shaderSources.DataES3; #else var shaderSource = shader.GetDataAsString(); #endif var shaderId = GL.CreateShader(shaderStage); GL.ShaderSource(shaderId, shaderSource); GL.CompileShader(shaderId); int compileStatus; GL.GetShader(shaderId, ShaderParameter.CompileStatus, out compileStatus); if (compileStatus != 1) { var glErrorMessage = GL.GetShaderInfoLog(shaderId); throw new InvalidOperationException("Error while compiling GLSL shader. [{0}]".ToFormat(glErrorMessage)); } GL.AttachShader(resourceId, shaderId); } #if !SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES // Mark program as retrievable (necessary for later GL.GetProgramBinary). GL.ProgramParameter(resourceId, AssemblyProgramParameterArb.ProgramBinaryRetrievableHint, 1); #endif // Link OpenGL program GL.LinkProgram(resourceId); // Check link results int linkStatus; GL.GetProgram(resourceId, ProgramParameter.LinkStatus, out linkStatus); if (linkStatus != 1) { var infoLog = GL.GetProgramInfoLog(resourceId); throw new InvalidOperationException("Error while linking GLSL shaders.\n" + infoLog); } if (inputSignature.Attributes.Count == 0) // the shader wasn't analyzed yet { // Build attributes list for shader signature int activeAttribCount; GL.GetProgram(resourceId, ProgramParameter.ActiveAttributes, out activeAttribCount); for (int activeAttribIndex = 0; activeAttribIndex < activeAttribCount; ++activeAttribIndex) { int size; ActiveAttribType type; var attribName = GL.GetActiveAttrib(resourceId, activeAttribIndex, out size, out type); #if SILICONSTUDIO_PLATFORM_ANDROID var attribIndex = GL.GetAttribLocation(resourceId, new StringBuilder(attribName)); #else var attribIndex = GL.GetAttribLocation(resourceId, attribName); #endif inputSignature.Attributes.Add(attribName, attribIndex); } } CreateReflection(effectBytecode.Reflection, effectBytecode.Stages[0].Stage); // need to regenerate the Uniforms on OpenGL ES #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES // Allocate a buffer that can cache all the bound parameters BoundUniforms = new byte[effectBytecode.Reflection.ConstantBuffers[0].Size]; #endif } // output the gathered errors foreach (var message in reflectionResult.Messages) { Console.WriteLine(message); } if (reflectionResult.HasErrors) { throw new Exception("Exception"); } }