private void CompleteDefInfo(int gltype, GpuProgramParameters.GpuConstantDefinition defToUpdate) { // decode uniform size and type // Note GLSL never packs rows into float4's(from an API perspective anyway) // therefore all values are tight in the buffer switch (gltype) { case Gl.GL_FLOAT: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Float1; break; case Gl.GL_FLOAT_VEC2: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Float2; break; case Gl.GL_FLOAT_VEC3: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Float3; break; case Gl.GL_FLOAT_VEC4: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Float4; break; case Gl.GL_SAMPLER_1D: // need to record samplers for GLSL defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Sampler1D; break; case Gl.GL_SAMPLER_2D: case Gl.GL_SAMPLER_2D_RECT_ARB: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Sampler2D; break; case Gl.GL_SAMPLER_3D: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Sampler3D; break; case Gl.GL_SAMPLER_CUBE: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.SamplerCube; break; case Gl.GL_SAMPLER_1D_SHADOW: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Sampler1DShadow; break; case Gl.GL_SAMPLER_2D_SHADOW: case Gl.GL_SAMPLER_2D_RECT_SHADOW_ARB: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Sampler2DShadow; break; case Gl.GL_INT: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Int1; break; case Gl.GL_INT_VEC2: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Int2; break; case Gl.GL_INT_VEC3: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Int3; break; case Gl.GL_INT_VEC4: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Int4; break; case Gl.GL_FLOAT_MAT2: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_2X2; break; case Gl.GL_FLOAT_MAT3: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_3X3; break; case Gl.GL_FLOAT_MAT4: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_4X4; break; case Gl.GL_FLOAT_MAT2x3: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_2X3; break; case Gl.GL_FLOAT_MAT3x2: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_3X2; break; case Gl.GL_FLOAT_MAT2x4: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_2X4; break; case Gl.GL_FLOAT_MAT4x2: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_4X2; break; case Gl.GL_FLOAT_MAT3x4: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_3X4; break; case Gl.GL_FLOAT_MAT4x3: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_4X3; break; default: defToUpdate.ConstantType = GpuProgramParameters.GpuConstantType.Unknown; break; } // GL doesn't pad defToUpdate.ElementSize = GpuProgramParameters.GpuConstantDefinition.GetElementSize(defToUpdate.ConstantType, false); }
///<summary> /// Populate a list of uniforms based on GLSL source. ///</summary> ///<param name="src">Reference to the source code</param> ///<param name="defs">The defs to populate (will not be cleared before adding, clear /// it yourself before calling this if that's what you want).</param> ///<param name="filename">The file name this came from, for logging errors.</param> public void ExtractConstantDefs(String src, GpuProgramParameters.GpuNamedConstants defs, String filename) { // Parse the output string and collect all uniforms // NOTE this relies on the source already having been preprocessed // which is done in GLSLProgram::loadFromSource string line; var currPos = src.IndexOf("uniform"); while (currPos != -1) { var def = new GpuProgramParameters.GpuConstantDefinition(); var paramName = ""; // Now check for using the word 'uniform' in a larger string & ignore bool inLargerString = false; if (currPos != 0) { var prev = src[currPos - 1]; if (prev != ' ' && prev != '\t' && prev != '\r' && prev != '\n' && prev != ';') { inLargerString = true; } } if (!inLargerString && currPos + 7 < src.Length) { var next = src[currPos + 7]; if (next != ' ' && next != '\t' && next != '\r' && next != '\n') { inLargerString = true; } } // skip 'uniform' currPos += 7; if (!inLargerString) { // find terminating semicolon var endPos = src.IndexOf(';', currPos); if (endPos == -1) { // problem, missing semicolon, abort break; } line = src.Substring(currPos, endPos - currPos); // Remove spaces before opening square braces, otherwise // the following split() can split the line at inappropriate // places (e.g. "vec3 something [3]" won't work). for (var sqp = line.IndexOf(" ["); sqp != -1; sqp = line.IndexOf(" [")) { line.Remove(sqp, 1); } // Split into tokens var parts = line.Split(", \t\r\n".ToCharArray()); foreach (var _i in parts) { var i = _i; int typei; if (this.typeEnumMap.TryGetValue(i, out typei)) { CompleteDefInfo(typei, def); } else { // if this is not a type, and not empty, it should be a name i = i.Trim(); if (i == string.Empty) { continue; } var arrayStart = i.IndexOf('['); if (arrayStart != -1) { // potential name (if butted up to array) var name = i.Substring(0, arrayStart); name = name.Trim(); if (name != string.Empty) { paramName = name; } var arrayEnd = i.IndexOf(']', arrayStart); var arrayDimTerm = i.Substring(arrayStart + 1, arrayEnd - arrayStart - 1); arrayDimTerm = arrayDimTerm.Trim(); // the array term might be a simple number or it might be // an expression (e.g. 24*3) or refer to a constant expression // we'd have to evaluate the expression which could get nasty // TODO def.ArraySize = int.Parse(arrayDimTerm); } else { paramName = i; def.ArraySize = 1; } // Name should be after the type, so complete def and add // We do this now so that comma-separated params will do // this part once for each name mentioned if (def.ConstantType == GpuProgramParameters.GpuConstantType.Unknown) { LogManager.Instance.Write("Problem parsing the following GLSL Uniform: '" + line + "' in file " + filename); // next uniform break; } // Complete def and add // increment physical buffer location def.LogicalIndex = 0; // not valid in GLSL if (def.IsFloat) { def.PhysicalIndex = defs.FloatBufferSize; defs.FloatBufferSize += def.ArraySize * def.ElementSize; } else { def.PhysicalIndex = defs.IntBufferSize; defs.IntBufferSize += def.ArraySize * def.ElementSize; } defs.Map.Add(paramName, def); #warning this aint working properly yet (fix this as soon we need array support for GLSL!) //defs.GenerateConstantDefinitionArrayEntries(paramName, def); } } } // Find next one currPos = src.IndexOf("uniform", currPos); } }
protected void PopulateDef(D3D9.ConstantDescription d3DDesc, GpuProgramParameters.GpuConstantDefinition def) { def.ArraySize = d3DDesc.Elements; switch (d3DDesc.Type) { case D3D9.ParameterType.Int: switch (d3DDesc.Columns) { case 1: def.ConstantType = GpuProgramParameters.GpuConstantType.Int1; break; case 2: def.ConstantType = GpuProgramParameters.GpuConstantType.Int2; break; case 3: def.ConstantType = GpuProgramParameters.GpuConstantType.Int3; break; case 4: def.ConstantType = GpuProgramParameters.GpuConstantType.Int4; break; } // columns break; case D3D9.ParameterType.Float: switch (d3DDesc.Class) { case D3D9.ParameterClass.MatrixColumns: case D3D9.ParameterClass.MatrixRows: { var firstDim = d3DDesc.RegisterCount / d3DDesc.Elements; var secondDim = d3DDesc.Class == D3D9.ParameterClass.MatrixRows ? d3DDesc.Columns : d3DDesc.Rows; switch (firstDim) { case 2: switch (secondDim) { case 2: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_2X2; def.ElementSize = 8; // HLSL always packs break; case 3: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_2X3; def.ElementSize = 8; // HLSL always packs break; case 4: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_2X4; def.ElementSize = 8; break; } // columns break; case 3: switch (secondDim) { case 2: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_3X2; def.ElementSize = 12; // HLSL always packs break; case 3: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_3X3; def.ElementSize = 12; // HLSL always packs break; case 4: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_3X4; def.ElementSize = 12; break; } // columns break; case 4: switch (secondDim) { case 2: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_4X2; def.ElementSize = 16; // HLSL always packs break; case 3: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_4X3; def.ElementSize = 16; // HLSL always packs break; case 4: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_4X4; def.ElementSize = 16; break; } // secondDim break; } // firstDim } break; case D3D9.ParameterClass.Scalar: case D3D9.ParameterClass.Vector: switch (d3DDesc.Columns) { case 1: def.ConstantType = GpuProgramParameters.GpuConstantType.Float1; break; case 2: def.ConstantType = GpuProgramParameters.GpuConstantType.Float2; break; case 3: def.ConstantType = GpuProgramParameters.GpuConstantType.Float3; break; case 4: def.ConstantType = GpuProgramParameters.GpuConstantType.Float4; break; } // columns break; } break; default: // not mapping samplers, don't need to take the space break; } ; // D3D9 pads to 4 elements def.ElementSize = GpuProgramParameters.GpuConstantDefinition.GetElementSize(def.ConstantType, true); }
protected void ProcessParamElement(D3D9.EffectHandle parent, string prefix, int index) { var constant = this.constTable.GetConstant(parent, index); // Since D3D HLSL doesn't deal with naming of array and struct parameters // automatically, we have to do it by hand var desc = this.constTable.GetConstantDescription(constant); var paramName = desc.Name; // trim the odd '$' which appears at the start of the names in HLSL if (paramName.StartsWith("$")) { paramName = paramName.Remove(0, 1); } // Also trim the '[0]' suffix if it exists, we will add our own indexing later if (paramName.EndsWith("[0]")) { paramName.Remove(paramName.Length - 3); } if (desc.Class == D3D9.ParameterClass.Struct) { // work out a new prefix for the nextest members if its an array, we need the index prefix += paramName + "."; // Cascade into struct for (var i = 0; i < desc.StructMembers; ++i) { ProcessParamElement(constant, prefix, i); } } else { // process params if (desc.Type == D3D9.ParameterType.Float || desc.Type == D3D9.ParameterType.Int || desc.Type == D3D9.ParameterType.Bool) { var paramIndex = desc.RegisterIndex; var name = prefix + paramName; var def = new GpuProgramParameters.GpuConstantDefinition(); def.LogicalIndex = paramIndex; // populate type, array size & element size PopulateDef(desc, def); if (def.IsFloat) { def.PhysicalIndex = floatLogicalToPhysical.BufferSize; lock (floatLogicalToPhysical.Mutex) { floatLogicalToPhysical.Map.Add(paramIndex, new GpuProgramParameters.GpuLogicalIndexUse(def.PhysicalIndex, def.ArraySize * def.ElementSize, GpuProgramParameters. GpuParamVariability.Global)); floatLogicalToPhysical.BufferSize += def.ArraySize * def.ElementSize; constantDefs.FloatBufferSize = floatLogicalToPhysical.BufferSize; } } else { def.PhysicalIndex = intLogicalToPhysical.BufferSize; lock (intLogicalToPhysical.Mutex) { intLogicalToPhysical.Map.Add(paramIndex, new GpuProgramParameters.GpuLogicalIndexUse(def.PhysicalIndex, def.ArraySize * def.ElementSize, GpuProgramParameters. GpuParamVariability.Global)); intLogicalToPhysical.BufferSize += def.ArraySize * def.ElementSize; constantDefs.IntBufferSize = intLogicalToPhysical.BufferSize; } } constantDefs.Map.Add(paramName.ToLower(), def); // Now deal with arrays constantDefs.GenerateConstantDefinitionArrayEntries(name, def); } } }
private void MapTypeAndElementSize(int cgType, bool isRegisterCombiner, GpuProgramParameters.GpuConstantDefinition def) { if (isRegisterCombiner) { // register combiners are the only single-float entries in our buffer def.ConstantType = GpuProgramParameters.GpuConstantType.Float1; def.ElementSize = 1; } else { switch (cgType) { case Cg.CG_FLOAT: case Cg.CG_FLOAT1: case Cg.CG_HALF: case Cg.CG_HALF1: def.ConstantType = GpuProgramParameters.GpuConstantType.Float1; break; case Cg.CG_FLOAT2: case Cg.CG_HALF2: def.ConstantType = GpuProgramParameters.GpuConstantType.Float2; break; case Cg.CG_FLOAT3: case Cg.CG_HALF3: def.ConstantType = GpuProgramParameters.GpuConstantType.Float3; break; case Cg.CG_FLOAT4: case Cg.CG_HALF4: def.ConstantType = GpuProgramParameters.GpuConstantType.Float4; break; case Cg.CG_FLOAT2x2: case Cg.CG_HALF2x2: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_2X2; break; case Cg.CG_FLOAT2x3: case Cg.CG_HALF2x3: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_2X3; break; case Cg.CG_FLOAT2x4: case Cg.CG_HALF2x4: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_2X4; break; case Cg.CG_FLOAT3x2: case Cg.CG_HALF3x2: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_3X2; break; case Cg.CG_FLOAT3x3: case Cg.CG_HALF3x3: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_3X3; break; case Cg.CG_FLOAT3x4: case Cg.CG_HALF3x4: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_3X4; break; case Cg.CG_FLOAT4x2: case Cg.CG_HALF4x2: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_4X2; break; case Cg.CG_FLOAT4x3: case Cg.CG_HALF4x3: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_4X3; break; case Cg.CG_FLOAT4x4: case Cg.CG_HALF4x4: def.ConstantType = GpuProgramParameters.GpuConstantType.Matrix_4X4; break; case Cg.CG_INT: case Cg.CG_INT1: def.ConstantType = GpuProgramParameters.GpuConstantType.Int1; break; case Cg.CG_INT2: def.ConstantType = GpuProgramParameters.GpuConstantType.Int2; break; case Cg.CG_INT3: def.ConstantType = GpuProgramParameters.GpuConstantType.Int3; break; case Cg.CG_INT4: def.ConstantType = GpuProgramParameters.GpuConstantType.Int4; break; default: def.ConstantType = GpuProgramParameters.GpuConstantType.Unknown; break; } // Cg pads def.ElementSize = GpuProgramParameters.GpuConstantDefinition.GetElementSize(def.ConstantType, true); } }
protected void RecurseParams(IntPtr parameter, int contextArraySize = 1) #endif { // loop through the rest of the params while (parameter != IntPtr.Zero) { // get the type of this param up front var paramType = Cg.cgGetParameterType(parameter); // Look for uniform parameters only // Don't bother enumerating unused parameters, especially since they will // be optimized out and therefore not in the indexed versions if (Cg.cgGetParameterVariability(parameter) == Cg.CG_UNIFORM && paramType != Cg.CG_SAMPLER1D && paramType != Cg.CG_SAMPLER2D && paramType != Cg.CG_SAMPLER3D && paramType != Cg.CG_SAMPLERCUBE && paramType != Cg.CG_SAMPLERRECT && Cg.cgGetParameterDirection(parameter) != Cg.CG_OUT && Cg.cgIsParameterReferenced(parameter) != 0) { int arraySize; switch (paramType) { case Cg.CG_STRUCT: RecurseParams(Cg.cgGetFirstStructParameter(parameter)); break; case Cg.CG_ARRAY: // Support only 1-dimensional arrays arraySize = Cg.cgGetArraySize(parameter, 0); RecurseParams(Cg.cgGetArrayParameter(parameter, 0), arraySize); break; default: // Normal path (leaf) var paramName = Cg.cgGetParameterName(parameter).ToLower(); var logicalIndex = Cg.cgGetParameterResourceIndex(parameter); // Get the parameter resource, to calculate the physical index var res = Cg.cgGetParameterResource(parameter); var isRegisterCombiner = false; var regCombinerPhysicalIndex = 0; switch (res) { case Cg.CG_COMBINER_STAGE_CONST0: // register combiner, const 0 // the index relates to the texture stage; store this as (stage * 2) + 0 regCombinerPhysicalIndex = logicalIndex * 2; isRegisterCombiner = true; break; case Cg.CG_COMBINER_STAGE_CONST1: // register combiner, const 1 // the index relates to the texture stage; store this as (stage * 2) + 1 regCombinerPhysicalIndex = (logicalIndex * 2) + 1; isRegisterCombiner = true; break; default: // normal constant break; } // Trim the '[0]' suffix if it exists, we will add our own indexing later if (paramName.EndsWith("[0]")) { paramName = paramName.Remove(paramName.Length - 3); } var def = new GpuProgramParameters.GpuConstantDefinition(); def.ArraySize = contextArraySize; MapTypeAndElementSize(paramType, isRegisterCombiner, def); if (def.ConstantType == GpuProgramParameters.GpuConstantType.Unknown) { LogManager.Instance.Write("Problem parsing the following Cg Uniform: '" + paramName + "' in file " + _name); // next uniform parameter = Cg.cgGetNextParameter(parameter); continue; } if (isRegisterCombiner) { def.PhysicalIndex = regCombinerPhysicalIndex; } else { // base position on existing buffer contents if (def.IsFloat) { def.PhysicalIndex = floatLogicalToPhysical.BufferSize; } else { def.PhysicalIndex = intLogicalToPhysical.BufferSize; } } def.LogicalIndex = logicalIndex; if (!this.parametersMap.ContainsKey(paramName)) { this.parametersMap.Add(paramName, def); parametersMapSizeAsBuffer += sizeof(int); parametersMapSizeAsBuffer += paramName.Length; //parametersMapSizeAsBuffer += sizeof(GpuProgramParameters.GpuConstantDefinition); } // Record logical / physical mapping if (def.IsFloat) { lock (floatLogicalToPhysical.Mutex) { floatLogicalToPhysical.Map.Add(def.LogicalIndex, new GpuProgramParameters.GpuLogicalIndexUse(def.PhysicalIndex, def.ArraySize * def.ElementSize, GpuProgramParameters.GpuParamVariability.Global)); floatLogicalToPhysical.BufferSize += def.ArraySize * def.ElementSize; } } else { lock (intLogicalToPhysical.Mutex) { intLogicalToPhysical.Map.Add(def.LogicalIndex, new GpuProgramParameters.GpuLogicalIndexUse(def.PhysicalIndex, def.ArraySize * def.ElementSize, GpuProgramParameters.GpuParamVariability.Global)); intLogicalToPhysical.BufferSize += def.ArraySize * def.ElementSize; } } break; } } // get the next param parameter = Cg.cgGetNextLeafParameter(parameter); } }
/// <summary> /// Populate a list of uniforms based on GLSL ES source. /// </summary> /// <param name="src"> Reference to the source code </param> /// <param name="constantDefs"> The defs to populate (will not be cleared before adding, clear it yourself before calling this if that's what you want). </param> /// <param name="fileName"> The file name this came from, for logging errors </param> public void ExtractConstantDefs(string src, Axiom.Graphics.GpuProgramParameters.GpuNamedConstants constantDefs, string fileName) { // Parse the output string and collect all uniforms // NOTE this relies on the source already having been preprocessed // which is done in GLSLESProgram::loadFromSource string line; int currPos = src.IndexOf("uniform"); while (currPos != -1) { var def = new GpuProgramParameters.GpuConstantDefinition(); string paramName = string.Empty; //Now check for using the word 'uniform' in a larger string & ignore bool inLargerString = false; if (currPos != 0) { char prev = src[currPos - 1]; if (prev != ' ' && prev != '\t' && prev != '\r' && prev != '\n' && prev != ';') { inLargerString = true; } } if (!inLargerString && currPos + 7 < src.Length) { char next = src[currPos + 7]; if (next != ' ' && next != '\t' && next != '\r' && next != '\n') { inLargerString = true; } } //skip uniform currPos += 7; if (!inLargerString) { //find terminatiing semicolon int endPos = -1; for (int i = 0; i < src.Length; i++) { if (src[i] == ';') { endPos = i; break; } } if (endPos == -1) { //problem, missing semicolon, abort break; } line = src.Substring(currPos, endPos - currPos); //remove spaces before opening square braces, otherwise the following split() can split the line at inapppropriate //places (e.g. "vec3 sometihng [3]" won't work). for (int sqp = line.IndexOf("["); sqp != -1; sqp = line.IndexOf(" [")) { line.Remove(sqp, 1); } string[] parts = line.Split('\t', '\r', '\n'); foreach (string i in parts) { //Is this a type if (this.typeEnumMap.ContainsKey(i)) { this.CompleteDefInfo(this.typeEnumMap[i], def); } else { //If this is not a type, and not empty, it should be a name string trim = i.Trim(); if (trim.Length == 0) { continue; } //Skip over precision keywords if (trim == "lowp" || trim == "mediump" || trim == "highp") { continue; } int arrayStart = -1; for (int j = 0; j < trim.Length; j++) { if (trim[j] == '[') { arrayStart = j; break; } } if (arrayStart != -1) { //potential name (if butted up to array) string name = trim.Substring(0, arrayStart); name = name.Trim(); if (name.Length > 0) { paramName = name; } int arrayEnd = -1; for (int k = 0; k < trim.Length; k++) { if (trim[k] == ']') { arrayEnd = k; break; } } string arrayDimTerm = trim.Substring(arrayStart + 1, arrayEnd - arrayStart - 1); arrayDimTerm = arrayDimTerm.Trim(); // the array term might be a simple number or it might be // an expression (e.g. 24*3) or refer to a constant expression // we'd have to evaluate the expression which could get nasty // Ogre TODO def.ArraySize = int.Parse(arrayDimTerm); } else { paramName = trim; def.ArraySize = 1; } //Name should be after the type, so complete def and add //We do this now so that comma-seperated params will do //this part once for each name mentioned if (def.ConstantType == GpuProgramParameters.GpuConstantType.Unknown) { Axiom.Core.LogManager.Instance.Write("Problem parsing the following GLSL Uniform: " + line + " in file " + fileName); //next uniform break; } //Complete def and add //increment physical buffer location def.LogicalIndex = 0; // not valid in GLSL if (def.IsFloat) { def.PhysicalIndex = constantDefs.FloatBufferSize; constantDefs.FloatBufferSize += def.ArraySize * def.ElementSize; } else { def.PhysicalIndex = constantDefs.IntBufferSize; constantDefs.IntBufferSize += def.ArraySize * def.ElementSize; } constantDefs.Map.Add(paramName, def); } } } //Find next one currPos = src.IndexOf("uniform"); } }