Setup system in Vulkan to reuse VkDescriptorSet allocations.
authoregdaniel <egdaniel@google.com>
Thu, 21 Jul 2016 18:50:37 +0000 (11:50 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 21 Jul 2016 18:50:37 +0000 (11:50 -0700)
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

12 files changed:
gyp/gpu.gypi
src/gpu/vk/GrVkCommandBuffer.cpp
src/gpu/vk/GrVkDescriptorSet.cpp [new file with mode: 0644]
src/gpu/vk/GrVkDescriptorSet.h [new file with mode: 0644]
src/gpu/vk/GrVkDescriptorSetManager.cpp [new file with mode: 0644]
src/gpu/vk/GrVkDescriptorSetManager.h [new file with mode: 0644]
src/gpu/vk/GrVkImage.h
src/gpu/vk/GrVkPipelineState.cpp
src/gpu/vk/GrVkPipelineState.h
src/gpu/vk/GrVkResource.h
src/gpu/vk/GrVkResourceProvider.cpp
src/gpu/vk/GrVkResourceProvider.h

index 67530c2..7d58662 100644 (file)
       '<(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',
index c9037c2..2e474ba 100644 (file)
@@ -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 (file)
index 0000000..47a997f
--- /dev/null
@@ -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 (file)
index 0000000..69e2d44
--- /dev/null
@@ -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 (file)
index 0000000..51138e1
--- /dev/null
@@ -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 (file)
index 0000000..33a7720
--- /dev/null
@@ -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
index 921d98e..21728c0 100644 (file)
@@ -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:
index cb37511..b9aa826 100644 (file)
@@ -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<GrVkGpu*>(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()) {
index d4cc19a..8988aa3 100644 (file)
@@ -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;
 
index 190ee36..fde3e37 100644 (file)
@@ -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:
index e3c19d6..ccf4716 100644 (file)
@@ -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<GrVkPipelineState> 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;
+
+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;
         }
-        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;
+
+    // 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();
+
 }
 
 ////////////////////////////////////////////////////////////////////////////////
index 3891539..cd0411b 100644 (file)
@@ -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;