Commit ed899835 by Tim Van Patten Committed by Commit Bot

Vulkan: Allocate descriptor pools with layouts

Descriptor set layouts and pools are very tightly coupled, since their binding types and counts must match to ensure the number of available descriptor sets within a pool remains accurate. To enforce this, the descriptor pools will now keep a copy of the VkDescriptorSetLayout that the pool was created for, which is verified when a descriptor set is allocated from the pool. If the handles don't match, an ASSERT() will fire. Bug: angleproject:5033 Test: CQ Change-Id: I4faf82c24f31052e57b656c968788bb0c131b619 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2407282Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Commit-Queue: Tim Van Patten <timvp@google.com>
parent cb286073
...@@ -775,7 +775,10 @@ void ContextVk::onDestroy(const gl::Context *context) ...@@ -775,7 +775,10 @@ void ContextVk::onDestroy(const gl::Context *context)
driverUniforms.destroy(mRenderer); driverUniforms.destroy(mRenderer);
} }
mDriverUniformsDescriptorPool.destroy(device); for (vk::DynamicDescriptorPool &dynamicDescriptorPool : mDriverUniformsDescriptorPools)
{
dynamicDescriptorPool.destroy(device);
}
mDefaultUniformStorage.release(mRenderer); mDefaultUniformStorage.release(mRenderer);
mEmptyBuffer.release(mRenderer); mEmptyBuffer.release(mRenderer);
...@@ -820,9 +823,6 @@ angle::Result ContextVk::initialize() ...@@ -820,9 +823,6 @@ angle::Result ContextVk::initialize()
{ {
ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::initialize"); ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::initialize");
VkDescriptorPoolSize driverSetSize = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1};
ANGLE_TRY(mDriverUniformsDescriptorPool.init(this, &driverSetSize, 1));
ANGLE_TRY(mQueryPools[gl::QueryType::AnySamples].init(this, VK_QUERY_TYPE_OCCLUSION, ANGLE_TRY(mQueryPools[gl::QueryType::AnySamples].init(this, VK_QUERY_TYPE_OCCLUSION,
vk::kDefaultOcclusionQueryPoolSize)); vk::kDefaultOcclusionQueryPoolSize));
ANGLE_TRY(mQueryPools[gl::QueryType::AnySamplesConservative].init( ANGLE_TRY(mQueryPools[gl::QueryType::AnySamplesConservative].init(
...@@ -853,6 +853,29 @@ angle::Result ContextVk::initialize() ...@@ -853,6 +853,29 @@ angle::Result ContextVk::initialize()
getDriverUniformsDescriptorSetDesc(kPipelineStages[pipeline]); getDriverUniformsDescriptorSetDesc(kPipelineStages[pipeline]);
ANGLE_TRY(mRenderer->getDescriptorSetLayout( ANGLE_TRY(mRenderer->getDescriptorSetLayout(
this, desc, &mDriverUniforms[pipeline].descriptorSetLayout)); this, desc, &mDriverUniforms[pipeline].descriptorSetLayout));
vk::DescriptorSetLayoutBindingVector bindingVector;
std::vector<VkSampler> immutableSamplers;
desc.unpackBindings(&bindingVector, &immutableSamplers);
std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
for (const VkDescriptorSetLayoutBinding &binding : bindingVector)
{
if (binding.descriptorCount > 0)
{
VkDescriptorPoolSize poolSize = {};
poolSize.type = binding.descriptorType;
poolSize.descriptorCount = binding.descriptorCount;
descriptorPoolSizes.emplace_back(poolSize);
}
}
if (!descriptorPoolSizes.empty())
{
ANGLE_TRY(mDriverUniformsDescriptorPools[pipeline].init(
this, descriptorPoolSizes.data(), descriptorPoolSizes.size(),
mDriverUniforms[pipeline].descriptorSetLayout.get().getHandle()));
}
} }
mGraphicsPipelineDesc.reset(new vk::GraphicsPipelineDesc()); mGraphicsPipelineDesc.reset(new vk::GraphicsPipelineDesc());
...@@ -3893,8 +3916,10 @@ angle::Result ContextVk::updateDriverUniformsDescriptorSet( ...@@ -3893,8 +3916,10 @@ angle::Result ContextVk::updateDriverUniformsDescriptorSet(
} }
// Allocate a new descriptor set. // Allocate a new descriptor set.
bool isCompute = getState().getProgramExecutable()->isCompute();
PipelineType pipelineType = isCompute ? PipelineType::Compute : PipelineType::Graphics;
bool newPoolAllocated; bool newPoolAllocated;
ANGLE_TRY(mDriverUniformsDescriptorPool.allocateSetsAndGetInfo( ANGLE_TRY(mDriverUniformsDescriptorPools[pipelineType].allocateSetsAndGetInfo(
this, driverUniforms->descriptorSetLayout.get().ptr(), 1, this, driverUniforms->descriptorSetLayout.get().ptr(), 1,
&driverUniforms->descriptorPoolBinding, &driverUniforms->descriptorSet, &newPoolAllocated)); &driverUniforms->descriptorPoolBinding, &driverUniforms->descriptorSet, &newPoolAllocated));
......
...@@ -963,7 +963,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -963,7 +963,7 @@ class ContextVk : public ContextImpl, public vk::Context
// threads simultaneously. Hence, we keep them in the ContextVk instead of the RendererVk. // threads simultaneously. Hence, we keep them in the ContextVk instead of the RendererVk.
// Note that this implementation would need to change in shared resource scenarios. Likely // Note that this implementation would need to change in shared resource scenarios. Likely
// we'd instead share a single set of pools between the share groups. // we'd instead share a single set of pools between the share groups.
vk::DynamicDescriptorPool mDriverUniformsDescriptorPool; angle::PackedEnumMap<PipelineType, vk::DynamicDescriptorPool> mDriverUniformsDescriptorPools;
angle::PackedEnumMap<gl::QueryType, vk::DynamicQueryPool> mQueryPools; angle::PackedEnumMap<gl::QueryType, vk::DynamicQueryPool> mQueryPools;
// Dirty bits. // Dirty bits.
......
...@@ -686,7 +686,8 @@ angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk, ...@@ -686,7 +686,8 @@ angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk,
angle::Result ProgramExecutableVk::initDynamicDescriptorPools( angle::Result ProgramExecutableVk::initDynamicDescriptorPools(
ContextVk *contextVk, ContextVk *contextVk,
vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc, vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc,
DescriptorSetIndex descriptorSetIndex) DescriptorSetIndex descriptorSetIndex,
VkDescriptorSetLayout descriptorSetLayout)
{ {
std::vector<VkDescriptorPoolSize> descriptorPoolSizes; std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
vk::DescriptorSetLayoutBindingVector bindingVector; vk::DescriptorSetLayoutBindingVector bindingVector;
...@@ -712,35 +713,18 @@ angle::Result ProgramExecutableVk::initDynamicDescriptorPools( ...@@ -712,35 +713,18 @@ angle::Result ProgramExecutableVk::initDynamicDescriptorPools(
{ {
// For this workaround, we have to create an empty descriptor set for each descriptor set // For this workaround, we have to create an empty descriptor set for each descriptor set
// index, so make sure their pools are initialized. // index, so make sure their pools are initialized.
switch (descriptorSetIndex) VkDescriptorPoolSize poolSize = {};
{ // The type doesn't matter, since it's not actually used for anything.
case DescriptorSetIndex::ShaderResource: poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
{ poolSize.descriptorCount = 1;
VkDescriptorPoolSize poolSize = {}; descriptorPoolSizes.emplace_back(poolSize);
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSize.descriptorCount = 1;
descriptorPoolSizes.emplace_back(poolSize);
break;
}
case DescriptorSetIndex::Texture:
{
VkDescriptorPoolSize poolSize = {};
poolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSize.descriptorCount = 1;
descriptorPoolSizes.emplace_back(poolSize);
break;
}
default:
break;
}
} }
if (!descriptorPoolSizes.empty()) if (!descriptorPoolSizes.empty())
{ {
ANGLE_TRY(mDynamicDescriptorPools[ToUnderlying(descriptorSetIndex)].init( ANGLE_TRY(mDynamicDescriptorPools[ToUnderlying(descriptorSetIndex)].init(
contextVk, descriptorPoolSizes.data(), descriptorPoolSizes.size())); contextVk, descriptorPoolSizes.data(), descriptorPoolSizes.size(),
descriptorSetLayout));
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -872,11 +856,18 @@ angle::Result ProgramExecutableVk::createPipelineLayout( ...@@ -872,11 +856,18 @@ angle::Result ProgramExecutableVk::createPipelineLayout(
&mPipelineLayout)); &mPipelineLayout));
// Initialize descriptor pools. // Initialize descriptor pools.
ANGLE_TRY(initDynamicDescriptorPools(contextVk, uniformsAndXfbSetDesc, ANGLE_TRY(initDynamicDescriptorPools(
DescriptorSetIndex::UniformsAndXfb)); contextVk, uniformsAndXfbSetDesc, DescriptorSetIndex::UniformsAndXfb,
ANGLE_TRY(initDynamicDescriptorPools(contextVk, resourcesSetDesc, mDescriptorSetLayouts[ToUnderlying(DescriptorSetIndex::UniformsAndXfb)].get().getHandle()));
DescriptorSetIndex::ShaderResource)); ANGLE_TRY(initDynamicDescriptorPools(
ANGLE_TRY(initDynamicDescriptorPools(contextVk, texturesSetDesc, DescriptorSetIndex::Texture)); contextVk, resourcesSetDesc, DescriptorSetIndex::ShaderResource,
mDescriptorSetLayouts[ToUnderlying(DescriptorSetIndex::ShaderResource)].get().getHandle()));
ANGLE_TRY(initDynamicDescriptorPools(
contextVk, texturesSetDesc, DescriptorSetIndex::Texture,
mDescriptorSetLayouts[ToUnderlying(DescriptorSetIndex::Texture)].get().getHandle()));
ANGLE_TRY(initDynamicDescriptorPools(
contextVk, driverUniformsSetDesc, DescriptorSetIndex::DriverUniforms,
mDescriptorSetLayouts[ToUnderlying(DescriptorSetIndex::DriverUniforms)].get().getHandle()));
mDynamicBufferOffsets.resize(glExecutable.getLinkedShaderStageCount()); mDynamicBufferOffsets.resize(glExecutable.getLinkedShaderStageCount());
......
...@@ -220,7 +220,8 @@ class ProgramExecutableVk ...@@ -220,7 +220,8 @@ class ProgramExecutableVk
ContextVk *contextVk); ContextVk *contextVk);
angle::Result initDynamicDescriptorPools(ContextVk *contextVk, angle::Result initDynamicDescriptorPools(ContextVk *contextVk,
vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc, vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc,
DescriptorSetIndex descriptorSetIndex); DescriptorSetIndex descriptorSetIndex,
VkDescriptorSetLayout descriptorSetLayout);
// Descriptor sets for uniform blocks and textures for this program. // Descriptor sets for uniform blocks and textures for this program.
vk::DescriptorSetLayoutArray<VkDescriptorSet> mDescriptorSets; vk::DescriptorSetLayoutArray<VkDescriptorSet> mDescriptorSets;
......
...@@ -1986,7 +1986,7 @@ const gl::Limitations &RendererVk::getNativeLimitations() const ...@@ -1986,7 +1986,7 @@ const gl::Limitations &RendererVk::getNativeLimitations() const
} }
angle::Result RendererVk::getDescriptorSetLayout( angle::Result RendererVk::getDescriptorSetLayout(
vk::Context *context, ContextVk *context,
const vk::DescriptorSetLayoutDesc &desc, const vk::DescriptorSetLayoutDesc &desc,
vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut) vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut)
{ {
......
...@@ -135,7 +135,7 @@ class RendererVk : angle::NonCopyable ...@@ -135,7 +135,7 @@ class RendererVk : angle::NonCopyable
// Queries the descriptor set layout cache. Creates the layout if not present. // Queries the descriptor set layout cache. Creates the layout if not present.
angle::Result getDescriptorSetLayout( angle::Result getDescriptorSetLayout(
vk::Context *context, ContextVk *context,
const vk::DescriptorSetLayoutDesc &desc, const vk::DescriptorSetLayoutDesc &desc,
vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut); vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut);
......
...@@ -552,6 +552,31 @@ angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk, ...@@ -552,6 +552,31 @@ angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk,
contextVk, descriptorSetDesc, contextVk, descriptorSetDesc,
&mDescriptorSetLayouts[function][ToUnderlying(DescriptorSetIndex::InternalShader)])); &mDescriptorSetLayouts[function][ToUnderlying(DescriptorSetIndex::InternalShader)]));
vk::DescriptorSetLayoutBindingVector bindingVector;
std::vector<VkSampler> immutableSamplers;
descriptorSetDesc.unpackBindings(&bindingVector, &immutableSamplers);
std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
for (const VkDescriptorSetLayoutBinding &binding : bindingVector)
{
if (binding.descriptorCount > 0)
{
VkDescriptorPoolSize poolSize = {};
poolSize.type = binding.descriptorType;
poolSize.descriptorCount = binding.descriptorCount;
descriptorPoolSizes.emplace_back(poolSize);
}
}
if (!descriptorPoolSizes.empty())
{
ANGLE_TRY(mDescriptorPools[function].init(
contextVk, descriptorPoolSizes.data(), descriptorPoolSizes.size(),
mDescriptorSetLayouts[function][ToUnderlying(DescriptorSetIndex::InternalShader)]
.get()
.getHandle()));
}
gl::ShaderType pushConstantsShaderStage = gl::ShaderType pushConstantsShaderStage =
isCompute ? gl::ShaderType::Compute : gl::ShaderType::Fragment; isCompute ? gl::ShaderType::Compute : gl::ShaderType::Fragment;
...@@ -570,12 +595,6 @@ angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk, ...@@ -570,12 +595,6 @@ angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk,
mDescriptorSetLayouts[function], mDescriptorSetLayouts[function],
&mPipelineLayouts[function])); &mPipelineLayouts[function]));
if (setSizesCount > 0)
{
ANGLE_TRY(mDescriptorPools[function].init(contextVk, setSizes,
static_cast<uint32_t>(setSizesCount)));
}
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -52,6 +52,7 @@ enum DescriptorSetIndex : uint32_t ...@@ -52,6 +52,7 @@ enum DescriptorSetIndex : uint32_t
namespace vk namespace vk
{ {
class DynamicDescriptorPool;
class ImageHelper; class ImageHelper;
enum class ImageLayout; enum class ImageLayout;
......
...@@ -1726,13 +1726,16 @@ angle::Result DescriptorPoolHelper::allocateSets(ContextVk *contextVk, ...@@ -1726,13 +1726,16 @@ angle::Result DescriptorPoolHelper::allocateSets(ContextVk *contextVk,
} }
// DynamicDescriptorPool implementation. // DynamicDescriptorPool implementation.
DynamicDescriptorPool::DynamicDescriptorPool() : mCurrentPoolIndex(0) {} DynamicDescriptorPool::DynamicDescriptorPool()
: mCurrentPoolIndex(0), mCachedDescriptorSetLayout(VK_NULL_HANDLE)
{}
DynamicDescriptorPool::~DynamicDescriptorPool() = default; DynamicDescriptorPool::~DynamicDescriptorPool() = default;
angle::Result DynamicDescriptorPool::init(ContextVk *contextVk, angle::Result DynamicDescriptorPool::init(ContextVk *contextVk,
const VkDescriptorPoolSize *setSizes, const VkDescriptorPoolSize *setSizes,
size_t setSizeCount) size_t setSizeCount,
VkDescriptorSetLayout descriptorSetLayout)
{ {
ASSERT(setSizes); ASSERT(setSizes);
ASSERT(setSizeCount); ASSERT(setSizeCount);
...@@ -1740,6 +1743,7 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk, ...@@ -1740,6 +1743,7 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk,
ASSERT(mDescriptorPools.empty() || ASSERT(mDescriptorPools.empty() ||
(mDescriptorPools.size() == 1 && (mDescriptorPools.size() == 1 &&
mDescriptorPools[mCurrentPoolIndex]->get().hasCapacity(mMaxSetsPerPool))); mDescriptorPools[mCurrentPoolIndex]->get().hasCapacity(mMaxSetsPerPool)));
ASSERT(mCachedDescriptorSetLayout == VK_NULL_HANDLE);
mPoolSizes.assign(setSizes, setSizes + setSizeCount); mPoolSizes.assign(setSizes, setSizes + setSizeCount);
for (uint32_t i = 0; i < setSizeCount; ++i) for (uint32_t i = 0; i < setSizeCount; ++i)
...@@ -1747,6 +1751,8 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk, ...@@ -1747,6 +1751,8 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk,
mPoolSizes[i].descriptorCount *= mMaxSetsPerPool; mPoolSizes[i].descriptorCount *= mMaxSetsPerPool;
} }
mCachedDescriptorSetLayout = descriptorSetLayout;
mDescriptorPools.push_back(new RefCountedDescriptorPoolHelper()); mDescriptorPools.push_back(new RefCountedDescriptorPoolHelper());
mCurrentPoolIndex = mDescriptorPools.size() - 1; mCurrentPoolIndex = mDescriptorPools.size() - 1;
return mDescriptorPools[mCurrentPoolIndex]->get().init(contextVk, mPoolSizes, mMaxSetsPerPool); return mDescriptorPools[mCurrentPoolIndex]->get().init(contextVk, mPoolSizes, mMaxSetsPerPool);
...@@ -1762,6 +1768,7 @@ void DynamicDescriptorPool::destroy(VkDevice device) ...@@ -1762,6 +1768,7 @@ void DynamicDescriptorPool::destroy(VkDevice device)
} }
mDescriptorPools.clear(); mDescriptorPools.clear();
mCachedDescriptorSetLayout = VK_NULL_HANDLE;
} }
void DynamicDescriptorPool::release(ContextVk *contextVk) void DynamicDescriptorPool::release(ContextVk *contextVk)
...@@ -1774,6 +1781,7 @@ void DynamicDescriptorPool::release(ContextVk *contextVk) ...@@ -1774,6 +1781,7 @@ void DynamicDescriptorPool::release(ContextVk *contextVk)
} }
mDescriptorPools.clear(); mDescriptorPools.clear();
mCachedDescriptorSetLayout = VK_NULL_HANDLE;
} }
angle::Result DynamicDescriptorPool::allocateSetsAndGetInfo( angle::Result DynamicDescriptorPool::allocateSetsAndGetInfo(
...@@ -1785,6 +1793,7 @@ angle::Result DynamicDescriptorPool::allocateSetsAndGetInfo( ...@@ -1785,6 +1793,7 @@ angle::Result DynamicDescriptorPool::allocateSetsAndGetInfo(
bool *newPoolAllocatedOut) bool *newPoolAllocatedOut)
{ {
ASSERT(!mDescriptorPools.empty()); ASSERT(!mDescriptorPools.empty());
ASSERT(*descriptorSetLayout == mCachedDescriptorSetLayout);
*newPoolAllocatedOut = false; *newPoolAllocatedOut = false;
......
...@@ -287,7 +287,8 @@ class DynamicDescriptorPool final : angle::NonCopyable ...@@ -287,7 +287,8 @@ class DynamicDescriptorPool final : angle::NonCopyable
// an individual set. The pool size will be calculated accordingly. // an individual set. The pool size will be calculated accordingly.
angle::Result init(ContextVk *contextVk, angle::Result init(ContextVk *contextVk,
const VkDescriptorPoolSize *setSizes, const VkDescriptorPoolSize *setSizes,
size_t setSizeCount); size_t setSizeCount,
VkDescriptorSetLayout descriptorSetLayout);
void destroy(VkDevice device); void destroy(VkDevice device);
void release(ContextVk *contextVk); void release(ContextVk *contextVk);
...@@ -324,6 +325,10 @@ class DynamicDescriptorPool final : angle::NonCopyable ...@@ -324,6 +325,10 @@ class DynamicDescriptorPool final : angle::NonCopyable
size_t mCurrentPoolIndex; size_t mCurrentPoolIndex;
std::vector<RefCountedDescriptorPoolHelper *> mDescriptorPools; std::vector<RefCountedDescriptorPoolHelper *> mDescriptorPools;
std::vector<VkDescriptorPoolSize> mPoolSizes; std::vector<VkDescriptorPoolSize> mPoolSizes;
// This cached handle is used for verifying the layout being used to allocate descriptor sets
// from the pool matches the layout that the pool was created for, to ensure that the free
// descriptor count is accurate and new pools are created appropriately.
VkDescriptorSetLayout mCachedDescriptorSetLayout;
}; };
template <typename Pool> template <typename Pool>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment