Make the Program's semantic index D3D-only.

This concept isn't strictly necessary for GL-side validation. Instead
we can use a bitset to track active attribs, and determine is a
particular location is active.

BUG=angleproject:1123

Change-Id: If7a920a3071672116bafffb3368671f721723b65
Reviewed-on: https://chromium-review.googlesource.com/294570
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index 1dcd5ea..44e2e67 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -355,6 +355,7 @@
     }
 
     mData.mAttributes.clear();
+    mData.mActiveAttribLocationsMask.reset();
     mData.mTransformFeedbackVaryingVars.clear();
 
     mProgram->reset();
@@ -403,11 +404,9 @@
         return Error(GL_NO_ERROR);
     }
 
-    // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
-    for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
-    {
-        stream.readInt(&mProgram->getSemanticIndexes()[i]);
-    }
+    static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
+                  "Too many vertex attribs for mask");
+    mData.mActiveAttribLocationsMask = stream.readInt<unsigned long>();
 
     unsigned int attribCount = stream.readInt<unsigned int>();
     ASSERT(mData.mAttributes.empty());
@@ -450,11 +449,7 @@
     stream.writeInt(ANGLE_MINOR_VERSION);
     stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
 
-    // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
-    for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
-    {
-        stream.writeInt(mProgram->getSemanticIndexes()[i]);
-    }
+    stream.writeInt(mData.mActiveAttribLocationsMask.to_ulong());
 
     stream.writeInt(mData.mAttributes.size());
     for (const sh::Attribute &attrib : mData.mAttributes)
@@ -594,16 +589,11 @@
     return static_cast<GLuint>(-1);
 }
 
-const int *Program::getSemanticIndexes() const
+bool Program::isAttribLocationActive(size_t attribLocation) const
 {
-    return mProgram->getSemanticIndexes();
-}
-
-int Program::getSemanticIndex(int attributeIndex) const
-{
-    ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
-
-    return mProgram->getSemanticIndexes()[attributeIndex];
+    ASSERT(attribLocation >= 0 &&
+           static_cast<size_t>(attribLocation) < mData.mActiveAttribLocationsMask.size());
+    return mData.mActiveAttribLocationsMask[attribLocation];
 }
 
 void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
@@ -1313,9 +1303,9 @@
         if (attribute.location != -1)
         {
             // Location is set by glBindAttribLocation or by location layout qualifier
-            const int rows = VariableRegisterCount(attribute.type);
+            const int regs = VariableRegisterCount(attribute.type);
 
-            if (static_cast<GLuint>(rows + attribute.location) > maxAttribs)
+            if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
             {
                 infoLog << "Active attribute (" << attribute.name << ") at location "
                         << attribute.location << " is too big to fit";
@@ -1323,10 +1313,10 @@
                 return false;
             }
 
-            for (int row = 0; row < rows; row++)
+            for (int reg = 0; reg < regs; reg++)
             {
-                const int rowLocation               = attribute.location + row;
-                sh::ShaderVariable *linkedAttribute = usedAttribMap[rowLocation];
+                const int regLocation               = attribute.location + reg;
+                sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
 
                 // In GLSL 3.00, attribute aliasing produces a link error
                 // In GLSL 1.00, attribute aliasing is allowed, but ANGLE currently has a bug
@@ -1336,16 +1326,16 @@
                     // if (mProgram->getShaderVersion() >= 300)
                     {
                         infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
-                                << linkedAttribute->name << "' at location " << rowLocation;
+                                << linkedAttribute->name << "' at location " << regLocation;
                         return false;
                     }
                 }
                 else
                 {
-                    usedAttribMap[rowLocation] = &attribute;
+                    usedAttribMap[regLocation] = &attribute;
                 }
 
-                usedLocations |= 1 << rowLocation;
+                usedLocations |= 1 << regLocation;
             }
         }
     }
@@ -1358,10 +1348,10 @@
         // Not set by glBindAttribLocation or by location layout qualifier
         if (attribute.location == -1)
         {
-            int rows = VariableRegisterCount(attribute.type);
-            int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, maxAttribs);
+            int regs           = VariableRegisterCount(attribute.type);
+            int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
 
-            if (availableIndex == -1 || static_cast<GLuint>(availableIndex + rows) > maxAttribs)
+            if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
             {
                 infoLog << "Too many active attributes (" << attribute.name << ")";
                 return false;
@@ -1371,18 +1361,15 @@
         }
     }
 
-    // TODO(jmadill): make semantic index D3D-only
     for (const sh::Attribute &attribute : mData.mAttributes)
     {
         ASSERT(attribute.staticUse);
+        ASSERT(attribute.location != -1);
+        int regs = VariableRegisterCount(attribute.type);
 
-        unsigned int attributeIndex = attribute.location;
-        int index                   = vertexShader->getSemanticIndex(attribute.name);
-        int rows                    = VariableRegisterCount(attribute.type);
-
-        for (int r = 0; r < rows; r++)
+        for (int r = 0; r < regs; r++)
         {
-            mProgram->getSemanticIndexes()[attributeIndex++] = index++;
+            mData.mActiveAttribLocationsMask.set(attribute.location + r);
         }
     }