Add a new path for querying active attributes from the shader translator, for use with layout qualifier support.

TRAC #23269

Signed-off-by: Geoff Lang
Signed-off-by: Nicolas Capens
Author: Jamie Madill
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index b36d456..d117a30 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -161,6 +161,11 @@
     return mActiveOutputVariables;
 }
 
+const ActiveShaderVariables &OutputHLSL::getAttributes() const
+{
+    return mActiveAttributes;
+}
+
 int OutputHLSL::vectorSize(const TType &type) const
 {
     int elementSize = type.isMatrix() ? type.getCols() : 1;
@@ -389,6 +394,10 @@
         const TString &name = attribute->second->getSymbol();
 
         attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+
+        ShaderVariable shaderVar(glVariableType(type), glVariablePrecision(type), name.c_str(),
+                                 (unsigned int)type.getArraySize(), type.getLayoutQualifier().location);
+        mActiveAttributes.push_back(shaderVar);
     }
 
     if (shaderType == SH_FRAGMENT_SHADER)
diff --git a/src/compiler/OutputHLSL.h b/src/compiler/OutputHLSL.h
index c22ad4f..6a409b4 100644
--- a/src/compiler/OutputHLSL.h
+++ b/src/compiler/OutputHLSL.h
@@ -35,6 +35,7 @@
     const ActiveUniforms &getUniforms();
     const ActiveInterfaceBlocks &getInterfaceBlocks() const;
     const ActiveShaderVariables &getOutputVariables() const;
+    const ActiveShaderVariables &getAttributes() const;
 
     TString typeString(const TType &type);
     TString textureString(const TType &type);
@@ -195,6 +196,7 @@
     ActiveUniforms mActiveUniforms;
     ActiveInterfaceBlocks mActiveInterfaceBlocks;
     ActiveShaderVariables mActiveOutputVariables;
+    ActiveShaderVariables mActiveAttributes;
 };
 }
 
diff --git a/src/compiler/ShaderLang.cpp b/src/compiler/ShaderLang.cpp
index 07313dd..efdcb67 100644
--- a/src/compiler/ShaderLang.cpp
+++ b/src/compiler/ShaderLang.cpp
@@ -382,6 +382,9 @@
     case SH_ACTIVE_OUTPUT_VARIABLES_ARRAY:
         *params = (void*)&translator->getOutputVariables();
         break;
+    case SH_ACTIVE_ATTRIBUTES_ARRAY:
+        *params = (void*)&translator->getAttributes();
+        break;
     default: UNREACHABLE();
     }
 }
diff --git a/src/compiler/TranslatorHLSL.cpp b/src/compiler/TranslatorHLSL.cpp
index 6ef91f4..83468d4 100644
--- a/src/compiler/TranslatorHLSL.cpp
+++ b/src/compiler/TranslatorHLSL.cpp
@@ -23,4 +23,5 @@
     mActiveUniforms = outputHLSL.getUniforms();
     mActiveInterfaceBlocks = outputHLSL.getInterfaceBlocks();
     mActiveOutputVariables = outputHLSL.getOutputVariables();
+    mActiveAttributes = outputHLSL.getAttributes();
 }
diff --git a/src/compiler/TranslatorHLSL.h b/src/compiler/TranslatorHLSL.h
index c031446..e53e831 100644
--- a/src/compiler/TranslatorHLSL.h
+++ b/src/compiler/TranslatorHLSL.h
@@ -18,6 +18,7 @@
     const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; }
     const sh::ActiveInterfaceBlocks &getInterfaceBlocks() const { return mActiveInterfaceBlocks; }
     const sh::ActiveShaderVariables &getOutputVariables() { return mActiveOutputVariables; }
+    const sh::ActiveShaderVariables &getAttributes() { return mActiveAttributes; }
 
 protected:
     virtual void translate(TIntermNode* root);
@@ -25,6 +26,7 @@
     sh::ActiveUniforms mActiveUniforms;
     sh::ActiveInterfaceBlocks mActiveInterfaceBlocks;
     sh::ActiveShaderVariables mActiveOutputVariables;
+    sh::ActiveShaderVariables mActiveAttributes;
     ShShaderOutput mOutputType;
 };
 
diff --git a/src/compiler/Uniform.cpp b/src/compiler/Uniform.cpp
index 602eed5..3cd3599 100644
--- a/src/compiler/Uniform.cpp
+++ b/src/compiler/Uniform.cpp
@@ -11,6 +11,14 @@
 namespace sh
 {
 
+ShaderVariable::ShaderVariable()
+    : type(GL_NONE),
+      precision(GL_NONE),
+      arraySize(0),
+      location(-1)
+{
+}
+
 ShaderVariable::ShaderVariable(GLenum type, GLenum precision, const char *name, unsigned int arraySize, int location)
     : type(type),
       precision(precision),
diff --git a/src/compiler/Uniform.h b/src/compiler/Uniform.h
index e43533a..ac0fdfd 100644
--- a/src/compiler/Uniform.h
+++ b/src/compiler/Uniform.h
@@ -19,6 +19,7 @@
 
 struct ShaderVariable
 {
+    ShaderVariable();
     ShaderVariable(GLenum type, GLenum precision, const char *name, unsigned int arraySize, int location);
 
     GLenum type;
diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp
index eead8ab..34cec04 100644
--- a/src/libGLESv2/ProgramBinary.cpp
+++ b/src/libGLESv2/ProgramBinary.cpp
@@ -1210,12 +1210,14 @@
                   "{\n";
 
     int semanticIndex = 0;
-    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
+    const sh::ActiveShaderVariables &activeAttributes = vertexShader->mActiveAttributes;
+    for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
     {
-        vertexHLSL += "    " + gl_d3d::TypeString(TransposeMatrixType(attribute->type)) + " ";
-        vertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
+        const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
+        vertexHLSL += "    " + gl_d3d::TypeString(TransposeMatrixType(attribute.type)) + " ";
+        vertexHLSL += decorateAttribute(attribute.name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
 
-        semanticIndex += AttributeRegisterCount(attribute->type);
+        semanticIndex += AttributeRegisterCount(attribute.type);
     }
 
     vertexHLSL += "};\n"
@@ -1250,16 +1252,17 @@
                   "VS_OUTPUT main(VS_INPUT input)\n"
                   "{\n";
 
-    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
+    for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
     {
-        vertexHLSL += "    " + decorateAttribute(attribute->name) + " = ";
+        const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
+        vertexHLSL += "    " + decorateAttribute(attribute.name) + " = ";
 
-        if (IsMatrixType(attribute->type))   // Matrix
+        if (IsMatrixType(attribute.type))   // Matrix
         {
             vertexHLSL += "transpose";
         }
 
-        vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
+        vertexHLSL += "(input." + decorateAttribute(attribute.name) + ");\n";
     }
 
     if (vertexHLSL.find("dx_initConstantBuffers") != std::string::npos)
@@ -2065,11 +2068,13 @@
 bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
 {
     unsigned int usedLocations = 0;
+    const sh::ActiveShaderVariables &activeAttributes = vertexShader->mActiveAttributes;
 
     // Link attributes that have a binding location
-    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
+    for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
     {
-        int location = attributeBindings.getAttributeBinding(attribute->name);
+        const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
+        const int location = attributeBindings.getAttributeBinding(attribute.name);
 
         if (location != -1)   // Set by glBindAttribLocation
         {
@@ -2078,13 +2083,13 @@
                 // Multiple active attributes bound to the same location; not an error
             }
 
-            mLinkedAttribute[location] = *attribute;
+            mLinkedAttribute[location] = attribute;
 
-            int rows = AttributeRegisterCount(attribute->type);
+            int rows = AttributeRegisterCount(attribute.type);
 
             if (rows + location > MAX_VERTEX_ATTRIBS)
             {
-                infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
+                infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location);
 
                 return false;
             }
@@ -2097,23 +2102,24 @@
     }
 
     // Link attributes that don't have a binding location
-    for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
+    for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
     {
-        int location = attributeBindings.getAttributeBinding(attribute->name);
+        const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
+        int location = attributeBindings.getAttributeBinding(attribute.name);
 
         if (location == -1)   // Not set by glBindAttribLocation
         {
-            int rows = AttributeRegisterCount(attribute->type);
+            int rows = AttributeRegisterCount(attribute.type);
             int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
 
             if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
             {
-                infoLog.append("Too many active attributes (%s)", attribute->name.c_str());
+                infoLog.append("Too many active attributes (%s)", attribute.name.c_str());
 
                 return false;   // Fail to link
             }
 
-            mLinkedAttribute[availableIndex] = *attribute;
+            mLinkedAttribute[availableIndex] = attribute;
         }
     }
 
diff --git a/src/libGLESv2/ProgramBinary.h b/src/libGLESv2/ProgramBinary.h
index a29cf93..8401483 100644
--- a/src/libGLESv2/ProgramBinary.h
+++ b/src/libGLESv2/ProgramBinary.h
@@ -186,7 +186,7 @@
     rx::ShaderExecutable *mVertexExecutable;
     rx::ShaderExecutable *mGeometryExecutable;
 
-    Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
+    sh::ShaderVariable mLinkedAttribute[MAX_VERTEX_ATTRIBS];
     int mSemanticIndex[MAX_VERTEX_ATTRIBS];
 
     struct Sampler
diff --git a/src/libGLESv2/Shader.cpp b/src/libGLESv2/Shader.cpp
index c18706a..4ab3789 100644
--- a/src/libGLESv2/Shader.cpp
+++ b/src/libGLESv2/Shader.cpp
@@ -628,7 +628,7 @@
     Shader::uncompile();
 
     // set by ParseAttributes
-    mAttributes.clear();
+    mActiveAttributes.clear();
 }
 
 void VertexShader::compile()
@@ -645,14 +645,16 @@
     if (!attributeName.empty())
     {
         int semanticIndex = 0;
-        for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
+        for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
         {
-            if (attribute->name == attributeName)
+            const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex];
+
+            if (attribute.name == attributeName)
             {
                 return semanticIndex;
             }
 
-            semanticIndex += AttributeRegisterCount(attribute->type);
+            semanticIndex += AttributeRegisterCount(attribute.type);
         }
     }
 
@@ -664,24 +666,9 @@
     const char *hlsl = getHLSL();
     if (hlsl)
     {
-        const char *input = strstr(hlsl, "// Attributes") + 14;
-
-        while(true)
-        {
-            char attributeType[256];
-            char attributeName[256];
-
-            int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName);
-
-            if (matches != 2)
-            {
-                break;
-            }
-
-            mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
-
-            input = strstr(input, ";") + 2;
-        }
+        void *activeAttributes;
+        ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes);
+        mActiveAttributes = *(sh::ActiveShaderVariables*)activeAttributes;
     }
 }
 
diff --git a/src/libGLESv2/Shader.h b/src/libGLESv2/Shader.h
index e5c600a..b5df3f4 100644
--- a/src/libGLESv2/Shader.h
+++ b/src/libGLESv2/Shader.h
@@ -141,22 +141,6 @@
     ResourceManager *mResourceManager;
 };
 
-struct Attribute
-{
-    Attribute() : type(GL_NONE), name("")
-    {
-    }
-
-    Attribute(GLenum type, const std::string &name) : type(type), name(name)
-    {
-    }
-
-    GLenum type;
-    std::string name;
-};
-
-typedef std::vector<Attribute> AttributeArray;
-
 class VertexShader : public Shader
 {
     friend class ProgramBinary;
@@ -176,7 +160,7 @@
 
     void parseAttributes();
 
-    AttributeArray mAttributes;
+    sh::ActiveShaderVariables mActiveAttributes;
 };
 
 class FragmentShader : public Shader