diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp index 7fb143ed98..c9037c28c3 100644 --- a/src/gpu/vk/GrVkCommandBuffer.cpp +++ b/src/gpu/vk/GrVkCommandBuffer.cpp @@ -40,6 +40,10 @@ void GrVkCommandBuffer::freeGPUData(const GrVkGpu* gpu) const { fTrackedResources[i]->unref(gpu); } + for (int i = 0; i < fTrackedRecycledResources.count(); ++i) { + fTrackedRecycledResources[i]->recycle(const_cast(gpu)); + } + GR_VK_CALL(gpu->vkInterface(), FreeCommandBuffers(gpu->device(), gpu->cmdPool(), 1, &fCmdBuffer)); @@ -50,6 +54,11 @@ void GrVkCommandBuffer::abandonSubResources() const { for (int i = 0; i < fTrackedResources.count(); ++i) { fTrackedResources[i]->unrefAndAbandon(); } + + for (int i = 0; i < fTrackedRecycledResources.count(); ++i) { + // We don't recycle resources when abandoning them. + fTrackedRecycledResources[i]->unrefAndAbandon(); + } } void GrVkCommandBuffer::reset(GrVkGpu* gpu) { @@ -59,6 +68,12 @@ void GrVkCommandBuffer::reset(GrVkGpu* gpu) { } fTrackedResources.reset(); + for (int i = 0; i < fTrackedRecycledResources.count(); ++i) { + fTrackedRecycledResources[i]->recycle(const_cast(gpu)); + } + fTrackedRecycledResources.reset(); + + this->invalidateState(); // we will retain resources for later use diff --git a/src/gpu/vk/GrVkCommandBuffer.h b/src/gpu/vk/GrVkCommandBuffer.h index c8bac336d5..f439b27613 100644 --- a/src/gpu/vk/GrVkCommandBuffer.h +++ b/src/gpu/vk/GrVkCommandBuffer.h @@ -117,11 +117,19 @@ public: fTrackedResources.push_back(resource); } + // Add ref-counted resource that will be tracked and released when this command buffer finishes + // execution. When it is released, it will signal that the resource can be recycled for reuse. + void addRecycledResource(const GrVkRecycledResource* resource) { + resource->ref(); + fTrackedRecycledResources.push_back(resource); + } + void reset(GrVkGpu* gpu); protected: GrVkCommandBuffer(VkCommandBuffer cmdBuffer, const GrVkRenderPass* rp = VK_NULL_HANDLE) : fTrackedResources(kInitialTrackedResourcesCount) + , fTrackedRecycledResources(kInitialTrackedResourcesCount) , fIsActive(false) , fActiveRenderPass(rp) , fCmdBuffer(cmdBuffer) @@ -129,7 +137,8 @@ protected: , fBoundIndexBufferIsValid(false) { this->invalidateState(); } - SkTArray fTrackedResources; + SkTArray fTrackedResources; + SkTArray fTrackedRecycledResources; // Tracks whether we are in the middle of a command buffer begin/end calls and thus can add // new commands to the buffer; diff --git a/src/gpu/vk/GrVkResource.h b/src/gpu/vk/GrVkResource.h index 83e82fb5b1..190ee36b1a 100644 --- a/src/gpu/vk/GrVkResource.h +++ b/src/gpu/vk/GrVkResource.h @@ -191,5 +191,21 @@ private: typedef SkNoncopyable INHERITED; }; +// This subclass allows for recycling +class GrVkRecycledResource : public GrVkResource { +public: + // When recycle is called and there is only one ref left on the resource, we will signal that + // the resource can be recycled for reuse. This function will always unref the object. Thus + // if the object is recycled it should be ref'd inside the onRecycle call. + void recycle(GrVkGpu* gpu) const { + if (this->unique()) { + this->onRecycle(gpu); + } + this->unref(gpu); + } + +private: + virtual void onRecycle(GrVkGpu* gpu) const = 0; +}; #endif