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/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];