Re-land "In D3D, cache static vertex buffers to prevent wasteful recreation"

BUG=angleproject:197

Changes since first failed patch:
 - Optimized BufferD3D::getStaticVertexBuffer()
 - Removed loop to commit static buffers
 - Out-of-date static buffers (which are much rarer anyway after this patch)
   are marked for deletion at the *next* draw call, rather than searched for
   before each draw call. That search was expensive.

The change should see a net improvement to DrawCallPerfBenchmark for D3D null.

Change-Id: If4942e0afd9e8fefadce8820a1305e13636547ef
Reviewed-on: https://chromium-review.googlesource.com/311115
Tested-by: Austin Kinross <aukinros@microsoft.com>
Tryjob-Request: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
index 559e633..5376e6c 100644
--- a/src/libANGLE/renderer/d3d/VertexDataManager.cpp
+++ b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
@@ -88,10 +88,17 @@
     {
         gl::Buffer *buffer = translated->attribute->buffer.get();
         BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
-        StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : nullptr;
+        StaticVertexBufferInterface *staticBuffer =
+            storage
+                ? storage->getStaticVertexBuffer(*translated->attribute, D3D_BUFFER_DO_NOT_CREATE)
+                : nullptr;
 
         if (staticBuffer)
         {
+            // Commit all the static vertex buffers. This fixes them in size/contents, and forces
+            // ANGLE to use a new static buffer (or recreate the static buffers) next time
+            staticBuffer->commit();
+
             staticBuffer->getVertexBuffer()->hintUnmapResource();
         }
     }
@@ -146,10 +153,14 @@
             {
                 mActiveEnabledAttributes.push_back(translated);
 
-                // Also invalidate static buffers that don't contain matching attributes
-                invalidateMatchingStaticData(
-                    vertexAttributes[attribIndex],
-                    state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)));
+                gl::Buffer *buffer = vertexAttributes[attribIndex].buffer.get();
+                if (buffer)
+                {
+                    // Also reinitialize static buffers which didn't contain matching data
+                    // last time they were used
+                    BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer);
+                    bufferImpl->reinitOutOfDateStaticData();
+                }
             }
             else
             {
@@ -215,26 +226,6 @@
     return gl::Error(GL_NO_ERROR);
 }
 
-void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib,
-                                                     const gl::VertexAttribCurrentValueData &currentValue) const
-{
-    gl::Buffer *buffer = attrib.buffer.get();
-
-    if (buffer)
-    {
-        BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer);
-        StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer();
-
-        if (staticBuffer &&
-            staticBuffer->getBufferSize() > 0 &&
-            !staticBuffer->lookupAttribute(attrib, NULL) &&
-            !staticBuffer->directStoragePossible(attrib, currentValue.Type))
-        {
-            bufferImpl->invalidateStaticData();
-        }
-    }
-}
-
 gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
                                                    GLsizei count,
                                                    GLsizei instances) const
@@ -242,7 +233,9 @@
     const gl::VertexAttribute &attrib = *translatedAttrib.attribute;
     gl::Buffer *buffer = attrib.buffer.get();
     BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
-    StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL;
+    StaticVertexBufferInterface *staticBuffer =
+        bufferImpl ? bufferImpl->getStaticVertexBuffer(attrib, D3D_BUFFER_CREATE_IF_NECESSARY)
+                   : NULL;
     VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
 
     if (!vertexBuffer->directStoragePossible(attrib, translatedAttrib.currentValueType))
@@ -291,7 +284,8 @@
     ASSERT(attrib.enabled);
 
     BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
-    StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
+    StaticVertexBufferInterface *staticBuffer =
+        storage ? storage->getStaticVertexBuffer(attrib, D3D_BUFFER_DO_NOT_CREATE) : NULL;
     VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
     bool directStorage = vertexBuffer->directStoragePossible(attrib, translated->currentValueType);