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/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index fbfa887..9b3f963 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -109,7 +109,7 @@
 
 struct AttributeSorter
 {
-    AttributeSorter(const ProgramImpl::SemanticIndexArray &semanticIndices)
+    AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices)
         : originalIndices(&semanticIndices)
     {
     }
@@ -124,7 +124,7 @@
         return (indexA < indexB);
     }
 
-    const ProgramImpl::SemanticIndexArray *originalIndices;
+    const ProgramD3D::SemanticIndexArray *originalIndices;
 };
 
 bool LinkVaryingRegisters(gl::InfoLog &infoLog,
@@ -513,6 +513,12 @@
 
     stream->readInt(&mShaderVersion);
 
+    // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
+    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
+    {
+        stream->readInt(&mSemanticIndexes[i]);
+    }
+
     const unsigned int psSamplerCount = stream->readInt<unsigned int>();
     for (unsigned int i = 0; i < psSamplerCount; ++i)
     {
@@ -763,6 +769,12 @@
 
     stream->writeInt(mShaderVersion);
 
+    // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
+    for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
+    {
+        stream->writeInt(mSemanticIndexes[i]);
+    }
+
     stream->writeInt(mSamplersPS.size());
     for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
     {
@@ -1148,7 +1160,7 @@
 
     mUsesPointSize = vertexShaderD3D->usesPointSize();
 
-    initAttributesByLayout();
+    initSemanticIndex();
 
     if (!defineUniforms(infoLog, *data.caps))
     {
@@ -2065,6 +2077,7 @@
     mUsedPixelSamplerRange = 0;
     mDirtySamplerMapping = true;
 
+    std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
     std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
 
     mTransformFeedbackLinkedVaryings.clear();
@@ -2080,6 +2093,27 @@
     return mCurrentSerial++;
 }
 
+void ProgramD3D::initSemanticIndex()
+{
+    const gl::Shader *vertexShader = mData.getAttachedVertexShader();
+    ASSERT(vertexShader != nullptr);
+
+    // Init semantic index
+    for (const sh::Attribute &attribute : mData.getAttributes())
+    {
+        int attributeIndex = attribute.location;
+        int index          = vertexShader->getSemanticIndex(attribute.name);
+        int regs           = gl::VariableRegisterCount(attribute.type);
+
+        for (int reg = 0; reg < regs; ++reg)
+        {
+            mSemanticIndexes[attributeIndex + reg] = index + reg;
+        }
+    }
+
+    initAttributesByLayout();
+}
+
 void ProgramD3D::initAttributesByLayout()
 {
     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
@@ -2087,7 +2121,8 @@
         mAttributesByLayout[i] = i;
     }
 
-    std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
+    std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
+              AttributeSorter(mSemanticIndexes));
 }
 
 void ProgramD3D::sortAttributesByLayout(const std::vector<TranslatedAttribute> &unsortedAttributes,
@@ -2097,21 +2132,19 @@
     for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
     {
         int oldIndex = mAttributesByLayout[attribIndex];
-        sortedSemanticIndicesOut[attribIndex] = mSemanticIndex[oldIndex];
+        sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
         sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
     }
 }
 
-void ProgramD3D::updateCachedInputLayout(const gl::Program *program, const gl::State &state)
+void ProgramD3D::updateCachedInputLayout(const gl::State &state)
 {
     mCachedInputLayout.clear();
-    const int *semanticIndexes = program->getSemanticIndexes();
-
     const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
 
     for (unsigned int attributeIndex = 0; attributeIndex < vertexAttributes.size(); attributeIndex++)
     {
-        int semanticIndex = semanticIndexes[attributeIndex];
+        int semanticIndex = mSemanticIndexes[attributeIndex];
 
         if (semanticIndex != -1)
         {