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:
parent
fe8d2cf520
commit
707bbd622b
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -90,6 +90,7 @@ private:
|
||||
uint32_t fCurrentSamplerBinding;
|
||||
|
||||
friend class GrVkPipelineStateBuilder;
|
||||
friend class GrVkDescriptorSetManager;
|
||||
|
||||
typedef GrGLSLUniformHandler INHERITED;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user