public bool SameAs(ConstantBufferData other)
        {
            // If the names of the constant buffers don't
            // match then consider them different right off 
            // the bat... even if their parameters are the same.
            if (Name != other.Name)
                return false;

            // Do we have the same count of parameters and size?
            if (Size != other.Size ||
                    Parameters.Count != other.Parameters.Count)
                return false;

            // Compare the parameters themselves.
            for (var i = 0; i < Parameters.Count; i++)
            {
                var p1 = Parameters[i];
                var p2 = other.Parameters[i];

                // Check the importaint bits.
                if (p1.name != p2.name ||
                        p1.rows != p2.rows ||
                        p1.columns != p2.columns ||
                        p1.class_ != p2.class_ ||
                        p1.type != p2.type ||
                        p1.bufferOffset != p2.bufferOffset)
                    return false;
            }

            // These are equal.
            return true;
        }
        public bool SameAs(ConstantBufferData other)
        {
            // If the names of the constant buffers don't
            // match then consider them different right off
            // the bat... even if their parameters are the same.
            if (Name != other.Name)
            {
                return(false);
            }

            // Do we have the same count of parameters and size?
            if (Size != other.Size ||
                Parameters.Count != other.Parameters.Count)
            {
                return(false);
            }

            // Compare the parameters themselves.
            for (var i = 0; i < Parameters.Count; i++)
            {
                var p1 = Parameters[i];
                var p2 = other.Parameters[i];

                // Check the importaint bits.
                if (p1.name != p2.name ||
                    p1.rows != p2.rows ||
                    p1.columns != p2.columns ||
                    p1.class_ != p2.class_ ||
                    p1.type != p2.type ||
                    p1.bufferOffset != p2.bufferOffset)
                {
                    return(false);
                }
            }

            // These are equal.
            return(true);
        }
        public static ShaderData CreatePureGLSL(byte[] byteCode, string filename, bool isVertexShader, List <ConstantBufferData> cbuffers, int sharedIndex, Dictionary <string, SamplerStateInfo> samplerStates, string shaderInfo, bool debug)
        {
            var dxshader = new ShaderData();

            dxshader.SharedIndex = sharedIndex;
            dxshader.Bytecode    = (byte[])byteCode.Clone();
            // Use MojoShader to convert the HLSL bytecode to GLSL.
            string glsl = System.Text.Encoding.ASCII.GetString(byteCode);

            if (isVertexShader)
            {
                glsl = AddPosFixup(glsl);
            }

            Dictionary <string, MojoShader.MOJOSHADER_usage> usageMapping = new Dictionary <string, MojoShader.MOJOSHADER_usage> ();
            XmlDocument doc = new XmlDocument();

            doc.LoadXml(shaderInfo);
            XmlElement shader = (XmlElement)doc.FirstChild;

            foreach (XmlElement attribute in shader.ChildNodes)
            {
                if (attribute.Name == "attribute")
                {
                    usageMapping.Add(attribute.GetAttribute("name"), (MojoShader.MOJOSHADER_usage)Enum.Parse(typeof(MojoShader.MOJOSHADER_usage), "MOJOSHADER_USAGE_" + attribute.InnerText.ToUpper(), true));
                }
            }
            Additional.GLSLShaderParser parser = new Additional.GLSLShaderParser(glsl, filename, isVertexShader, usageMapping);
            if (!parser.Parse())
            {
                return(null);
            }

            dxshader.IsVertexShader = isVertexShader;

            dxshader._attributes = parser.Attributes.ToArray();

            var symbols = parser.Symbols.ToArray();

            //try to put the symbols in the order they are eventually packed into the uniform arrays
            //this /should/ be done by pulling the info from mojoshader
            Array.Sort(symbols, delegate(MojoShader.MOJOSHADER_symbol a, MojoShader.MOJOSHADER_symbol b) {
                uint va = a.register_index;
                if (a.info.elements == 1)
                {
                    va += 1024;                     //hax. mojoshader puts array objects first
                }
                uint vb = b.register_index;
                if (b.info.elements == 1)
                {
                    vb += 1024;
                }
                return(va.CompareTo(vb));
            }
                       ); //(a, b) => ((int)(a.info.elements > 1))a.register_index.CompareTo(b.register_index));

            // NOTE: It seems the latest versions of MojoShader only
            // output vec4 register sets.  We leave the code below, but
            // the runtime has been optimized for this case.

            // For whatever reason the register indexing is
            // incorrect from MojoShader.
            {
                uint bool_index   = 0;
                uint float4_index = 0;
                uint int4_index   = 0;

                for (var i = 0; i < symbols.Length; i++)
                {
                    switch (symbols [i].register_set)
                    {
                    case MojoShader.MOJOSHADER_symbolRegisterSet.MOJOSHADER_SYMREGSET_BOOL:
                        symbols [i].register_index = bool_index;
                        bool_index += symbols [i].register_count;
                        break;

                    case MojoShader.MOJOSHADER_symbolRegisterSet.MOJOSHADER_SYMREGSET_FLOAT4:
                        symbols [i].register_index = float4_index;
                        float4_index += symbols [i].register_count;
                        break;

                    case MojoShader.MOJOSHADER_symbolRegisterSet.MOJOSHADER_SYMREGSET_INT4:
                        symbols [i].register_index = int4_index;
                        int4_index += symbols [i].register_count;
                        break;
                    }
                }
            }
            // Get the samplers.
            var samplers = parser.Samplers.ToArray();

            dxshader._samplers = new Sampler[samplers.Length];
            for (var i = 0; i < samplers.Length; i++)
            {
                // We need the original sampler name... look for that in the symbols.
                var originalSamplerName =
                    symbols.First(e => e.register_set == MojoShader.MOJOSHADER_symbolRegisterSet.MOJOSHADER_SYMREGSET_SAMPLER &&
                                  e.register_index == samplers [i].index
                                  ).name;

                var sampler = new Sampler {
                    //sampler mapping to parameter is unknown atm
                    parameter = -1,

                    // GLSL needs the MojoShader mangled sampler name.
                    samplerName = samplers [i].name,

                    // By default use the original sampler name for the parameter name.
                    parameterName = originalSamplerName,

                    textureSlot = samplers [i].index,
                    samplerSlot = samplers [i].index,
                    type        = samplers [i].type,
                };

                SamplerStateInfo state;
                if (samplerStates.TryGetValue(originalSamplerName, out state))
                {
                    sampler.state         = state.State;
                    sampler.parameterName = state.TextureName ?? originalSamplerName;
                }

                // Store the sampler.
                dxshader._samplers [i] = sampler;
            }

            // Gather all the parameters used by this shader.
            var symbol_types = new[] {
                new { name = dxshader.IsVertexShader ? "vs_uniforms_bool" : "ps_uniforms_bool", set = MojoShader.MOJOSHADER_symbolRegisterSet.MOJOSHADER_SYMREGSET_BOOL, },
                new { name = dxshader.IsVertexShader ? "vs_uniforms_ivec4" : "ps_uniforms_ivec4", set = MojoShader.MOJOSHADER_symbolRegisterSet.MOJOSHADER_SYMREGSET_INT4, },
                new { name = dxshader.IsVertexShader ? "vs_uniforms_vec4" : "ps_uniforms_vec4", set = MojoShader.MOJOSHADER_symbolRegisterSet.MOJOSHADER_SYMREGSET_FLOAT4, },
            };
            var cbuffer_index = new List <int> ();

            for (var i = 0; i < symbol_types.Length; i++)
            {
                var cbuffer = new ConstantBufferData(symbol_types [i].name,
                                                     symbol_types [i].set,
                                                     symbols);
                if (cbuffer.Size == 0)
                {
                    continue;
                }

                var match = cbuffers.FindIndex(e => e.SameAs(cbuffer));
                if (match == -1)
                {
                    cbuffer_index.Add(cbuffers.Count);
                    cbuffers.Add(cbuffer);
                }
                else
                {
                    cbuffer_index.Add(match);
                }
            }
            dxshader._cbuffers = cbuffer_index.ToArray();



            //TODO: glslCode translator


            // TODO: This sort of sucks... why does MojoShader not produce
            // code valid for GLES out of the box?

            // GLES platforms do not like this.
            //glsl = glsl.Replace ("#version 110", "");

            // Add the required precision specifiers for GLES.
            AddPrecisions(glsl, dxshader.IsVertexShader, debug);


            // Store the code for serialization.
            dxshader.ShaderCode = Encoding.ASCII.GetBytes(glsl);
            return(dxshader);
        }