public IShaderProgram Program(ShaderProgramDescription description)
        {
            ShaderProgram result;
            string        errors;

            if (!ShaderProgram.TryLink(context, description, out result, out errors))
            {
                throw new ShaderException("Failed to link a shader prgram:\r\n\r\n" + errors);
            }
            return(result);
        }
Exemple #2
0
        public static unsafe bool TryLink(
            IContext context,
            ShaderProgramDescription description,
            out ShaderProgram program,
            out string errors)
        {
            var gl = context.GL;

            description.VertexAttributeNames = description.VertexAttributeNames ?? EmptyStringArray;
            if (description.VertexAttributeNames.Any(x => x != null && description.VertexAttributeNames.Count(y => y == x) != 1))
            {
                throw new ArgumentException("All non-null attribute names must be unique.");
            }

            description.UniformBufferNames = description.UniformBufferNames ?? EmptyStringArray;
            if (description.UniformBufferNames.Any(x => x != null && description.UniformBufferNames.Count(y => y == x) != 1))
            {
                throw new ArgumentException("All non-null uniform buffer names must be unique.");
            }

            description.TransformFeedbackAttributeNames = description.TransformFeedbackAttributeNames ?? EmptyStringArray;
            if (description.TransformFeedbackAttributeNames.Any(x => !x.StartsWith("gl_") &&
                                                                description.TransformFeedbackAttributeNames.Count(y => y == x) != 1))
            {
                throw new ArgumentException("All transform feedback attribute names (except gl_*** strings) must be unique.");
            }

            description.SamplerNames = description.SamplerNames ?? EmptyStringArray;
            if (description.SamplerNames.Any(x => x != null && description.SamplerNames.Count(y => y == x) != 1))
            {
                throw new ArgumentException("All non-null sampler names must be unique.");
            }

            uint handle = gl.CreateProgram();

            program = new ShaderProgram(context, handle);

            description.TesselationControlShaders    = description.TesselationControlShaders ?? EmptyTessControlShaderArray;
            description.TesselationEvaluationShaders = description.TesselationEvaluationShaders ?? EmptyTessEvalShaderArray;
            description.GeometryShaders = description.GeometryShaders ?? EmptyGeometryShaderArray;

            foreach (var shader in description.VertexShaders)
            {
                gl.AttachShader(handle, shader.Handle);
            }
            foreach (var shader in description.TesselationControlShaders)
            {
                gl.AttachShader(handle, shader.Handle);
            }
            foreach (var shader in description.TesselationEvaluationShaders)
            {
                gl.AttachShader(handle, shader.Handle);
            }
            foreach (var shader in description.GeometryShaders)
            {
                gl.AttachShader(handle, shader.Handle);
            }
            foreach (var shader in description.FragmentShaders)
            {
                gl.AttachShader(handle, shader.Handle);
            }

            for (uint i = 0; i < description.VertexAttributeNames.Length; i++)
            {
                if (description.VertexAttributeNames[i] != null)
                {
                    gl.BindAttribLocation(handle, i, description.VertexAttributeNames[i]);
                }
            }

            if (description.TransformFeedbackAttributeNames.Length > 0)
            {
                gl.TransformFeedbackVaryings(handle, description.TransformFeedbackAttributeNames.Length,
                                             description.TransformFeedbackAttributeNames, (int)description.TransformFeedbackMode);
            }

            gl.LinkProgram(handle);

            int isLinked;

            gl.GetProgram(handle, (int)All.LinkStatus, &isLinked);
            if (isLinked == 0)
            {
                program = null;
                errors  = gl.GetProgramInfoLog(handle);
                return(false);
            }

            for (int i = 0; i < description.VertexAttributeNames.Length; i++)
            {
                if (description.VertexAttributeNames[i] != null && gl.GetAttribLocation(handle, description.VertexAttributeNames[i]) != i)
                {
                    throw new ArgumentException(string.Format("Vertex attribute '{0}' is not present in the program.", description.VertexAttributeNames[i]));
                }
            }

            for (uint i = 0; i < description.UniformBufferNames.Length; i++)
            {
                if (description.UniformBufferNames[i] == null)
                {
                    continue;
                }

                uint programSpecificIndex = gl.GetUniformBlockIndex(handle, description.UniformBufferNames[i]);
                if (programSpecificIndex == (uint)All.InvalidIndex)
                {
                    program = null;
                    errors  = string.Format("Uniform Bufffer '{0}' not found.", description.UniformBufferNames[i]);
                    return(false);
                }

                gl.UniformBlockBinding(handle, programSpecificIndex, i);
            }

            context.Bindings.Program.Set(program);

            for (int i = 0; i < description.SamplerNames.Length; i++)
            {
                if (description.SamplerNames[i] == null)
                {
                    continue;
                }

                int samplerUniformLocation = gl.GetUniformLocation(handle, description.SamplerNames[i]);
                gl.Uniform(samplerUniformLocation, i);
            }

            errors = null;
            return(true);
        }
 public IShaderProgram Program(ShaderProgramDescription description)
 {
     ShaderProgram result;
     string errors;
     if (!ShaderProgram.TryLink(context, description, out result, out errors))
         throw new ShaderException("Failed to link a shader prgram:\r\n\r\n" + errors);
     return result;
 }