VertexDataManager now supports direct buffers when vertex conversion is not needed.

TRAC #22297

Signed-off-by: Jamie Madill
Signed-off-by: Nicolas Capens
Author: Geoff Lang

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1886 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/InputLayoutCache.cpp b/src/libGLESv2/renderer/InputLayoutCache.cpp
index 8e76cec..6bef612 100644
--- a/src/libGLESv2/renderer/InputLayoutCache.cpp
+++ b/src/libGLESv2/renderer/InputLayoutCache.cpp
@@ -9,6 +9,7 @@
 
 #include "libGLESv2/renderer/InputLayoutCache.h"
 #include "libGLESv2/renderer/VertexBuffer11.h"
+#include "libGLESv2/renderer/BufferStorage11.h"
 #include "libGLESv2/renderer/ShaderExecutable11.h"
 #include "libGLESv2/ProgramBinary.h"
 
@@ -69,6 +70,7 @@
         if (attributes[i].active)
         {
             VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer);
+            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;
 
@@ -81,7 +83,7 @@
             ilKey.elements[ilKey.elementCount].InstanceDataStepRate = attributes[i].divisor;
             ilKey.elementCount++;
 
-            vertexBuffers[i] = vertexBuffer->getBuffer();
+            vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer();
             vertexStrides[i] = attributes[i].stride;
             vertexOffsets[i] = attributes[i].offset;
         }
diff --git a/src/libGLESv2/renderer/VertexDataManager.cpp b/src/libGLESv2/renderer/VertexDataManager.cpp
index 00a1633..f0b7123 100644
--- a/src/libGLESv2/renderer/VertexDataManager.cpp
+++ b/src/libGLESv2/renderer/VertexDataManager.cpp
@@ -86,25 +86,33 @@
         {
             gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
             StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
+            VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
 
             BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
-            if (staticBuffer)
+            bool alignedStride = attribs[i].stride() % 4 == 0;
+            bool directStorage = alignedStride && storage && storage->supportsDirectBinding() &&
+                                 !vertexBuffer->getVertexBuffer()->requiresConversion(attribs[i]);
+
+            if (!directStorage)
             {
-                if (staticBuffer->getBufferSize() == 0)
+                if (staticBuffer)
                 {
-                    int totalCount = elementsInBuffer(attribs[i], storage->getSize());
-                    staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0);
+                    if (staticBuffer->getBufferSize() == 0)
+                    {
+                        int totalCount = elementsInBuffer(attribs[i], storage->getSize());
+                        staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0);
+                    }
+                    else if (staticBuffer->lookupAttribute(attribs[i]) == -1)
+                    {
+                        mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances);
+                        buffer->invalidateStaticData();
+                    }
                 }
-                else if (staticBuffer->lookupAttribute(attribs[i]) == -1)
+                else
                 {
                     mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances);
-                    buffer->invalidateStaticData();
                 }
             }
-            else
-            {
-                mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances);
-            }
         }
     }
 
@@ -128,11 +136,20 @@
                 VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
 
                 BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
+                bool alignedStride = attribs[i].stride() % 4 == 0;
+                bool directStorage = alignedStride && storage && storage->supportsDirectBinding() &&
+                                     !vertexBuffer->getVertexBuffer()->requiresConversion(attribs[i]);
 
                 std::size_t streamOffset = -1;
                 unsigned int outputElementSize = 0;
 
-                if (staticBuffer)
+                if (directStorage)
+                {
+                    outputElementSize = attribs[i].stride();
+                    streamOffset = attribs[i].mOffset + outputElementSize * start;
+                    storage->markBufferUsage();
+                }
+                else if (staticBuffer)
                 {
                     streamOffset = staticBuffer->lookupAttribute(attribs[i]);
                     outputElementSize = staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0);
@@ -167,8 +184,9 @@
                     return GL_OUT_OF_MEMORY;
                 }
 
+                translated[i].storage = directStorage ? storage : NULL;
                 translated[i].vertexBuffer = vertexBuffer->getVertexBuffer();
-                translated[i].serial = vertexBuffer->getSerial();
+                translated[i].serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial();
                 translated[i].divisor = attribs[i].mDivisor;
 
                 translated[i].attribute = &attribs[i];
@@ -200,6 +218,7 @@
                     mCurrentValueOffsets[i] = streamOffset;
                 }
 
+                translated[i].storage = NULL;
                 translated[i].vertexBuffer = mCurrentValueBuffer[i]->getVertexBuffer();
                 translated[i].serial = mCurrentValueBuffer[i]->getSerial();
                 translated[i].divisor = 0;
diff --git a/src/libGLESv2/renderer/VertexDataManager.h b/src/libGLESv2/renderer/VertexDataManager.h
index bd7bbaa..1c54838 100644
--- a/src/libGLESv2/renderer/VertexDataManager.h
+++ b/src/libGLESv2/renderer/VertexDataManager.h
@@ -31,6 +31,7 @@
     UINT stride;   // 0 means not to advance the read pointer at all
 
     VertexBuffer *vertexBuffer;
+    BufferStorage *storage;
     unsigned int serial;
     unsigned int divisor;
 };
diff --git a/src/libGLESv2/renderer/VertexDeclarationCache.cpp b/src/libGLESv2/renderer/VertexDeclarationCache.cpp
index 8ed226d..a65a158 100644
--- a/src/libGLESv2/renderer/VertexDeclarationCache.cpp
+++ b/src/libGLESv2/renderer/VertexDeclarationCache.cpp
@@ -82,6 +82,9 @@
     {
         if (attributes[i].active)
         {
+            // Directly binding the storage buffer is not supported for d3d9
+            ASSERT(attributes[i].storage == NULL);
+
             int stream = i;
 
             if (instances > 0)