Refactor VertexAttribute to split the "current value" for generic attributes into its own class.

VAOs in GLES 3 do not store the current values, so these must be handled separately from other Vertex
Attribute data.

TRAC #23390

Signed-off-by: Shannon Woods
Signed-off-by: Geoff Lang
Authored-by: Jamie Madill
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index fd81f54..5694c02 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -244,9 +244,11 @@
         mIncompleteTextures[type].set(NULL);
     }
 
-    for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+    const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+    for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
     {
-        mState.vertexAttribute[i].mBoundBuffer.set(NULL);
+        mState.vertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
+        mState.vertexAttribute[attribIndex].mBoundBuffer.set(NULL);
     }
 
     for (int i = 0; i < QUERY_TYPE_COUNT; i++)
@@ -685,14 +687,22 @@
 
 void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
 {
+    ASSERT(attribNum < MAX_VERTEX_ATTRIBS);
     mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
 }
 
-const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
+const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) const
 {
+    ASSERT(attribNum < MAX_VERTEX_ATTRIBS);
     return mState.vertexAttribute[attribNum];
 }
 
+const VertexAttribCurrentValueData &Context::getVertexAttribCurrentValue(unsigned int attribNum) const
+{
+    ASSERT(attribNum < MAX_VERTEX_ATTRIBS);
+    return mState.vertexAttribCurrentValues[attribNum];
+}
+
 void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
                                    bool pureInteger, GLsizei stride, const void *pointer)
 {
@@ -2256,7 +2266,7 @@
 
     ProgramBinary *programBinary = getCurrentProgramBinary();
 
-    GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances);
+    GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, mState.vertexAttribCurrentValues, first, count, instances);
     if (err != GL_NO_ERROR)
     {
         return gl::error(err);
@@ -2315,7 +2325,7 @@
     ProgramBinary *programBinary = getCurrentProgramBinary();
 
     GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
-    err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances);
+    err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, mState.vertexAttribCurrentValues, indexInfo.minIndex, vertexCount, instances);
     if (err != GL_NO_ERROR)
     {
         return gl::error(err);
@@ -2845,37 +2855,19 @@
 void Context::setVertexAttribf(GLuint index, const GLfloat values[4])
 {
     ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
-
-    mState.vertexAttribute[index].mCurrentValue.FloatValues[0] = values[0];
-    mState.vertexAttribute[index].mCurrentValue.FloatValues[1] = values[1];
-    mState.vertexAttribute[index].mCurrentValue.FloatValues[2] = values[2];
-    mState.vertexAttribute[index].mCurrentValue.FloatValues[3] = values[3];
-    mState.vertexAttribute[index].mCurrentValue.Type = GL_FLOAT;
-    mState.vertexAttribute[index].mPureInteger = false;
+    mState.vertexAttribCurrentValues[index].setFloatValues(values);
 }
 
 void Context::setVertexAttribu(GLuint index, const GLuint values[4])
 {
     ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
-
-    mState.vertexAttribute[index].mCurrentValue.UnsignedIntValues[0] = values[0];
-    mState.vertexAttribute[index].mCurrentValue.UnsignedIntValues[1] = values[1];
-    mState.vertexAttribute[index].mCurrentValue.UnsignedIntValues[2] = values[2];
-    mState.vertexAttribute[index].mCurrentValue.UnsignedIntValues[3] = values[3];
-    mState.vertexAttribute[index].mCurrentValue.Type = GL_UNSIGNED_INT;
-    mState.vertexAttribute[index].mPureInteger = true;
+    mState.vertexAttribCurrentValues[index].setUnsignedIntValues(values);
 }
 
 void Context::setVertexAttribi(GLuint index, const GLint values[4])
 {
     ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
-
-    mState.vertexAttribute[index].mCurrentValue.IntValues[0] = values[0];
-    mState.vertexAttribute[index].mCurrentValue.IntValues[1] = values[1];
-    mState.vertexAttribute[index].mCurrentValue.IntValues[2] = values[2];
-    mState.vertexAttribute[index].mCurrentValue.IntValues[3] = values[3];
-    mState.vertexAttribute[index].mCurrentValue.Type = GL_INT;
-    mState.vertexAttribute[index].mPureInteger = true;
+    mState.vertexAttribCurrentValues[index].setIntValues(values);
 }
 
 void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 67f3e02..0230669 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -114,7 +114,9 @@
     BindingPointer<Renderbuffer> renderbuffer;
     GLuint currentProgram;
 
+    VertexAttribCurrentValueData vertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib
     VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS];
+
     BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
     BindingPointer<Query> activeQuery[QUERY_TYPE_COUNT];
 
@@ -227,7 +229,8 @@
     GLuint getActiveQuery(GLenum target) const;
 
     void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
-    const VertexAttribute &getVertexAttribState(unsigned int attribNum);
+    const VertexAttribute &getVertexAttribState(unsigned int attribNum) const;
+    const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
     void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,
                               bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
     const void *getVertexAttribPointer(unsigned int attribNum) const;
diff --git a/src/libGLESv2/VertexAttribute.h b/src/libGLESv2/VertexAttribute.h
index f49f99f..80e780e 100644
--- a/src/libGLESv2/VertexAttribute.h
+++ b/src/libGLESv2/VertexAttribute.h
@@ -21,11 +21,6 @@
     VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mPureInteger(false),
                         mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0)
     {
-        mCurrentValue.FloatValues[0] = 0.0f;
-        mCurrentValue.FloatValues[1] = 0.0f;
-        mCurrentValue.FloatValues[2] = 0.0f;
-        mCurrentValue.FloatValues[3] = 1.0f;
-        mCurrentValue.Type = GL_FLOAT;
     }
 
     int typeSize() const
@@ -67,22 +62,47 @@
 
     BindingPointer<Buffer> mBoundBuffer;   // Captured when glVertexAttribPointer is called.
     bool mArrayEnabled;   // From glEnable/DisableVertexAttribArray
-
-    struct CurrentValueData
-    {
-        union
-        {
-            GLfloat FloatValues[4];
-            GLint IntValues[4];
-            GLuint UnsignedIntValues[4];
-        };
-        GLenum Type;
-    };
-    CurrentValueData mCurrentValue; // From glVertexAttrib
-
     unsigned int mDivisor;
 };
 
+struct VertexAttribCurrentValueData
+{
+    union
+    {
+        GLfloat FloatValues[4];
+        GLint IntValues[4];
+        GLuint UnsignedIntValues[4];
+    };
+    GLenum Type;
+
+    void setFloatValues(const GLfloat floatValues[4])
+    {
+        for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+        {
+            FloatValues[valueIndex] = floatValues[valueIndex];
+        }
+        Type = GL_FLOAT;
+    }
+
+    void setIntValues(const GLint intValues[4])
+    {
+        for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+        {
+            IntValues[valueIndex] = intValues[valueIndex];
+        }
+        Type = GL_INT;
+    }
+
+    void setUnsignedIntValues(const GLuint unsignedIntValues[4])
+    {
+        for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+        {
+            UnsignedIntValues[valueIndex] = unsignedIntValues[valueIndex];
+        }
+        Type = GL_UNSIGNED_INT;
+    }
+};
+
 }
 
 #endif // LIBGLESV2_VERTEXATTRIBUTE_H_
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index f2c9723..72e35ab 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -5878,9 +5878,12 @@
                 *params = (GLfloat)attribState.mBoundBuffer.id();
                 break;
               case GL_CURRENT_VERTEX_ATTRIB:
-                for (int i = 0; i < 4; ++i)
                 {
-                    params[i] = attribState.mCurrentValue.FloatValues[i];
+                    const gl::VertexAttribCurrentValueData &currentValueData = context->getVertexAttribCurrentValue(index);
+                    for (int i = 0; i < 4; ++i)
+                    {
+                        params[i] = currentValueData.FloatValues[i];
+                    }
                 }
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
@@ -5936,10 +5939,13 @@
                 *params = attribState.mBoundBuffer.id();
                 break;
               case GL_CURRENT_VERTEX_ATTRIB:
-                for (int i = 0; i < 4; ++i)
                 {
-                    float currentValue = attribState.mCurrentValue.FloatValues[i];
-                    params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
+                    const gl::VertexAttribCurrentValueData &currentValueData = context->getVertexAttribCurrentValue(index);
+                    for (int i = 0; i < 4; ++i)
+                    {
+                        float currentValue = currentValueData.FloatValues[i];
+                        params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
+                    }
                 }
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
diff --git a/src/libGLESv2/renderer/InputLayoutCache.cpp b/src/libGLESv2/renderer/InputLayoutCache.cpp
index a9d4857..28b0767 100644
--- a/src/libGLESv2/renderer/InputLayoutCache.cpp
+++ b/src/libGLESv2/renderer/InputLayoutCache.cpp
@@ -79,6 +79,9 @@
             BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL;
 
             D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
+            DXGI_FORMAT dxgiFormat = attributes[i].attribute->mArrayEnabled ?
+                                     VertexBuffer11::getAttributeDXGIFormat(*attributes[i].attribute) :
+                                     VertexBuffer11::getCurrentValueDXGIFormat(attributes[i].currentValueType);
 
             // Record the type of the associated vertex shader vector in our key
             // This will prevent mismatched vertex shaders from using the same input layout
@@ -87,7 +90,7 @@
 
             ilKey.elements[ilKey.elementCount].SemanticName = semanticName;
             ilKey.elements[ilKey.elementCount].SemanticIndex = sortedSemanticIndices[i];
-            ilKey.elements[ilKey.elementCount].Format = vertexBuffer->getDXGIFormat(*attributes[i].attribute);
+            ilKey.elements[ilKey.elementCount].Format = dxgiFormat;
             ilKey.elements[ilKey.elementCount].InputSlot = i;
             ilKey.elements[ilKey.elementCount].AlignedByteOffset = 0;
             ilKey.elements[ilKey.elementCount].InputSlotClass = inputClass;
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index fa50bc0..a16efb5 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -43,6 +43,7 @@
 class Buffer;
 class Texture;
 class Framebuffer;
+struct VertexAttribCurrentValueData;
 }
 
 namespace rx
@@ -130,7 +131,8 @@
     virtual void applyShaders(gl::ProgramBinary *programBinary) = 0;
     virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) = 0;
     virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) = 0;
+    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
+                                     GLint first, GLsizei count, GLsizei instances) = 0;
     virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0;
 
     virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances) = 0;
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 00c1159..95b589d 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -1034,10 +1034,11 @@
     return true;
 }
 
-GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
+GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
+                                     GLint first, GLsizei count, GLsizei instances)
 {
     TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
-    GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
+    GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances);
     if (err != GL_NO_ERROR)
     {
         return err;
diff --git a/src/libGLESv2/renderer/Renderer11.h b/src/libGLESv2/renderer/Renderer11.h
index 7ca1456..92a3eef 100644
--- a/src/libGLESv2/renderer/Renderer11.h
+++ b/src/libGLESv2/renderer/Renderer11.h
@@ -74,7 +74,8 @@
     virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
     virtual void applyShaders(gl::ProgramBinary *programBinary);
     virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray);
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances);
+    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
+                                     GLint first, GLsizei count, GLsizei instances);
     virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
 
     virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances);
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index 6a54b47..5bb1cae 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -1338,10 +1338,11 @@
     return true;
 }
 
-GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
+GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
+                                    GLint first, GLsizei count, GLsizei instances)
 {
     TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
-    GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
+    GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances);
     if (err != GL_NO_ERROR)
     {
         return err;
diff --git a/src/libGLESv2/renderer/Renderer9.h b/src/libGLESv2/renderer/Renderer9.h
index 47b8a4f..fe607ba 100644
--- a/src/libGLESv2/renderer/Renderer9.h
+++ b/src/libGLESv2/renderer/Renderer9.h
@@ -88,7 +88,8 @@
     virtual void applyShaders(gl::ProgramBinary *programBinary);
     virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray);
     virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
-    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances);
+    virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
+                                     GLint first, GLsizei count, GLsizei instances);
     virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
 
     virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances);
diff --git a/src/libGLESv2/renderer/VertexBuffer.cpp b/src/libGLESv2/renderer/VertexBuffer.cpp
index 781f253..9c683b6 100644
--- a/src/libGLESv2/renderer/VertexBuffer.cpp
+++ b/src/libGLESv2/renderer/VertexBuffer.cpp
@@ -87,7 +87,8 @@
     return mVertexBuffer->discard();
 }
 
-int VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances)
+int VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+                                                 GLint start, GLsizei count, GLsizei instances)
 {
     if (!reserveSpace(mReservedSpace))
     {
@@ -95,7 +96,7 @@
     }
     mReservedSpace = 0;
 
-    if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition))
+    if (!mVertexBuffer->storeVertexAttributes(attrib, currentValue, start, count, instances, mWritePosition))
     {
         return -1;
     }
@@ -194,13 +195,14 @@
     }
 }
 
-int StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances)
+int StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+                                                       GLint start, GLsizei count, GLsizei instances)
 {
     int attributeOffset = attrib.mOffset % attrib.stride();
     VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attrib.mPureInteger, attributeOffset, getWritePosition() };
     mCache.push_back(element);
 
-    return VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances);
+    return VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances);
 }
 
 }
diff --git a/src/libGLESv2/renderer/VertexBuffer.h b/src/libGLESv2/renderer/VertexBuffer.h
index 50a0539..64a8264 100644
--- a/src/libGLESv2/renderer/VertexBuffer.h
+++ b/src/libGLESv2/renderer/VertexBuffer.h
@@ -15,6 +15,7 @@
 namespace gl
 {
 class VertexAttribute;
+struct VertexAttribCurrentValueData;
 }
 
 namespace rx
@@ -29,12 +30,13 @@
 
     virtual bool initialize(unsigned int size, bool dynamicUsage) = 0;
 
-    virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
-                                       GLsizei instances, unsigned int offset) = 0;
+    virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+                                       GLint start, GLsizei count, GLsizei instances, unsigned int offset) = 0;
     virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
                                           GLsizei instances) const = 0;
 
     virtual bool requiresConversion(const gl::VertexAttribute &attrib) const = 0;
+    virtual bool requiresConversion(const gl::VertexAttribCurrentValueData &currentValue) const = 0;
 
     virtual unsigned int getBufferSize() const = 0;
     virtual bool setBufferSize(unsigned int size) = 0;
@@ -64,7 +66,8 @@
 
     unsigned int getSerial() const;
 
-    virtual int storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances);
+    virtual int storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+                                      GLint start, GLsizei count, GLsizei instances);
 
     VertexBuffer* getVertexBuffer() const;
 
@@ -106,7 +109,8 @@
     explicit StaticVertexBufferInterface(rx::Renderer *renderer);
     ~StaticVertexBufferInterface();
 
-    int storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances);
+    int storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+                              GLint start, GLsizei count, GLsizei instances);
 
     // Returns the offset into the vertex buffer, or -1 if not found
     int lookupAttribute(const gl::VertexAttribute &attribute);
diff --git a/src/libGLESv2/renderer/VertexBuffer11.cpp b/src/libGLESv2/renderer/VertexBuffer11.cpp
index ad70542..6e9d48b 100644
--- a/src/libGLESv2/renderer/VertexBuffer11.cpp
+++ b/src/libGLESv2/renderer/VertexBuffer11.cpp
@@ -14,6 +14,46 @@
 #include "libGLESv2/renderer/Renderer11.h"
 #include "libGLESv2/VertexAttribute.h"
 
+namespace
+{
+
+unsigned int GetIntegerTypeIndex(GLenum type)
+{
+    switch (type)
+    {
+      case GL_BYTE:                        return 0;
+      case GL_UNSIGNED_BYTE:               return 1;
+      case GL_SHORT:                       return 2;
+      case GL_UNSIGNED_SHORT:              return 3;
+      case GL_INT:                         return 4;
+      case GL_UNSIGNED_INT:                return 5;
+      case GL_INT_2_10_10_10_REV:          return 6;
+      case GL_UNSIGNED_INT_2_10_10_10_REV: return 7;
+      default:                             UNREACHABLE(); return 0;
+    }
+}
+
+unsigned int GetFloatTypeIndex(GLenum type)
+{
+    switch (type)
+    {
+      case GL_BYTE:                        return 0;
+      case GL_UNSIGNED_BYTE:               return 1;
+      case GL_SHORT:                       return 2;
+      case GL_UNSIGNED_SHORT:              return 3;
+      case GL_INT:                         return 4;
+      case GL_UNSIGNED_INT:                return 5;
+      case GL_INT_2_10_10_10_REV:          return 6;
+      case GL_UNSIGNED_INT_2_10_10_10_REV: return 7;
+      case GL_FIXED:                       return 8;
+      case GL_HALF_FLOAT:                  return 9;
+      case GL_FLOAT:                       return 10;
+      default:                             UNREACHABLE(); return 0;
+    }
+}
+
+}
+
 namespace rx
 {
 
@@ -73,15 +113,17 @@
     return static_cast<VertexBuffer11*>(vetexBuffer);
 }
 
-bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
-                                           GLsizei instances, unsigned int offset)
+bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+                                           GLint start, GLsizei count, GLsizei instances, unsigned int offset)
 {
     if (mBuffer)
     {
         gl::Buffer *buffer = attrib.mBoundBuffer.get();
 
         int inputStride = attrib.stride();
-        const VertexConverter &converter = getVertexConversion(attrib);
+        const VertexConverter &converter = attrib.mArrayEnabled ?
+                                           getVertexConversion(attrib) :
+                                           getVertexConversion(currentValue.Type, currentValue.Type != GL_FLOAT, false, 4);
 
         ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
 
@@ -110,7 +152,7 @@
         }
         else
         {
-            input = reinterpret_cast<const char*>(attrib.mCurrentValue.FloatValues);
+            input = reinterpret_cast<const char*>(currentValue.FloatValues);
         }
 
         if (instances == 0 || attrib.mDivisor == 0)
@@ -135,10 +177,10 @@
 unsigned int VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
                                               GLsizei instances) const
 {
-    unsigned int elementSize = getVertexConversion(attrib).outputElementSize;
-
     if (attrib.mArrayEnabled)
     {
+        unsigned int elementSize = getVertexConversion(attrib).outputElementSize;
+
         if (instances == 0 || attrib.mDivisor == 0)
         {
             return elementSize * count;
@@ -150,6 +192,7 @@
     }
     else
     {
+        unsigned int elementSize = 4;
         return elementSize * 4;
     }
 }
@@ -159,6 +202,11 @@
     return !getVertexConversion(attrib).identity;
 }
 
+bool VertexBuffer11::requiresConversion(const gl::VertexAttribCurrentValueData &currentValue) const
+{
+    return !getVertexConversion(currentValue.Type, currentValue.Type != GL_FLOAT, false, 4).identity;
+}
+
 unsigned int VertexBuffer11::getBufferSize() const
 {
     return mBufferSize;
@@ -201,16 +249,24 @@
     }
 }
 
-unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const
-{
-    return getVertexConversion(attrib).outputElementSize;
-}
-
-DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const
+DXGI_FORMAT VertexBuffer11::getAttributeDXGIFormat(const gl::VertexAttribute &attrib)
 {
     return getVertexConversion(attrib).dxgiFormat;
 }
 
+DXGI_FORMAT VertexBuffer11::getCurrentValueDXGIFormat(GLenum currentValueType)
+{
+    if (currentValueType == GL_FLOAT)
+    {
+        return mFloatVertexTranslations[GetFloatTypeIndex(GL_FLOAT)][0][3].dxgiFormat;
+    }
+    else
+    {
+        ASSERT(currentValueType == GL_INT || currentValueType == GL_UNSIGNED_INT);
+        return mIntegerVertexTranslations[GetIntegerTypeIndex(currentValueType)][3].dxgiFormat;
+    }
+}
+
 ID3D11Buffer *VertexBuffer11::getBuffer() const
 {
     return mBuffer;
@@ -722,45 +778,20 @@
 
 const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(const gl::VertexAttribute &attribute)
 {
-    GLenum type = attribute.mArrayEnabled ? attribute.mType : attribute.mCurrentValue.Type;
-    if (attribute.mPureInteger)
-    {
-        unsigned int typeIndex = 0;
-        switch (type)
-        {
-          case GL_BYTE:                        typeIndex = 0; break;
-          case GL_UNSIGNED_BYTE:               typeIndex = 1; break;
-          case GL_SHORT:                       typeIndex = 2; break;
-          case GL_UNSIGNED_SHORT:              typeIndex = 3; break;
-          case GL_INT:                         typeIndex = 4; break;
-          case GL_UNSIGNED_INT:                typeIndex = 5; break;
-          case GL_INT_2_10_10_10_REV:          typeIndex = 6; break;
-          case GL_UNSIGNED_INT_2_10_10_10_REV: typeIndex = 7; break;
-          default:                             UNREACHABLE(); break;
-        }
+    return getVertexConversion(attribute.mType, attribute.mPureInteger, attribute.mNormalized, attribute.mSize);
+}
 
-        return mIntegerVertexTranslations[typeIndex][attribute.mSize - 1];
+const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(GLenum type, bool pureInteger, bool normalized, int size)
+{
+    if (pureInteger)
+    {
+        const unsigned int typeIndex = GetIntegerTypeIndex(type);
+        return mIntegerVertexTranslations[typeIndex][size - 1];
     }
     else
     {
-        unsigned int typeIndex = 0;
-        switch (type)
-        {
-          case GL_BYTE:                        typeIndex =  0; break;
-          case GL_UNSIGNED_BYTE:               typeIndex =  1; break;
-          case GL_SHORT:                       typeIndex =  2; break;
-          case GL_UNSIGNED_SHORT:              typeIndex =  3; break;
-          case GL_INT:                         typeIndex =  4; break;
-          case GL_UNSIGNED_INT:                typeIndex =  5; break;
-          case GL_INT_2_10_10_10_REV:          typeIndex =  6; break;
-          case GL_UNSIGNED_INT_2_10_10_10_REV: typeIndex =  7; break;
-          case GL_FIXED:                       typeIndex =  8; break;
-          case GL_HALF_FLOAT:                  typeIndex =  9; break;
-          case GL_FLOAT:                       typeIndex = 10; break;
-          default:                             UNREACHABLE(); break;
-        }
-
-        return mFloatVertexTranslations[typeIndex][attribute.mNormalized ? 1 : 0][attribute.mSize - 1];
+        const unsigned int typeIndex = GetFloatTypeIndex(type);
+        return mFloatVertexTranslations[typeIndex][normalized ? 1 : 0][size - 1];
     }
 }
 
diff --git a/src/libGLESv2/renderer/VertexBuffer11.h b/src/libGLESv2/renderer/VertexBuffer11.h
index a2be854..66f7f61 100644
--- a/src/libGLESv2/renderer/VertexBuffer11.h
+++ b/src/libGLESv2/renderer/VertexBuffer11.h
@@ -25,19 +25,20 @@
 
     static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer);
 
-    virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
-                                       unsigned int offset);
+    virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+                                       GLint start, GLsizei count, GLsizei instances, unsigned int offset);
 
     virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const;
 
     virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
+    virtual bool requiresConversion(const gl::VertexAttribCurrentValueData &currentValue) const;
 
     virtual unsigned int getBufferSize() const;
     virtual bool setBufferSize(unsigned int size);
     virtual bool discard();
 
-    unsigned int getVertexSize(const gl::VertexAttribute &attrib) const;
-    DXGI_FORMAT getDXGIFormat(const gl::VertexAttribute &attrib) const;
+    static DXGI_FORMAT getAttributeDXGIFormat(const gl::VertexAttribute &attrib);
+    static DXGI_FORMAT getCurrentValueDXGIFormat(GLenum currentValueType);
 
     ID3D11Buffer *getBuffer() const;
 
@@ -66,6 +67,7 @@
     static const VertexConverter mIntegerVertexTranslations[NUM_GL_INTEGER_VERTEX_ATTRIB_TYPES][4]; // [GL types as enumerated by typeIndex()][size - 1]
 
     static const VertexConverter &getVertexConversion(const gl::VertexAttribute &attribute);
+    static const VertexConverter &getVertexConversion(GLenum type, bool pureInteger, bool normalized, int size);
 };
 
 }
diff --git a/src/libGLESv2/renderer/VertexBuffer9.cpp b/src/libGLESv2/renderer/VertexBuffer9.cpp
index 36826aa..f1b6c9c 100644
--- a/src/libGLESv2/renderer/VertexBuffer9.cpp
+++ b/src/libGLESv2/renderer/VertexBuffer9.cpp
@@ -81,8 +81,8 @@
     return static_cast<VertexBuffer9*>(vertexBuffer);
 }
 
-bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
-                                             GLsizei instances, unsigned int offset)
+bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+                                          GLint start, GLsizei count, GLsizei instances, unsigned int offset)
 {
     if (mVertexBuffer)
     {
@@ -118,7 +118,7 @@
         }
         else
         {
-            input = reinterpret_cast<const char*>(attrib.mCurrentValue.FloatValues);
+            input = reinterpret_cast<const char*>(currentValue.FloatValues);
         }
 
         if (instances == 0 || attrib.mDivisor == 0)
@@ -156,9 +156,10 @@
     return formatConverter(attrib).identity;
 }
 
-unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const
+bool VertexBuffer9::requiresConversion(const gl::VertexAttribCurrentValueData &currentValue) const
 {
-    return spaceRequired(attrib, 1, 0);
+    ASSERT(currentValue.Type == GL_FLOAT);
+    return getCurrentValueFormatConverter().identity;
 }
 
 D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const
@@ -445,11 +446,19 @@
 
 const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute)
 {
+    if (!attribute.mArrayEnabled)
+    {
+        return getCurrentValueFormatConverter();
+    }
+
     // Pure integer attributes only supported in ES3.0
     ASSERT(!attribute.mPureInteger);
+    return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
+}
 
-    GLenum type = attribute.mArrayEnabled ? attribute.mType : attribute.mCurrentValue.Type;
-    return mFormatConverters[typeIndex(type)][attribute.mNormalized][attribute.mSize - 1];
+const VertexBuffer9::FormatConverter &VertexBuffer9::getCurrentValueFormatConverter()
+{
+    return mFormatConverters[typeIndex(GL_FLOAT)][0][3];
 }
 
 unsigned int VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances)
diff --git a/src/libGLESv2/renderer/VertexBuffer9.h b/src/libGLESv2/renderer/VertexBuffer9.h
index 8950959..73708b4 100644
--- a/src/libGLESv2/renderer/VertexBuffer9.h
+++ b/src/libGLESv2/renderer/VertexBuffer9.h
@@ -25,14 +25,14 @@
 
     static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer);
 
-    virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
-                                       unsigned int offset);
+    virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
+                                       GLint start, GLsizei count, GLsizei instances, unsigned int offset);
 
     virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const;
 
     virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
+    virtual bool requiresConversion(const gl::VertexAttribCurrentValueData &currentValue) const;
 
-    unsigned int getVertexSize(const gl::VertexAttribute &attrib) const;
     D3DDECLTYPE getDeclType(const gl::VertexAttribute &attrib) const;
 
     virtual unsigned int getBufferSize() const;
@@ -80,6 +80,7 @@
 
     static unsigned int typeIndex(GLenum type);
     static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute);
+    static const FormatConverter &getCurrentValueFormatConverter();
 
     static unsigned int spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances);
 };
diff --git a/src/libGLESv2/renderer/VertexDataManager.cpp b/src/libGLESv2/renderer/VertexDataManager.cpp
index 78b2e4f..2cd18d8 100644
--- a/src/libGLESv2/renderer/VertexDataManager.cpp
+++ b/src/libGLESv2/renderer/VertexDataManager.cpp
@@ -26,12 +26,25 @@
 namespace rx
 {
 
-static int elementsInBuffer(const gl::VertexAttribute &attribute, int size)
+static int ElementsInBuffer(const gl::VertexAttribute &attribute, int size)
 {
     int stride = attribute.stride();
     return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride;
 }
 
+static bool DirectStoragePossible(VertexBufferInterface *vb, const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue)
+{
+    gl::Buffer *buffer = attrib.mBoundBuffer.get();
+    BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
+
+    const bool isAligned = (attrib.stride() % 4 == 0) && (attrib.mOffset % 4 == 0);
+    const bool requiresConversion = attrib.mArrayEnabled ?
+                                    vb->getVertexBuffer()->requiresConversion(attrib) :
+                                    vb->getVertexBuffer()->requiresConversion(currentValue);
+
+    return storage && storage->supportsDirectBinding() && !requiresConversion && isAligned;
+}
+
 VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer)
 {
     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
@@ -63,17 +76,8 @@
     }
 }
 
-static bool directStoragePossible(VertexBufferInterface* vb, const gl::VertexAttribute& attrib)
-{
-    gl::Buffer *buffer = attrib.mBoundBuffer.get();
-    BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
-
-    const bool isAligned = (attrib.stride() % 4 == 0) && (attrib.mOffset % 4 == 0);
-
-    return storage && storage->supportsDirectBinding() && !vb->getVertexBuffer()->requiresConversion(attrib) && isAligned;
-}
-
-GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
+GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[],
+                                            gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
 {
     if (!mStreamingBuffer)
     {
@@ -94,7 +98,7 @@
             StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
 
             if (staticBuffer && staticBuffer->getBufferSize() > 0 && staticBuffer->lookupAttribute(attribs[i]) == -1 &&
-                !directStoragePossible(staticBuffer, attribs[i]))
+                !DirectStoragePossible(staticBuffer, attribs[i], currentValues[i]))
             {
                 buffer->invalidateStaticData();
             }
@@ -110,13 +114,13 @@
             StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
             VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
 
-            if (!directStoragePossible(vertexBuffer, attribs[i]))
+            if (!DirectStoragePossible(vertexBuffer, attribs[i], currentValues[i]))
             {
                 if (staticBuffer)
                 {
                     if (staticBuffer->getBufferSize() == 0)
                     {
-                        int totalCount = elementsInBuffer(attribs[i], buffer->size());
+                        int totalCount = ElementsInBuffer(attribs[i], buffer->size());
                         staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0);
                     }
                 }
@@ -148,7 +152,7 @@
                 VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
 
                 BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
-                bool directStorage = directStoragePossible(vertexBuffer, attribs[i]);
+                bool directStorage = DirectStoragePossible(vertexBuffer, attribs[i], currentValues[i]);
 
                 std::size_t streamOffset = -1;
                 unsigned int outputElementSize = 0;
@@ -166,10 +170,10 @@
                     if (streamOffset == -1)
                     {
                         // Convert the entire buffer
-                        int totalCount = elementsInBuffer(attribs[i], storage->getSize());
+                        int totalCount = ElementsInBuffer(attribs[i], storage->getSize());
                         int startIndex = attribs[i].mOffset / attribs[i].stride();
 
-                        streamOffset = staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0);
+                        streamOffset = staticBuffer->storeVertexAttributes(attribs[i], currentValues[i], -startIndex, totalCount, 0);
                     }
 
                     if (streamOffset != -1)
@@ -185,7 +189,7 @@
                 else
                 {
                     outputElementSize = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0);
-                    streamOffset = mStreamingBuffer->storeVertexAttributes(attribs[i], start, count, instances);
+                    streamOffset = mStreamingBuffer->storeVertexAttributes(attribs[i], currentValues[i], start, count, instances);
                 }
 
                 if (streamOffset == -1)
@@ -199,6 +203,7 @@
                 translated[i].divisor = attribs[i].mDivisor;
 
                 translated[i].attribute = &attribs[i];
+                translated[i].currentValueType = currentValues[i].Type;
                 translated[i].stride = outputElementSize;
                 translated[i].offset = streamOffset;
             }
@@ -211,10 +216,10 @@
 
                 StreamingVertexBufferInterface *buffer = mCurrentValueBuffer[i];
 
-                if (memcmp(&mCurrentValue[i], &attribs[i].mCurrentValue, sizeof(gl::VertexAttribute::CurrentValueData)) != 0)
+                if (memcmp(&mCurrentValue[i], &currentValues[i], sizeof(gl::VertexAttribCurrentValueData)) != 0)
                 {
                     buffer->reserveVertexSpace(attribs[i], 1, 0);
-                    int streamOffset = buffer->storeVertexAttributes(attribs[i], 0, 1, 0);
+                    int streamOffset = buffer->storeVertexAttributes(attribs[i], currentValues[i], 0, 1, 0);
                     if (streamOffset == -1)
                     {
                         return GL_OUT_OF_MEMORY;
@@ -229,6 +234,7 @@
                 translated[i].divisor = 0;
 
                 translated[i].attribute = &attribs[i];
+                translated[i].currentValueType = currentValues[i].Type;
                 translated[i].stride = 0;
                 translated[i].offset = mCurrentValueOffsets[i];
             }
diff --git a/src/libGLESv2/renderer/VertexDataManager.h b/src/libGLESv2/renderer/VertexDataManager.h
index 04c8ad3..b442c46 100644
--- a/src/libGLESv2/renderer/VertexDataManager.h
+++ b/src/libGLESv2/renderer/VertexDataManager.h
@@ -32,6 +32,7 @@
     bool active;
 
     const gl::VertexAttribute *attribute;
+    GLenum currentValueType;
     UINT offset;
     UINT stride;   // 0 means not to advance the read pointer at all
 
@@ -47,7 +48,8 @@
     VertexDataManager(rx::Renderer *renderer);
     virtual ~VertexDataManager();
 
-    GLenum prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
+    GLenum prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[],
+                             gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
@@ -56,7 +58,7 @@
 
     StreamingVertexBufferInterface *mStreamingBuffer;
 
-    gl::VertexAttribute::CurrentValueData mCurrentValue[gl::MAX_VERTEX_ATTRIBS];
+    gl::VertexAttribCurrentValueData mCurrentValue[gl::MAX_VERTEX_ATTRIBS];
 
     StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS];
     std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS];