Vulkan: Enable command queueing.

This adds the ability for rendering to happen asynchronously. If
objects in-use are deleted as they are being accessed, ownership
is transferred to the Renderer and they are deleted when not in
use. We determine they're ready for delete using a Fence object.

BUG=angleproject:1898

Change-Id: I4fcfd90ad0665d127bf01a10214a604f3407d9e4
Reviewed-on: https://chromium-review.googlesource.com/428353
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index 490fad3..2df08e8 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -576,7 +576,7 @@
     return &mCommandBuffer;
 }
 
-vk::Error RendererVk::submitAndFinishCommandBuffer(const vk::CommandBuffer &commandBuffer)
+vk::Error RendererVk::submitCommandBuffer(const vk::CommandBuffer &commandBuffer)
 {
     VkFenceCreateInfo fenceInfo;
     fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
@@ -599,7 +599,12 @@
     // TODO(jmadill): Investigate how to properly submit command buffers.
     ANGLE_TRY(submit(submitInfo));
 
-    // Wait indefinitely for the queue to finish.
+    return vk::NoError();
+}
+
+vk::Error RendererVk::submitAndFinishCommandBuffer(const vk::CommandBuffer &commandBuffer)
+{
+    ANGLE_TRY(submitCommandBuffer(commandBuffer));
     ANGLE_TRY(finish());
 
     return vk::NoError();
@@ -635,13 +640,15 @@
 vk::Error RendererVk::finish()
 {
     ASSERT(mQueue != VK_NULL_HANDLE);
-    checkInFlightCommands();
     ANGLE_VK_TRY(vkQueueWaitIdle(mQueue));
+    checkInFlightCommands();
     return vk::NoError();
 }
 
 vk::Error RendererVk::checkInFlightCommands()
 {
+    bool anyFinished = false;
+
     // Check if any in-flight command buffers are finished.
     for (size_t index = 0; index < mInFlightCommands.size();)
     {
@@ -655,6 +662,7 @@
             mLastCompletedQueueSerial = inFlightCommand->queueSerial();
             inFlightCommand->destroy(mDevice);
             mInFlightCommands.erase(mInFlightCommands.begin() + index);
+            anyFinished = true;
         }
         else
         {
@@ -662,6 +670,22 @@
         }
     }
 
+    if (anyFinished)
+    {
+        size_t freeIndex = 0;
+        for (; freeIndex < mGarbage.size(); ++freeIndex)
+        {
+            if (!mGarbage[freeIndex]->destroyIfComplete(mDevice, mLastCompletedQueueSerial))
+                break;
+        }
+
+        // Remove the entries from the garbage list - they should be ready to go.
+        if (freeIndex > 0)
+        {
+            mGarbage.erase(mGarbage.begin(), mGarbage.begin() + freeIndex);
+        }
+    }
+
     return vk::NoError();
 }