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/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp
index 75a459a..99b4d12 100644
--- a/src/gpu/vk/GrVkResourceProvider.cpp
+++ b/src/gpu/vk/GrVkResourceProvider.cpp
@@ -7,14 +7,17 @@
#include "GrVkResourceProvider.h"
+#include "GrContextPriv.h"
#include "GrSamplerState.h"
#include "GrVkCommandBuffer.h"
+#include "GrVkCommandPool.h"
#include "GrVkCopyPipeline.h"
#include "GrVkGpu.h"
#include "GrVkPipeline.h"
#include "GrVkRenderTarget.h"
#include "GrVkUniformBuffer.h"
#include "GrVkUtil.h"
+#include "SkTaskGroup.h"
#ifdef SK_TRACE_VK_RESOURCES
std::atomic<uint32_t> GrVkResource::fKeyCounter{0};
@@ -274,49 +277,42 @@
fDescriptorSetManagers[managerIdx]->recycleDescriptorSet(descSet);
}
-GrVkPrimaryCommandBuffer* GrVkResourceProvider::findOrCreatePrimaryCommandBuffer() {
- GrVkPrimaryCommandBuffer* cmdBuffer = nullptr;
- int count = fAvailableCommandBuffers.count();
- if (count > 0) {
- cmdBuffer = fAvailableCommandBuffers[count - 1];
- SkASSERT(cmdBuffer->finished(fGpu));
- fAvailableCommandBuffers.removeShuffle(count - 1);
+GrVkCommandPool* GrVkResourceProvider::findOrCreateCommandPool() {
+ std::unique_lock<std::recursive_mutex> lock(fBackgroundMutex);
+ GrVkCommandPool* result;
+ if (fAvailableCommandPools.count()) {
+ result = fAvailableCommandPools.back();
+ fAvailableCommandPools.pop_back();
} else {
- cmdBuffer = GrVkPrimaryCommandBuffer::Create(fGpu, fGpu->cmdPool());
+ result = GrVkCommandPool::Create(fGpu);
}
- fActiveCommandBuffers.push_back(cmdBuffer);
- cmdBuffer->ref();
- return cmdBuffer;
+ SkASSERT(result->unique());
+ SkDEBUGCODE(
+ for (const GrVkCommandPool* pool : fActiveCommandPools) {
+ SkASSERT(pool != result);
+ }
+ for (const GrVkCommandPool* pool : fAvailableCommandPools) {
+ SkASSERT(pool != result);
+ }
+ );
+ fActiveCommandPools.push_back(result);
+ result->ref();
+ return result;
}
void GrVkResourceProvider::checkCommandBuffers() {
- for (int i = fActiveCommandBuffers.count()-1; i >= 0; --i) {
- if (fActiveCommandBuffers[i]->finished(fGpu)) {
- GrVkPrimaryCommandBuffer* cmdBuffer = fActiveCommandBuffers[i];
- cmdBuffer->reset(fGpu);
- fAvailableCommandBuffers.push_back(cmdBuffer);
- fActiveCommandBuffers.removeShuffle(i);
+ for (int i = fActiveCommandPools.count() - 1; i >= 0; --i) {
+ GrVkCommandPool* pool = fActiveCommandPools[i];
+ if (!pool->isOpen()) {
+ GrVkPrimaryCommandBuffer* buffer = pool->getPrimaryCommandBuffer();
+ if (buffer->finished(fGpu)) {
+ fActiveCommandPools.removeShuffle(i);
+ this->backgroundReset(pool);
+ }
}
}
}
-GrVkSecondaryCommandBuffer* GrVkResourceProvider::findOrCreateSecondaryCommandBuffer() {
- GrVkSecondaryCommandBuffer* cmdBuffer = nullptr;
- int count = fAvailableSecondaryCommandBuffers.count();
- if (count > 0) {
- cmdBuffer = fAvailableSecondaryCommandBuffers[count-1];
- fAvailableSecondaryCommandBuffers.removeShuffle(count - 1);
- } else {
- cmdBuffer = GrVkSecondaryCommandBuffer::Create(fGpu, fGpu->cmdPool());
- }
- return cmdBuffer;
-}
-
-void GrVkResourceProvider::recycleSecondaryCommandBuffer(GrVkSecondaryCommandBuffer* cb) {
- cb->reset(fGpu);
- fAvailableSecondaryCommandBuffers.push_back(cb);
-}
-
const GrVkResource* GrVkResourceProvider::findOrCreateStandardUniformBufferResource() {
const GrVkResource* resource = nullptr;
int count = fAvailableUniformBufferResources.count();
@@ -334,28 +330,10 @@
}
void GrVkResourceProvider::destroyResources(bool deviceLost) {
- // release our active command buffers
- for (int i = 0; i < fActiveCommandBuffers.count(); ++i) {
- SkASSERT(deviceLost || fActiveCommandBuffers[i]->finished(fGpu));
- SkASSERT(fActiveCommandBuffers[i]->unique());
- fActiveCommandBuffers[i]->reset(fGpu);
- fActiveCommandBuffers[i]->unref(fGpu);
+ SkTaskGroup* taskGroup = fGpu->getContext()->contextPriv().getTaskGroup();
+ if (taskGroup) {
+ taskGroup->wait();
}
- fActiveCommandBuffers.reset();
- // release our available command buffers
- for (int i = 0; i < fAvailableCommandBuffers.count(); ++i) {
- SkASSERT(deviceLost || fAvailableCommandBuffers[i]->finished(fGpu));
- SkASSERT(fAvailableCommandBuffers[i]->unique());
- fAvailableCommandBuffers[i]->unref(fGpu);
- }
- fAvailableCommandBuffers.reset();
-
- // release our available secondary command buffers
- for (int i = 0; i < fAvailableSecondaryCommandBuffers.count(); ++i) {
- SkASSERT(fAvailableSecondaryCommandBuffers[i]->unique());
- fAvailableSecondaryCommandBuffers[i]->unref(fGpu);
- }
- fAvailableSecondaryCommandBuffers.reset();
// Release all copy pipelines
for (int i = 0; i < fCopyPipelines.count(); ++i) {
@@ -380,6 +358,18 @@
GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineCache(fGpu->device(), fPipelineCache, nullptr));
fPipelineCache = VK_NULL_HANDLE;
+ for (GrVkCommandPool* pool : fActiveCommandPools) {
+ SkASSERT(pool->unique());
+ pool->unref(fGpu);
+ }
+ fActiveCommandPools.reset();
+
+ for (GrVkCommandPool* pool : fAvailableCommandPools) {
+ SkASSERT(pool->unique());
+ pool->unref(fGpu);
+ }
+ fAvailableCommandPools.reset();
+
// We must release/destroy all command buffers and pipeline states before releasing the
// GrVkDescriptorSetManagers
for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
@@ -396,25 +386,22 @@
}
void GrVkResourceProvider::abandonResources() {
- // release our active command buffers
- for (int i = 0; i < fActiveCommandBuffers.count(); ++i) {
- SkASSERT(fActiveCommandBuffers[i]->unique());
- fActiveCommandBuffers[i]->unrefAndAbandon();
+ SkTaskGroup* taskGroup = fGpu->getContext()->contextPriv().getTaskGroup();
+ if (taskGroup) {
+ taskGroup->wait();
}
- fActiveCommandBuffers.reset();
- // release our available command buffers
- for (int i = 0; i < fAvailableCommandBuffers.count(); ++i) {
- SkASSERT(fAvailableCommandBuffers[i]->unique());
- fAvailableCommandBuffers[i]->unrefAndAbandon();
- }
- fAvailableCommandBuffers.reset();
- // release our available secondary command buffers
- for (int i = 0; i < fAvailableSecondaryCommandBuffers.count(); ++i) {
- SkASSERT(fAvailableSecondaryCommandBuffers[i]->unique());
- fAvailableSecondaryCommandBuffers[i]->unrefAndAbandon();
+ // Abandon all command pools
+ for (int i = 0; i < fActiveCommandPools.count(); ++i) {
+ SkASSERT(fActiveCommandPools[i]->unique());
+ fActiveCommandPools[i]->unrefAndAbandon();
}
- fAvailableSecondaryCommandBuffers.reset();
+ fActiveCommandPools.reset();
+ for (int i = 0; i < fAvailableCommandPools.count(); ++i) {
+ SkASSERT(fAvailableCommandPools[i]->unique());
+ fAvailableCommandPools[i]->unrefAndAbandon();
+ }
+ fAvailableCommandPools.reset();
// Abandon all copy pipelines
for (int i = 0; i < fCopyPipelines.count(); ++i) {
@@ -453,6 +440,26 @@
fAvailableUniformBufferResources.reset();
}
+void GrVkResourceProvider::backgroundReset(GrVkCommandPool* pool) {
+ SkASSERT(pool->unique());
+ pool->releaseResources(fGpu);
+ SkTaskGroup* taskGroup = fGpu->getContext()->contextPriv().getTaskGroup();
+ if (taskGroup) {
+ taskGroup->add([this, pool]() {
+ this->reset(pool);
+ });
+ } else {
+ this->reset(pool);
+ }
+}
+
+void GrVkResourceProvider::reset(GrVkCommandPool* pool) {
+ SkASSERT(pool->unique());
+ pool->reset(fGpu);
+ std::unique_lock<std::recursive_mutex> providerLock(fBackgroundMutex);
+ fAvailableCommandPools.push_back(pool);
+}
+
////////////////////////////////////////////////////////////////////////////////
GrVkResourceProvider::CompatibleRenderPassSet::CompatibleRenderPassSet(
@@ -488,7 +495,7 @@
return renderPass;
}
-void GrVkResourceProvider::CompatibleRenderPassSet::releaseResources(const GrVkGpu* gpu) {
+void GrVkResourceProvider::CompatibleRenderPassSet::releaseResources(GrVkGpu* gpu) {
for (int i = 0; i < fRenderPasses.count(); ++i) {
if (fRenderPasses[i]) {
fRenderPasses[i]->unref(gpu);