Vulkan: fix logic that determines when to grow descriptor pool.
When we added per-layout arenas for each of the 3 descriptor types, we did not account for them when determining how much of the Vk Pool is in use. Therefore the "growth" (really a re-creation) of the Vk Pool wasn't always occurring when necessary, causing descriptor set allocation to fail with large models.
This commit is contained in:
@@ -232,9 +232,18 @@ VulkanPipelineCache::DescriptorCacheEntry* VulkanPipelineCache::createDescriptor
|
||||
// are no longer used. This occurs during the cleanup phase during command buffer submission.
|
||||
auto& descriptorSetArenas = layoutCacheEntry->descriptorSetArenas;
|
||||
if (descriptorSetArenas[0].empty()) {
|
||||
if (mDescriptorSets.size() >= mDescriptorPoolSize) {
|
||||
|
||||
// If allocating a new descriptor set from the pool would cause it to overflow, then
|
||||
// recreate the pool. The number of descriptor sets that have already been allocated from
|
||||
// the pool is the sum of the "active" descriptor sets (mDescriptorSets) and the "dormant"
|
||||
// descriptor sets (mDescriptorArenasCount).
|
||||
//
|
||||
// NOTE: technically both sides of the inequality below should be multiplied by
|
||||
// DESCRIPTOR_TYPE_COUNT to get the true number of descriptor sets.
|
||||
if (mDescriptorSets.size() + mDescriptorArenasCount + 1 > mDescriptorPoolSize) {
|
||||
growDescriptorPool();
|
||||
}
|
||||
|
||||
VkDescriptorSetAllocateInfo allocInfo = {};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
allocInfo.descriptorPool = mDescriptorPool;
|
||||
@@ -251,6 +260,8 @@ VulkanPipelineCache::DescriptorCacheEntry* VulkanPipelineCache::createDescriptor
|
||||
descriptorCacheEntry.handles[i] = descriptorSetArenas[i].back();
|
||||
descriptorSetArenas[i].pop_back();
|
||||
}
|
||||
assert_invariant(mDescriptorArenasCount > 0);
|
||||
mDescriptorArenasCount--;
|
||||
}
|
||||
|
||||
// Rewrite every binding in the new descriptor sets.
|
||||
@@ -704,6 +715,7 @@ void VulkanPipelineCache::onCommandBuffer(const VulkanCommandBuffer& cmdbuffer)
|
||||
for (uint32_t i = 0; i < DESCRIPTOR_TYPE_COUNT; ++i) {
|
||||
arenas[i].push_back(cacheEntry.handles[i]);
|
||||
}
|
||||
++mDescriptorArenasCount;
|
||||
iter = mDescriptorSets.erase(iter);
|
||||
} else {
|
||||
++iter;
|
||||
@@ -738,6 +750,12 @@ void VulkanPipelineCache::onCommandBuffer(const VulkanCommandBuffer& cmdbuffer)
|
||||
#endif
|
||||
vkDestroyDescriptorSetLayout(mDevice, setLayout, VKALLOC);
|
||||
}
|
||||
auto& arenas = iter->second.descriptorSetArenas;
|
||||
assert_invariant(mDescriptorArenasCount >= arenas[0].size());
|
||||
mDescriptorArenasCount -= arenas[0].size();
|
||||
for (auto& arena : arenas) {
|
||||
vkFreeDescriptorSets(mDevice, mDescriptorPool, arena.size(), arena.data());
|
||||
}
|
||||
iter = mPipelineLayouts.erase(iter);
|
||||
} else {
|
||||
++iter;
|
||||
@@ -839,6 +857,7 @@ void VulkanPipelineCache::growDescriptorPool() noexcept {
|
||||
arena.clear();
|
||||
}
|
||||
}
|
||||
mDescriptorArenasCount = 0;
|
||||
|
||||
// Move all in-use descriptors from the primary cache into an "extinct" list, so that they will
|
||||
// later be destroyed rather than reclaimed.
|
||||
|
||||
@@ -399,8 +399,19 @@ private:
|
||||
// The descriptor set pool starts out with a decent number of descriptor sets. The cache can
|
||||
// grow the pool by re-creating it with a larger size. See growDescriptorPool().
|
||||
VkDescriptorPool mDescriptorPool;
|
||||
|
||||
// This describes the number of descriptor sets in mDescriptorPool. Note that this needs to be
|
||||
// multiplied by DESCRIPTOR_TYPE_COUNT to get the actual number of descriptor sets. Also note
|
||||
// that the number of low-level "descriptors" (not descriptor *sets*) is actually much more than
|
||||
// this size. It can be computed only by factoring in UBUFFER_BINDING_COUNT etc.
|
||||
uint32_t mDescriptorPoolSize = INITIAL_DESCRIPTOR_SET_POOL_SIZE;
|
||||
|
||||
// To get the actual number of descriptor sets that have been allocated from the pool,
|
||||
// take the sum of mDescriptorArenasCount (these are inactive descriptor sets) and the
|
||||
// number of entries in the mDescriptorPool map (active descriptor sets). Multiply the result by
|
||||
// DESCRIPTOR_TYPE_COUNT.
|
||||
uint32_t mDescriptorArenasCount = 0;
|
||||
|
||||
// After a growth event (i.e. when the VkDescriptorPool is replaced with a bigger version), all
|
||||
// currently used descriptors are moved into the "extinct" sets so that they can be safely
|
||||
// destroyed a few frames later.
|
||||
|
||||
Reference in New Issue
Block a user