Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        ///<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);
            }
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
        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);
                }
            }
        }
Exemplo n.º 5
0
        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);
            }
        }
Exemplo n.º 6
0
        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);
            }
        }
Exemplo n.º 7
0
        /// <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");
            }
        }