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
This commit is contained in:
egdaniel 2016-07-21 11:50:37 -07:00 committed by Commit bot
parent 81681949d3
commit a95220d3b8
12 changed files with 404 additions and 71 deletions

View File

@ -455,6 +455,10 @@
'<(skia_src_path)/gpu/vk/GrVkCommandBuffer.h', '<(skia_src_path)/gpu/vk/GrVkCommandBuffer.h',
'<(skia_src_path)/gpu/vk/GrVkDescriptorPool.cpp', '<(skia_src_path)/gpu/vk/GrVkDescriptorPool.cpp',
'<(skia_src_path)/gpu/vk/GrVkDescriptorPool.h', '<(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.cpp',
'<(skia_src_path)/gpu/vk/GrVkExtensions.h', '<(skia_src_path)/gpu/vk/GrVkExtensions.h',
'<(skia_src_path)/gpu/vk/GrVkFramebuffer.cpp', '<(skia_src_path)/gpu/vk/GrVkFramebuffer.cpp',

View File

@ -73,7 +73,6 @@ void GrVkCommandBuffer::reset(GrVkGpu* gpu) {
} }
fTrackedRecycledResources.reset(); fTrackedRecycledResources.reset();
this->invalidateState(); this->invalidateState();
// we will retain resources for later use // we will retain resources for later use

View File

@ -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();
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -110,7 +110,7 @@ private:
#ifdef SK_TRACE_VK_RESOURCES #ifdef SK_TRACE_VK_RESOURCES
void dumpInfo() const override { void dumpInfo() const override {
SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt()); SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt());
} }
#endif #endif
private: private:

View File

@ -11,6 +11,7 @@
#include "GrTexturePriv.h" #include "GrTexturePriv.h"
#include "GrVkCommandBuffer.h" #include "GrVkCommandBuffer.h"
#include "GrVkDescriptorPool.h" #include "GrVkDescriptorPool.h"
#include "GrVkDescriptorSet.h"
#include "GrVkGpu.h" #include "GrVkGpu.h"
#include "GrVkImageView.h" #include "GrVkImageView.h"
#include "GrVkMemory.h" #include "GrVkMemory.h"
@ -39,6 +40,7 @@ GrVkPipelineState::GrVkPipelineState(GrVkGpu* gpu,
const GrGLSLFragProcs& fragmentProcessors) const GrGLSLFragProcs& fragmentProcessors)
: fPipeline(pipeline) : fPipeline(pipeline)
, fPipelineLayout(layout) , fPipelineLayout(layout)
, fUniformDescriptorSet(nullptr)
, fStartDS(SK_MaxS32) , fStartDS(SK_MaxS32)
, fDSCount(0) , fDSCount(0)
, fBuiltinUniformHandles(builtinUniformHandles) , fBuiltinUniformHandles(builtinUniformHandles)
@ -48,8 +50,7 @@ GrVkPipelineState::GrVkPipelineState(GrVkGpu* gpu,
, fDesc(desc) , fDesc(desc)
, fDataManager(uniforms, vertexUniformSize, fragmentUniformSize) , fDataManager(uniforms, vertexUniformSize, fragmentUniformSize)
, fSamplerPoolManager(dsSamplerLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, , fSamplerPoolManager(dsSamplerLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
numSamplers, gpu) numSamplers, gpu) {
, fCurrentUniformDescPool(nullptr) {
fSamplers.setReserve(numSamplers); fSamplers.setReserve(numSamplers);
fTextureViews.setReserve(numSamplers); fTextureViews.setReserve(numSamplers);
fTextures.setReserve(numSamplers); fTextures.setReserve(numSamplers);
@ -124,9 +125,10 @@ void GrVkPipelineState::freeGPUResources(const GrVkGpu* gpu) {
} }
fSamplerPoolManager.freeGPUResources(gpu); fSamplerPoolManager.freeGPUResources(gpu);
if (fCurrentUniformDescPool) {
fCurrentUniformDescPool->unref(gpu); if (fUniformDescriptorSet) {
fCurrentUniformDescPool = nullptr; fUniformDescriptorSet->recycle(const_cast<GrVkGpu*>(gpu));
fUniformDescriptorSet = nullptr;
} }
this->freeTempResources(gpu); this->freeTempResources(gpu);
@ -157,9 +159,10 @@ void GrVkPipelineState::abandonGPUResources() {
fTextures.rewind(); fTextures.rewind();
fSamplerPoolManager.abandonGPUResources(); fSamplerPoolManager.abandonGPUResources();
if (fCurrentUniformDescPool) {
fCurrentUniformDescPool->unrefAndAbandon(); if (fUniformDescriptorSet) {
fCurrentUniformDescPool = nullptr; fUniformDescriptorSet->unrefAndAbandon();
fUniformDescriptorSet = nullptr;
} }
} }
@ -208,18 +211,13 @@ void GrVkPipelineState::setData(GrVkGpu* gpu,
if (fVertexUniformBuffer.get() || fFragmentUniformBuffer.get()) { if (fVertexUniformBuffer.get() || fFragmentUniformBuffer.get()) {
if (fDataManager.uploadUniformBuffers(gpu, fVertexUniformBuffer, fFragmentUniformBuffer) || if (fDataManager.uploadUniformBuffers(gpu, fVertexUniformBuffer, fFragmentUniformBuffer) ||
VK_NULL_HANDLE == fDescriptorSets[GrVkUniformHandler::kUniformBufferDescSet]) { !fUniformDescriptorSet) {
const GrVkDescriptorPool* pool; if (fUniformDescriptorSet) {
int uniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet; fUniformDescriptorSet->recycle(gpu);
gpu->resourceProvider().getUniformDescriptorSet(&fDescriptorSets[uniformDSIdx],
&pool);
if (pool != fCurrentUniformDescPool) {
if (fCurrentUniformDescPool) {
fCurrentUniformDescPool->unref(gpu);
}
fCurrentUniformDescPool = pool;
fCurrentUniformDescPool->ref();
} }
fUniformDescriptorSet = gpu->resourceProvider().getUniformDescriptorSet();
int uniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet;
fDescriptorSets[uniformDSIdx] = fUniformDescriptorSet->descriptorSet();
this->writeUniformBuffers(gpu); this->writeUniformBuffers(gpu);
} }
} }
@ -370,8 +368,9 @@ void GrVkPipelineState::addUniformResources(GrVkCommandBuffer& commandBuffer) {
if (fSamplerPoolManager.fPool) { if (fSamplerPoolManager.fPool) {
commandBuffer.addResource(fSamplerPoolManager.fPool); commandBuffer.addResource(fSamplerPoolManager.fPool);
} }
if (fCurrentUniformDescPool) {
commandBuffer.addResource(fCurrentUniformDescPool); if (fUniformDescriptorSet) {
commandBuffer.addRecycledResource(fUniformDescriptorSet);
} }
if (fVertexUniformBuffer.get()) { if (fVertexUniformBuffer.get()) {

View File

@ -20,6 +20,7 @@
class GrPipeline; class GrPipeline;
class GrVkCommandBuffer; class GrVkCommandBuffer;
class GrVkDescriptorPool; class GrVkDescriptorPool;
class GrVkDescriptorSet;
class GrVkGpu; class GrVkGpu;
class GrVkImageView; class GrVkImageView;
class GrVkPipeline; class GrVkPipeline;
@ -256,6 +257,10 @@ private:
// GrVkPipelineState since we update the descriptor sets and bind them at separate times; // GrVkPipelineState since we update the descriptor sets and bind them at separate times;
VkDescriptorSet fDescriptorSets[2]; 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. // Meta data so we know which descriptor sets we are using and need to bind.
int fStartDS; int fStartDS;
int fDSCount; int fDSCount;
@ -282,7 +287,6 @@ private:
GrVkPipelineStateDataManager fDataManager; GrVkPipelineStateDataManager fDataManager;
DescriptorPoolManager fSamplerPoolManager; DescriptorPoolManager fSamplerPoolManager;
const GrVkDescriptorPool* fCurrentUniformDescPool;
int fNumSamplers; int fNumSamplers;

View File

@ -195,13 +195,14 @@ private:
class GrVkRecycledResource : public GrVkResource { class GrVkRecycledResource : public GrVkResource {
public: public:
// When recycle is called and there is only one ref left on the resource, we will signal that // 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 // the resource can be recycled for reuse. If the sublass (or whoever is managing this resource)
// if the object is recycled it should be ref'd inside the onRecycle call. // decides not to recycle the objects, it is their responsibility to call unref on the object.
void recycle(GrVkGpu* gpu) const { void recycle(GrVkGpu* gpu) const {
if (this->unique()) { if (this->unique()) {
this->onRecycle(gpu); this->onRecycle(gpu);
} else {
this->unref(gpu);
} }
this->unref(gpu);
} }
private: private:

View File

@ -22,7 +22,6 @@ uint32_t GrVkResource::fKeyCounter = 0;
GrVkResourceProvider::GrVkResourceProvider(GrVkGpu* gpu) GrVkResourceProvider::GrVkResourceProvider(GrVkGpu* gpu)
: fGpu(gpu) : fGpu(gpu)
, fPipelineCache(VK_NULL_HANDLE) , fPipelineCache(VK_NULL_HANDLE)
, fUniformDescPool(nullptr)
, fCurrentUniformDescCount(0) { , fCurrentUniformDescCount(0) {
fPipelineStateCache = new PipelineStateCache(gpu); fPipelineStateCache = new PipelineStateCache(gpu);
} }
@ -61,9 +60,8 @@ void GrVkResourceProvider::initUniformDescObjects() {
&dsUniformLayoutCreateInfo, &dsUniformLayoutCreateInfo,
nullptr, nullptr,
&fUniformDescLayout)); &fUniformDescLayout));
fCurrMaxUniDescriptors = kStartNumUniformDescriptors;
fUniformDescPool = this->findOrCreateCompatibleDescriptorPool(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->getDescSetHandle(0, fUniformDescLayout, &fUniformDSHandle);
fCurrMaxUniDescriptors);
} }
void GrVkResourceProvider::init() { void GrVkResourceProvider::init() {
@ -191,42 +189,46 @@ sk_sp<GrVkPipelineState> GrVkResourceProvider::findOrCreateCompatiblePipelineSta
return fPipelineStateCache->refPipelineState(pipeline, proc, primitiveType, renderPass); 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; void GrVkResourceProvider::getDescSetHandle(uint32_t numSamplers, VkDescriptorSetLayout layout,
memset(&dsAllocateInfo, 0, sizeof(VkDescriptorSetAllocateInfo)); GrVkDescriptorSetManager::Handle* handle) {
dsAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; SkASSERT(handle);
dsAllocateInfo.pNext = nullptr; for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
dsAllocateInfo.descriptorPool = fUniformDescPool->descPool(); if (fDescriptorSetManagers[i].isCompatible(numSamplers)) {
dsAllocateInfo.descriptorSetCount = 1; *handle = GrVkDescriptorSetManager::Handle(i);
dsAllocateInfo.pSetLayouts = &fUniformDescLayout; return;
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* GrVkResourceProvider::findOrCreatePrimaryCommandBuffer() {
GrVkPrimaryCommandBuffer* cmdBuffer = nullptr; GrVkPrimaryCommandBuffer* cmdBuffer = nullptr;
int count = fAvailableCommandBuffers.count(); int count = fAvailableCommandBuffers.count();
if (count > 0) { if (count > 0) {
cmdBuffer = fAvailableCommandBuffers[count -1]; cmdBuffer = fAvailableCommandBuffers[count - 1];
SkASSERT(cmdBuffer->finished(fGpu)); SkASSERT(cmdBuffer->finished(fGpu));
fAvailableCommandBuffers.removeShuffle(count - 1); fAvailableCommandBuffers.removeShuffle(count - 1);
} else { } else {
@ -313,7 +315,13 @@ void GrVkResourceProvider::destroyResources() {
nullptr)); nullptr));
fUniformDescLayout = VK_NULL_HANDLE; 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() { void GrVkResourceProvider::abandonResources() {
@ -356,8 +364,13 @@ void GrVkResourceProvider::abandonResources() {
fPipelineCache = VK_NULL_HANDLE; fPipelineCache = VK_NULL_HANDLE;
fUniformDescLayout = VK_NULL_HANDLE; // We must abandon all command buffers and pipeline states before abandoning the
fUniformDescPool->unrefAndAbandon(); // GrVkDescriptorSetManagers
for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
fDescriptorSetManagers[i].abandon();
}
fDescriptorSetManagers.reset();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -11,6 +11,7 @@
#include "GrGpu.h" #include "GrGpu.h"
#include "GrResourceHandle.h" #include "GrResourceHandle.h"
#include "GrVkDescriptorPool.h" #include "GrVkDescriptorPool.h"
#include "GrVkDescriptorSetManager.h"
#include "GrVkPipelineState.h" #include "GrVkPipelineState.h"
#include "GrVkRenderPass.h" #include "GrVkRenderPass.h"
#include "GrVkResource.h" #include "GrVkResource.h"
@ -100,18 +101,33 @@ public:
GrPrimitiveType, GrPrimitiveType,
const GrVkRenderPass& renderPass); const GrVkRenderPass& renderPass);
// For all our GrVkPipelineState objects, we require a layout where the first set contains two // Returns a handle which the GrVkResourceProvider uses to know which compatible
// uniform buffers, one for the vertex shader and one for the fragment shader. Thus it is // GrVkDescriptorSetManager to use when getting or recycling a GrVkDescriptorSet. Passing in a
// possible for us to use a shadered descriptor pool to allocate all these similar descriptor // value of 0 for numSamplers is used to signal this is for the uniform descriptor set.
// sets. The caller is responsible for reffing the outPool for as long as the returned void getDescSetHandle(uint32_t numSamplers, VkDescriptorSetLayout layout,
// VkDescriptor set is in use. GrVkDescriptorSetManager::Handle* handle);
void getUniformDescriptorSet(VkDescriptorSet*, const GrVkDescriptorPool** outPool);
// 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 // 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 // own the VkDescriptorSetLayout and thus should not delete it. This function should be used
// when the caller needs the layout to create a VkPipelineLayout. // when the caller needs the layout to create a VkPipelineLayout.
VkDescriptorSetLayout getUniDSLayout() const { return fUniformDescLayout; } 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. // 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. // 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 // For resource tracing to work properly, this should be called after unrefing all other
@ -163,7 +179,6 @@ private:
#endif #endif
}; };
class CompatibleRenderPassSet { class CompatibleRenderPassSet {
public: public:
// This will always construct the basic load store render pass (all attachments load and // This will always construct the basic load store render pass (all attachments load and
@ -218,8 +233,11 @@ private:
// Cache of GrVkPipelineStates // Cache of GrVkPipelineStates
PipelineStateCache* fPipelineStateCache; PipelineStateCache* fPipelineStateCache;
SkSTArray<4, GrVkDescriptorSetManager> fDescriptorSetManagers;
GrVkDescriptorSetManager::Handle fUniformDSHandle;
// Current pool to allocate uniform descriptor sets from // Current pool to allocate uniform descriptor sets from
const GrVkDescriptorPool* fUniformDescPool;
VkDescriptorSetLayout fUniformDescLayout; VkDescriptorSetLayout fUniformDescLayout;
//Curent number of uniform descriptors allocated from the pool //Curent number of uniform descriptors allocated from the pool
int fCurrentUniformDescCount; int fCurrentUniformDescCount;