Skip to content

Commit 7692a3d

Browse files
authored
Merge pull request #114313 from blueskythlikesclouds/handle-descriptor-fragmentation
Create new pools when they become fragmented on Vulkan.
2 parents 329bc58 + 3b23931 commit 7692a3d

File tree

2 files changed

+43
-41
lines changed

2 files changed

+43
-41
lines changed

drivers/vulkan/rendering_device_driver_vulkan.cpp

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4082,21 +4082,7 @@ void RenderingDeviceDriverVulkan::shader_destroy_modules(ShaderID p_shader) {
40824082
/*********************/
40834083
/**** UNIFORM SET ****/
40844084
/*********************/
4085-
VkDescriptorPool RenderingDeviceDriverVulkan::_descriptor_set_pool_find_or_create(const DescriptorSetPoolKey &p_key, DescriptorSetPools::Iterator *r_pool_sets_it, int p_linear_pool_index) {
4086-
bool linear_pool = p_linear_pool_index >= 0;
4087-
DescriptorSetPools::Iterator pool_sets_it = linear_pool ? linear_descriptor_set_pools[p_linear_pool_index].find(p_key) : descriptor_set_pools.find(p_key);
4088-
4089-
if (pool_sets_it) {
4090-
for (KeyValue<VkDescriptorPool, uint32_t> &E : pool_sets_it->value) {
4091-
if (E.value < max_descriptor_sets_per_pool) {
4092-
*r_pool_sets_it = pool_sets_it;
4093-
return E.key;
4094-
}
4095-
}
4096-
}
4097-
4098-
// Create a new one.
4099-
4085+
VkDescriptorPool RenderingDeviceDriverVulkan::_descriptor_set_pool_create(const DescriptorSetPoolKey &p_key, bool p_linear_pool) {
41004086
// Here comes more vulkan API strangeness.
41014087
VkDescriptorPoolSize *vk_sizes = ALLOCA_ARRAY(VkDescriptorPoolSize, UNIFORM_TYPE_MAX);
41024088
uint32_t vk_sizes_count = 0;
@@ -4184,7 +4170,7 @@ VkDescriptorPool RenderingDeviceDriverVulkan::_descriptor_set_pool_find_or_creat
41844170

41854171
VkDescriptorPoolCreateInfo descriptor_set_pool_create_info = {};
41864172
descriptor_set_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
4187-
if (linear_descriptor_pools_enabled && linear_pool) {
4173+
if (linear_descriptor_pools_enabled && p_linear_pool) {
41884174
descriptor_set_pool_create_info.flags = 0;
41894175
} else {
41904176
descriptor_set_pool_create_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; // Can't think how somebody may NOT need this flag.
@@ -4199,18 +4185,6 @@ VkDescriptorPool RenderingDeviceDriverVulkan::_descriptor_set_pool_find_or_creat
41994185
ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateDescriptorPool failed with error " + itos(res) + ".");
42004186
}
42014187

4202-
// Bookkeep.
4203-
4204-
if (!pool_sets_it) {
4205-
if (linear_pool) {
4206-
pool_sets_it = linear_descriptor_set_pools[p_linear_pool_index].insert(p_key, HashMap<VkDescriptorPool, uint32_t>());
4207-
} else {
4208-
pool_sets_it = descriptor_set_pools.insert(p_key, HashMap<VkDescriptorPool, uint32_t>());
4209-
}
4210-
}
4211-
HashMap<VkDescriptorPool, uint32_t> &pool_rcs = pool_sets_it->value;
4212-
pool_rcs.insert(vk_pool, 0);
4213-
*r_pool_sets_it = pool_sets_it;
42144188
return vk_pool;
42154189
}
42164190

@@ -4454,27 +4428,55 @@ RDD::UniformSetID RenderingDeviceDriverVulkan::uniform_set_create(VectorView<Bou
44544428
writes_amount++;
44554429
}
44564430

4457-
// Need a descriptor pool.
4458-
DescriptorSetPools::Iterator pool_sets_it;
4459-
VkDescriptorPool vk_pool = _descriptor_set_pool_find_or_create(pool_key, &pool_sets_it, p_linear_pool_index);
4460-
DEV_ASSERT(vk_pool);
4461-
pool_sets_it->value[vk_pool]++;
4431+
bool linear_pool = p_linear_pool_index >= 0;
4432+
DescriptorSetPools::Iterator pool_sets_it = linear_pool ? linear_descriptor_set_pools[p_linear_pool_index].find(pool_key) : descriptor_set_pools.find(pool_key);
4433+
if (!pool_sets_it) {
4434+
if (linear_pool) {
4435+
pool_sets_it = linear_descriptor_set_pools[p_linear_pool_index].insert(pool_key, HashMap<VkDescriptorPool, uint32_t>());
4436+
} else {
4437+
pool_sets_it = descriptor_set_pools.insert(pool_key, HashMap<VkDescriptorPool, uint32_t>());
4438+
}
4439+
}
44624440

44634441
VkDescriptorSetAllocateInfo descriptor_set_allocate_info = {};
44644442
descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
4465-
descriptor_set_allocate_info.descriptorPool = vk_pool;
44664443
descriptor_set_allocate_info.descriptorSetCount = 1;
44674444
const ShaderInfo *shader_info = (const ShaderInfo *)p_shader.id;
44684445
descriptor_set_allocate_info.pSetLayouts = &shader_info->vk_descriptor_set_layouts[p_set_index];
44694446

44704447
VkDescriptorSet vk_descriptor_set = VK_NULL_HANDLE;
4448+
for (KeyValue<VkDescriptorPool, uint32_t> &E : pool_sets_it->value) {
4449+
if (E.value < max_descriptor_sets_per_pool) {
4450+
descriptor_set_allocate_info.descriptorPool = E.key;
4451+
VkResult res = vkAllocateDescriptorSets(vk_device, &descriptor_set_allocate_info, &vk_descriptor_set);
44714452

4472-
VkResult res = vkAllocateDescriptorSets(vk_device, &descriptor_set_allocate_info, &vk_descriptor_set);
4473-
if (res) {
4474-
_descriptor_set_pool_unreference(pool_sets_it, vk_pool, p_linear_pool_index);
4475-
ERR_FAIL_V_MSG(UniformSetID(), "Cannot allocate descriptor sets, error " + itos(res) + ".");
4453+
// Break early on success.
4454+
if (res == VK_SUCCESS) {
4455+
break;
4456+
}
4457+
4458+
// "Fragmented pool" and "out of memory pool" errors are handled by creating more pools. Any other error is unexpected.
4459+
if (res != VK_ERROR_FRAGMENTED_POOL && res != VK_ERROR_OUT_OF_POOL_MEMORY) {
4460+
ERR_FAIL_V_MSG(UniformSetID(), "Cannot allocate descriptor sets, error " + itos(res) + ".");
4461+
}
4462+
}
44764463
}
44774464

4465+
// Create a new pool when no allocations could be made from the existing pools.
4466+
if (vk_descriptor_set == VK_NULL_HANDLE) {
4467+
descriptor_set_allocate_info.descriptorPool = _descriptor_set_pool_create(pool_key, linear_pool);
4468+
VkResult res = vkAllocateDescriptorSets(vk_device, &descriptor_set_allocate_info, &vk_descriptor_set);
4469+
4470+
// All errors are unexpected at this stage.
4471+
if (res) {
4472+
vkDestroyDescriptorPool(vk_device, descriptor_set_allocate_info.descriptorPool, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_DESCRIPTOR_POOL));
4473+
ERR_FAIL_V_MSG(UniformSetID(), "Cannot allocate descriptor sets, error " + itos(res) + ".");
4474+
}
4475+
}
4476+
4477+
DEV_ASSERT(descriptor_set_allocate_info.descriptorPool != VK_NULL_HANDLE && vk_descriptor_set != VK_NULL_HANDLE);
4478+
pool_sets_it->value[descriptor_set_allocate_info.descriptorPool]++;
4479+
44784480
for (uint32_t i = 0; i < writes_amount; i++) {
44794481
vk_writes[i].dstSet = vk_descriptor_set;
44804482
}
@@ -4485,9 +4487,9 @@ RDD::UniformSetID RenderingDeviceDriverVulkan::uniform_set_create(VectorView<Bou
44854487
UniformSetInfo *usi = VersatileResource::allocate<UniformSetInfo>(resources_allocator);
44864488
usi->vk_descriptor_set = vk_descriptor_set;
44874489
if (p_linear_pool_index >= 0) {
4488-
usi->vk_linear_descriptor_pool = vk_pool;
4490+
usi->vk_linear_descriptor_pool = descriptor_set_allocate_info.descriptorPool;
44894491
} else {
4490-
usi->vk_descriptor_pool = vk_pool;
4492+
usi->vk_descriptor_pool = descriptor_set_allocate_info.descriptorPool;
44914493
}
44924494
usi->pool_sets_it = pool_sets_it;
44934495
usi->dynamic_buffers.resize(num_dynamic_buffers);

drivers/vulkan/rendering_device_driver_vulkan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
496496

497497
HashMap<int, DescriptorSetPools> linear_descriptor_set_pools;
498498
bool linear_descriptor_pools_enabled = true;
499-
VkDescriptorPool _descriptor_set_pool_find_or_create(const DescriptorSetPoolKey &p_key, DescriptorSetPools::Iterator *r_pool_sets_it, int p_linear_pool_index);
499+
VkDescriptorPool _descriptor_set_pool_create(const DescriptorSetPoolKey &p_key, bool p_linear_pool);
500500
void _descriptor_set_pool_unreference(DescriptorSetPools::Iterator p_pool_sets_it, VkDescriptorPool p_vk_descriptor_pool, int p_linear_pool_index);
501501

502502
// Global flag to toggle usage of immutable sampler when creating pipeline layouts.

0 commit comments

Comments
 (0)