Reuse sampler descriptor set allocations in Vulkan

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2172873003

Review-Url: https://codereview.chromium.org/2172873003
This commit is contained in:
egdaniel 2016-07-26 07:19:47 -07:00 committed by Commit bot
parent fe8d2cf520
commit 707bbd622b
8 changed files with 237 additions and 186 deletions

View File

@ -10,13 +10,25 @@
#include "GrVkDescriptorPool.h"
#include "GrVkDescriptorSet.h"
#include "GrVkGpu.h"
#include "GrVkUniformHandler.h"
#include "glsl/GrGLSLSampler.h"
GrVkDescriptorSetManager::GrVkDescriptorSetManager(GrVkGpu* gpu,
VkDescriptorSetLayout layout,
VkDescriptorType type,
uint32_t samplerCount)
: fPoolManager(layout, type, samplerCount, gpu)
, fNumSamplerBindings(samplerCount) {
const GrVkUniformHandler* uniformHandler)
: fPoolManager(type, gpu, uniformHandler) {
if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
SkASSERT(uniformHandler);
for (int i = 0; i < uniformHandler->numSamplers(); ++i) {
fBindingVisibilities.push_back(uniformHandler->getSampler(i).visibility());
}
} else {
SkASSERT(type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
// We set the visibility of the first binding to the vertex shader and the second to the
// fragment shader.
fBindingVisibilities.push_back(kVertex_GrShaderFlag);
fBindingVisibilities.push_back(kFragment_GrShaderFlag);
}
}
const GrVkDescriptorSet* GrVkDescriptorSetManager::getDescriptorSet(GrVkGpu* gpu,
@ -59,8 +71,122 @@ void GrVkDescriptorSetManager::abandon() {
fFreeSets.reset();
}
bool GrVkDescriptorSetManager::isCompatible(VkDescriptorType type,
const GrVkUniformHandler* uniHandler) const {
SkASSERT(uniHandler);
if (type != fPoolManager.fDescType) {
return false;
}
if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
if (fBindingVisibilities.count() != uniHandler->numSamplers()) {
return false;
}
for (int i = 0; i < uniHandler->numSamplers(); ++i) {
if (uniHandler->getSampler(i).visibility() != fBindingVisibilities[i]) {
return false;
}
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
VkShaderStageFlags visibility_to_vk_stage_flags(uint32_t visibility) {
VkShaderStageFlags flags = 0;
if (visibility & kVertex_GrShaderFlag) {
flags |= VK_SHADER_STAGE_VERTEX_BIT;
}
if (visibility & kGeometry_GrShaderFlag) {
flags |= VK_SHADER_STAGE_GEOMETRY_BIT;
}
if (visibility & kFragment_GrShaderFlag) {
flags |= VK_SHADER_STAGE_FRAGMENT_BIT;
}
return flags;
}
GrVkDescriptorSetManager::DescriptorPoolManager::DescriptorPoolManager(
VkDescriptorType type,
GrVkGpu* gpu,
const GrVkUniformHandler* uniformHandler)
: fDescType(type)
, fCurrentDescriptorCount(0)
, fPool(nullptr) {
if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
SkASSERT(uniformHandler);
uint32_t numSamplers = (uint32_t)uniformHandler->numSamplers();
SkAutoTDeleteArray<VkDescriptorSetLayoutBinding> dsSamplerBindings(
new VkDescriptorSetLayoutBinding[numSamplers]);
for (uint32_t i = 0; i < numSamplers; ++i) {
const GrVkGLSLSampler& sampler =
static_cast<const GrVkGLSLSampler&>(uniformHandler->getSampler(i));
SkASSERT(sampler.binding() == i);
dsSamplerBindings[i].binding = sampler.binding();
dsSamplerBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
dsSamplerBindings[i].descriptorCount = 1;
dsSamplerBindings[i].stageFlags = visibility_to_vk_stage_flags(sampler.visibility());
dsSamplerBindings[i].pImmutableSamplers = nullptr;
}
VkDescriptorSetLayoutCreateInfo dsSamplerLayoutCreateInfo;
memset(&dsSamplerLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
dsSamplerLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
dsSamplerLayoutCreateInfo.pNext = nullptr;
dsSamplerLayoutCreateInfo.flags = 0;
dsSamplerLayoutCreateInfo.bindingCount = numSamplers;
// Setting to nullptr fixes an error in the param checker validation layer. Even though
// bindingCount is 0 (which is valid), it still tries to validate pBindings unless it is
// null.
dsSamplerLayoutCreateInfo.pBindings = numSamplers ? dsSamplerBindings.get() : nullptr;
GR_VK_CALL_ERRCHECK(gpu->vkInterface(),
CreateDescriptorSetLayout(gpu->device(),
&dsSamplerLayoutCreateInfo,
nullptr,
&fDescLayout));
fDescCountPerSet = numSamplers;
} else {
SkASSERT(type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
// Create Uniform Buffer Descriptor
// The vertex uniform buffer will have binding 0 and the fragment binding 1.
VkDescriptorSetLayoutBinding dsUniBindings[kUniformDescPerSet];
memset(&dsUniBindings, 0, 2 * sizeof(VkDescriptorSetLayoutBinding));
dsUniBindings[0].binding = GrVkUniformHandler::kVertexBinding;
dsUniBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsUniBindings[0].descriptorCount = 1;
dsUniBindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
dsUniBindings[0].pImmutableSamplers = nullptr;
dsUniBindings[1].binding = GrVkUniformHandler::kFragBinding;
dsUniBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsUniBindings[1].descriptorCount = 1;
dsUniBindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
dsUniBindings[1].pImmutableSamplers = nullptr;
VkDescriptorSetLayoutCreateInfo uniformLayoutCreateInfo;
memset(&uniformLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
uniformLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
uniformLayoutCreateInfo.pNext = nullptr;
uniformLayoutCreateInfo.flags = 0;
uniformLayoutCreateInfo.bindingCount = 2;
uniformLayoutCreateInfo.pBindings = dsUniBindings;
GR_VK_CALL_ERRCHECK(gpu->vkInterface(), CreateDescriptorSetLayout(gpu->device(),
&uniformLayoutCreateInfo,
nullptr,
&fDescLayout));
fDescCountPerSet = kUniformDescPerSet;
}
SkASSERT(fDescCountPerSet < kStartNumDescriptors);
fMaxDescriptors = kStartNumDescriptors;
SkASSERT(fMaxDescriptors > 0);
this->getNewPool(gpu);
}
void GrVkDescriptorSetManager::DescriptorPoolManager::getNewPool(GrVkGpu* gpu) {
if (fPool) {
fPool->unref(gpu);
@ -101,9 +227,11 @@ void GrVkDescriptorSetManager::DescriptorPoolManager::getNewDescriptorSet(GrVkGp
}
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 (fDescLayout) {
GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDescLayout,
nullptr));
fDescLayout = VK_NULL_HANDLE;
}
if (fPool) {
fPool->unref(gpu);

View File

@ -16,6 +16,7 @@
class GrVkDescriptorSet;
class GrVkGpu;
class GrVkUniformHandler;
/**
* This class handles the allocation of descriptor sets for a given VkDescriptorSetLayout. It will
@ -26,40 +27,25 @@ public:
GR_DEFINE_RESOURCE_HANDLE_CLASS(Handle);
GrVkDescriptorSetManager(GrVkGpu* gpu,
VkDescriptorSetLayout layout,
VkDescriptorType,
uint32_t samplerCount);
const GrVkUniformHandler* handler = nullptr);
~GrVkDescriptorSetManager() {}
void abandon();
void release(const GrVkGpu* gpu);
VkDescriptorSetLayout layout() const { return fPoolManager.fDescLayout; }
const GrVkDescriptorSet* getDescriptorSet(GrVkGpu* gpu, const Handle& handle);
void recycleDescriptorSet(const GrVkDescriptorSet*);
int isCompatible(uint32_t numSamplers) const { return numSamplers == fNumSamplerBindings; }
bool isCompatible(VkDescriptorType type, const GrVkUniformHandler*) const;
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(VkDescriptorType type, GrVkGpu* gpu,
const GrVkUniformHandler* handler = nullptr);
~DescriptorPoolManager() {
SkASSERT(!fDescLayout);
@ -71,7 +57,7 @@ private:
void freeGPUResources(const GrVkGpu* gpu);
void abandonGPUResources();
VkDescriptorSetLayout fDescLayout; // Not owned by this class
VkDescriptorSetLayout fDescLayout;
VkDescriptorType fDescType;
uint32_t fDescCountPerSet;
uint32_t fMaxDescriptors;
@ -80,7 +66,7 @@ private:
private:
enum {
kNumUniformDescPerSet = 2,
kUniformDescPerSet = 2,
kMaxDescriptors = 1024,
kStartNumDescriptors = 16, // must be less than kMaxUniformDescriptors
};
@ -88,10 +74,9 @@ private:
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;
DescriptorPoolManager fPoolManager;
SkTArray<const GrVkDescriptorSet*, true> fFreeSets;
SkSTArray<4, uint32_t> fBindingVisibilities;
};
#endif

View File

@ -29,7 +29,7 @@ GrVkPipelineState::GrVkPipelineState(GrVkGpu* gpu,
const GrVkPipelineState::Desc& desc,
GrVkPipeline* pipeline,
VkPipelineLayout layout,
VkDescriptorSetLayout dsSamplerLayout,
const GrVkDescriptorSetManager::Handle& samplerDSHandle,
const BuiltinUniformHandles& builtinUniformHandles,
const UniformInfoArray& uniforms,
uint32_t vertexUniformSize,
@ -41,6 +41,8 @@ GrVkPipelineState::GrVkPipelineState(GrVkGpu* gpu,
: fPipeline(pipeline)
, fPipelineLayout(layout)
, fUniformDescriptorSet(nullptr)
, fSamplerDescriptorSet(nullptr)
, fSamplerDSHandle(samplerDSHandle)
, fStartDS(SK_MaxS32)
, fDSCount(0)
, fBuiltinUniformHandles(builtinUniformHandles)
@ -48,9 +50,7 @@ GrVkPipelineState::GrVkPipelineState(GrVkGpu* gpu,
, fXferProcessor(xferProcessor)
, fFragmentProcessors(fragmentProcessors)
, fDesc(desc)
, fDataManager(uniforms, vertexUniformSize, fragmentUniformSize)
, fSamplerPoolManager(dsSamplerLayout, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
numSamplers, gpu) {
, fDataManager(uniforms, vertexUniformSize, fragmentUniformSize) {
fSamplers.setReserve(numSamplers);
fTextureViews.setReserve(numSamplers);
fTextures.setReserve(numSamplers);
@ -124,13 +124,16 @@ void GrVkPipelineState::freeGPUResources(const GrVkGpu* gpu) {
fFragmentUniformBuffer->release(gpu);
}
fSamplerPoolManager.freeGPUResources(gpu);
if (fUniformDescriptorSet) {
fUniformDescriptorSet->recycle(const_cast<GrVkGpu*>(gpu));
fUniformDescriptorSet = nullptr;
}
if (fSamplerDescriptorSet) {
fSamplerDescriptorSet->recycle(const_cast<GrVkGpu*>(gpu));
fSamplerDescriptorSet = nullptr;
}
this->freeTempResources(gpu);
}
@ -158,12 +161,15 @@ void GrVkPipelineState::abandonGPUResources() {
}
fTextures.rewind();
fSamplerPoolManager.abandonGPUResources();
if (fUniformDescriptorSet) {
fUniformDescriptorSet->unrefAndAbandon();
fUniformDescriptorSet = nullptr;
}
if (fSamplerDescriptorSet) {
fSamplerDescriptorSet->unrefAndAbandon();
fSamplerDescriptorSet = nullptr;
}
}
static void append_texture_bindings(const GrProcessor& processor,
@ -204,8 +210,12 @@ void GrVkPipelineState::setData(GrVkGpu* gpu,
// Get new descriptor sets
if (fNumSamplers) {
fSamplerPoolManager.getNewDescriptorSet(gpu,
&fDescriptorSets[GrVkUniformHandler::kSamplerDescSet]);
if (fSamplerDescriptorSet) {
fSamplerDescriptorSet->recycle(gpu);
}
fSamplerDescriptorSet = gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle);
int samplerDSIdx = GrVkUniformHandler::kSamplerDescSet;
fDescriptorSets[samplerDSIdx] = fSamplerDescriptorSet->descriptorSet();
this->writeSamplers(gpu, textureBindings, pipeline.getAllowSRGBInputs());
}
@ -365,13 +375,13 @@ void GrVkPipelineState::bind(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffe
}
void GrVkPipelineState::addUniformResources(GrVkCommandBuffer& commandBuffer) {
if (fSamplerPoolManager.fPool) {
commandBuffer.addResource(fSamplerPoolManager.fPool);
}
if (fUniformDescriptorSet) {
commandBuffer.addRecycledResource(fUniformDescriptorSet);
}
if (fSamplerDescriptorSet) {
commandBuffer.addRecycledResource(fSamplerDescriptorSet);
}
if (fVertexUniformBuffer.get()) {
commandBuffer.addResource(fVertexUniformBuffer->resource());

View File

@ -10,6 +10,7 @@
#define GrVkPipelineState_DEFINED
#include "GrStencilSettings.h"
#include "GrVkDescriptorSetManager.h"
#include "GrVkImage.h"
#include "GrVkProgramDesc.h"
#include "GrVkPipelineStateDataManager.h"
@ -151,7 +152,7 @@ private:
const GrVkPipelineState::Desc&,
GrVkPipeline* pipeline,
VkPipelineLayout layout,
VkDescriptorSetLayout dsSamplerLayout,
const GrVkDescriptorSetManager::Handle& samplerDSHandle,
const BuiltinUniformHandles& builtinUniformHandles,
const UniformInfoArray& uniforms,
uint32_t vertexUniformSize,
@ -260,6 +261,9 @@ private:
// 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;
const GrVkDescriptorSet* fSamplerDescriptorSet;
const GrVkDescriptorSetManager::Handle fSamplerDSHandle;
// Meta data so we know which descriptor sets we are using and need to bind.
int fStartDS;
@ -286,8 +290,6 @@ private:
GrVkPipelineStateDataManager fDataManager;
DescriptorPoolManager fSamplerPoolManager;
int fNumSamplers;
friend class GrVkPipelineStateBuilder;

View File

@ -7,6 +7,7 @@
#include "vk/GrVkPipelineStateBuilder.h"
#include "vk/GrVkDescriptorSetManager.h"
#include "vk/GrVkGpu.h"
#include "vk/GrVkRenderPass.h"
#if USE_SKSL
@ -60,21 +61,6 @@ void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrGLSLShaderVar& o
outputColor.setLayoutQualifier("location = 0, index = 1");
}
VkShaderStageFlags visibility_to_vk_stage_flags(uint32_t visibility) {
VkShaderStageFlags flags = 0;
if (visibility & kVertex_GrShaderFlag) {
flags |= VK_SHADER_STAGE_VERTEX_BIT;
}
if (visibility & kGeometry_GrShaderFlag) {
flags |= VK_SHADER_STAGE_GEOMETRY_BIT;
}
if (visibility & kFragment_GrShaderFlag) {
flags |= VK_SHADER_STAGE_FRAGMENT_BIT;
}
return flags;
}
#if USE_SKSL
SkSL::Program::Kind vk_shader_stage_to_skiasl_kind(VkShaderStageFlagBits stage) {
if (VK_SHADER_STAGE_VERTEX_BIT == stage) {
@ -124,7 +110,7 @@ bool GrVkPipelineStateBuilder::CreateVkShaderModule(const GrVkGpu* gpu,
} else {
#if USE_SKSL
bool result = gpu->shaderCompiler()->toSPIRV(vk_shader_stage_to_skiasl_kind(stage),
bool result = gpu->shaderCompiler()->toSPIRV(vk_shader_stage_to_skiasl_kind(stage),
std::string(shaderString.c_str()),
&code);
if (!result) {
@ -194,39 +180,14 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(GrPrimitiveType primitiveT
VkShaderModule vertShaderModule;
VkShaderModule fragShaderModule;
uint32_t numSamplers = (uint32_t)fUniformHandler.numSamplers();
SkAutoTDeleteArray<VkDescriptorSetLayoutBinding> dsSamplerBindings(
new VkDescriptorSetLayoutBinding[numSamplers]);
for (uint32_t i = 0; i < numSamplers; ++i) {
const GrVkGLSLSampler& sampler =
static_cast<const GrVkGLSLSampler&>(fUniformHandler.getSampler(i));
SkASSERT(sampler.binding() == i);
dsSamplerBindings[i].binding = sampler.binding();
dsSamplerBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
dsSamplerBindings[i].descriptorCount = 1;
dsSamplerBindings[i].stageFlags = visibility_to_vk_stage_flags(sampler.visibility());
dsSamplerBindings[i].pImmutableSamplers = nullptr;
}
VkDescriptorSetLayoutCreateInfo dsSamplerLayoutCreateInfo;
memset(&dsSamplerLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
dsSamplerLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
dsSamplerLayoutCreateInfo.pNext = nullptr;
dsSamplerLayoutCreateInfo.flags = 0;
dsSamplerLayoutCreateInfo.bindingCount = numSamplers;
// Setting to nullptr fixes an error in the param checker validation layer. Even though
// bindingCount is 0 (which is valid), it still tries to validate pBindings unless it is null.
dsSamplerLayoutCreateInfo.pBindings = numSamplers ? dsSamplerBindings.get() : nullptr;
GR_VK_CALL_ERRCHECK(fGpu->vkInterface(),
CreateDescriptorSetLayout(fGpu->device(),
&dsSamplerLayoutCreateInfo,
nullptr,
&dsLayout[GrVkUniformHandler::kSamplerDescSet]));
GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
// This layout is not owned by the PipelineStateBuilder and thus should no be destroyed
dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = fGpu->resourceProvider().getUniDSLayout();
dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
GrVkDescriptorSetManager::Handle samplerDSHandle;
resourceProvider.getSamplerDescriptorSetHandle(fUniformHandler, &samplerDSHandle);
dsLayout[GrVkUniformHandler::kSamplerDescSet] =
resourceProvider.getSamplerDSLayout(samplerDSHandle);
// Create the VkPipelineLayout
VkPipelineLayoutCreateInfo layoutCreateInfo;
@ -266,7 +227,6 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(GrPrimitiveType primitiveT
&fragShaderModule,
&shaderStageInfo[1]));
GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
fPrimProc,
shaderStageInfo,
@ -295,13 +255,14 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(GrPrimitiveType primitiveT
desc,
pipeline,
pipelineLayout,
dsLayout[GrVkUniformHandler::kSamplerDescSet],
samplerDSHandle,
fUniformHandles,
fUniformHandler.fUniforms,
fUniformHandler.fCurrentVertexUBOOffset,
fUniformHandler.fCurrentFragmentUBOOffset,
numSamplers,
(uint32_t)fUniformHandler.numSamplers(),
fGeometryProcessor,
fXferProcessor,
fFragmentProcessors);
}

View File

@ -9,6 +9,7 @@
#include "GrTextureParams.h"
#include "GrVkCommandBuffer.h"
#include "GrVkGLSLSampler.h"
#include "GrVkPipeline.h"
#include "GrVkRenderTarget.h"
#include "GrVkSampler.h"
@ -22,8 +23,7 @@ uint32_t GrVkResource::fKeyCounter = 0;
GrVkResourceProvider::GrVkResourceProvider(GrVkGpu* gpu)
: fGpu(gpu)
, fPipelineCache(VK_NULL_HANDLE)
, fCurrentUniformDescCount(0) {
, fPipelineCache(VK_NULL_HANDLE) {
fPipelineStateCache = new PipelineStateCache(gpu);
}
@ -33,38 +33,6 @@ GrVkResourceProvider::~GrVkResourceProvider() {
delete fPipelineStateCache;
}
void GrVkResourceProvider::initUniformDescObjects() {
// Create Uniform Buffer Descriptor
// The vertex uniform buffer will have binding 0 and the fragment binding 1.
VkDescriptorSetLayoutBinding dsUniBindings[2];
memset(&dsUniBindings, 0, 2 * sizeof(VkDescriptorSetLayoutBinding));
dsUniBindings[0].binding = GrVkUniformHandler::kVertexBinding;
dsUniBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsUniBindings[0].descriptorCount = 1;
dsUniBindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
dsUniBindings[0].pImmutableSamplers = nullptr;
dsUniBindings[1].binding = GrVkUniformHandler::kFragBinding;
dsUniBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsUniBindings[1].descriptorCount = 1;
dsUniBindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
dsUniBindings[1].pImmutableSamplers = nullptr;
VkDescriptorSetLayoutCreateInfo dsUniformLayoutCreateInfo;
memset(&dsUniformLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
dsUniformLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
dsUniformLayoutCreateInfo.pNext = nullptr;
dsUniformLayoutCreateInfo.flags = 0;
dsUniformLayoutCreateInfo.bindingCount = 2;
dsUniformLayoutCreateInfo.pBindings = dsUniBindings;
GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreateDescriptorSetLayout(fGpu->device(),
&dsUniformLayoutCreateInfo,
nullptr,
&fUniformDescLayout));
this->getDescSetHandle(0, fUniformDescLayout, &fUniformDSHandle);
}
void GrVkResourceProvider::init() {
VkPipelineCacheCreateInfo createInfo;
memset(&createInfo, 0, sizeof(VkPipelineCacheCreateInfo));
@ -81,7 +49,10 @@ void GrVkResourceProvider::init() {
fPipelineCache = VK_NULL_HANDLE;
}
this->initUniformDescObjects();
// Init uniform descriptor objects
fDescriptorSetManagers.emplace_back(fGpu, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
SkASSERT(1 == fDescriptorSetManagers.count());
fUniformDSHandle = GrVkDescriptorSetManager::Handle(0);
}
GrVkPipeline* GrVkResourceProvider::createPipeline(const GrPipeline& pipeline,
@ -190,31 +161,44 @@ sk_sp<GrVkPipelineState> GrVkResourceProvider::findOrCreateCompatiblePipelineSta
return fPipelineStateCache->refPipelineState(pipeline, proc, primitiveType, renderPass);
}
void GrVkResourceProvider::getDescSetHandle(uint32_t numSamplers, VkDescriptorSetLayout layout,
GrVkDescriptorSetManager::Handle* handle) {
void GrVkResourceProvider::getSamplerDescriptorSetHandle(const GrVkUniformHandler& uniformHandler,
GrVkDescriptorSetManager::Handle* handle) {
SkASSERT(handle);
for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {
if (fDescriptorSetManagers[i].isCompatible(numSamplers)) {
if (fDescriptorSetManagers[i].isCompatible(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
&uniformHandler)) {
*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);
fDescriptorSetManagers.emplace_back(fGpu, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
&uniformHandler);
*handle = GrVkDescriptorSetManager::Handle(fDescriptorSetManagers.count() - 1);
}
VkDescriptorSetLayout GrVkResourceProvider::getUniformDSLayout() const {
SkASSERT(fUniformDSHandle.isValid());
return fDescriptorSetManagers[fUniformDSHandle.toIndex()].layout();
}
VkDescriptorSetLayout GrVkResourceProvider::getSamplerDSLayout(
const GrVkDescriptorSetManager::Handle& handle) const {
SkASSERT(handle.isValid());
return fDescriptorSetManagers[handle.toIndex()].layout();
}
const GrVkDescriptorSet* GrVkResourceProvider::getUniformDescriptorSet() {
SkASSERT(fUniformDSHandle.isValid());
return fDescriptorSetManagers[fUniformDSHandle.toIndex()].getDescriptorSet(fGpu,
fUniformDSHandle);
}
const GrVkDescriptorSet* GrVkResourceProvider::getSamplerDescriptorSet(
const GrVkDescriptorSetManager::Handle& handle) {
SkASSERT(handle.isValid());
return fDescriptorSetManagers[handle.toIndex()].getDescriptorSet(fGpu, handle);
}
void GrVkResourceProvider::recycleDescriptorSet(const GrVkDescriptorSet* descSet,
const GrVkDescriptorSetManager::Handle& handle) {
@ -326,13 +310,6 @@ void GrVkResourceProvider::destroyResources() {
GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineCache(fGpu->device(), fPipelineCache, nullptr));
fPipelineCache = VK_NULL_HANDLE;
if (fUniformDescLayout) {
GR_VK_CALL(fGpu->vkInterface(), DestroyDescriptorSetLayout(fGpu->device(),
fUniformDescLayout,
nullptr));
fUniformDescLayout = VK_NULL_HANDLE;
}
// We must release/destroy all command buffers and pipeline states before releasing the
// GrVkDescriptorSetManagers
for (int i = 0; i < fDescriptorSetManagers.count(); ++i) {

View File

@ -32,6 +32,7 @@ class GrVkPrimaryCommandBuffer;
class GrVkRenderTarget;
class GrVkSampler;
class GrVkSecondaryCommandBuffer;
class GrVkUniformHandler;
class GrVkResourceProvider {
public:
@ -101,27 +102,28 @@ public:
GrPrimitiveType,
const GrVkRenderPass& renderPass);
// 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);
void getSamplerDescriptorSetHandle(const GrVkUniformHandler&,
GrVkDescriptorSetManager::Handle* 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 getUniformDSLayout() const;
// Returns the compatible VkDescriptorSetLayout to use for a specific sampler handle. 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 getSamplerDSLayout(const GrVkDescriptorSetManager::Handle&) const;
// 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 GrVkDescriptorSetManager::Handle passed in. 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.
@ -216,9 +218,6 @@ private:
int fLastReturnedIndex;
};
// Initialiaze the vkDescriptorSetLayout used for allocating new uniform buffer descritpor sets.
void initUniformDescObjects();
GrVkGpu* fGpu;
// Central cache for creating pipelines
@ -227,15 +226,15 @@ private:
SkSTArray<4, CompatibleRenderPassSet> fRenderPassArray;
// Array of PrimaryCommandBuffers that are currently in flight
SkSTArray<4, GrVkPrimaryCommandBuffer*> fActiveCommandBuffers;
SkSTArray<4, GrVkPrimaryCommandBuffer*, true> fActiveCommandBuffers;
// Array of available primary command buffers that are not in flight
SkSTArray<4, GrVkPrimaryCommandBuffer*> fAvailableCommandBuffers;
SkSTArray<4, GrVkPrimaryCommandBuffer*, true> fAvailableCommandBuffers;
// Array of available secondary command buffers
SkSTArray<16, GrVkSecondaryCommandBuffer*> fAvailableSecondaryCommandBuffers;
SkSTArray<16, GrVkSecondaryCommandBuffer*, true> fAvailableSecondaryCommandBuffers;
// Array of available uniform buffer resources
SkSTArray<16, const GrVkResource*> fAvailableUniformBufferResources;
SkSTArray<16, const GrVkResource*, true> fAvailableUniformBufferResources;
// Stores GrVkSampler objects that we've already created so we can reuse them across multiple
// GrVkPipelineStates
@ -244,21 +243,9 @@ private:
// Cache of GrVkPipelineStates
PipelineStateCache* fPipelineStateCache;
SkSTArray<4, GrVkDescriptorSetManager> fDescriptorSetManagers;
SkSTArray<4, GrVkDescriptorSetManager, true> fDescriptorSetManagers;
GrVkDescriptorSetManager::Handle fUniformDSHandle;
// Current pool to allocate uniform descriptor sets from
VkDescriptorSetLayout fUniformDescLayout;
//Curent number of uniform descriptors allocated from the pool
int fCurrentUniformDescCount;
int fCurrMaxUniDescriptors;
enum {
kMaxUniformDescriptors = 1024,
kNumUniformDescPerSet = 2,
kStartNumUniformDescriptors = 16, // must be less than kMaxUniformDescriptors
};
GrVkDescriptorSetManager::Handle fUniformDSHandle;
};
#endif

View File

@ -90,6 +90,7 @@ private:
uint32_t fCurrentSamplerBinding;
friend class GrVkPipelineStateBuilder;
friend class GrVkDescriptorSetManager;
typedef GrGLSLUniformHandler INHERITED;
};