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)
driverUniforms.destroy(mRenderer);
}
mDriverUniformsDescriptorPool.destroy(device);
for (vk::DynamicDescriptorPool &dynamicDescriptorPool : mDriverUniformsDescriptorPools)
{
dynamicDescriptorPool.destroy(device);
}
mDefaultUniformStorage.release(mRenderer);
mEmptyBuffer.release(mRenderer);
......@@ -820,9 +823,6 @@ angle::Result 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,
vk::kDefaultOcclusionQueryPoolSize));
ANGLE_TRY(mQueryPools[gl::QueryType::AnySamplesConservative].init(
......@@ -853,6 +853,29 @@ angle::Result ContextVk::initialize()
getDriverUniformsDescriptorSetDesc(kPipelineStages[pipeline]);
ANGLE_TRY(mRenderer->getDescriptorSetLayout(
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());
......@@ -3893,8 +3916,10 @@ angle::Result ContextVk::updateDriverUniformsDescriptorSet(
}
// Allocate a new descriptor set.
bool isCompute = getState().getProgramExecutable()->isCompute();
PipelineType pipelineType = isCompute ? PipelineType::Compute : PipelineType::Graphics;
bool newPoolAllocated;
ANGLE_TRY(mDriverUniformsDescriptorPool.allocateSetsAndGetInfo(
ANGLE_TRY(mDriverUniformsDescriptorPools[pipelineType].allocateSetsAndGetInfo(
this, driverUniforms->descriptorSetLayout.get().ptr(), 1,
&driverUniforms->descriptorPoolBinding, &driverUniforms->descriptorSet, &newPoolAllocated));
......
......@@ -963,7 +963,7 @@ class ContextVk : public ContextImpl, public vk::Context
// 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
// 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;
// Dirty bits.
......
......@@ -686,7 +686,8 @@ angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk,
angle::Result ProgramExecutableVk::initDynamicDescriptorPools(
ContextVk *contextVk,
vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc,
DescriptorSetIndex descriptorSetIndex)
DescriptorSetIndex descriptorSetIndex,
VkDescriptorSetLayout descriptorSetLayout)
{
std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
vk::DescriptorSetLayoutBindingVector bindingVector;
......@@ -712,35 +713,18 @@ angle::Result ProgramExecutableVk::initDynamicDescriptorPools(
{
// For this workaround, we have to create an empty descriptor set for each descriptor set
// index, so make sure their pools are initialized.
switch (descriptorSetIndex)
{
case DescriptorSetIndex::ShaderResource:
{
VkDescriptorPoolSize 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;
}
VkDescriptorPoolSize poolSize = {};
// The type doesn't matter, since it's not actually used for anything.
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSize.descriptorCount = 1;
descriptorPoolSizes.emplace_back(poolSize);
}
if (!descriptorPoolSizes.empty())
{
ANGLE_TRY(mDynamicDescriptorPools[ToUnderlying(descriptorSetIndex)].init(
contextVk, descriptorPoolSizes.data(), descriptorPoolSizes.size()));
contextVk, descriptorPoolSizes.data(), descriptorPoolSizes.size(),
descriptorSetLayout));
}
return angle::Result::Continue;
......@@ -872,11 +856,18 @@ angle::Result ProgramExecutableVk::createPipelineLayout(
&mPipelineLayout));
// Initialize descriptor pools.
ANGLE_TRY(initDynamicDescriptorPools(contextVk, uniformsAndXfbSetDesc,
DescriptorSetIndex::UniformsAndXfb));
ANGLE_TRY(initDynamicDescriptorPools(contextVk, resourcesSetDesc,
DescriptorSetIndex::ShaderResource));
ANGLE_TRY(initDynamicDescriptorPools(contextVk, texturesSetDesc, DescriptorSetIndex::Texture));
ANGLE_TRY(initDynamicDescriptorPools(
contextVk, uniformsAndXfbSetDesc, DescriptorSetIndex::UniformsAndXfb,
mDescriptorSetLayouts[ToUnderlying(DescriptorSetIndex::UniformsAndXfb)].get().getHandle()));
ANGLE_TRY(initDynamicDescriptorPools(
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());
......
......@@ -220,7 +220,8 @@ class ProgramExecutableVk
ContextVk *contextVk);
angle::Result initDynamicDescriptorPools(ContextVk *contextVk,
vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc,
DescriptorSetIndex descriptorSetIndex);
DescriptorSetIndex descriptorSetIndex,
VkDescriptorSetLayout descriptorSetLayout);
// Descriptor sets for uniform blocks and textures for this program.
vk::DescriptorSetLayoutArray<VkDescriptorSet> mDescriptorSets;
......
......@@ -1986,7 +1986,7 @@ const gl::Limitations &RendererVk::getNativeLimitations() const
}
angle::Result RendererVk::getDescriptorSetLayout(
vk::Context *context,
ContextVk *context,
const vk::DescriptorSetLayoutDesc &desc,
vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut)
{
......
......@@ -135,7 +135,7 @@ class RendererVk : angle::NonCopyable
// Queries the descriptor set layout cache. Creates the layout if not present.
angle::Result getDescriptorSetLayout(
vk::Context *context,
ContextVk *context,
const vk::DescriptorSetLayoutDesc &desc,
vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut);
......
......@@ -552,6 +552,31 @@ angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk,
contextVk, descriptorSetDesc,
&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 =
isCompute ? gl::ShaderType::Compute : gl::ShaderType::Fragment;
......@@ -570,12 +595,6 @@ angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk,
mDescriptorSetLayouts[function],
&mPipelineLayouts[function]));
if (setSizesCount > 0)
{
ANGLE_TRY(mDescriptorPools[function].init(contextVk, setSizes,
static_cast<uint32_t>(setSizesCount)));
}
return angle::Result::Continue;
}
......
......@@ -52,6 +52,7 @@ enum DescriptorSetIndex : uint32_t
namespace vk
{
class DynamicDescriptorPool;
class ImageHelper;
enum class ImageLayout;
......
......@@ -1726,13 +1726,16 @@ angle::Result DescriptorPoolHelper::allocateSets(ContextVk *contextVk,
}
// DynamicDescriptorPool implementation.
DynamicDescriptorPool::DynamicDescriptorPool() : mCurrentPoolIndex(0) {}
DynamicDescriptorPool::DynamicDescriptorPool()
: mCurrentPoolIndex(0), mCachedDescriptorSetLayout(VK_NULL_HANDLE)
{}
DynamicDescriptorPool::~DynamicDescriptorPool() = default;
angle::Result DynamicDescriptorPool::init(ContextVk *contextVk,
const VkDescriptorPoolSize *setSizes,
size_t setSizeCount)
size_t setSizeCount,
VkDescriptorSetLayout descriptorSetLayout)
{
ASSERT(setSizes);
ASSERT(setSizeCount);
......@@ -1740,6 +1743,7 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk,
ASSERT(mDescriptorPools.empty() ||
(mDescriptorPools.size() == 1 &&
mDescriptorPools[mCurrentPoolIndex]->get().hasCapacity(mMaxSetsPerPool)));
ASSERT(mCachedDescriptorSetLayout == VK_NULL_HANDLE);
mPoolSizes.assign(setSizes, setSizes + setSizeCount);
for (uint32_t i = 0; i < setSizeCount; ++i)
......@@ -1747,6 +1751,8 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk,
mPoolSizes[i].descriptorCount *= mMaxSetsPerPool;
}
mCachedDescriptorSetLayout = descriptorSetLayout;
mDescriptorPools.push_back(new RefCountedDescriptorPoolHelper());
mCurrentPoolIndex = mDescriptorPools.size() - 1;
return mDescriptorPools[mCurrentPoolIndex]->get().init(contextVk, mPoolSizes, mMaxSetsPerPool);
......@@ -1762,6 +1768,7 @@ void DynamicDescriptorPool::destroy(VkDevice device)
}
mDescriptorPools.clear();
mCachedDescriptorSetLayout = VK_NULL_HANDLE;
}
void DynamicDescriptorPool::release(ContextVk *contextVk)
......@@ -1774,6 +1781,7 @@ void DynamicDescriptorPool::release(ContextVk *contextVk)
}
mDescriptorPools.clear();
mCachedDescriptorSetLayout = VK_NULL_HANDLE;
}
angle::Result DynamicDescriptorPool::allocateSetsAndGetInfo(
......@@ -1785,6 +1793,7 @@ angle::Result DynamicDescriptorPool::allocateSetsAndGetInfo(
bool *newPoolAllocatedOut)
{
ASSERT(!mDescriptorPools.empty());
ASSERT(*descriptorSetLayout == mCachedDescriptorSetLayout);
*newPoolAllocatedOut = false;
......
......@@ -287,7 +287,8 @@ class DynamicDescriptorPool final : angle::NonCopyable
// an individual set. The pool size will be calculated accordingly.
angle::Result init(ContextVk *contextVk,
const VkDescriptorPoolSize *setSizes,
size_t setSizeCount);
size_t setSizeCount,
VkDescriptorSetLayout descriptorSetLayout);
void destroy(VkDevice device);
void release(ContextVk *contextVk);
......@@ -324,6 +325,10 @@ class DynamicDescriptorPool final : angle::NonCopyable
size_t mCurrentPoolIndex;
std::vector<RefCountedDescriptorPoolHelper *> mDescriptorPools;
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>
......
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