diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 67530c2b65..7d586620b6 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -455,6 +455,10 @@ '<(skia_src_path)/gpu/vk/GrVkCommandBuffer.h', '<(skia_src_path)/gpu/vk/GrVkDescriptorPool.cpp', '<(skia_src_path)/gpu/vk/GrVkDescriptorPool.h', + '<(skia_src_path)/gpu/vk/GrVkDescriptorSet.cpp', + '<(skia_src_path)/gpu/vk/GrVkDescriptorSet.h', + '<(skia_src_path)/gpu/vk/GrVkDescriptorSetManager.cpp', + '<(skia_src_path)/gpu/vk/GrVkDescriptorSetManager.h', '<(skia_src_path)/gpu/vk/GrVkExtensions.cpp', '<(skia_src_path)/gpu/vk/GrVkExtensions.h', '<(skia_src_path)/gpu/vk/GrVkFramebuffer.cpp', diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp index c9037c28c3..2e474bad12 100644 --- a/src/gpu/vk/GrVkCommandBuffer.cpp +++ b/src/gpu/vk/GrVkCommandBuffer.cpp @@ -73,7 +73,6 @@ void GrVkCommandBuffer::reset(GrVkGpu* gpu) { } fTrackedRecycledResources.reset(); - this->invalidateState(); // we will retain resources for later use diff --git a/src/gpu/vk/GrVkDescriptorSet.cpp b/src/gpu/vk/GrVkDescriptorSet.cpp new file mode 100644 index 0000000000..47a997f550 --- /dev/null +++ b/src/gpu/vk/GrVkDescriptorSet.cpp @@ -0,0 +1,34 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#include "GrVkDescriptorSet.h" + +#include "GrVkDescriptorPool.h" +#include "GrVkGpu.h" +#include "GrVkResourceProvider.h" + +GrVkDescriptorSet::GrVkDescriptorSet(VkDescriptorSet descSet, + GrVkDescriptorPool* pool, + GrVkDescriptorSetManager::Handle handle) + : fDescSet(descSet) + , fPool(pool) + , fHandle(handle) { + fPool->ref(); +} + +void GrVkDescriptorSet::freeGPUData(const GrVkGpu* gpu) const { + fPool->unref(gpu); +} + +void GrVkDescriptorSet::onRecycle(GrVkGpu* gpu) const { + gpu->resourceProvider().recycleDescriptorSet(this, fHandle); +} + +void GrVkDescriptorSet::abandonSubResources() const { + fPool->unrefAndAbandon(); +} + diff --git a/src/gpu/vk/GrVkDescriptorSet.h b/src/gpu/vk/GrVkDescriptorSet.h new file mode 100644 index 0000000000..69e2d44336 --- /dev/null +++ b/src/gpu/vk/GrVkDescriptorSet.h @@ -0,0 +1,44 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#ifndef GrVkDescriptorSet_DEFINED +#define GrVkDescriptorSet_DEFINED + +#include "GrVkDescriptorSetManager.h" +#include "GrVkResource.h" +#include "vk/GrVkDefines.h" + +class GrVkDescriptorPool; +class GrVkGpu; + +class GrVkDescriptorSet : public GrVkRecycledResource { +public: + GrVkDescriptorSet(VkDescriptorSet descSet, + GrVkDescriptorPool* pool, + GrVkDescriptorSetManager::Handle handle); + + ~GrVkDescriptorSet() override {} + + VkDescriptorSet descriptorSet() const { return fDescSet; } + +#ifdef SK_TRACE_VK_RESOURCES + void dumpInfo() const override { + SkDebugf("GrVkDescriptorSet: %d (%d refs)\n", fDescSet, this->getRefCnt()); + } +#endif + +private: + void freeGPUData(const GrVkGpu* gpu) const override; + void abandonSubResources() const override; + void onRecycle(GrVkGpu* gpu) const override; + + VkDescriptorSet fDescSet; + SkDEBUGCODE(mutable) GrVkDescriptorPool* fPool; + GrVkDescriptorSetManager::Handle fHandle; +}; + +#endif diff --git a/src/gpu/vk/GrVkDescriptorSetManager.cpp b/src/gpu/vk/GrVkDescriptorSetManager.cpp new file mode 100644 index 0000000000..51138e1a07 --- /dev/null +++ b/src/gpu/vk/GrVkDescriptorSetManager.cpp @@ -0,0 +1,120 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#include "GrVkDescriptorSetManager.h" + +#include "GrVkDescriptorPool.h" +#include "GrVkDescriptorSet.h" +#include "GrVkGpu.h" + +GrVkDescriptorSetManager::GrVkDescriptorSetManager(GrVkGpu* gpu, + VkDescriptorSetLayout layout, + VkDescriptorType type, + uint32_t samplerCount) + : fPoolManager(layout, type, samplerCount, gpu) + , fNumSamplerBindings(samplerCount) { +} + +const GrVkDescriptorSet* GrVkDescriptorSetManager::getDescriptorSet(GrVkGpu* gpu, + const Handle& handle) { + const GrVkDescriptorSet* ds = nullptr; + int count = fFreeSets.count(); + if (count > 0) { + ds = fFreeSets[count - 1]; + fFreeSets.removeShuffle(count - 1); + } else { + VkDescriptorSet vkDS; + fPoolManager.getNewDescriptorSet(gpu, &vkDS); + + ds = new GrVkDescriptorSet(vkDS, fPoolManager.fPool, handle); + } + SkASSERT(ds); + return ds; +} + +void GrVkDescriptorSetManager::recycleDescriptorSet(const GrVkDescriptorSet* descSet) { + SkASSERT(descSet); + fFreeSets.push_back(descSet); +} + +void GrVkDescriptorSetManager::release(const GrVkGpu* gpu) { + fPoolManager.freeGPUResources(gpu); + + for (int i = 0; i < fFreeSets.count(); ++i) { + fFreeSets[i]->unref(gpu); + } + fFreeSets.reset(); +} + +void GrVkDescriptorSetManager::abandon() { + fPoolManager.abandonGPUResources(); + + for (int i = 0; i < fFreeSets.count(); ++i) { + fFreeSets[i]->unrefAndAbandon(); + } + fFreeSets.reset(); +} + +//////////////////////////////////////////////////////////////////////////////// + +void GrVkDescriptorSetManager::DescriptorPoolManager::getNewPool(GrVkGpu* gpu) { + if (fPool) { + fPool->unref(gpu); + uint32_t newPoolSize = fMaxDescriptors + ((fMaxDescriptors + 1) >> 1); + if (newPoolSize < kMaxDescriptors) { + fMaxDescriptors = newPoolSize; + } else { + fMaxDescriptors = kMaxDescriptors; + } + + } + fPool = gpu->resourceProvider().findOrCreateCompatibleDescriptorPool(fDescType, + fMaxDescriptors); + SkASSERT(fPool); +} + +void GrVkDescriptorSetManager::DescriptorPoolManager::getNewDescriptorSet(GrVkGpu* gpu, + VkDescriptorSet* ds) { + if (!fMaxDescriptors) { + return; + } + fCurrentDescriptorCount += fDescCountPerSet; + if (fCurrentDescriptorCount > fMaxDescriptors) { + this->getNewPool(gpu); + fCurrentDescriptorCount = fDescCountPerSet; + } + + VkDescriptorSetAllocateInfo dsAllocateInfo; + memset(&dsAllocateInfo, 0, sizeof(VkDescriptorSetAllocateInfo)); + dsAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + dsAllocateInfo.pNext = nullptr; + dsAllocateInfo.descriptorPool = fPool->descPool(); + dsAllocateInfo.descriptorSetCount = 1; + dsAllocateInfo.pSetLayouts = &fDescLayout; + GR_VK_CALL_ERRCHECK(gpu->vkInterface(), AllocateDescriptorSets(gpu->device(), + &dsAllocateInfo, + ds)); +} + +void GrVkDescriptorSetManager::DescriptorPoolManager::freeGPUResources(const GrVkGpu* gpu) { + // The layout should be owned by the class which owns the DescriptorSetManager so it will + // take care of destroying it. + fDescLayout = VK_NULL_HANDLE; + + if (fPool) { + fPool->unref(gpu); + fPool = nullptr; + } +} + +void GrVkDescriptorSetManager::DescriptorPoolManager::abandonGPUResources() { + fDescLayout = VK_NULL_HANDLE; + if (fPool) { + fPool->unrefAndAbandon(); + fPool = nullptr; + } +} diff --git a/src/gpu/vk/GrVkDescriptorSetManager.h b/src/gpu/vk/GrVkDescriptorSetManager.h new file mode 100644 index 0000000000..33a7720ab3 --- /dev/null +++ b/src/gpu/vk/GrVkDescriptorSetManager.h @@ -0,0 +1,97 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#ifndef GrVkDescriptorSetManager_DEFINED +#define GrVkDescriptorSetManager_DEFINED + +#include "GrResourceHandle.h" +#include "GrVkDescriptorPool.h" +#include "SkRefCnt.h" +#include "SkTArray.h" +#include "vk/GrVkDefines.h" + +class GrVkDescriptorSet; +class GrVkGpu; + +/** + * This class handles the allocation of descriptor sets for a given VkDescriptorSetLayout. It will + * try to reuse previously allocated descriptor sets if they are no longer in use by other objects. + */ +class GrVkDescriptorSetManager { +public: + GR_DEFINE_RESOURCE_HANDLE_CLASS(Handle); + + GrVkDescriptorSetManager(GrVkGpu* gpu, + VkDescriptorSetLayout layout, + VkDescriptorType, + uint32_t samplerCount); + ~GrVkDescriptorSetManager() {} + + void abandon(); + void release(const GrVkGpu* gpu); + + const GrVkDescriptorSet* getDescriptorSet(GrVkGpu* gpu, const Handle& handle); + + void recycleDescriptorSet(const GrVkDescriptorSet*); + + int isCompatible(uint32_t numSamplers) const { return numSamplers == fNumSamplerBindings; } + +private: + struct DescriptorPoolManager { + DescriptorPoolManager(VkDescriptorSetLayout layout, VkDescriptorType type, + uint32_t samplerCount, GrVkGpu* gpu) + : fDescLayout(layout) + , fDescType(type) + , fCurrentDescriptorCount(0) + , fPool(nullptr) { + if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER == type) { + fDescCountPerSet = kNumUniformDescPerSet; + } else { + SkASSERT(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + fDescCountPerSet = samplerCount; + } + + SkASSERT(fDescCountPerSet < kStartNumDescriptors); + fMaxDescriptors = kStartNumDescriptors; + SkASSERT(fMaxDescriptors > 0); + this->getNewPool(gpu); + } + + ~DescriptorPoolManager() { + SkASSERT(!fDescLayout); + SkASSERT(!fPool); + } + + void getNewDescriptorSet(GrVkGpu* gpu, VkDescriptorSet* ds); + + void freeGPUResources(const GrVkGpu* gpu); + void abandonGPUResources(); + + VkDescriptorSetLayout fDescLayout; // Not owned by this class + VkDescriptorType fDescType; + uint32_t fDescCountPerSet; + uint32_t fMaxDescriptors; + uint32_t fCurrentDescriptorCount; + GrVkDescriptorPool* fPool; + + private: + enum { + kNumUniformDescPerSet = 2, + kMaxDescriptors = 1024, + kStartNumDescriptors = 16, // must be less than kMaxUniformDescriptors + }; + + void getNewPool(GrVkGpu* gpu); + }; + + DescriptorPoolManager fPoolManager; + SkTArray fFreeSets; + // If the number of bindings is 0 we assume this is for uniform buffers + uint32_t fNumSamplerBindings; +}; + +#endif diff --git a/src/gpu/vk/GrVkImage.h b/src/gpu/vk/GrVkImage.h index 921d98e6ac..21728c0056 100644 --- a/src/gpu/vk/GrVkImage.h +++ b/src/gpu/vk/GrVkImage.h @@ -110,7 +110,7 @@ private: #ifdef SK_TRACE_VK_RESOURCES void dumpInfo() const override { - SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt()); + SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt()); } #endif private: diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp index cb3751191c..b9aa826375 100644 --- a/src/gpu/vk/GrVkPipelineState.cpp +++ b/src/gpu/vk/GrVkPipelineState.cpp @@ -11,6 +11,7 @@ #include "GrTexturePriv.h" #include "GrVkCommandBuffer.h" #include "GrVkDescriptorPool.h" +#include "GrVkDescriptorSet.h" #include "GrVkGpu.h" #include "GrVkImageView.h" #include "GrVkMemory.h" @@ -39,6 +40,7 @@ GrVkPipelineState::GrVkPipelineState(GrVkGpu* gpu, const GrGLSLFragProcs& fragmentProcessors) : fPipeline(pipeline) , fPipelineLayout(layout) + , fUniformDescriptorSet(nullptr) , fStartDS(SK_MaxS32) , fDSCount(0) , fBuiltinUniformHandles(builtinUniformHandles) @@ -48,8 +50,7 @@ GrVkPipelineState::GrVkPipelineState(GrVkGpu* gpu, , fDesc(desc) , fDataManager(uniforms, vertexUniformSize, fragmentUniformSize) , fSamplerPoolManager(dsSamplerLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - numSamplers, gpu) - , fCurrentUniformDescPool(nullptr) { + numSamplers, gpu) { fSamplers.setReserve(numSamplers); fTextureViews.setReserve(numSamplers); fTextures.setReserve(numSamplers); @@ -124,9 +125,10 @@ void GrVkPipelineState::freeGPUResources(const GrVkGpu* gpu) { } fSamplerPoolManager.freeGPUResources(gpu); - if (fCurrentUniformDescPool) { - fCurrentUniformDescPool->unref(gpu); - fCurrentUniformDescPool = nullptr; + + if (fUniformDescriptorSet) { + fUniformDescriptorSet->recycle(const_cast(gpu)); + fUniformDescriptorSet = nullptr; } this->freeTempResources(gpu); @@ -157,9 +159,10 @@ void GrVkPipelineState::abandonGPUResources() { fTextures.rewind(); fSamplerPoolManager.abandonGPUResources(); - if (fCurrentUniformDescPool) { - fCurrentUniformDescPool->unrefAndAbandon(); - fCurrentUniformDescPool = nullptr; + + if (fUniformDescriptorSet) { + fUniformDescriptorSet->unrefAndAbandon(); + fUniformDescriptorSet = nullptr; } } @@ -208,18 +211,13 @@ void GrVkPipelineState::setData(GrVkGpu* gpu, if (fVertexUniformBuffer.get() || fFragmentUniformBuffer.get()) { if (fDataManager.uploadUniformBuffers(gpu, fVertexUniformBuffer, fFragmentUniformBuffer) || - VK_NULL_HANDLE == fDescriptorSets[GrVkUniformHandler::kUniformBufferDescSet]) { - const GrVkDescriptorPool* pool; - int uniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet; - gpu->resourceProvider().getUniformDescriptorSet(&fDescriptorSets[uniformDSIdx], - &pool); - if (pool != fCurrentUniformDescPool) { - if (fCurrentUniformDescPool) { - fCurrentUniformDescPool->unref(gpu); - } - fCurrentUniformDescPool = pool; - fCurrentUniformDescPool->ref(); + !fUniformDescriptorSet) { + if (fUniformDescriptorSet) { + fUniformDescriptorSet->recycle(gpu); } + fUniformDescriptorSet = gpu->resourceProvider().getUniformDescriptorSet(); + int uniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet; + fDescriptorSets[uniformDSIdx] = fUniformDescriptorSet->descriptorSet(); this->writeUniformBuffers(gpu); } } @@ -370,8 +368,9 @@ void GrVkPipelineState::addUniformResources(GrVkCommandBuffer& commandBuffer) { if (fSamplerPoolManager.fPool) { commandBuffer.addResource(fSamplerPoolManager.fPool); } - if (fCurrentUniformDescPool) { - commandBuffer.addResource(fCurrentUniformDescPool); + + if (fUniformDescriptorSet) { + commandBuffer.addRecycledResource(fUniformDescriptorSet); } if (fVertexUniformBuffer.get()) { diff --git a/src/gpu/vk/GrVkPipelineState.h b/src/gpu/vk/GrVkPipelineState.h index d4cc19a9a3..8988aa340b 100644 --- a/src/gpu/vk/GrVkPipelineState.h +++ b/src/gpu/vk/GrVkPipelineState.h @@ -20,6 +20,7 @@ class GrPipeline; class GrVkCommandBuffer; class GrVkDescriptorPool; +class GrVkDescriptorSet; class GrVkGpu; class GrVkImageView; class GrVkPipeline; @@ -256,6 +257,10 @@ private: // GrVkPipelineState since we update the descriptor sets and bind them at separate times; VkDescriptorSet fDescriptorSets[2]; + // Once we move samplers over to use the resource provider for descriptor sets we will not need + // the above array and instead just use GrVkDescriptorSet like the uniform one here. + const GrVkDescriptorSet* fUniformDescriptorSet; + // Meta data so we know which descriptor sets we are using and need to bind. int fStartDS; int fDSCount; @@ -282,7 +287,6 @@ private: GrVkPipelineStateDataManager fDataManager; DescriptorPoolManager fSamplerPoolManager; - const GrVkDescriptorPool* fCurrentUniformDescPool; int fNumSamplers; diff --git a/src/gpu/vk/GrVkResource.h b/src/gpu/vk/GrVkResource.h index 190ee36b1a..fde3e37712 100644 --- a/src/gpu/vk/GrVkResource.h +++ b/src/gpu/vk/GrVkResource.h @@ -195,13 +195,14 @@ private: 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. + // the resource can be recycled for reuse. If the sublass (or whoever is managing this resource) + // decides not to recycle the objects, it is their responsibility to call unref on the object. void recycle(GrVkGpu* gpu) const { if (this->unique()) { this->onRecycle(gpu); + } else { + this->unref(gpu); } - this->unref(gpu); } private: diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp index e3c19d67a0..ccf47167c6 100644 --- a/src/gpu/vk/GrVkResourceProvider.cpp +++ b/src/gpu/vk/GrVkResourceProvider.cpp @@ -22,7 +22,6 @@ uint32_t GrVkResource::fKeyCounter = 0; GrVkResourceProvider::GrVkResourceProvider(GrVkGpu* gpu) : fGpu(gpu) , fPipelineCache(VK_NULL_HANDLE) - , fUniformDescPool(nullptr) , fCurrentUniformDescCount(0) { fPipelineStateCache = new PipelineStateCache(gpu); } @@ -61,9 +60,8 @@ void GrVkResourceProvider::initUniformDescObjects() { &dsUniformLayoutCreateInfo, nullptr, &fUniformDescLayout)); - fCurrMaxUniDescriptors = kStartNumUniformDescriptors; - fUniformDescPool = this->findOrCreateCompatibleDescriptorPool(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - fCurrMaxUniDescriptors); + + this->getDescSetHandle(0, fUniformDescLayout, &fUniformDSHandle); } void GrVkResourceProvider::init() { @@ -191,42 +189,46 @@ sk_sp GrVkResourceProvider::findOrCreateCompatiblePipelineSta return fPipelineStateCache->refPipelineState(pipeline, proc, primitiveType, renderPass); } -void GrVkResourceProvider::getUniformDescriptorSet(VkDescriptorSet* ds, - const GrVkDescriptorPool** outPool) { - fCurrentUniformDescCount += kNumUniformDescPerSet; - if (fCurrentUniformDescCount > fCurrMaxUniDescriptors) { - fUniformDescPool->unref(fGpu); - uint32_t newPoolSize = fCurrMaxUniDescriptors + ((fCurrMaxUniDescriptors + 1) >> 1); - if (newPoolSize < kMaxUniformDescriptors) { - fCurrMaxUniDescriptors = newPoolSize; - } else { - fCurrMaxUniDescriptors = kMaxUniformDescriptors; - } - fUniformDescPool = - this->findOrCreateCompatibleDescriptorPool(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - fCurrMaxUniDescriptors); - fCurrentUniformDescCount = kNumUniformDescPerSet; - } - SkASSERT(fUniformDescPool); - VkDescriptorSetAllocateInfo dsAllocateInfo; - memset(&dsAllocateInfo, 0, sizeof(VkDescriptorSetAllocateInfo)); - dsAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - dsAllocateInfo.pNext = nullptr; - dsAllocateInfo.descriptorPool = fUniformDescPool->descPool(); - dsAllocateInfo.descriptorSetCount = 1; - dsAllocateInfo.pSetLayouts = &fUniformDescLayout; - GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), AllocateDescriptorSets(fGpu->device(), - &dsAllocateInfo, - ds)); - *outPool = fUniformDescPool; +void GrVkResourceProvider::getDescSetHandle(uint32_t numSamplers, VkDescriptorSetLayout layout, + GrVkDescriptorSetManager::Handle* handle) { + SkASSERT(handle); + for (int i = 0; i < fDescriptorSetManagers.count(); ++i) { + if (fDescriptorSetManagers[i].isCompatible(numSamplers)) { + *handle = GrVkDescriptorSetManager::Handle(i); + return; + } + } + + // Failed to find a DescSetManager, we must create a new one; + VkDescriptorType type = numSamplers ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + + fDescriptorSetManagers.emplace_back(fGpu, layout, type, numSamplers); + *handle = GrVkDescriptorSetManager::Handle(fDescriptorSetManagers.count() - 1); +} + +const GrVkDescriptorSet* GrVkResourceProvider::getUniformDescriptorSet() { + SkASSERT(fUniformDSHandle.isValid()); + return fDescriptorSetManagers[fUniformDSHandle.toIndex()].getDescriptorSet(fGpu, + fUniformDSHandle); +} + + +void GrVkResourceProvider::recycleDescriptorSet(const GrVkDescriptorSet* descSet, + const GrVkDescriptorSetManager::Handle& handle) { + SkASSERT(descSet); + SkASSERT(handle.isValid()); + int managerIdx = handle.toIndex(); + SkASSERT(managerIdx < fDescriptorSetManagers.count()); + fDescriptorSetManagers[managerIdx].recycleDescriptorSet(descSet); } GrVkPrimaryCommandBuffer* GrVkResourceProvider::findOrCreatePrimaryCommandBuffer() { GrVkPrimaryCommandBuffer* cmdBuffer = nullptr; int count = fAvailableCommandBuffers.count(); if (count > 0) { - cmdBuffer = fAvailableCommandBuffers[count -1]; + cmdBuffer = fAvailableCommandBuffers[count - 1]; SkASSERT(cmdBuffer->finished(fGpu)); fAvailableCommandBuffers.removeShuffle(count - 1); } else { @@ -313,7 +315,13 @@ void GrVkResourceProvider::destroyResources() { nullptr)); fUniformDescLayout = VK_NULL_HANDLE; } - fUniformDescPool->unref(fGpu); + + // We must release/destroy all command buffers and pipeline states before releasing the + // GrVkDescriptorSetManagers + for (int i = 0; i < fDescriptorSetManagers.count(); ++i) { + fDescriptorSetManagers[i].release(fGpu); + } + fDescriptorSetManagers.reset(); } void GrVkResourceProvider::abandonResources() { @@ -356,8 +364,13 @@ void GrVkResourceProvider::abandonResources() { fPipelineCache = VK_NULL_HANDLE; - fUniformDescLayout = VK_NULL_HANDLE; - fUniformDescPool->unrefAndAbandon(); + // We must abandon all command buffers and pipeline states before abandoning the + // GrVkDescriptorSetManagers + for (int i = 0; i < fDescriptorSetManagers.count(); ++i) { + fDescriptorSetManagers[i].abandon(); + } + fDescriptorSetManagers.reset(); + } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/vk/GrVkResourceProvider.h b/src/gpu/vk/GrVkResourceProvider.h index 3891539b0c..cd0411b83b 100644 --- a/src/gpu/vk/GrVkResourceProvider.h +++ b/src/gpu/vk/GrVkResourceProvider.h @@ -11,6 +11,7 @@ #include "GrGpu.h" #include "GrResourceHandle.h" #include "GrVkDescriptorPool.h" +#include "GrVkDescriptorSetManager.h" #include "GrVkPipelineState.h" #include "GrVkRenderPass.h" #include "GrVkResource.h" @@ -100,18 +101,33 @@ public: GrPrimitiveType, const GrVkRenderPass& renderPass); - // For all our GrVkPipelineState objects, we require a layout where the first set contains two - // uniform buffers, one for the vertex shader and one for the fragment shader. Thus it is - // possible for us to use a shadered descriptor pool to allocate all these similar descriptor - // sets. The caller is responsible for reffing the outPool for as long as the returned - // VkDescriptor set is in use. - void getUniformDescriptorSet(VkDescriptorSet*, const GrVkDescriptorPool** outPool); + // Returns a handle which the GrVkResourceProvider uses to know which compatible + // GrVkDescriptorSetManager to use when getting or recycling a GrVkDescriptorSet. Passing in a + // value of 0 for numSamplers is used to signal this is for the uniform descriptor set. + void getDescSetHandle(uint32_t numSamplers, VkDescriptorSetLayout layout, + GrVkDescriptorSetManager::Handle* handle); + + // Returns a GrVkDescriptorSet that can be used for uniform buffers. The GrVkDescriptorSet + // is already reffed for the caller. + const GrVkDescriptorSet* getUniformDescriptorSet(); + + // Returns a GrVkDescriptorSet that can be used for sampler descriptors that are compatible with + // the GrVkDescriptorSetManager::Handle passed int.. The GrVkDescriptorSet is already reffed for + // the caller. + // TODO: Move samplers in GrVkPipelineState to use the GrVkResourceProvider to allocate + // descriptor sets from. + const GrVkDescriptorSet* getSamplerDescriptorSet(const GrVkDescriptorSetManager::Handle&); // Returns the compatible VkDescriptorSetLayout to use for uniform buffers. The caller does not // own the VkDescriptorSetLayout and thus should not delete it. This function should be used // when the caller needs the layout to create a VkPipelineLayout. VkDescriptorSetLayout getUniDSLayout() const { return fUniformDescLayout; } + // Signals that the descriptor set passed it, which is compatible with the passed in handle, + // can be reused by the next allocation request. + void recycleDescriptorSet(const GrVkDescriptorSet* descSet, + const GrVkDescriptorSetManager::Handle&); + // Destroy any cached resources. To be called before destroying the VkDevice. // The assumption is that all queues are idle and all command buffers are finished. // For resource tracing to work properly, this should be called after unrefing all other @@ -163,7 +179,6 @@ private: #endif }; - class CompatibleRenderPassSet { public: // This will always construct the basic load store render pass (all attachments load and @@ -218,8 +233,11 @@ private: // Cache of GrVkPipelineStates PipelineStateCache* fPipelineStateCache; + SkSTArray<4, GrVkDescriptorSetManager> fDescriptorSetManagers; + + GrVkDescriptorSetManager::Handle fUniformDSHandle; + // Current pool to allocate uniform descriptor sets from - const GrVkDescriptorPool* fUniformDescPool; VkDescriptorSetLayout fUniformDescLayout; //Curent number of uniform descriptors allocated from the pool int fCurrentUniformDescCount;