Cache applied vertex buffers and input layout.

Issue #451

Signed-off-by: Jamie Madill
Signed-off-by: Shannon Woods
Author: Geoff Lang
diff --git a/src/libGLESv2/renderer/InputLayoutCache.cpp b/src/libGLESv2/renderer/InputLayoutCache.cpp
index 0402bb3..fcc6f7c 100644
--- a/src/libGLESv2/renderer/InputLayoutCache.cpp
+++ b/src/libGLESv2/renderer/InputLayoutCache.cpp
@@ -28,6 +28,13 @@
     mCounter = 0;
     mDevice = NULL;
     mDeviceContext = NULL;
+    mCurrentIL = NULL;
+    for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+    {
+        mCurrentBuffers[i] = -1;
+        mCurrentVertexStrides[i] = -1;
+        mCurrentVertexOffsets[i] = -1;
+    }
 }
 
 InputLayoutCache::~InputLayoutCache()
@@ -49,6 +56,18 @@
         i->second.inputLayout->Release();
     }
     mInputLayoutMap.clear();
+    markDirty();
+}
+
+void InputLayoutCache::markDirty()
+{
+    mCurrentIL = NULL;
+    for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+    {
+        mCurrentBuffers[i] = -1;
+        mCurrentVertexStrides[i] = -1;
+        mCurrentVertexOffsets[i] = -1;
+    }
 }
 
 GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
@@ -66,6 +85,7 @@
     InputLayoutKey ilKey = { 0 };
 
     ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL };
+    unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 };
     UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 };
     UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 };
 
@@ -95,6 +115,7 @@
             ilKey.elementCount++;
 
             vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer();
+            vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial();
             vertexStrides[i] = attributes[i].stride;
             vertexOffsets[i] = attributes[i].offset;
         }
@@ -143,8 +164,23 @@
         mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair));
     }
 
-    mDeviceContext->IASetInputLayout(inputLayout);
-    mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, vertexBuffers, vertexStrides, vertexOffsets);
+    if (inputLayout != mCurrentIL)
+    {
+        mDeviceContext->IASetInputLayout(inputLayout);
+        mCurrentIL = inputLayout;
+    }
+
+    for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+    {
+        if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] ||
+            vertexOffsets[i] != mCurrentVertexOffsets[i])
+        {
+            mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]);
+            mCurrentBuffers[i] = vertexBufferSerials[i];
+            mCurrentVertexStrides[i] = vertexStrides[i];
+            mCurrentVertexOffsets[i] = vertexOffsets[i];
+        }
+    }
 
     return GL_NO_ERROR;
 }
diff --git a/src/libGLESv2/renderer/InputLayoutCache.h b/src/libGLESv2/renderer/InputLayoutCache.h
index d95f39f..797853d 100644
--- a/src/libGLESv2/renderer/InputLayoutCache.h
+++ b/src/libGLESv2/renderer/InputLayoutCache.h
@@ -30,6 +30,7 @@
 
     void initialize(ID3D11Device *device, ID3D11DeviceContext *context);
     void clear();
+    void markDirty();
 
     GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
                               gl::ProgramBinary *programBinary);
@@ -50,6 +51,11 @@
         unsigned long long lastUsedTime;
     };
 
+    ID3D11InputLayout *mCurrentIL;
+    unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS];
+    UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS];
+    UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS];
+
     static std::size_t hashInputLayout(const InputLayoutKey &inputLayout);
     static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b);
 
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index e544b40..c0066d0 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -1797,6 +1797,8 @@
     mAppliedProgramBinarySerial = 0;
     memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants));
     memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants));
+
+    mInputLayoutCache.markDirty();
 }
 
 void Renderer11::releaseDeviceResources()