Vulkan: Implement "default" vertex attributes.

Rendering from disabled attributes is implemented using small dynamic
buffers. The buffers use a stride of zero so the same vertex data is
pulled for every index.

This fixes all the disable attribute tests in dEQP.

Bug: angleproject:2444
Change-Id: I04fe139076da3e3ff723bed8eb17e333b4cb0ddf
Reviewed-on: https://chromium-review.googlesource.com/1136664
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
index 51ad876..cd9433c 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -147,16 +147,16 @@
     return angle::Result::Continue();
 }
 
-#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX)                                                      \
-    case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX:                                              \
-        syncDirtyAttrib(rendererVk, attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
-        invalidatePipeline = true;                                                                 \
+#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX)                                                     \
+    case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX:                                             \
+        syncDirtyAttrib(contextVk, attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
+        invalidatePipeline = true;                                                                \
         break;
 
-#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX)                                                     \
-    case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX:                                             \
-        syncDirtyAttrib(rendererVk, attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
-        invalidatePipeline = true;                                                                 \
+#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX)                                                    \
+    case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX:                                            \
+        syncDirtyAttrib(contextVk, attribs[INDEX], bindings[attribs[INDEX].bindingIndex], INDEX); \
+        invalidatePipeline = true;                                                                \
         break;
 
 #define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX)         \
@@ -173,8 +173,7 @@
     bool invalidatePipeline = false;
 
     // Invalidate current pipeline.
-    ContextVk *contextVk   = vk::GetImpl(context);
-    RendererVk *rendererVk = contextVk->getRenderer();
+    ContextVk *contextVk = vk::GetImpl(context);
 
     // Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
     // TODO(jmadill): Handle buffer storage changes.
@@ -233,7 +232,7 @@
     return gl::NoError();
 }
 
-void VertexArrayVk::syncDirtyAttrib(const RendererVk *renderer,
+void VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
                                     const gl::VertexAttribute &attrib,
                                     const gl::VertexBinding &binding,
                                     size_t attribIndex)
@@ -241,6 +240,8 @@
     // Invalidate the input description for pipelines.
     mDirtyPackedInputs.set(attribIndex);
 
+    RendererVk *renderer = contextVk->getRenderer();
+
     if (attrib.enabled)
     {
         gl::Buffer *bufferGL = binding.getBuffer().get();
@@ -273,7 +274,15 @@
     }
     else
     {
-        WARN() << "Default vertex attributes unimplemented. http://anglebug.com/2444";
+        contextVk->invalidateDefaultAttribute(attribIndex);
+
+        // These will be filled out by the ContextVk.
+        mCurrentArrayBufferResources[attribIndex] = nullptr;
+        mCurrentArrayBufferHandles[attribIndex]   = VK_NULL_HANDLE;
+        mCurrentArrayBufferOffsets[attribIndex]   = 0;
+        mCurrentArrayBufferStrides[attribIndex]   = 0;
+        mCurrentArrayBufferFormats[attribIndex] =
+            &renderer->getFormat(angle::Format::ID::R32G32B32A32_FLOAT);
     }
 }
 
@@ -326,7 +335,14 @@
         }
         else
         {
-            WARN() << "Default vertex attributes unimplemented. http://anglebug.com/2444";
+            vk::PackedVertexInputBindingDesc &bindingDesc = mPackedInputBindings[attribIndex];
+            bindingDesc.stride                            = 0;
+            bindingDesc.inputRate                         = VK_VERTEX_INPUT_RATE_VERTEX;
+
+            vk::PackedVertexInputAttributeDesc &attribDesc = mPackedInputAttributes[attribIndex];
+            attribDesc.format   = static_cast<uint16_t>(VK_FORMAT_R32G32B32A32_SFLOAT);
+            attribDesc.location = static_cast<uint16_t>(attribIndex);
+            attribDesc.offset   = 0;
         }
     }
 
@@ -581,4 +597,21 @@
 
     return gl::NoError();
 }
+
+void VertexArrayVk::updateDefaultAttrib(RendererVk *renderer,
+                                        size_t attribIndex,
+                                        VkBuffer bufferHandle,
+                                        uint32_t offset)
+{
+    if (!mState.getEnabledAttributesMask().test(attribIndex))
+    {
+        mCurrentArrayBufferHandles[attribIndex]   = bufferHandle;
+        mCurrentArrayBufferOffsets[attribIndex]   = offset;
+        mCurrentArrayBufferResources[attribIndex] = nullptr;
+        mCurrentArrayBufferStrides[attribIndex]   = 0;
+        mCurrentArrayBufferFormats[attribIndex] =
+            &renderer->getFormat(angle::Format::ID::R32G32B32A32_FIXED);
+        mDirtyPackedInputs.set(attribIndex);
+    }
+}
 }  // namespace rx