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 ); } } }
protected void RecurseParams(IntPtr parameter, int contextArraySize = 1) { // 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.cgIsParameterReferenced(parameter) != 0 && Cg.cgGetParameterVariability(parameter) == Cg.CG_UNIFORM && Cg.cgGetParameterDirection(parameter) != Cg.CG_OUT && paramType != Cg.CG_SAMPLER1D && paramType != Cg.CG_SAMPLER2D && paramType != Cg.CG_SAMPLER3D && paramType != Cg.CG_SAMPLERCUBE && paramType != Cg.CG_SAMPLERRECT ) { 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 ); 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.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 ( !parametersMap.ContainsKey( paramName ) ) { parametersMap.Add( paramName, def); /* mParametersMapSizeAsBuffer += sizeof ( size_t ); mParametersMapSizeAsBuffer += paramName.size(); mParametersMapSizeAsBuffer += sizeof ( 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" ); } }
///<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 (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*/ 1; } else { def.PhysicalIndex = defs.IntBufferSize; defs.IntBufferSize += /*def.ArraySize * def.ElementSize*/ 1; } defs.Map.Add(paramName, def); // Axiom: This is not stable yet //defs.GenerateConstantDefinitionArrayEntries(paramName, def); } } } // Find next one currPos = src.IndexOf("uniform", currPos); } }