private void UpdateUniformBuffers() { UniformInfo ui = new UniformInfo { LightPos = new Vector4(0, 0, 0, 1) }; ui.Projection = Matrix4x4.CreatePerspectiveFieldOfView(DegreesToRadians(60.0f), _window.Width / (float)_window.Height, 0.1f, 256.0f); Matrix4x4 cameraRot = Matrix4x4.CreateFromYawPitchRoll( DegreesToRadians(_rotation.Y), DegreesToRadians(_rotation.X), DegreesToRadians(_rotation.Z)); Vector3 cameraLookDir = Vector3.Transform(-Vector3.UnitZ, cameraRot); Matrix4x4 viewMatrix = Matrix4x4.CreateLookAt(_cameraPos, _cameraPos + cameraLookDir, Vector3.UnitY); ui.View = viewMatrix; ui.Model = Matrix4x4.CreateRotationX(DegreesToRadians(_dragonRotation.X)); ui.Model = Matrix4x4.CreateRotationY(DegreesToRadians(_dragonRotation.Y)) * ui.Model; ui.Model = Matrix4x4.CreateTranslation(_dragonPos) * ui.Model; _gd.UpdateBuffer(_uniformBuffers_vsShared, 0, ref ui); // Mirror ui.Model = Matrix4x4.Identity; _gd.UpdateBuffer(_uniformBuffers_vsMirror, 0, ref ui); }
public void Link() { GL.LinkProgram(ProgramID); var log = GL.GetProgramInfoLog(ProgramID); if (!string.IsNullOrWhiteSpace(log)) { Console.WriteLine(log); } GL.GetProgram(ProgramID, GetProgramParameterName.ActiveAttributes, out AttributeCount); GL.GetProgram(ProgramID, GetProgramParameterName.ActiveUniforms, out UniformCount); for (int i = 0; i < AttributeCount; i++) { AttributeInfo info = new AttributeInfo(); GL.GetActiveAttrib(ProgramID, i, 256, out var length, out info.size, out info.type, out info.name); info.address = GL.GetAttribLocation(ProgramID, info.name); Attributes.Add(info.name, info); } for (int i = 0; i < UniformCount; i++) { UniformInfo info = new UniformInfo(); GL.GetActiveUniform(ProgramID, i, 256, out var length, out info.size, out info.type, out info.name); Uniforms.Add(info.name, info); info.address = GL.GetUniformLocation(ProgramID, info.name); } }
public void Link() { GL.LinkProgram(ProgramID); GL.GetProgram(ProgramID, GetProgramParameterName.ActiveAttributes, out AttributeCount); GL.GetProgram(ProgramID, GetProgramParameterName.ActiveUniforms, out UniformCount); for (int i = 0; i < AttributeCount; i++) { AttributeInfo info = new AttributeInfo(); GL.GetActiveAttrib(ProgramID, i, 256, out int length, out info.size, out info.type, out string name); info.name = name.ToString(); info.address = GL.GetAttribLocation(ProgramID, info.name); Attributes.Add(name.ToString(), info); } for (int i = 0; i < UniformCount; i++) { UniformInfo info = new UniformInfo(); GL.GetActiveUniform(ProgramID, i, 256, out int length, out info.size, out info.type, out string name); info.name = name.ToString(); Uniforms.Add(name.ToString(), info); info.address = GL.GetUniformLocation(ProgramID, info.name); } }
public static UniformInfo[] Hlsl2Glsl_GetUniformInfo(IntPtr handle) { var numUniforms = Hlsl2Glsl_GetUniformCount(handle); var uniformInfosPtr = Hlsl2Glsl_GetUniformInfo_Impl(handle); var structSize = Marshal.SizeOf(typeof(UniformInfo)); var result = new UniformInfo[numUniforms]; for (int i = 0; i < numUniforms; ++i) { var data = IntPtr.Add(uniformInfosPtr, structSize * i); result[i] = (UniformInfo)Marshal.PtrToStructure(data, typeof(UniformInfo)); } return(result); }
private void UpdateUniformBufferOffscreen() { UniformInfo ui = new UniformInfo { LightPos = new Vector4(0, 0, 0, 1) }; ui.Projection = Matrix4x4.CreatePerspectiveFieldOfView(DegreesToRadians(60.0f), Window.Width / (float)Window.Height, 0.1f, 256.0f); ui.View = Matrix4x4.CreateLookAt(_camera.Position, _camera.Position + _camera.Forward, Vector3.UnitY); ui.Model = Matrix4x4.CreateRotationX(DegreesToRadians(_dragonRotation.X)); ui.Model = Matrix4x4.CreateRotationY(DegreesToRadians(_dragonRotation.Y)) * ui.Model; ui.Model = Matrix4x4.CreateScale(new Vector3(1, -1, 1)) * ui.Model; ui.Model = Matrix4x4.CreateTranslation(_dragonPos) * ui.Model; GraphicsDevice.UpdateBuffer(_uniformBuffers_vsOffScreen, 0, ref ui); }
private Dictionary <string, UniformInfo> GetUniformsInformation(int shaderProgramId) { GL.GetProgram(shaderProgramId, GetProgramParameterName.ActiveUniforms, out int UniformCount); Dictionary <string, UniformInfo> uniforms = new Dictionary <string, UniformInfo>(); for (int i = 0; i < UniformCount; i++) { UniformInfo info = new UniformInfo(); GL.GetActiveUniform(shaderProgramId, i, 256, out int length, out info.Size, out ActiveUniformType type, out string name); info.Name = name.ToString(); info.Address = GL.GetAttribLocation(shaderProgramId, info.Name); info.Type = (int)type; uniforms.Add(name.ToString(), info); } return(uniforms); }
private void Reflect(ShaderProgram.Sampler[] samplers) { GL.GetProgram(GLProgram, ProgramParameter.ActiveUniforms, out int uniformCount); GLHelper.CheckGLErrors(); GL.GetProgram(GLProgram, ProgramParameter.ActiveUniformMaxLength, out int maxUniformNameLength); GLHelper.CheckGLErrors(); uniformInfos = new UniformInfo[uniformCount]; uniformStagingDataSize = 0; var sb = new StringBuilder(maxUniformNameLength); for (var i = 0; i < uniformCount; i++) { sb.Clear(); GL.GetActiveUniform(GLProgram, i, maxUniformNameLength, out _, out var arraySize, out ActiveUniformType type, sb); GLHelper.CheckGLErrors(); var name = sb.ToString(); var location = GL.GetUniformLocation(GLProgram, name); GLHelper.CheckGLErrors(); var info = new UniformInfo { Name = AdjustUniformName(name), Type = ConvertUniformType(type), ArraySize = arraySize, Location = location, StagingDataOffset = -1, TextureSlot = -1 }; if (info.Type.IsSampler()) { if (info.ArraySize > 1) { throw new NotSupportedException(); } info.TextureSlot = samplers.First(sampler => sampler.Name == info.Name).Stage; } else { info.StagingDataOffset = uniformStagingDataSize; info.ElementSize = 4 * info.Type.GetRowCount() * info.Type.GetColumnCount(); uniformStagingDataSize += info.ElementSize * info.ArraySize; } uniformInfos[i] = info; } }
private void SetUniforms() { int number; GL.GetProgram(ProgramID, GetProgramParameterName.ActiveUniforms, out number); for (int i = 0; i < number; i++) { UniformInfo info = new UniformInfo(); int length = 0; StringBuilder name = new StringBuilder(); GL.GetActiveUniform(ProgramID, i, 256, out length, out info.Size, out info.type, name); info.Name = name.ToString(); uniforms.Add(name.ToString(), info); info.Address = GL.GetUniformLocation(ProgramID, info.Name); } }
public void Link() { GL.LinkProgram(ProgramID); Console.WriteLine(GL.GetProgramInfoLog(ProgramID)); #pragma warning disable CS0618 // Type or member is obsolete GL.GetProgram(ProgramID, ProgramParameter.ActiveAttributes, out AttributeCount); GL.GetProgram(ProgramID, ProgramParameter.ActiveUniforms, out UniformCount); #pragma warning restore CS0618 // Type or member is obsolete for (int i = 0; i < AttributeCount; i++) { AttributeInfo info = new AttributeInfo(); int length = 0; StringBuilder name = new StringBuilder(); GL.GetActiveAttrib(ProgramID, i, 256, out length, out info.size, out info.type, name); info.name = name.ToString(); info.address = GL.GetAttribLocation(ProgramID, info.name); Attributes.Add(name.ToString(), info); } for (int i = 0; i < UniformCount; i++) { UniformInfo info = new UniformInfo(); int length = 0; StringBuilder name = new StringBuilder(); GL.GetActiveUniform(ProgramID, i, 256, out length, out info.size, out info.type, name); info.name = name.ToString(); Uniforms.Add(name.ToString(), info); info.address = GL.GetUniformLocation(ProgramID, info.name); } }
/// <exception cref="InvalidOperationException"> /// <paramref name="required"/> is <see langword="true"/> and either <paramref name="vertexShader"/> or <paramref name="fragmentShader"/> is unavailable (their <see cref="Shader.Available"/> property is <see langword="false"/>), or /// <c>glLinkProgram</c> call did not produce expected result /// </exception> public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required, string memo) { // if the shaders aren't available, the pipeline isn't either if (!vertexShader.Available || !fragmentShader.Available) { string errors = $"Vertex Shader:\r\n {vertexShader.Errors} \r\n-------\r\nFragment Shader:\r\n{fragmentShader.Errors}"; if (required) { throw new InvalidOperationException($"Couldn't build required GL pipeline:\r\n{errors}"); } var pipeline = new Pipeline(this, null, false, null, null, null) { Errors = errors }; return(pipeline); } bool success = true; var vsw = vertexShader.Opaque as ShaderWrapper; var fsw = fragmentShader.Opaque as ShaderWrapper; var sws = new[] { vsw, fsw }; ErrorCode errcode; int pid = GL.CreateProgram(); GL.AttachShader(pid, vsw.sid); errcode = GL.GetError(); GL.AttachShader(pid, fsw.sid); errcode = GL.GetError(); GL.LinkProgram(pid); errcode = GL.GetError(); string resultLog = GL.GetProgramInfoLog(pid); if (errcode != ErrorCode.NoError) { if (required) { throw new InvalidOperationException($"Error creating pipeline (error returned from glLinkProgram): {errcode}\r\n\r\n{resultLog}"); } else { success = false; } } GL.GetProgram(pid, GetProgramParameterName.LinkStatus, out var linkStatus); if (linkStatus == 0) { if (required) { throw new InvalidOperationException($"Error creating pipeline (link status false returned from glLinkProgram): \r\n\r\n{resultLog}"); } else { success = false; } resultLog = GL.GetProgramInfoLog(pid); Util.DebugWriteLine(resultLog); } //need to work on validation. apparently there are some weird caveats to glValidate which make it complicated and possibly excuses (barely) the intel drivers' dysfunctional operation //"A sampler points to a texture unit used by fixed function with an incompatible target" // //info: //http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml //This function mimics the validation operation that OpenGL implementations must perform when rendering commands are issued while programmable shaders are part of current state. //glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state //This function is typically useful only during application development. // //So, this is no big deal. we shouldn't be calling validate right now anyway. //conclusion: glValidate is very complicated and is of virtually no use unless your draw calls are returning errors and you want to know why //GL.ValidateProgram(pid); //errcode = GL.GetError(); //resultLog = GL.GetProgramInfoLog(pid); //if (errcode != ErrorCode.NoError) // throw new InvalidOperationException($"Error creating pipeline (error returned from glValidateProgram): {errcode}\r\n\r\n{resultLog}"); //int validateStatus; //GL.GetProgram(pid, GetProgramParameterName.ValidateStatus, out validateStatus); //if (validateStatus == 0) // throw new InvalidOperationException($"Error creating pipeline (validateStatus status false returned from glValidateProgram): \r\n\r\n{resultLog}"); //set the program to active, in case we need to set sampler uniforms on it GL.UseProgram(pid); //get all the attributes (not needed) List <AttributeInfo> attributes = new List <AttributeInfo>(); GL.GetProgram(pid, GetProgramParameterName.ActiveAttributes, out var nAttributes); for (int i = 0; i < nAttributes; i++) { int size, length; string name = new System.Text.StringBuilder(1024).ToString(); ActiveAttribType type; GL.GetActiveAttrib(pid, i, 1024, out length, out size, out type, out name); attributes.Add(new AttributeInfo() { Handle = new IntPtr(i), Name = name }); } //get all the uniforms List <UniformInfo> uniforms = new List <UniformInfo>(); GL.GetProgram(pid, GetProgramParameterName.ActiveUniforms, out var nUniforms); List <int> samplers = new List <int>(); for (int i = 0; i < nUniforms; i++) { int size, length; string name = new System.Text.StringBuilder(1024).ToString(); GL.GetActiveUniform(pid, i, 1024, out length, out size, out var type, out name); errcode = GL.GetError(); int loc = GL.GetUniformLocation(pid, name); var ui = new UniformInfo { Name = name, Opaque = loc }; if (type == ActiveUniformType.Sampler2D) { ui.IsSampler = true; ui.SamplerIndex = samplers.Count; ui.Opaque = loc | (samplers.Count << 24); samplers.Add(loc); } uniforms.Add(ui); } // deactivate the program, so we don't accidentally use it GL.UseProgram(0); if (!vertexShader.Available) { success = false; } if (!fragmentShader.Available) { success = false; } var pw = new PipelineWrapper { pid = pid, VertexShader = vertexShader, FragmentShader = fragmentShader, SamplerLocs = samplers }; return(new Pipeline(this, pw, success, vertexLayout, uniforms, memo)); }
public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required, string memo) { //if the shaders arent available, the pipeline isn't either if (!vertexShader.Available || !fragmentShader.Available) { string errors = string.Format("Vertex Shader:\r\n {0} \r\n-------\r\nFragment Shader:\r\n{1}", vertexShader.Errors, fragmentShader.Errors); if (required) { throw new InvalidOperationException("Couldn't build required GL pipeline:\r\n" + errors); } var pipeline = new Pipeline(this, null, false, null, null, null); pipeline.Errors = errors; return(pipeline); } bool success = true; var vsw = vertexShader.Opaque as ShaderWrapper; var fsw = fragmentShader.Opaque as ShaderWrapper; var sws = new[] { vsw, fsw }; bool mapVariables = vsw.MapCodeToNative != null || fsw.MapCodeToNative != null; ErrorCode errcode; int pid = GL.CreateProgram(); GL.AttachShader(pid, vsw.sid); errcode = GL.GetError(); GL.AttachShader(pid, fsw.sid); errcode = GL.GetError(); //NOT BEING USED NOW: USING SEMANTICS INSTEAD ////bind the attribute locations from the vertex layout ////as we go, look for attribute mappings (CGC will happily reorder and rename our attribute mappings) ////what's more it will _RESIZE_ them but this seems benign..somehow.. ////WELLLLLLL we wish we could do that by names ////but the shaders dont seem to be adequate quality (oddly named attributes.. texCoord vs texCoord1). need to use semantics instead. //foreach (var kvp in vertexLayout.Items) //{ // string name = kvp.Value.Name; // //if (mapVariables) // //{ // // foreach (var sw in sws) // // { // // if (sw.MapNativeToCode.ContainsKey(name)) // // { // // name = sw.MapNativeToCode[name]; // // break; // // } // // } // //} // if(mapVariables) { // ////proxy for came-from-cgc // //switch (kvp.Value.Usage) // //{ // // case AttributeUsage.Position: // //} // } // //GL.BindAttribLocation(pid, kvp.Key, name); //} GL.LinkProgram(pid); errcode = GL.GetError(); string resultLog = GL.GetProgramInfoLog(pid); if (errcode != ErrorCode.NoError) { if (required) { throw new InvalidOperationException("Error creating pipeline (error returned from glLinkProgram): " + errcode + "\r\n\r\n" + resultLog); } else { success = false; } } int linkStatus; GL.GetProgram(pid, GetProgramParameterName.LinkStatus, out linkStatus); if (linkStatus == 0) { if (required) { throw new InvalidOperationException("Error creating pipeline (link status false returned from glLinkProgram): " + "\r\n\r\n" + resultLog); } else { success = false; } } //need to work on validation. apparently there are some weird caveats to glValidate which make it complicated and possibly excuses (barely) the intel drivers' dysfunctional operation //"A sampler points to a texture unit used by fixed function with an incompatible target" // //info: //http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml //This function mimics the validation operation that OpenGL implementations must perform when rendering commands are issued while programmable shaders are part of current state. //glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state //This function is typically useful only during application development. // //So, this is no big deal. we shouldnt be calling validate right now anyway. //conclusion: glValidate is very complicated and is of virtually no use unless your draw calls are returning errors and you want to know why //GL.ValidateProgram(pid); //errcode = GL.GetError(); //resultLog = GL.GetProgramInfoLog(pid); //if (errcode != ErrorCode.NoError) // throw new InvalidOperationException("Error creating pipeline (error returned from glValidateProgram): " + errcode + "\r\n\r\n" + resultLog); //int validateStatus; //GL.GetProgram(pid, GetProgramParameterName.ValidateStatus, out validateStatus); //if (validateStatus == 0) // throw new InvalidOperationException("Error creating pipeline (validateStatus status false returned from glValidateProgram): " + "\r\n\r\n" + resultLog); //set the program to active, in case we need to set sampler uniforms on it GL.UseProgram(pid); //get all the attributes (not needed) List <AttributeInfo> attributes = new List <AttributeInfo>(); int nAttributes; GL.GetProgram(pid, GetProgramParameterName.ActiveAttributes, out nAttributes); for (int i = 0; i < nAttributes; i++) { int size, length; string name = new System.Text.StringBuilder(1024).ToString(); ActiveAttribType type; GL.GetActiveAttrib(pid, i, 1024, out length, out size, out type, out name); attributes.Add(new AttributeInfo() { Handle = new IntPtr(i), Name = name }); } //get all the uniforms List <UniformInfo> uniforms = new List <UniformInfo>(); int nUniforms; GL.GetProgram(pid, GetProgramParameterName.ActiveUniforms, out nUniforms); List <int> samplers = new List <int>(); for (int i = 0; i < nUniforms; i++) { int size, length; ActiveUniformType type; string name = new System.Text.StringBuilder(1024).ToString().ToString(); GL.GetActiveUniform(pid, i, 1024, out length, out size, out type, out name); errcode = GL.GetError(); int loc = GL.GetUniformLocation(pid, name); //translate name if appropriate //not sure how effective this approach will be, due to confusion of vertex and fragment uniforms if (mapVariables) { if (vsw.MapCodeToNative.ContainsKey(name)) { name = vsw.MapCodeToNative[name]; } if (fsw.MapCodeToNative.ContainsKey(name)) { name = fsw.MapCodeToNative[name]; } } var ui = new UniformInfo(); ui.Name = name; ui.Opaque = loc; if (type == ActiveUniformType.Sampler2D) { ui.IsSampler = true; ui.SamplerIndex = samplers.Count; ui.Opaque = loc | (samplers.Count << 24); samplers.Add(loc); } uniforms.Add(ui); } //deactivate the program, so we dont accidentally use it GL.UseProgram(0); if (!vertexShader.Available) { success = false; } if (!fragmentShader.Available) { success = false; } var pw = new PipelineWrapper() { pid = pid, VertexShader = vertexShader, FragmentShader = fragmentShader, SamplerLocs = samplers }; return(new Pipeline(this, pw, success, vertexLayout, uniforms, memo)); }
public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required, string memo) { if (!vertexShader.Available || !fragmentShader.Available) { string errors = string.Format("Vertex Shader:\r\n {0} \r\n-------\r\nFragment Shader:\r\n{1}", vertexShader.Errors, fragmentShader.Errors); if (required) { throw new InvalidOperationException("Couldn't build required GL pipeline:\r\n" + errors); } var pipeline = new Pipeline(this, null, false, null, null, null); pipeline.Errors = errors; return(pipeline); } VertexElement[] ves = new VertexElement[vertexLayout.Items.Count]; int stride = 0; foreach (var kvp in vertexLayout.Items) { var item = kvp.Value; d3d9.DeclarationType decltype = DeclarationType.Float1; switch (item.AttribType) { case gl.VertexAttribPointerType.Float: if (item.Components == 1) { decltype = DeclarationType.Float1; } else if (item.Components == 2) { decltype = DeclarationType.Float2; } else if (item.Components == 3) { decltype = DeclarationType.Float3; } else if (item.Components == 4) { decltype = DeclarationType.Float4; } else { throw new NotSupportedException(); } stride += 4 * item.Components; break; default: throw new NotSupportedException(); } d3d9.DeclarationUsage usage = DeclarationUsage.Position; byte usageIndex = 0; switch (item.Usage) { case AttributeUsage.Position: usage = DeclarationUsage.Position; break; case AttributeUsage.Texcoord0: usage = DeclarationUsage.TextureCoordinate; break; case AttributeUsage.Texcoord1: usage = DeclarationUsage.TextureCoordinate; usageIndex = 1; break; case AttributeUsage.Color0: usage = DeclarationUsage.Color; break; default: throw new NotSupportedException(); } ves[kvp.Key] = new VertexElement(0, (short)item.Offset, decltype, DeclarationMethod.Default, usage, usageIndex); } var pw = new PipelineWrapper() { VertexDeclaration = new VertexDeclaration(dev, ves), VertexShader = vertexShader.Opaque as ShaderWrapper, FragmentShader = fragmentShader.Opaque as ShaderWrapper, VertexStride = stride, }; //scan uniforms from constant tables //handles must be disposed later (with the pipeline probably) var uniforms = new List <UniformInfo>(); var fs = pw.FragmentShader; var vs = pw.VertexShader; var fsct = fs.bytecode.ConstantTable; var vsct = vs.bytecode.ConstantTable; foreach (var ct in new[] { fsct, vsct }) { Queue <Tuple <string, EffectHandle> > todo = new Queue <Tuple <string, EffectHandle> >(); int n = ct.Description.Constants; for (int i = 0; i < n; i++) { var handle = ct.GetConstant(null, i); todo.Enqueue(Tuple.Create("", handle)); } while (todo.Count != 0) { var tuple = todo.Dequeue(); var prefix = tuple.Item1; var handle = tuple.Item2; var descr = ct.GetConstantDescription(handle); //Console.WriteLine("D3D UNIFORM: " + descr.Name); if (descr.StructMembers != 0) { string newprefix = prefix + descr.Name + "."; for (int j = 0; j < descr.StructMembers; j++) { var subhandle = ct.GetConstant(handle, j); todo.Enqueue(Tuple.Create(newprefix, subhandle)); } continue; } UniformInfo ui = new UniformInfo(); UniformWrapper uw = new UniformWrapper(); ui.Opaque = uw; string name = prefix + descr.Name; //mehhh not happy about this stuff if (fs.MapCodeToNative != null || vs.MapCodeToNative != null) { string key = name.TrimStart('$'); if (descr.Rows != 1) { key = key + "[0]"; } if (fs.MapCodeToNative != null && ct == fsct) { if (fs.MapCodeToNative.ContainsKey(key)) { name = fs.MapCodeToNative[key]; } } if (vs.MapCodeToNative != null && ct == vsct) { if (vs.MapCodeToNative.ContainsKey(key)) { name = vs.MapCodeToNative[key]; } } } ui.Name = name; uw.Description = descr; uw.EffectHandle = handle; uw.FS = (ct == fsct); uw.CT = ct; if (descr.Type == ParameterType.Sampler2D) { ui.IsSampler = true; ui.SamplerIndex = descr.RegisterIndex; uw.SamplerIndex = descr.RegisterIndex; } uniforms.Add(ui); } } pw.fsct = fsct; pw.vsct = vsct; return(new Pipeline(this, pw, true, vertexLayout, uniforms, memo)); }
public void Link() { GL.LinkProgram(ProgramID); Console.WriteLine(GL.GetProgramInfoLog(ProgramID)); GL.GetProgram(ProgramID, ProgramParameter.ActiveAttributes, out AttributeCount); GL.GetProgram(ProgramID, ProgramParameter.ActiveUniforms, out UniformCount); for (int i = 0; i < AttributeCount; i++) { AttributeInfo info = new AttributeInfo(); int length = 0; StringBuilder name = new StringBuilder(); GL.GetActiveAttrib(ProgramID, i, 256, out length, out info.size, out info.type, name); info.name = name.ToString(); info.address = GL.GetAttribLocation(ProgramID, info.name); Attributes.Add(name.ToString(), info); } for (int i = 0; i < UniformCount; i++) { UniformInfo info = new UniformInfo(); int length = 0; StringBuilder name = new StringBuilder(); GL.GetActiveUniform(ProgramID, i, 256, out length, out info.size, out info.type, name); info.name = name.ToString(); Uniforms.Add(name.ToString(), info); info.address = GL.GetUniformLocation(ProgramID, info.name); } }
internal ConversionResult(string glslCode, UniformInfo[] uniforms) { GlslCode = glslCode; Uniforms = uniforms; }
public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required) { bool success = true; ErrorCode errcode; int pid = GL.CreateProgram(); GL.AttachShader(pid, vertexShader.Id.ToInt32()); errcode = GL.GetError(); GL.AttachShader(pid, fragmentShader.Id.ToInt32()); errcode = GL.GetError(); //bind the attribute locations from the vertex layout foreach (var kvp in vertexLayout.Items) { GL.BindAttribLocation(pid, kvp.Key, kvp.Value.Name); } GL.LinkProgram(pid); errcode = GL.GetError(); string resultLog = GL.GetProgramInfoLog(pid); if (errcode != ErrorCode.NoError) { if (required) { throw new InvalidOperationException("Error creating pipeline (error returned from glLinkProgram): " + errcode + "\r\n\r\n" + resultLog); } else { success = false; } } int linkStatus; GL.GetProgram(pid, GetProgramParameterName.LinkStatus, out linkStatus); if (linkStatus == 0) { if (required) { throw new InvalidOperationException("Error creating pipeline (link status false returned from glLinkProgram): " + "\r\n\r\n" + resultLog); } else { success = false; } } //need to work on validation. apparently there are some weird caveats to glValidate which make it complicated and possibly excuses (barely) the intel drivers' dysfunctional operation //"A sampler points to a texture unit used by fixed function with an incompatible target" // //info: //http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml //This function mimics the validation operation that OpenGL implementations must perform when rendering commands are issued while programmable shaders are part of current state. //glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state //This function is typically useful only during application development. // //So, this is no big deal. we shouldnt be calling validate right now anyway. //conclusion: glValidate is very complicated and is of virtually no use unless your draw calls are returning errors and you want to know why //GL.ValidateProgram(pid); //errcode = GL.GetError(); //resultLog = GL.GetProgramInfoLog(pid); //if (errcode != ErrorCode.NoError) // throw new InvalidOperationException("Error creating pipeline (error returned from glValidateProgram): " + errcode + "\r\n\r\n" + resultLog); //int validateStatus; //GL.GetProgram(pid, GetProgramParameterName.ValidateStatus, out validateStatus); //if (validateStatus == 0) // throw new InvalidOperationException("Error creating pipeline (validateStatus status false returned from glValidateProgram): " + "\r\n\r\n" + resultLog); //set the program to active, in case we need to set sampler uniforms on it GL.UseProgram(pid); ////get all the attributes (not needed) //List<AttributeInfo> attributes = new List<AttributeInfo>(); //int nAttributes; //GL.GetProgram(pid, GetProgramParameterName.ActiveAttributes, out nAttributes); //for (int i = 0; i < nAttributes; i++) //{ // int size, length; // var sbName = new System.Text.StringBuilder(); // ActiveAttribType type; // GL.GetActiveAttrib(pid, i, 1024, out length, out size, out type, sbName); // attributes.Add(new AttributeInfo() { Handle = new IntPtr(i), Name = sbName.ToString() }); //} //get all the uniforms List <UniformInfo> uniforms = new List <UniformInfo>(); int nUniforms; int nSamplers = 0; GL.GetProgram(pid, GetProgramParameterName.ActiveUniforms, out nUniforms); for (int i = 0; i < nUniforms; i++) { int size, length; ActiveUniformType type; var sbName = new System.Text.StringBuilder(); GL.GetActiveUniform(pid, i, 1024, out length, out size, out type, sbName); errcode = GL.GetError(); string name = sbName.ToString(); int loc = GL.GetUniformLocation(pid, name); var ui = new UniformInfo(); ui.Name = name; ui.Handle = new IntPtr(loc); //automatically assign sampler uniforms to texture units (and bind them) bool isSampler = (type == ActiveUniformType.Sampler2D); if (isSampler) { ui.SamplerIndex = nSamplers; GL.Uniform1(loc, nSamplers); nSamplers++; } uniforms.Add(ui); } //deactivate the program, so we dont accidentally use it GL.UseProgram(0); if (!vertexShader.Available) { success = false; } if (!fragmentShader.Available) { success = false; } return(new Pipeline(this, new IntPtr(pid), success, vertexLayout, uniforms)); }
public static UniformInfo[] Hlsl2Glsl_GetUniformInfo(IntPtr handle) { var numUniforms = Hlsl2Glsl_GetUniformCount(handle); var uniformInfosPtr = Hlsl2Glsl_GetUniformInfo_Impl(handle); var structSize = Marshal.SizeOf(typeof(UniformInfo)); var result = new UniformInfo[numUniforms]; for (int i = 0; i < numUniforms; ++i) { var data = IntPtr.Add(uniformInfosPtr, structSize * i); result[i] = (UniformInfo) Marshal.PtrToStructure(data, typeof (UniformInfo)); } return result; }