Vulkan: Use minimal dirty bits in VertexArrayVk.

This should slightly reduce draw call overhead.

BUG=angleproject:1898

Change-Id: I0e515bf2868f237f1d6948c12942f8cb6637c0c0
Reviewed-on: https://chromium-review.googlesource.com/707690
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
index 5d5497a..896dd56 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -12,12 +12,16 @@
 #include "common/debug.h"
 
 #include "libANGLE/Context.h"
+#include "libANGLE/renderer/vulkan/BufferVk.h"
 #include "libANGLE/renderer/vulkan/ContextVk.h"
 
 namespace rx
 {
 
-VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state) : VertexArrayImpl(state)
+VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state)
+    : VertexArrayImpl(state),
+      mCurrentVertexBufferHandlesCache(state.getMaxAttribs(), VK_NULL_HANDLE),
+      mCurrentVkBuffersCache(state.getMaxAttribs(), nullptr)
 {
 }
 
@@ -30,9 +34,60 @@
 {
     ASSERT(dirtyBits.any());
 
+    // Invalidate current pipeline.
     // TODO(jmadill): Use pipeline cache.
     auto contextVk = GetImplAs<ContextVk>(context);
     contextVk->invalidateCurrentPipeline();
+
+    // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
+    // TODO(jmadill): Handle buffer storage changes.
+    const auto &attribs  = mState.getVertexAttributes();
+    const auto &bindings = mState.getVertexBindings();
+
+    for (auto dirtyBit : dirtyBits)
+    {
+        if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
+            continue;
+
+        size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
+
+        const auto &attrib  = attribs[attribIndex];
+        const auto &binding = bindings[attrib.bindingIndex];
+        if (attrib.enabled)
+        {
+            gl::Buffer *bufferGL = binding.getBuffer().get();
+
+            if (bufferGL)
+            {
+                BufferVk *bufferVk                            = GetImplAs<BufferVk>(bufferGL);
+                mCurrentVkBuffersCache[attribIndex]           = bufferVk;
+                mCurrentVertexBufferHandlesCache[attribIndex] = bufferVk->getVkBuffer().getHandle();
+            }
+            else
+            {
+                mCurrentVkBuffersCache[attribIndex]           = nullptr;
+                mCurrentVertexBufferHandlesCache[attribIndex] = VK_NULL_HANDLE;
+            }
+        }
+        else
+        {
+            UNIMPLEMENTED();
+        }
+    }
+}
+
+const std::vector<VkBuffer> &VertexArrayVk::getCurrentVertexBufferHandlesCache() const
+{
+    return mCurrentVertexBufferHandlesCache;
+}
+
+void VertexArrayVk::updateCurrentBufferSerials(const gl::AttributesMask &activeAttribsMask,
+                                               Serial serial)
+{
+    for (auto attribIndex : activeAttribsMask)
+    {
+        mCurrentVkBuffersCache[attribIndex]->setQueueSerial(serial);
+    }
 }
 
 }  // namespace rx