private bool CompleteParamSource(String paramName, GpuProgramParameters.GpuConstantDefinitionMap vertexConstantDefs, GpuProgramParameters.GpuConstantDefinitionMap geometryConstantDefs, GpuProgramParameters.GpuConstantDefinitionMap fragmentConstantDefs, GLSLLinkProgram.UniformReference refToUpdate) { GpuProgramParameters.GpuConstantDefinition parami; if (vertexConstantDefs != null) { if (vertexConstantDefs.TryGetValue(paramName, out parami)) { refToUpdate.SourceProgType = GpuProgramType.Vertex; refToUpdate.ConstantDef = parami; return(true); } } if (geometryConstantDefs != null) { if (geometryConstantDefs.TryGetValue(paramName, out parami)) { refToUpdate.SourceProgType = GpuProgramType.Geometry; refToUpdate.ConstantDef = parami; return(true); } } if (fragmentConstantDefs != null) { if (fragmentConstantDefs.TryGetValue(paramName, out parami)) { refToUpdate.SourceProgType = GpuProgramType.Fragment; refToUpdate.ConstantDef = parami; return(true); } } return(false); }
///<summary> /// Populate a list of uniforms based on a program object. ///</summary> ///<param name="programObject">Handle to the program object to query</param> ///<param name="vertexConstantDefs">Definition of the constants extracted from the /// vertex program, used to match up physical buffer indexes with program /// uniforms. May be null if there is no vertex program.</param> ///<param name="geometryConstantDefs">Definition of the constants extracted from the /// geometry program, used to match up physical buffer indexes with program /// uniforms. May be null if there is no geometry program.</param> ///<param name="fragmentConstantDefs">Definition of the constants extracted from the /// fragment program, used to match up physical buffer indexes with program /// uniforms. May be null if there is no fragment program.</param> ///<param name="list">The list to populate (will not be cleared before adding, clear /// it yourself before calling this if that's what you want).</param> public void ExtractUniforms(int programObject, GpuProgramParameters.GpuConstantDefinitionMap vertexConstantDefs, GpuProgramParameters.GpuConstantDefinitionMap geometryConstantDefs, GpuProgramParameters.GpuConstantDefinitionMap fragmentConstantDefs, GLSLLinkProgram.UniformReferenceList list) { // scan through the active uniforms and add them to the reference list // get the number of active uniforms int uniformCount; const int BUFFERSIZE = 200; Gl.glGetObjectParameterivARB(programObject, Gl.GL_OBJECT_ACTIVE_UNIFORMS_ARB, out uniformCount); // Loop over each of the active uniforms, and add them to the reference container // only do this for user defined uniforms, ignore built in gl state uniforms for (var index = 0; index < uniformCount; index++) { // important for Axiom: dont pull this var to the outer scope // because UniformReference is by value (class) // if we'd share the instance we would push the same instance // to the result list each iteration var newGLUniformReference = new GLSLLinkProgram.UniformReference(); var uniformName = new StringBuilder(); int arraySize; int glType; Gl.glGetActiveUniformARB(programObject, index, BUFFERSIZE, null, out arraySize, out glType, uniformName); newGLUniformReference.Location = Gl.glGetUniformLocationARB(programObject, uniformName.ToString()); if (newGLUniformReference.Location >= 0) { // user defined uniform found, add it to the reference list var paramName = uniformName.ToString(); // currant ATI drivers (Catalyst 7.2 and earlier) and older NVidia drivers will include all array elements as uniforms but we only want the root array name and location // Also note that ATI Catalyst 6.8 to 7.2 there is a bug with glUniform that does not allow you to update a uniform array past the first uniform array element // ie you can't start updating an array starting at element 1, must always be element 0. // if the uniform name has a "[" in it then its an array element uniform. var arrayStart = paramName.IndexOf('['); if (arrayStart != -1) { // if not the first array element then skip it and continue to the next uniform if (paramName.Substring(arrayStart, paramName.Length - 1) != "[0]") { continue; } paramName = paramName.Substring(0, arrayStart); } // find out which params object this comes from var foundSource = CompleteParamSource(paramName, vertexConstantDefs, geometryConstantDefs, fragmentConstantDefs, newGLUniformReference); // only add this parameter if we found the source if (foundSource) { Debug.Assert(arraySize == newGLUniformReference.ConstantDef.ArraySize, "GL doesn't agree with our array size!"); list.Add(newGLUniformReference); } // Don't bother adding individual array params, they will be // picked up in the 'parent' parameter can copied all at once // anyway, individual indexes are only needed for lookup from // user params } // end if } // end for }
///<summary> /// Populate a list of uniforms based on a program object. ///</summary> ///<param name="programObject">Handle to the program object to query</param> ///<param name="vertexConstantDefs">Definition of the constants extracted from the /// vertex program, used to match up physical buffer indexes with program /// uniforms. May be null if there is no vertex program.</param> ///<param name="geometryConstantDefs">Definition of the constants extracted from the /// geometry program, used to match up physical buffer indexes with program /// uniforms. May be null if there is no geometry program.</param> ///<param name="fragmentConstantDefs">Definition of the constants extracted from the /// fragment program, used to match up physical buffer indexes with program /// uniforms. May be null if there is no fragment program.</param> ///<param name="list">The list to populate (will not be cleared before adding, clear /// it yourself before calling this if that's what you want).</param> public void ExtractUniforms(int programObject, GpuProgramParameters.GpuConstantDefinitionMap vertexConstantDefs, GpuProgramParameters.GpuConstantDefinitionMap geometryConstantDefs, GpuProgramParameters.GpuConstantDefinitionMap fragmentConstantDefs, GLSLLinkProgram.UniformReferenceList list) { // scan through the active uniforms and add them to the reference list // get the number of active uniforms int uniformCount; const int BUFFERSIZE = 200; Gl.glGetObjectParameterivARB(programObject, Gl.GL_OBJECT_ACTIVE_UNIFORMS_ARB, out uniformCount); // Loop over each of the active uniforms, and add them to the reference container // only do this for user defined uniforms, ignore built in gl state uniforms for (var index = 0; index < uniformCount; index++) { // important for Axiom: dont pull this var to the outer scope // because UniformReference is by value (class) // if we'd share the instance we would push the same instance // to the result list each iteration var newGLUniformReference = new GLSLLinkProgram.UniformReference(); var uniformName = new StringBuilder(); int arraySize; int glType; Gl.glGetActiveUniformARB(programObject, index, BUFFERSIZE, null, out arraySize, out glType, uniformName); newGLUniformReference.Location = Gl.glGetUniformLocationARB(programObject, uniformName.ToString()); if (newGLUniformReference.Location >= 0) { // user defined uniform found, add it to the reference list var paramName = uniformName.ToString(); // currant ATI drivers (Catalyst 7.2 and earlier) and older NVidia drivers will include all array elements as uniforms but we only want the root array name and location // Also note that ATI Catalyst 6.8 to 7.2 there is a bug with glUniform that does not allow you to update a uniform array past the first uniform array element // ie you can't start updating an array starting at element 1, must always be element 0. // if the uniform name has a "[" in it then its an array element uniform. var arrayStart = paramName.IndexOf( '[' ); if (arrayStart != -1) { // if not the first array element then skip it and continue to the next uniform if (paramName.Substring(arrayStart, paramName.Length - 1) != "[0]") continue; paramName = paramName.Substring(0, arrayStart); } // find out which params object this comes from var foundSource = CompleteParamSource( paramName, vertexConstantDefs, geometryConstantDefs, fragmentConstantDefs, newGLUniformReference ); // only add this parameter if we found the source if (foundSource) { Debug.Assert( arraySize == newGLUniformReference.ConstantDef.ArraySize, "GL doesn't agree with our array size!" ); list.Add(newGLUniformReference); } // Don't bother adding individual array params, they will be // picked up in the 'parent' parameter can copied all at once // anyway, individual indexes are only needed for lookup from // user params } // end if } // end for }