Beispiel #1
0
        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");
            }
        }