Re-land "Perform Vulkan resets in a background thread"

Bug: skia:
Change-Id: I1c7ec365a370137ca64d9091cb60e6430c3f1c28
Reviewed-on: https://skia-review.googlesource.com/c/177069
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/gpu/vk/GrVkCommandPool.cpp b/src/gpu/vk/GrVkCommandPool.cpp
new file mode 100644
index 0000000..9d7c17e
--- /dev/null
+++ b/src/gpu/vk/GrVkCommandPool.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrVkCommandPool.h"
+
+#include "GrContextPriv.h"
+#include "GrVkCommandBuffer.h"
+#include "GrVkGpu.h"
+
+GrVkCommandPool* GrVkCommandPool::Create(const GrVkGpu* gpu) {
+    const VkCommandPoolCreateInfo cmdPoolInfo = {
+        VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType
+        nullptr,                                         // pNext
+        VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
+        VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // CmdPoolCreateFlags
+        gpu->queueIndex(),                              // queueFamilyIndex
+    };
+    VkCommandPool pool;
+    GR_VK_CALL_ERRCHECK(gpu->vkInterface(), CreateCommandPool(gpu->device(), &cmdPoolInfo,
+                                                               nullptr, &pool));
+    return new GrVkCommandPool(gpu, pool);
+}
+
+GrVkCommandPool::GrVkCommandPool(const GrVkGpu* gpu, VkCommandPool commandPool)
+        : fCommandPool(commandPool) {
+    fPrimaryCommandBuffer = GrVkPrimaryCommandBuffer::Create(gpu, this);
+}
+
+GrVkSecondaryCommandBuffer* GrVkCommandPool::findOrCreateSecondaryCommandBuffer(GrVkGpu* gpu) {
+    if (fAvailableSecondaryBuffers.count()) {
+        GrVkSecondaryCommandBuffer* result = fAvailableSecondaryBuffers.back();
+        fAvailableSecondaryBuffers.pop_back();
+        return result;
+    }
+    return GrVkSecondaryCommandBuffer::Create(gpu, this);
+}
+
+void GrVkCommandPool::recycleSecondaryCommandBuffer(GrVkSecondaryCommandBuffer* buffer) {
+    SkASSERT(buffer->commandPool() == this);
+    fAvailableSecondaryBuffers.push_back(buffer);
+}
+
+void GrVkCommandPool::close() {
+    fOpen = false;
+}
+
+void GrVkCommandPool::reset(GrVkGpu* gpu) {
+    SkASSERT(!fOpen);
+    fOpen = true;
+    fPrimaryCommandBuffer->recycleSecondaryCommandBuffers();
+    GR_VK_CALL_ERRCHECK(gpu->vkInterface(), ResetCommandPool(gpu->device(), fCommandPool, 0));
+}
+
+void GrVkCommandPool::releaseResources(GrVkGpu* gpu) {
+    SkASSERT(!fOpen);
+    fPrimaryCommandBuffer->releaseResources(gpu);
+    for (GrVkSecondaryCommandBuffer* buffer : fAvailableSecondaryBuffers) {
+        buffer->releaseResources(gpu);
+    }
+}
+
+void GrVkCommandPool::abandonGPUData() const {
+    fPrimaryCommandBuffer->unrefAndAbandon();
+    for (GrVkSecondaryCommandBuffer* buffer : fAvailableSecondaryBuffers) {
+        SkASSERT(buffer->unique());
+        buffer->unrefAndAbandon();
+    }
+}
+
+void GrVkCommandPool::freeGPUData(GrVkGpu* gpu) const {
+    fPrimaryCommandBuffer->unref(gpu);
+    for (GrVkSecondaryCommandBuffer* buffer : fAvailableSecondaryBuffers) {
+        SkASSERT(buffer->unique());
+        buffer->unref(gpu);
+    }
+    if (fCommandPool != VK_NULL_HANDLE) {
+        GR_VK_CALL(gpu->vkInterface(),
+                   DestroyCommandPool(gpu->device(), fCommandPool, nullptr));
+    }
+}