Vulkan: Add vkCmdFillBuffer support

Implemented as part of an experiment.  Allows easier buffer-related
testing by providing a quick way of filling the buffer with dummy data.

Bug: angleproject:3205
Change-Id: Ice8cfd0c2566c91a5fb10aaea57985d671d0e7b7
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1665351
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Tobin Ehlis <tobine@google.com>
diff --git a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp
index da02a5f..5a559f6 100644
--- a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp
+++ b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp
@@ -204,6 +204,13 @@
                     vkCmdEndQuery(cmdBuffer, params->queryPool, params->query);
                     break;
                 }
+                case CommandID::FillBuffer:
+                {
+                    const FillBufferParams *params = getParamPtr<FillBufferParams>(currentCommand);
+                    vkCmdFillBuffer(cmdBuffer, params->dstBuffer, params->dstOffset, params->size,
+                                    params->data);
+                    break;
+                }
                 case CommandID::ImageBarrier:
                 {
                     const ImageBarrierParams *params =
@@ -388,6 +395,9 @@
                 case CommandID::EndQuery:
                     result += "EndQuery";
                     break;
+                case CommandID::FillBuffer:
+                    result += "FillBuffer";
+                    break;
                 case CommandID::ImageBarrier:
                     result += "ImageBarrier";
                     break;
diff --git a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h
index 35a24cd..9a02ad3 100644
--- a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h
+++ b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h
@@ -50,6 +50,7 @@
     DrawIndexedInstanced,
     DrawInstanced,
     EndQuery,
+    FillBuffer,
     ImageBarrier,
     MemoryBarrier,
     PipelineBarrier,
@@ -220,6 +221,15 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(DispatchParams)
 
+struct FillBufferParams
+{
+    VkBuffer dstBuffer;
+    VkDeviceSize dstOffset;
+    VkDeviceSize size;
+    uint32_t data;
+};
+VERIFY_4_BYTE_ALIGNMENT(FillBufferParams)
+
 struct MemoryBarrierParams
 {
     VkPipelineStageFlags srcStageMask;
@@ -429,6 +439,11 @@
 
     void endQuery(VkQueryPool queryPool, uint32_t query);
 
+    void fillBuffer(const Buffer &dstBuffer,
+                    VkDeviceSize dstOffset,
+                    VkDeviceSize size,
+                    uint32_t data);
+
     void imageBarrier(VkPipelineStageFlags srcStageMask,
                       VkPipelineStageFlags dstStageMask,
                       const VkImageMemoryBarrier *imageMemoryBarrier);
@@ -865,6 +880,18 @@
     paramStruct->query          = query;
 }
 
+ANGLE_INLINE void SecondaryCommandBuffer::fillBuffer(const Buffer &dstBuffer,
+                                                     VkDeviceSize dstOffset,
+                                                     VkDeviceSize size,
+                                                     uint32_t data)
+{
+    FillBufferParams *paramStruct = initCommand<FillBufferParams>(CommandID::FillBuffer);
+    paramStruct->dstBuffer        = dstBuffer.getHandle();
+    paramStruct->dstOffset        = dstOffset;
+    paramStruct->size             = size;
+    paramStruct->data             = data;
+}
+
 ANGLE_INLINE void SecondaryCommandBuffer::imageBarrier(
     VkPipelineStageFlags srcStageMask,
     VkPipelineStageFlags dstStageMask,
diff --git a/src/libANGLE/renderer/vulkan/vk_wrapper.h b/src/libANGLE/renderer/vulkan/vk_wrapper.h
index a6a5196..fb506dd 100644
--- a/src/libANGLE/renderer/vulkan/vk_wrapper.h
+++ b/src/libANGLE/renderer/vulkan/vk_wrapper.h
@@ -287,6 +287,11 @@
     void endRenderPass();
     void executeCommands(uint32_t commandBufferCount, const CommandBuffer *commandBuffers);
 
+    void fillBuffer(const Buffer &dstBuffer,
+                    VkDeviceSize dstOffset,
+                    VkDeviceSize size,
+                    uint32_t data);
+
     void imageBarrier(VkPipelineStageFlags srcStageMask,
                       VkPipelineStageFlags dstStageMask,
                       const VkImageMemoryBarrier *imageMemoryBarrier);
@@ -794,6 +799,15 @@
     vkCmdExecuteCommands(mHandle, commandBufferCount, commandBuffers[0].ptr());
 }
 
+ANGLE_INLINE void CommandBuffer::fillBuffer(const Buffer &dstBuffer,
+                                            VkDeviceSize dstOffset,
+                                            VkDeviceSize size,
+                                            uint32_t data)
+{
+    ASSERT(valid());
+    vkCmdFillBuffer(mHandle, dstBuffer.getHandle(), dstOffset, size, data);
+}
+
 ANGLE_INLINE void CommandBuffer::pushConstants(const PipelineLayout &layout,
                                                VkShaderStageFlags flag,
                                                uint32_t offset,