Store multiple vertex executables in the program binary.

With dynamic vertex conversion the GPU, we will have different input
layouts resulting in different executables. This patch adds a way
of mapping the input layouts to vertex executables.

BUG=angle:560
Change-Id: Ie36f2f8ac2dfcb96f562af577d31f57d6d89b447
Reviewed-on: https://chromium-review.googlesource.com/185192
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index c94f944..6b91d91 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -2407,9 +2407,14 @@
 }
 
 // Applies the shaders and shader constants to the Direct3D 9 device
-void Context::applyShaders(ProgramBinary *programBinary, bool rasterizerDiscard)
+void Context::applyShaders(ProgramBinary *programBinary)
 {
-    mRenderer->applyShaders(programBinary, rasterizerDiscard);
+    const VertexAttribute *vertexAttributes = getCurrentVertexArray()->getVertexAttributes();
+
+    VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS];
+    VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.vertexAttribCurrentValues);
+
+    mRenderer->applyShaders(programBinary, mState.rasterizer.rasterizerDiscard, inputLayout);
 
     programBinary->applyUniforms();
 }
@@ -2879,7 +2884,7 @@
         return gl::error(err);
     }
 
-    applyShaders(programBinary, mState.rasterizer.rasterizerDiscard);
+    applyShaders(programBinary);
     applyTextures(programBinary);
 
     if (!applyUniformBuffers())
@@ -2942,7 +2947,7 @@
         return gl::error(err);
     }
 
-    applyShaders(programBinary, mState.rasterizer.rasterizerDiscard);
+    applyShaders(programBinary);
     applyTextures(programBinary);
 
     if (!applyUniformBuffers())
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 9026377..391ea63 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -453,7 +453,7 @@
 
     bool applyRenderTarget(GLenum drawMode, bool ignoreViewport);
     void applyState(GLenum drawMode);
-    void applyShaders(ProgramBinary *programBinary, bool rasterizerDiscard);
+    void applyShaders(ProgramBinary *programBinary);
     void applyTextures(ProgramBinary *programBinary);
     void applyTextures(ProgramBinary *programBinary, SamplerType type);
     bool applyUniformBuffers();
diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp
index a3e600b..a5d6a46 100644
--- a/src/libGLESv2/ProgramBinary.cpp
+++ b/src/libGLESv2/ProgramBinary.cpp
@@ -50,6 +50,23 @@
     return subscript;
 }
 
+void GetInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
+{
+    for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
+    {
+        const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex];
+        VertexFormat *defaultFormat = &inputLayout[attributeIndex];
+
+        if (shaderAttr.type != GL_NONE)
+        {
+            defaultFormat->mType        = UniformComponentType(shaderAttr.type);
+            defaultFormat->mNormalized  = false;
+            defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool
+            defaultFormat->mComponents  = UniformComponentCount(shaderAttr.type);
+        }
+    }
+}
+
 }
 
 VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) 
@@ -57,14 +74,38 @@
 {
 }
 
+ProgramBinary::VertexExecutable::VertexExecutable(rx::Renderer *const renderer,
+                                                  const VertexFormat inputLayout[],
+                                                  rx::ShaderExecutable *shaderExecutable)
+    : mShaderExecutable(shaderExecutable)
+{
+    for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        mInputs[attributeIndex] = inputLayout[attributeIndex];
+    }
+}
+
+bool ProgramBinary::VertexExecutable::matchesInputLayout(const VertexFormat attributes[]) const
+{
+    for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        if (mInputs[attributeIndex] != attributes[attributeIndex])
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 unsigned int ProgramBinary::mCurrentSerial = 1;
 
 ProgramBinary::ProgramBinary(rx::Renderer *renderer)
     : RefCountObject(0),
       mRenderer(renderer),
       mDynamicHLSL(NULL),
+      mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
       mPixelExecutable(NULL),
-      mVertexExecutable(NULL),
       mGeometryExecutable(NULL),
       mUsedVertexSamplerRange(0),
       mUsedPixelSamplerRange(0),
@@ -95,9 +136,14 @@
 
 ProgramBinary::~ProgramBinary()
 {
-    SafeDelete(mPixelExecutable);
-    SafeDelete(mVertexExecutable);
+    while (!mVertexExecutables.empty())
+    {
+        delete mVertexExecutables.back();
+        mVertexExecutables.pop_back();
+    }
+
     SafeDelete(mGeometryExecutable);
+    SafeDelete(mPixelExecutable);
 
     while (!mUniforms.empty())
     {
@@ -136,9 +182,32 @@
     return mPixelExecutable;
 }
 
-rx::ShaderExecutable *ProgramBinary::getVertexExecutable() const
+rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS])
 {
-    return mVertexExecutable;
+    for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
+    {
+        if (mVertexExecutables[executableIndex]->matchesInputLayout(inputLayout))
+        {
+            return mVertexExecutables[executableIndex]->shaderExecutable();
+        }
+    }
+
+    // Generate new vertex executable
+    InfoLog tempInfoLog;
+    rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, mVertexHLSL.c_str(), rx::SHADER_VERTEX, mVertexWorkarounds);
+
+    if (!vertexExecutable)
+    {
+        std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
+        tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
+        ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
+    }
+    else
+    {
+        mVertexExecutables.push_back(new VertexExecutable(mRenderer, inputLayout, vertexExecutable));
+    }
+
+    return vertexExecutable;
 }
 
 rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() const
@@ -1091,15 +1160,73 @@
         stream.read(&mUniformIndex[i].index);
     }
 
+    stream.read(&mVertexHLSL);
+    stream.read(&mVertexWorkarounds);
+
+    unsigned int vertexShaderCount;
+    stream.read(&vertexShaderCount);
+
+    for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
+    {
+        VertexFormat vertexInputs[gl::MAX_VERTEX_ATTRIBS];
+
+        for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
+        {
+            VertexFormat *vertexInput = &vertexInputs[inputIndex];
+            stream.read(&vertexInput->mType);
+            stream.read(&vertexInput->mNormalized);
+            stream.read(&vertexInput->mComponents);
+            stream.read(&vertexInput->mPureInteger);
+        }
+
+        unsigned int vertexShaderSize;
+        stream.read(&vertexShaderSize);
+
+        const char *vertexShaderFunction = (const char*) binary + stream.offset();
+
+        rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
+                                                                           vertexShaderSize, rx::SHADER_VERTEX);
+        if (!shaderExecutable)
+        {
+            infoLog.append("Could not create vertex shader.");
+            return false;
+        }
+
+        mVertexExecutables.push_back(new VertexExecutable(mRenderer, vertexInputs, shaderExecutable));
+
+        stream.skip(vertexShaderSize);
+    }
+
     unsigned int pixelShaderSize;
     stream.read(&pixelShaderSize);
 
-    unsigned int vertexShaderSize;
-    stream.read(&vertexShaderSize);
+    const char *pixelShaderFunction = (const char*) binary + stream.offset();
+    mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(pixelShaderFunction),
+                                                 pixelShaderSize, rx::SHADER_PIXEL);
+    if (!mPixelExecutable)
+    {
+        infoLog.append("Could not create pixel shader.");
+        return false;
+    }
+    stream.skip(pixelShaderSize);
 
     unsigned int geometryShaderSize;
     stream.read(&geometryShaderSize);
 
+    if (geometryShaderSize > 0)
+    {
+        const char *geometryShaderFunction = (const char*) binary + stream.offset();
+        mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
+                                                        geometryShaderSize, rx::SHADER_GEOMETRY);
+        if (!mGeometryExecutable)
+        {
+            infoLog.append("Could not create geometry shader.");
+            SafeDelete(mPixelExecutable);
+            return false;
+        }
+        stream.skip(geometryShaderSize);
+    }
+
     const char *ptr = (const char*) binary + stream.offset();
 
     const GUID *binaryIdentifier = (const GUID *) ptr;
@@ -1112,52 +1239,6 @@
         return false;
     }
 
-    const char *pixelShaderFunction = ptr;
-    ptr += pixelShaderSize;
-
-    const char *vertexShaderFunction = ptr;
-    ptr += vertexShaderSize;
-
-    const char *geometryShaderFunction = geometryShaderSize > 0 ? ptr : NULL;
-    ptr += geometryShaderSize;
-
-    mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(pixelShaderFunction),
-                                                 pixelShaderSize, rx::SHADER_PIXEL);
-    if (!mPixelExecutable)
-    {
-        infoLog.append("Could not create pixel shader.");
-        return false;
-    }
-
-    mVertexExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
-                                                  vertexShaderSize, rx::SHADER_VERTEX);
-    if (!mVertexExecutable)
-    {
-        infoLog.append("Could not create vertex shader.");
-        delete mPixelExecutable;
-        mPixelExecutable = NULL;
-        return false;
-    }
-
-    if (geometryShaderFunction != NULL && geometryShaderSize > 0)
-    {
-        mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
-                                                        geometryShaderSize, rx::SHADER_GEOMETRY);
-        if (!mGeometryExecutable)
-        {
-            infoLog.append("Could not create geometry shader.");
-            delete mPixelExecutable;
-            mPixelExecutable = NULL;
-            delete mVertexExecutable;
-            mVertexExecutable = NULL;
-            return false;
-        }
-    }
-    else
-    {
-        mGeometryExecutable = NULL;
-    }
-
     initializeUniformStorage();
 
     return true;
@@ -1200,7 +1281,7 @@
     stream.write(mShaderVersion);
 
     stream.write(mUniforms.size());
-    for (unsigned int uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
+    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
     {
         const Uniform &uniform = *mUniforms[uniformIndex];
 
@@ -1222,7 +1303,7 @@
     }
 
     stream.write(mUniformBlocks.size());
-    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
+    for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
     {
         const UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
 
@@ -1241,28 +1322,60 @@
     }
 
     stream.write(mUniformIndex.size());
-    for (unsigned int i = 0; i < mUniformIndex.size(); ++i)
+    for (size_t i = 0; i < mUniformIndex.size(); ++i)
     {
         stream.write(mUniformIndex[i].name);
         stream.write(mUniformIndex[i].element);
         stream.write(mUniformIndex[i].index);
     }
 
+    stream.write(mVertexHLSL);
+    stream.write(mVertexWorkarounds);
+
+    UINT vertexShadersTotalSize = 0;
+
+    stream.write(mVertexExecutables.size());
+    for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
+    {
+        VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
+
+        for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
+        {
+            const VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex];
+            stream.write(vertexInput.mType);
+            stream.write(vertexInput.mNormalized);
+            stream.write(vertexInput.mComponents);
+            stream.write(vertexInput.mPureInteger);
+        }
+
+        UINT vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
+        stream.write(vertexShaderSize);
+
+        unsigned char *vertexBlob = static_cast<unsigned char *>(vertexExecutable->shaderExecutable()->getFunction());
+        stream.write(vertexBlob, vertexShaderSize);
+    }
+
     UINT pixelShaderSize = mPixelExecutable->getLength();
     stream.write(pixelShaderSize);
 
-    UINT vertexShaderSize = mVertexExecutable->getLength();
-    stream.write(vertexShaderSize);
+    unsigned char *pixelBlob = static_cast<unsigned char *>(mPixelExecutable->getFunction());
+    stream.write(pixelBlob, pixelShaderSize);
 
     UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
     stream.write(geometryShaderSize);
 
+    if (mGeometryExecutable != NULL && geometryShaderSize > 0)
+    {
+        unsigned char *geometryBlob = static_cast<unsigned char *>(mGeometryExecutable->getFunction());
+        stream.write(geometryBlob, geometryShaderSize);
+    }
+
     GUID identifier = mRenderer->getAdapterIdentifier();
 
     GLsizei streamLength = stream.length();
     const void *streamData = stream.data();
 
-    GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize + geometryShaderSize;
+    GLsizei totalLength = streamLength + sizeof(GUID);
     if (totalLength > bufSize)
     {
         if (length)
@@ -1283,18 +1396,6 @@
         memcpy(ptr, &identifier, sizeof(GUID));
         ptr += sizeof(GUID);
 
-        memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize);
-        ptr += pixelShaderSize;
-
-        memcpy(ptr, mVertexExecutable->getFunction(), vertexShaderSize);
-        ptr += vertexShaderSize;
-
-        if (mGeometryExecutable != NULL && geometryShaderSize > 0)
-        {
-            memcpy(ptr, mGeometryExecutable->getFunction(), geometryShaderSize);
-            ptr += geometryShaderSize;
-        }
-
         ASSERT(ptr - totalLength == binary);
     }
 
@@ -1334,7 +1435,8 @@
     mShaderVersion = vertexShader->getShaderVersion();
 
     std::string pixelHLSL = fragmentShader->getHLSL();
-    std::string vertexHLSL = vertexShader->getHLSL();
+    mVertexHLSL = vertexShader->getHLSL();
+    mVertexWorkarounds = vertexShader->getD3DWorkarounds();
 
     // Map the varyings to the register file
     const sh::ShaderVariable *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL};
@@ -1351,7 +1453,8 @@
     }
 
     mUsesPointSize = vertexShader->usesPointSize();
-    if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader, &mOutputVariables))
+    if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, pixelHLSL, mVertexHLSL,
+                                              fragmentShader, vertexShader, &mOutputVariables))
     {
         return false;
     }
@@ -1383,8 +1486,11 @@
 
     if (success)
     {
-        mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, vertexShader->getD3DWorkarounds());
-        mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, vertexShader->getD3DWorkarounds());
+        VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS];
+        GetInputLayoutFromShader(vertexShader->activeAttributes(), defaultInputLayout);
+
+        rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout);
+        mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, fragmentShader->getD3DWorkarounds());
 
         if (usesGeometryShader())
         {
@@ -1392,17 +1498,19 @@
             mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, rx::ANGLE_D3D_WORKAROUND_NONE);
         }
 
-        if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
+        if (!defaultVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
         {
             infoLog.append("Failed to create D3D shaders.");
             success = false;
 
-            delete mVertexExecutable;
-            mVertexExecutable = NULL;
-            delete mPixelExecutable;
-            mPixelExecutable = NULL;
-            delete mGeometryExecutable;
-            mGeometryExecutable = NULL;
+            while (!mVertexExecutables.empty())
+            {
+                delete mVertexExecutables.back();
+                mVertexExecutables.pop_back();
+            }
+
+            SafeDelete(mGeometryExecutable);
+            SafeDelete(mPixelExecutable);
         }
     }
 
diff --git a/src/libGLESv2/ProgramBinary.h b/src/libGLESv2/ProgramBinary.h
index 54f9920..808f387 100644
--- a/src/libGLESv2/ProgramBinary.h
+++ b/src/libGLESv2/ProgramBinary.h
@@ -25,6 +25,7 @@
 #include "libGLESv2/Uniform.h"
 #include "libGLESv2/Shader.h"
 #include "libGLESv2/Constants.h"
+#include "libGLESv2/renderer/VertexDataManager.h"
 
 namespace rx
 {
@@ -65,7 +66,7 @@
     ~ProgramBinary();
 
     rx::ShaderExecutable *getPixelExecutable() const;
-    rx::ShaderExecutable *getVertexExecutable() const;
+    rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]);
     rx::ShaderExecutable *getGeometryExecutable() const;
 
     GLuint getAttributeLocation(const char *name);
@@ -185,12 +186,30 @@
 
     static TextureType getTextureType(GLenum samplerType, InfoLog &infoLog);
 
+    class VertexExecutable
+    {
+      public:
+        VertexExecutable(rx::Renderer *const renderer,
+                         const VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
+                         rx::ShaderExecutable *shaderExecutable);
+        bool matchesInputLayout(const VertexFormat attributes[gl::MAX_VERTEX_ATTRIBS]) const;
+
+        const VertexFormat *inputs() const { return mInputs; }
+        rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
+
+      private:
+        VertexFormat mInputs[gl::MAX_VERTEX_ATTRIBS];
+        rx::ShaderExecutable *mShaderExecutable;
+    };
+
     rx::Renderer *const mRenderer;
     DynamicHLSL *mDynamicHLSL;
 
-    rx::ShaderExecutable *mPixelExecutable;
-    rx::ShaderExecutable *mVertexExecutable;
+    std::string mVertexHLSL;
+    rx::D3DWorkaroundType mVertexWorkarounds;
+    std::vector<VertexExecutable *> mVertexExecutables;
     rx::ShaderExecutable *mGeometryExecutable;
+    rx::ShaderExecutable *mPixelExecutable;
 
     sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
     int mSemanticIndex[MAX_VERTEX_ATTRIBS];
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index 61cb0fe..fa14806 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -130,7 +130,7 @@
                              bool ignoreViewport) = 0;
 
     virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0;
-    virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard) = 0;
+    virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, const gl::VertexFormat inputLayout[]) = 0;
     virtual void applyUniforms(const gl::ProgramBinary &programBinary) = 0;
     virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
     virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
diff --git a/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp b/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp
index b88a54f..5962862 100644
--- a/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp
+++ b/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp
@@ -22,6 +22,21 @@
 namespace rx
 {
 
+static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS],
+                           gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS])
+{
+    for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex];
+
+        if (translatedAttributes[attributeIndex].active)
+        {
+            inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute,
+                                                           translatedAttribute.currentValueType);
+        }
+    }
+}
+
 const unsigned int InputLayoutCache::kMaxInputLayouts = 1024;
 
 InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts)
@@ -135,7 +150,9 @@
     }
     else
     {
-        ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
+        gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS];
+        GetInputLayout(attributes, shaderInputLayout);
+        ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutableForInputLayout(shaderInputLayout));
 
         D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
         for (unsigned int j = 0; j < ilKey.elementCount; ++j)
diff --git a/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/libGLESv2/renderer/d3d11/Renderer11.cpp
index a4037f6..31d31c4 100644
--- a/src/libGLESv2/renderer/d3d11/Renderer11.cpp
+++ b/src/libGLESv2/renderer/d3d11/Renderer11.cpp
@@ -1403,9 +1403,9 @@
     }
 }
 
-void Renderer11::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard)
+void Renderer11::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, const gl::VertexFormat inputLayout[])
 {
-    ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
+    ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout);
     ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
     ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
 
diff --git a/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/libGLESv2/renderer/d3d11/Renderer11.h
index 69e04ab..2f7d403 100644
--- a/src/libGLESv2/renderer/d3d11/Renderer11.h
+++ b/src/libGLESv2/renderer/d3d11/Renderer11.h
@@ -75,7 +75,7 @@
 
     virtual bool applyPrimitiveType(GLenum mode, GLsizei count);
     virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
-    virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard);
+    virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, const gl::VertexFormat inputLayout[]);
     virtual void applyUniforms(const gl::ProgramBinary &programBinary);
     virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
                                      GLint first, GLsizei count, GLsizei instances);
diff --git a/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
index d857c01..2e7c083 100644
--- a/src/libGLESv2/renderer/d3d9/Renderer9.cpp
+++ b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
@@ -30,6 +30,7 @@
 #include "libGLESv2/renderer/d3d9/BufferStorage9.h"
 #include "libGLESv2/renderer/d3d9/Query9.h"
 #include "libGLESv2/renderer/d3d9/Fence9.h"
+#include "libGLESv2/angletypes.h"
 
 #include "libEGL/Display.h"
 
@@ -1722,11 +1723,11 @@
     }
 }
 
-void Renderer9::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard)
+void Renderer9::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, const gl::VertexFormat inputLayout[])
 {
     ASSERT(!rasterizerDiscard);
 
-    ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
+    ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout);
     ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
 
     IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL);
diff --git a/src/libGLESv2/renderer/d3d9/Renderer9.h b/src/libGLESv2/renderer/d3d9/Renderer9.h
index c665006..78e70cc 100644
--- a/src/libGLESv2/renderer/d3d9/Renderer9.h
+++ b/src/libGLESv2/renderer/d3d9/Renderer9.h
@@ -58,17 +58,6 @@
     IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length);
     HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
     HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer);
-#if 0
-    void *createTexture2D();
-    void *createTextureCube();
-    void *createQuery();
-    void *createIndexBuffer();
-    void *createVertexbuffer();
-
-    // state setup
-    void applyShaders();
-    void applyConstants();
-#endif
     virtual void generateSwizzle(gl::Texture *texture);
     virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
     virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture);
@@ -86,7 +75,7 @@
                              bool ignoreViewport);
 
     virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
-    virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard);
+    virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, const gl::VertexFormat inputLayout[]);
     virtual void applyUniforms(const gl::ProgramBinary &programBinary);
     virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
     virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],