Move some D3D-specific stuff into ProgramD3D.

BUG=angle:773

Change-Id: I48b42e7a3e82a43d3dde16a8d1016d28280eae39
Reviewed-on: https://chromium-review.googlesource.com/232968
Reviewed-by: Jamie Madill <jmadill@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 844aa16..2a7ead2 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -7,16 +7,17 @@
 // ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
 
 #include "libANGLE/renderer/d3d/ProgramD3D.h"
-#include "libANGLE/features.h"
+
+#include "common/utilities.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/FramebufferAttachment.h"
 #include "libANGLE/Program.h"
+#include "libANGLE/features.h"
 #include "libANGLE/renderer/ShaderExecutable.h"
 #include "libANGLE/renderer/d3d/DynamicHLSL.h"
 #include "libANGLE/renderer/d3d/RendererD3D.h"
 #include "libANGLE/renderer/d3d/ShaderD3D.h"
-
-#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
 
 namespace rx
 {
@@ -100,6 +101,23 @@
     return false;
 }
 
+struct AttributeSorter
+{
+    AttributeSorter(const ProgramImpl::SemanticIndexArray &semanticIndices)
+        : originalIndices(semanticIndices)
+    {
+    }
+
+    bool operator()(int a, int b)
+    {
+        if (originalIndices[a] == -1) return false;
+        if (originalIndices[b] == -1) return true;
+        return (originalIndices[a] < originalIndices[b]);
+    }
+
+    const ProgramImpl::SemanticIndexArray &originalIndices;
+};
+
 }
 
 ProgramD3D::VertexExecutable::VertexExecutable(const gl::VertexFormat inputLayout[],
@@ -655,6 +673,7 @@
     }
 
     initializeUniformStorage();
+    initAttributesByLayout();
 
     return LinkResult(true, gl::Error(GL_NO_ERROR));
 }
@@ -1035,6 +1054,8 @@
 
     mUsesPointSize = vertexShaderD3D->usesPointSize();
 
+    initAttributesByLayout();
+
     return LinkResult(true, gl::Error(GL_NO_ERROR));
 }
 
@@ -1930,6 +1951,8 @@
     mUsedVertexSamplerRange = 0;
     mUsedPixelSamplerRange = 0;
     mDirtySamplerMapping = true;
+
+    std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
 }
 
 unsigned int ProgramD3D::getSerial() const
@@ -1942,4 +1965,32 @@
     return mCurrentSerial++;
 }
 
+void ProgramD3D::initAttributesByLayout()
+{
+    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+    {
+        mAttributesByLayout[i] = i;
+    }
+
+    std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
+}
+
+void ProgramD3D::sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
+                                        int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]) const
+{
+    rx::TranslatedAttribute oldTranslatedAttributes[gl::MAX_VERTEX_ATTRIBS];
+
+    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+    {
+        oldTranslatedAttributes[i] = attributes[i];
+    }
+
+    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+    {
+        int oldIndex = mAttributesByLayout[i];
+        sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
+        attributes[i] = oldTranslatedAttributes[oldIndex];
+    }
+}
+
 }