Setup system in Vulkan to reuse VkDescriptorSet allocations.
This CL uses the new system for uniform buffers. In a follow up CL I will
add support for samplers.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2163673002
Review-Url: https://codereview.chromium.org/2163673002
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 67530c2..7d58662 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 c9037c2..2e474ba 100644
--- a/src/gpu/vk/GrVkCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkCommandBuffer.cpp
@@ -73,7 +73,6 @@
}
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 0000000..47a997f
--- /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 0000000..69e2d44
--- /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 0000000..51138e1
--- /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 0000000..33a7720
--- /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<const GrVkDescriptorSet*> 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 921d98e..21728c0 100644
--- a/src/gpu/vk/GrVkImage.h
+++ b/src/gpu/vk/GrVkImage.h
@@ -110,7 +110,7 @@
#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 cb37511..b9aa826 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 @@
const GrGLSLFragProcs& fragmentProcessors)
: fPipeline(pipeline)
, fPipelineLayout(layout)
+ , fUniformDescriptorSet(nullptr)
, fStartDS(SK_MaxS32)
, fDSCount(0)
, fBuiltinUniformHandles(builtinUniformHandles)
@@ -48,8 +50,7 @@
, 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 @@
}
fSamplerPoolManager.freeGPUResources(gpu);
- if (fCurrentUniformDescPool) {
- fCurrentUniformDescPool->unref(gpu);
- fCurrentUniformDescPool = nullptr;
+
+ if (fUniformDescriptorSet) {
+ fUniformDescriptorSet->recycle(const_cast<GrVkGpu*>(gpu));
+ fUniformDescriptorSet = nullptr;
}
this->freeTempResources(gpu);
@@ -157,9 +159,10 @@
fTextures.rewind();
fSamplerPoolManager.abandonGPUResources();
- if (fCurrentUniformDescPool) {
- fCurrentUniformDescPool->unrefAndAbandon();
- fCurrentUniformDescPool = nullptr;
+
+ if (fUniformDescriptorSet) {
+ fUniformDescriptorSet->unrefAndAbandon();
+ fUniformDescriptorSet = nullptr;
}
}
@@ -208,18 +211,13 @@
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 @@
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 d4cc19a..8988aa3 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 @@
// 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 @@
GrVkPipelineStateDataManager fDataManager;
DescriptorPoolManager fSamplerPoolManager;
- const GrVkDescriptorPool* fCurrentUniformDescPool;
int fNumSamplers;
diff --git a/src/gpu/vk/GrVkResource.h b/src/gpu/vk/GrVkResource.h
index 190ee36..fde3e37 100644
--- a/src/gpu/vk/GrVkResource.h
+++ b/src/gpu/vk/GrVkResource.h
@@ -195,13 +195,14 @@
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 e3c19d6..ccf4716 100644
--- a/src/gpu/vk/GrVkResourceProvider.cpp
+++ b/src/gpu/vk/GrVkResourceProvider.cpp
@@ -22,7 +22,6 @@
GrVkResourceProvider::GrVkResourceProvider(GrVkGpu* gpu)
: fGpu(gpu)
, fPipelineCache(VK_NULL_HANDLE)
- , fUniformDescPool(nullptr)
, fCurrentUniformDescCount(0) {
fPipelineStateCache = new PipelineStateCache(gpu);
}
@@ -61,9 +60,8 @@
&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 @@
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 @@
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 @@
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 3891539..cd0411b 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 @@
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 @@
#endif
};
-
class CompatibleRenderPassSet {
public:
// This will always construct the basic load store render pass (all attachments load and
@@ -218,8 +233,11 @@
// 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;