From b3bd2209beb936c3d80c0893a6078b6c78a9b4db Mon Sep 17 00:00:00 2001 From: Gregory Wells Date: Mon, 16 Jun 2025 10:51:56 -0400 Subject: [PATCH] on nvidia GPUs allow for dynamic descriptor allocation --- .../src/output_device/vulkan_output_device.c | 4 + .../src/output_device/vulkan_output_devices.h | 2 + .../vulkan/src/uniforms/vulkan_uniform_pool.c | 116 +++++++++++------- .../vulkan/src/uniforms/vulkan_uniform_pool.h | 2 +- 4 files changed, 82 insertions(+), 42 deletions(-) diff --git a/rendering_api/vulkan/src/output_device/vulkan_output_device.c b/rendering_api/vulkan/src/output_device/vulkan_output_device.c index 8c7f392..d07285e 100644 --- a/rendering_api/vulkan/src/output_device/vulkan_output_device.c +++ b/rendering_api/vulkan/src/output_device/vulkan_output_device.c @@ -32,6 +32,10 @@ gnReturnCode gnCreateOutputDeviceFn(gnOutputDeviceHandle outputDevice, gnInstanc }; deviceCreateInfo.ppEnabledExtensionNames = vkGetGryphnDeviceExtensions(&deviceCreateInfo.enabledExtensionCount, deviceInfo.physicalDevice.physicalDevice->device); + outputDevice->outputDevice->enabledOversizedDescriptorPools = gnFalse; + for (int i = 0; i < deviceCreateInfo.enabledExtensionCount; i++) + if (strcmp(deviceCreateInfo.ppEnabledExtensionNames[i], VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME) == 0) outputDevice->outputDevice->enabledOversizedDescriptorPools = gnTrue; + if (instance->debugger == NULL) deviceCreateInfo.enabledLayerCount = 0; else { diff --git a/rendering_api/vulkan/src/output_device/vulkan_output_devices.h b/rendering_api/vulkan/src/output_device/vulkan_output_devices.h index b03f1ac..60ed033 100644 --- a/rendering_api/vulkan/src/output_device/vulkan_output_devices.h +++ b/rendering_api/vulkan/src/output_device/vulkan_output_devices.h @@ -9,6 +9,8 @@ typedef struct gnPlatformOutputDevice_t { VkQueue transferQueue; VkCommandPool transferCommandPool; + + gnBool enabledOversizedDescriptorPools; } gnPlatformOutputDevice; VkCommandBuffer gnBeginVulkanTransferOperation(gnDevice device); diff --git a/rendering_api/vulkan/src/uniforms/vulkan_uniform_pool.c b/rendering_api/vulkan/src/uniforms/vulkan_uniform_pool.c index caf60ff..335bc65 100644 --- a/rendering_api/vulkan/src/uniforms/vulkan_uniform_pool.c +++ b/rendering_api/vulkan/src/uniforms/vulkan_uniform_pool.c @@ -9,58 +9,94 @@ gnReturnCode gnCreateUniformPoolFn(gnUniformPool pool, gnDeviceHandle device) { pool->uniformPool = malloc(sizeof(struct gnPlatformUniformPool_t)); pool->uniformPool->poolCount = 0; - pool->uniformPool->maxPoolCount = 1; + pool->uniformPool->maxPoolCount = 2; pool->uniformPool->pools = malloc(sizeof(vkGryphnUniformPool) * pool->uniformPool->maxPoolCount); + + if (device->outputDevice->enabledOversizedDescriptorPools == gnTrue) { + VkDescriptorPoolCreateInfo poolInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV, + .poolSizeCount = 0, + .pPoolSizes = NULL, + .maxSets = 0 + }; + + if (vkCreateDescriptorPool( + pool->device->outputDevice->device, &poolInfo, NULL, + &pool->uniformPool->pools[pool->uniformPool->poolCount].pool + ) != VK_SUCCESS) + return GN_FAILED_TO_ALLOCATE_MEMORY; + + pool->uniformPool->poolCount = 1; + } + + pool->uniformPool->currentPool = 0; + return GN_SUCCESS; } gnUniform* gnUniformPoolAllocateUniformsFn(gnUniformPool pool, gnUniformAllocationInfo allocInfo) { - if (pool->uniformPool->poolCount >= pool->uniformPool->maxPoolCount) { - pool->uniformPool->maxPoolCount *= 2; - pool->uniformPool->pools = realloc(pool->uniformPool->pools, sizeof(vkGryphnUniformPool) * pool->uniformPool->maxPoolCount); - } + gnBool fixedAllocCount = pool->device->outputDevice->enabledOversizedDescriptorPools; - pool->uniformPool->pools[pool->uniformPool->poolCount].layouts = malloc(sizeof(VkDescriptorSetLayout) * allocInfo.setCount); - pool->uniformPool->pools[pool->uniformPool->poolCount].layoutCount = allocInfo.setCount; - VkDescriptorPoolSize uniformBufferSize = { - .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 0 - }; - - VkDescriptorPoolSize imageSize = { - .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 0 - }; - - for (int i = 0; i < allocInfo.setCount; i++) { - for (int c = 0; c < allocInfo.sets[i].uniformBindingCount; c++) { - if (allocInfo.sets[i].uniformBindings[i].type == GN_UNIFORM_BUFFER_DESCRIPTOR) uniformBufferSize.descriptorCount++; - if (allocInfo.sets[i].uniformBindings[i].type == GN_IMAGE_DESCRIPTOR) imageSize.descriptorCount++; + if (fixedAllocCount) { + if (pool->uniformPool->poolCount >= pool->uniformPool->maxPoolCount) { + pool->uniformPool->maxPoolCount *= 2; + pool->uniformPool->pools = realloc(pool->uniformPool->pools, sizeof(vkGryphnUniformPool) * pool->uniformPool->maxPoolCount); } - pool->uniformPool->pools[pool->uniformPool->poolCount].layouts[i] = vkGryphnCreateSetLayouts(&allocInfo.sets[i], pool->device->outputDevice->device); + + VkDescriptorPoolSize uniformBufferSize = { + .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .descriptorCount = 0 + }; + + VkDescriptorPoolSize imageSize = { + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 0 + }; + + for (int i = 0; i < allocInfo.setCount; i++) { + for (int c = 0; c < allocInfo.sets[i].uniformBindingCount; c++) { + if (allocInfo.sets[i].uniformBindings[i].type == GN_UNIFORM_BUFFER_DESCRIPTOR) uniformBufferSize.descriptorCount++; + if (allocInfo.sets[i].uniformBindings[i].type == GN_IMAGE_DESCRIPTOR) imageSize.descriptorCount++; + } + } + + + + VkDescriptorPoolCreateInfo poolInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .poolSizeCount = 1, + .pPoolSizes = (VkDescriptorPoolSize[]){ uniformBufferSize, imageSize }, + .maxSets = allocInfo.setCount + }; + + if (vkCreateDescriptorPool( + pool->device->outputDevice->device, &poolInfo, NULL, + &pool->uniformPool->pools[pool->uniformPool->poolCount].pool + ) != VK_SUCCESS) + return NULL; + pool->uniformPool->poolCount++; + + uint32_t maxSets = uniformBufferSize.descriptorCount + uniformBufferSize.descriptorCount; } - uint32_t maxSets = uniformBufferSize.descriptorCount + uniformBufferSize.descriptorCount; - - VkDescriptorPoolCreateInfo poolInfo = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .poolSizeCount = 1, - .pPoolSizes = (VkDescriptorPoolSize[]){ uniformBufferSize, imageSize }, - .maxSets = maxSets - }; - - if (vkCreateDescriptorPool( - pool->device->outputDevice->device, &poolInfo, NULL, - &pool->uniformPool->pools[pool->uniformPool->poolCount].pool - ) != VK_SUCCESS) - return NULL; + if (fixedAllocCount) + pool->uniformPool->pools[pool->uniformPool->currentPool].layouts = malloc(sizeof(VkDescriptorSetLayout) * allocInfo.setCount); + else + pool->uniformPool->pools[pool->uniformPool->currentPool].layouts = realloc( + pool->uniformPool->pools[pool->uniformPool->currentPool].layouts, + sizeof(VkDescriptorSetLayout) * (allocInfo.setCount + pool->uniformPool->pools[pool->uniformPool->currentPool].layoutCount)); + for (int i = 0; i < allocInfo.setCount; i++) { + pool->uniformPool->pools[pool->uniformPool->currentPool].layouts[pool->uniformPool->pools[pool->uniformPool->currentPool].layoutCount + i] = vkGryphnCreateSetLayouts(&allocInfo.sets[i], pool->device->outputDevice->device); + } VkDescriptorSetAllocateInfo vkAllocInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .descriptorPool = pool->uniformPool->pools[pool->uniformPool->poolCount].pool, + .descriptorPool = pool->uniformPool->pools[pool->uniformPool->currentPool].pool, .descriptorSetCount = allocInfo.setCount, - .pSetLayouts = pool->uniformPool->pools[pool->uniformPool->poolCount].layouts + .pSetLayouts = &pool->uniformPool->pools[pool->uniformPool->currentPool].layouts[pool->uniformPool->pools[pool->uniformPool->currentPool].layoutCount] }; + pool->uniformPool->pools[pool->uniformPool->currentPool].layoutCount += allocInfo.setCount; VkDescriptorSet* sets = malloc(sizeof(VkDescriptorSet) * allocInfo.setCount); if (vkAllocateDescriptorSets(pool->device->outputDevice->device, &vkAllocInfo, sets) != VK_SUCCESS) @@ -72,8 +108,6 @@ gnUniform* gnUniformPoolAllocateUniformsFn(gnUniformPool pool, gnUniformAllocati uniforms[i]->uniform = malloc(sizeof(struct gnPlatformUniform_t)); uniforms[i]->uniform->set = sets[i]; } - - pool->uniformPool->poolCount++; return uniforms; } @@ -84,5 +118,5 @@ void gnDestroyUniformPoolFn(gnUniformPool pool) { vkDestroyDescriptorSetLayout(pool->device->outputDevice->device, pool->uniformPool->pools[i].layouts[k], NULL); } } - free(pool->uniformPool); + // free(pool->uniformPool); } diff --git a/rendering_api/vulkan/src/uniforms/vulkan_uniform_pool.h b/rendering_api/vulkan/src/uniforms/vulkan_uniform_pool.h index 8bef4ca..a20c404 100644 --- a/rendering_api/vulkan/src/uniforms/vulkan_uniform_pool.h +++ b/rendering_api/vulkan/src/uniforms/vulkan_uniform_pool.h @@ -9,6 +9,6 @@ typedef struct vkGryphnUniformPool { } vkGryphnUniformPool; struct gnPlatformUniformPool_t { - uint32_t poolCount, maxPoolCount; + uint32_t poolCount, maxPoolCount, currentPool; vkGryphnUniformPool* pools; };