From 980b4ff6dbe7a1005419c5126a66f72cc683b28d Mon Sep 17 00:00:00 2001
From: Evan Hemsley <[EMAIL REDACTED]>
Date: Fri, 20 Sep 2024 12:55:39 -0700
Subject: [PATCH] GPU: Vulkan descriptor management rewrite (#10910)
---
src/gpu/vulkan/SDL_gpu_vulkan.c | 1855 +++++++++++++++----------------
1 file changed, 907 insertions(+), 948 deletions(-)
diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c
index 6e215b908e65f..38f94eaf99bac 100644
--- a/src/gpu/vulkan/SDL_gpu_vulkan.c
+++ b/src/gpu/vulkan/SDL_gpu_vulkan.c
@@ -69,7 +69,7 @@ typedef struct VulkanExtensions
#define SMALL_ALLOCATION_SIZE 16777216 // 16 MiB
#define LARGE_ALLOCATION_INCREMENT 67108864 // 64 MiB
#define MAX_UBO_SECTION_SIZE 4096 // 4 KiB
-#define DESCRIPTOR_POOL_STARTING_SIZE 128
+#define DESCRIPTOR_POOL_SIZE 128
#define WINDOW_PROPERTY_DATA "SDL_GPUVulkanWindowPropertyData"
#define IDENTITY_SWIZZLE \
@@ -723,23 +723,69 @@ typedef struct VulkanDescriptorInfo
typedef struct DescriptorSetPool
{
- SDL_SpinLock lock;
+ // It's a pool... of pools!!!
+ Uint32 poolCount;
+ VkDescriptorPool *descriptorPools;
+
+ // We'll just manage the descriptor sets ourselves instead of freeing the sets
+ VkDescriptorSet *descriptorSets;
+ Uint32 descriptorSetCount;
+ Uint32 descriptorSetIndex;
+} DescriptorSetPool;
+
+// A command buffer acquires a cache at command buffer acquisition time
+typedef struct DescriptorSetCache
+{
+ // Pools are indexed by DescriptorSetLayoutID which increases monotonically
+ // There's only a certain number of maximum layouts possible since we de-duplicate them.
+ DescriptorSetPool *pools;
+ Uint32 poolCount;
+} DescriptorSetCache;
+
+typedef struct DescriptorSetLayoutHashTableKey
+{
+ VkShaderStageFlagBits shaderStage;
+ // Category 1: read resources
+ Uint32 samplerCount;
+ Uint32 storageBufferCount;
+ Uint32 storageTextureCount;
+ // Category 2: write resources
+ Uint32 writeStorageBufferCount;
+ Uint32 writeStorageTextureCount;
+ // Category 3: uniform buffers
+ Uint32 uniformBufferCount;
+} DescriptorSetLayoutHashTableKey;
+typedef uint32_t DescriptorSetLayoutID;
+
+typedef struct DescriptorSetLayout
+{
+ DescriptorSetLayoutID ID;
VkDescriptorSetLayout descriptorSetLayout;
- VulkanDescriptorInfo *descriptorInfos;
- Uint32 descriptorInfoCount;
+ // Category 1: read resources
+ Uint32 samplerCount;
+ Uint32 storageBufferCount;
+ Uint32 storageTextureCount;
+ // Category 2: write resources
+ Uint32 writeStorageBufferCount;
+ Uint32 writeStorageTextureCount;
+ // Category 3: uniform buffers
+ Uint32 uniformBufferCount;
+} DescriptorSetLayout;
- // This is actually a descriptor set and descriptor pool simultaneously
- VkDescriptorPool *descriptorPools;
- Uint32 descriptorPoolCount;
- Uint32 nextPoolSize;
+typedef struct GraphicsPipelineResourceLayoutHashTableKey
+{
+ Uint32 vertexSamplerCount;
+ Uint32 vertexStorageBufferCount;
+ Uint32 vertexStorageTextureCount;
+ Uint32 vertexUniformBufferCount;
- // We just manage a pool ourselves instead of freeing the sets
- VkDescriptorSet *inactiveDescriptorSets;
- Uint32 inactiveDescriptorSetCount;
- Uint32 inactiveDescriptorSetCapacity;
-} DescriptorSetPool;
+ Uint32 fragmentSamplerCount;
+ Uint32 fragmentStorageBufferCount;
+ Uint32 fragmentStorageTextureCount;
+ Uint32 fragmentUniformBufferCount;
+} GraphicsPipelineResourceLayoutHashTableKey;
typedef struct VulkanGraphicsPipelineResourceLayout
{
@@ -752,7 +798,7 @@ typedef struct VulkanGraphicsPipelineResourceLayout
* 2: fragment resources
* 3: fragment uniform buffers
*/
- DescriptorSetPool descriptorSetPools[4];
+ DescriptorSetLayout *descriptorSetLayouts[4];
Uint32 vertexSamplerCount;
Uint32 vertexStorageBufferCount;
@@ -770,7 +816,7 @@ typedef struct VulkanGraphicsPipeline
VkPipeline pipeline;
SDL_GPUPrimitiveType primitiveType;
- VulkanGraphicsPipelineResourceLayout resourceLayout;
+ VulkanGraphicsPipelineResourceLayout *resourceLayout;
VulkanShader *vertexShader;
VulkanShader *fragmentShader;
@@ -778,6 +824,16 @@ typedef struct VulkanGraphicsPipeline
SDL_AtomicInt referenceCount;
} VulkanGraphicsPipeline;
+typedef struct ComputePipelineResourceLayoutHashTableKey
+{
+ Uint32 samplerCount;
+ Uint32 readonlyStorageTextureCount;
+ Uint32 readonlyStorageBufferCount;
+ Uint32 writeonlyStorageTextureCount;
+ Uint32 writeonlyStorageBufferCount;
+ Uint32 uniformBufferCount;
+} ComputePipelineResourceLayoutHashTableKey;
+
typedef struct VulkanComputePipelineResourceLayout
{
VkPipelineLayout pipelineLayout;
@@ -788,7 +844,7 @@ typedef struct VulkanComputePipelineResourceLayout
* 1: write-only textures, then write-only buffers
* 2: uniform buffers
*/
- DescriptorSetPool descriptorSetPools[3];
+ DescriptorSetLayout *descriptorSetLayouts[3];
Uint32 numSamplers;
Uint32 numReadonlyStorageTextures;
@@ -802,7 +858,7 @@ typedef struct VulkanComputePipeline
{
VkShaderModule shaderModule;
VkPipeline pipeline;
- VulkanComputePipelineResourceLayout resourceLayout;
+ VulkanComputePipelineResourceLayout *resourceLayout;
SDL_AtomicInt referenceCount;
} VulkanComputePipeline;
@@ -851,12 +907,6 @@ typedef struct FramebufferHashTableKey
// Command structures
-typedef struct DescriptorSetData
-{
- DescriptorSetPool *descriptorSetPool;
- VkDescriptorSet descriptorSet;
-} DescriptorSetData;
-
typedef struct VulkanFencePool
{
SDL_Mutex *lock;
@@ -911,6 +961,8 @@ typedef struct VulkanCommandBuffer
// Resource bind state
+ DescriptorSetCache *descriptorSetCache; // acquired when command buffer is acquired
+
bool needNewVertexResourceDescriptorSet;
bool needNewVertexUniformDescriptorSet;
bool needNewVertexUniformOffsets;
@@ -932,10 +984,6 @@ typedef struct VulkanCommandBuffer
VkDescriptorSet computeWriteOnlyDescriptorSet;
VkDescriptorSet computeUniformDescriptorSet;
- DescriptorSetData *boundDescriptorSetDatas;
- Uint32 boundDescriptorSetDataCount;
- Uint32 boundDescriptorSetDataCapacity;
-
VulkanTexture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
VulkanSampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
VulkanTexture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
@@ -964,32 +1012,32 @@ typedef struct VulkanCommandBuffer
// Track used resources
VulkanBuffer **usedBuffers;
- Uint32 usedBufferCount;
- Uint32 usedBufferCapacity;
+ Sint32 usedBufferCount;
+ Sint32 usedBufferCapacity;
VulkanTexture **usedTextures;
- Uint32 usedTextureCount;
- Uint32 usedTextureCapacity;
+ Sint32 usedTextureCount;
+ Sint32 usedTextureCapacity;
VulkanSampler **usedSamplers;
- Uint32 usedSamplerCount;
- Uint32 usedSamplerCapacity;
+ Sint32 usedSamplerCount;
+ Sint32 usedSamplerCapacity;
VulkanGraphicsPipeline **usedGraphicsPipelines;
- Uint32 usedGraphicsPipelineCount;
- Uint32 usedGraphicsPipelineCapacity;
+ Sint32 usedGraphicsPipelineCount;
+ Sint32 usedGraphicsPipelineCapacity;
VulkanComputePipeline **usedComputePipelines;
- Uint32 usedComputePipelineCount;
- Uint32 usedComputePipelineCapacity;
+ Sint32 usedComputePipelineCount;
+ Sint32 usedComputePipelineCapacity;
VulkanFramebuffer **usedFramebuffers;
- Uint32 usedFramebufferCount;
- Uint32 usedFramebufferCapacity;
+ Sint32 usedFramebufferCount;
+ Sint32 usedFramebufferCapacity;
VulkanUniformBuffer **usedUniformBuffers;
- Uint32 usedUniformBufferCount;
- Uint32 usedUniformBufferCapacity;
+ Sint32 usedUniformBufferCount;
+ Sint32 usedUniformBufferCapacity;
VulkanFenceHandle *inFlightFence;
Uint8 autoReleaseFence;
@@ -1048,11 +1096,20 @@ struct VulkanRenderer
SDL_HashTable *commandPoolHashTable;
SDL_HashTable *renderPassHashTable;
SDL_HashTable *framebufferHashTable;
+ SDL_HashTable *graphicsPipelineResourceLayoutHashTable;
+ SDL_HashTable *computePipelineResourceLayoutHashTable;
+ SDL_HashTable *descriptorSetLayoutHashTable;
VulkanUniformBuffer **uniformBufferPool;
Uint32 uniformBufferPoolCount;
Uint32 uniformBufferPoolCapacity;
+ DescriptorSetCache **descriptorSetCachePool;
+ Uint32 descriptorSetCachePoolCount;
+ Uint32 descriptorSetCachePoolCapacity;
+
+ SDL_AtomicInt layoutResourceID;
+
Uint32 minUBOAlignment;
// Deferred resource destruction
@@ -2257,23 +2314,21 @@ static Uint8 VULKAN_INTERNAL_BindMemoryForBuffer(
commandBuffer->array[commandBuffer->count] = resource; \
commandBuffer->count += 1;
-#define TRACK_RESOURCE(resource, type, array, count, capacity) \
- Uint32 i; \
- \
- for (i = 0; i < commandBuffer->count; i += 1) { \
- if (commandBuffer->array[i] == resource) { \
- return; \
- } \
- } \
- \
- if (commandBuffer->count == commandBuffer->capacity) { \
- commandBuffer->capacity += 1; \
- commandBuffer->array = SDL_realloc( \
- commandBuffer->array, \
- commandBuffer->capacity * sizeof(type)); \
- } \
- commandBuffer->array[commandBuffer->count] = resource; \
- commandBuffer->count += 1; \
+#define TRACK_RESOURCE(resource, type, array, count, capacity) \
+ for (Sint32 i = commandBuffer->count - 1; i >= 0; i -= 1) { \
+ if (commandBuffer->array[i] == resource) { \
+ return; \
+ } \
+ } \
+ \
+ if (commandBuffer->count == commandBuffer->capacity) { \
+ commandBuffer->capacity += 1; \
+ commandBuffer->array = SDL_realloc( \
+ commandBuffer->array, \
+ commandBuffer->capacity * sizeof(type)); \
+ } \
+ commandBuffer->array[commandBuffer->count] = resource; \
+ commandBuffer->count += 1; \
SDL_AtomicIncRef(&resource->referenceCount);
static void VULKAN_INTERNAL_TrackBuffer(
@@ -2353,8 +2408,7 @@ static void VULKAN_INTERNAL_TrackUniformBuffer(
VulkanCommandBuffer *commandBuffer,
VulkanUniformBuffer *uniformBuffer)
{
- Uint32 i;
- for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
+ for (Sint32 i = commandBuffer->usedUniformBufferCount - 1; i >= 0; i -= 1) {
if (commandBuffer->usedUniformBuffers[i] == uniformBuffer) {
return;
}
@@ -2935,7 +2989,6 @@ static void VULKAN_INTERNAL_DestroyCommandPool(
SDL_free(commandBuffer->presentDatas);
SDL_free(commandBuffer->waitSemaphores);
SDL_free(commandBuffer->signalSemaphores);
- SDL_free(commandBuffer->boundDescriptorSetDatas);
SDL_free(commandBuffer->usedBuffers);
SDL_free(commandBuffer->usedTextures);
SDL_free(commandBuffer->usedSamplers);
@@ -2951,55 +3004,33 @@ static void VULKAN_INTERNAL_DestroyCommandPool(
SDL_free(commandPool);
}
-static void VULKAN_INTERNAL_DestroyDescriptorSetPool(
+static void VULKAN_INTERNAL_DestroyDescriptorSetLayout(
VulkanRenderer *renderer,
- DescriptorSetPool *pool)
+ DescriptorSetLayout *layout)
{
- Uint32 i;
-
- if (pool == NULL) {
+ if (layout == NULL) {
return;
}
- for (i = 0; i < pool->descriptorPoolCount; i += 1) {
- renderer->vkDestroyDescriptorPool(
+ if (layout->descriptorSetLayout != VK_NULL_HANDLE) {
+ renderer->vkDestroyDescriptorSetLayout(
renderer->logicalDevice,
- pool->descriptorPools[i],
+ layout->descriptorSetLayout,
NULL);
}
- renderer->vkDestroyDescriptorSetLayout(
- renderer->logicalDevice,
- pool->descriptorSetLayout,
- NULL);
-
- SDL_free(pool->descriptorInfos);
- SDL_free(pool->descriptorPools);
- SDL_free(pool->inactiveDescriptorSets);
+ SDL_free(layout);
}
static void VULKAN_INTERNAL_DestroyGraphicsPipeline(
VulkanRenderer *renderer,
VulkanGraphicsPipeline *graphicsPipeline)
{
- Uint32 i;
-
renderer->vkDestroyPipeline(
renderer->logicalDevice,
graphicsPipeline->pipeline,
NULL);
- renderer->vkDestroyPipelineLayout(
- renderer->logicalDevice,
- graphicsPipeline->resourceLayout.pipelineLayout,
- NULL);
-
- for (i = 0; i < 4; i += 1) {
- VULKAN_INTERNAL_DestroyDescriptorSetPool(
- renderer,
- &graphicsPipeline->resourceLayout.descriptorSetPools[i]);
- }
-
(void)SDL_AtomicDecRef(&graphicsPipeline->vertexShader->referenceCount);
(void)SDL_AtomicDecRef(&graphicsPipeline->fragmentShader->referenceCount);
@@ -3010,28 +3041,19 @@ static void VULKAN_INTERNAL_DestroyComputePipeline(
VulkanRenderer *renderer,
VulkanComputePipeline *computePipeline)
{
- Uint32 i;
-
- renderer->vkDestroyPipeline(
- renderer->logicalDevice,
- computePipeline->pipeline,
- NULL);
-
- renderer->vkDestroyPipelineLayout(
- renderer->logicalDevice,
- computePipeline->resourceLayout.pipelineLayout,
- NULL);
-
- for (i = 0; i < 3; i += 1) {
- VULKAN_INTERNAL_DestroyDescriptorSetPool(
- renderer,
- &computePipeline->resourceLayout.descriptorSetPools[i]);
+ if (computePipeline->pipeline != VK_NULL_HANDLE) {
+ renderer->vkDestroyPipeline(
+ renderer->logicalDevice,
+ computePipeline->pipeline,
+ NULL);
}
- renderer->vkDestroyShaderModule(
- renderer->logicalDevice,
- computePipeline->shaderModule,
- NULL);
+ if (computePipeline->shaderModule != VK_NULL_HANDLE) {
+ renderer->vkDestroyShaderModule(
+ renderer->logicalDevice,
+ computePipeline->shaderModule,
+ NULL);
+ }
SDL_free(computePipeline);
}
@@ -3119,8 +3141,148 @@ static void VULKAN_INTERNAL_DestroySwapchain(
SDL_free(swapchainData);
}
+static void VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(
+ VulkanRenderer *renderer,
+ VulkanGraphicsPipelineResourceLayout *resourceLayout)
+{
+ if (resourceLayout->pipelineLayout != VK_NULL_HANDLE) {
+ renderer->vkDestroyPipelineLayout(
+ renderer->logicalDevice,
+ resourceLayout->pipelineLayout,
+ NULL);
+ }
+
+ SDL_free(resourceLayout);
+}
+
+static void VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(
+ VulkanRenderer *renderer,
+ VulkanComputePipelineResourceLayout *resourceLayout)
+{
+ if (resourceLayout->pipelineLayout != VK_NULL_HANDLE) {
+ renderer->vkDestroyPipelineLayout(
+ renderer->logicalDevice,
+ resourceLayout->pipelineLayout,
+ NULL);
+ }
+
+ SDL_free(resourceLayout);
+}
+
+static void VULKAN_INTERNAL_DestroyDescriptorSetCache(
+ VulkanRenderer *renderer,
+ DescriptorSetCache *descriptorSetCache)
+{
+ for (Uint32 i = 0; i < descriptorSetCache->poolCount; i += 1) {
+ for (Uint32 j = 0; j < descriptorSetCache->pools[i].poolCount; j += 1) {
+ renderer->vkDestroyDescriptorPool(
+ renderer->logicalDevice,
+ descriptorSetCache->pools[i].descriptorPools[j],
+ NULL);
+ }
+ SDL_free(descriptorSetCache->pools[i].descriptorSets);
+ SDL_free(descriptorSetCache->pools[i].descriptorPools);
+ }
+ SDL_free(descriptorSetCache);
+}
+
// Hashtable functions
+static Uint32 VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashFunction(const void *key, void *data)
+{
+ GraphicsPipelineResourceLayoutHashTableKey *hashTableKey = (GraphicsPipelineResourceLayoutHashTableKey *)key;
+ /* The algorithm for this hashing function
+ * is taken from Josh Bloch's "Effective Java".
+ * (https://stackoverflow.com/a/113600/12492383)
+ */
+ const Uint32 hashFactor = 31;
+ Uint32 result = 1;
+ result = result * hashFactor + hashTableKey->vertexSamplerCount;
+ result = result * hashFactor + hashTableKey->vertexStorageBufferCount;
+ result = result * hashFactor + hashTableKey->vertexStorageTextureCount;
+ result = result * hashFactor + hashTableKey->vertexUniformBufferCount;
+ result = result * hashFactor + hashTableKey->fragmentSamplerCount;
+ result = result * hashFactor + hashTableKey->fragmentStorageBufferCount;
+ result = result * hashFactor + hashTableKey->fragmentStorageTextureCount;
+ result = result * hashFactor + hashTableKey->fragmentUniformBufferCount;
+ return result;
+}
+static bool VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashKeyMatch(const void *aKey, const void *bKey, void *data)
+{
+ return SDL_memcmp(aKey, bKey, sizeof(GraphicsPipelineResourceLayoutHashTableKey)) == 0;
+}
+static void VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashNuke(const void *key, const void *value, void *data)
+{
+ VulkanRenderer *renderer = (VulkanRenderer *)data;
+ VulkanGraphicsPipelineResourceLayout *resourceLayout = (VulkanGraphicsPipelineResourceLayout *)value;
+ VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(renderer, resourceLayout);
+ SDL_free((void*)key);
+}
+
+static Uint32 VULKAN_INTERNAL_ComputePipelineResourceLayoutHashFunction(const void *key, void *data)
+{
+ ComputePipelineResourceLayoutHashTableKey *hashTableKey = (ComputePipelineResourceLayoutHashTableKey *)key;
+ /* The algorithm for this hashing function
+ * is taken from Josh Bloch's "Effective Java".
+ * (https://stackoverflow.com/a/113600/12492383)
+ */
+ const Uint32 hashFactor = 31;
+ Uint32 result = 1;
+ result = result * hashFactor + hashTableKey->samplerCount;
+ result = result * hashFactor + hashTableKey->readonlyStorageTextureCount;
+ result = result * hashFactor + hashTableKey->readonlyStorageBufferCount;
+ result = result * hashFactor + hashTableKey->writeonlyStorageTextureCount;
+ result = result * hashFactor + hashTableKey->writeonlyStorageBufferCount;
+ result = result * hashFactor + hashTableKey->uniformBufferCount;
+ return result;
+}
+
+static bool VULKAN_INTERNAL_ComputePipelineResourceLayoutHashKeyMatch(const void *aKey, const void *bKey, void *data)
+{
+ return SDL_memcmp(aKey, bKey, sizeof(ComputePipelineResourceLayoutHashTableKey)) == 0;
+}
+
+static void VULKAN_INTERNAL_ComputePipelineResourceLayoutHashNuke(const void *key, const void *value, void *data)
+{
+ VulkanRenderer *renderer = (VulkanRenderer *)data;
+ VulkanComputePipelineResourceLayout *resourceLayout = (VulkanComputePipelineResourceLayout *)value;
+ VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(renderer, resourceLayout);
+ SDL_free((void*)key);
+}
+
+static Uint32 VULKAN_INTERNAL_DescriptorSetLayoutHashFunction(const void *key, void *data)
+{
+ DescriptorSetLayoutHashTableKey *hashTableKey = (DescriptorSetLayoutHashTableKey *)key;
+
+ /* The algorithm for this hashing function
+ * is taken from Josh Bloch's "Effective Java".
+ * (https://stackoverflow.com/a/113600/12492383)
+ */
+ const Uint32 hashFactor = 31;
+ Uint32 result = 1;
+ result = result * hashFactor + hashTableKey->shaderStage;
+ result = result * hashFactor + hashTableKey->samplerCount;
+ result = result * hashFactor + hashTableKey->storageTextureCount;
+ result = result * hashFactor + hashTableKey->storageBufferCount;
+ result = result * hashFactor + hashTableKey->writeStorageTextureCount;
+ result = result * hashFactor + hashTableKey->writeStorageBufferCount;
+ result = result * hashFactor + hashTableKey->uniformBufferCount;
+ return result;
+}
+
+static bool VULKAN_INTERNAL_DescriptorSetLayoutHashKeyMatch(const void *aKey, const void *bKey, void *data)
+{
+ return SDL_memcmp(aKey, bKey, sizeof(DescriptorSetLayoutHashTableKey)) == 0;
+}
+
+static void VULKAN_INTERNAL_DescriptorSetLayoutHashNuke(const void *key, const void *value, void *data)
+{
+ VulkanRenderer *renderer = (VulkanRenderer *)data;
+ DescriptorSetLayout *layout = (DescriptorSetLayout *)value;
+ VULKAN_INTERNAL_DestroyDescriptorSetLayout(renderer, layout);
+ SDL_free((void*)key);
+}
+
static Uint32 VULKAN_INTERNAL_CommandPoolHashFunction(const void *key, void *data)
{
return (Uint32)((CommandPoolHashTableKey *)key)->threadID;
@@ -3301,53 +3463,7 @@ static void VULKAN_INTERNAL_FramebufferHashNuke(const void *key, const void *val
SDL_free((void *)key);
}
-// Descriptor pool stuff
-
-static bool VULKAN_INTERNAL_CreateDescriptorPool(
- VulkanRenderer *renderer,
- VulkanDescriptorInfo *descriptorInfos,
- Uint32 descriptorInfoCount,
- Uint32 descriptorSetPoolSize,
- VkDescriptorPool *pDescriptorPool)
-{
- VkDescriptorPoolSize *descriptorPoolSizes;
- VkDescriptorPoolCreateInfo descriptorPoolInfo;
- VkResult vulkanResult;
- Uint32 i;
-
- descriptorPoolSizes = NULL;
-
- if (descriptorInfoCount > 0) {
- descriptorPoolSizes = SDL_stack_alloc(VkDescriptorPoolSize, descriptorInfoCount);
-
- for (i = 0; i < descriptorInfoCount; i += 1) {
- descriptorPoolSizes[i].type = descriptorInfos[i].descriptorType;
- descriptorPoolSizes[i].descriptorCount = descriptorSetPoolSize;
- }
- }
-
- descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
- descriptorPoolInfo.pNext = NULL;
- descriptorPoolInfo.flags = 0;
- descriptorPoolInfo.maxSets = descriptorSetPoolSize;
- descriptorPoolInfo.poolSizeCount = descriptorInfoCount;
- descriptorPoolInfo.pPoolSizes = descriptorPoolSizes;
-
- vulkanResult = renderer->vkCreateDescriptorPool(
- renderer->logicalDevice,
- &descriptorPoolInfo,
- NULL,
- pDescriptorPool);
-
- SDL_stack_free(descriptorPoolSizes);
-
- if (vulkanResult != VK_SUCCESS) {
- LogVulkanResultAsError("vkCreateDescriptorPool", vulkanResult);
- return false;
- }
-
- return true;
-}
+// Descriptor pools
static bool VULKAN_INTERNAL_AllocateDescriptorSets(
VulkanRenderer *renderer,
@@ -3376,506 +3492,436 @@ static bool VULKAN_INTERNAL_AllocateDescriptorSets(
&descriptorSetAllocateInfo,
descriptorSetArray);
+ SDL_stack_free(descriptorSetLayouts);
+
if (vulkanResult != VK_SUCCESS) {
LogVulkanResultAsError("vkAllocateDescriptorSets", vulkanResult);
- SDL_stack_free(descriptorSetLayouts);
return false;
}
- SDL_stack_free(descriptorSetLayouts);
return true;
}
-static void VULKAN_INTERNAL_InitializeDescriptorSetPool(
+static void VULKAN_INTERNAL_AllocateDescriptorsFromPool(
VulkanRenderer *renderer,
+ DescriptorSetLayout *descriptorSetLayout,
DescriptorSetPool *descriptorSetPool)
{
- descriptorSetPool->lock = 0;
-
- // Descriptor set layout and descriptor infos are already set when this function is called
-
- descriptorSetPool->descriptorPoolCount = 1;
- descriptorSetPool->descriptorPools = SDL_malloc(sizeof(VkDescriptorPool));
- descriptorSetPool->nextPoolSize = DESCRIPTOR_POOL_STARTING_SIZE * 2;
-
- VULKAN_INTERNAL_CreateDescriptorPool(
- renderer,
- descriptorSetPool->descriptorInfos,
- descriptorSetPool->descriptorInfoCount,
- DESCRIPTOR_POOL_STARTING_SIZE,
- &descriptorSetPool->descriptorPools[0]);
-
- descriptorSetPool->inactiveDescriptorSetCapacity = DESCRIPTOR_POOL_STARTING_SIZE;
- descriptorSetPool->inactiveDescriptorSetCount = DESCRIPTOR_POOL_STARTING_SIZE;
- descriptorSetPool->inactiveDescriptorSets = SDL_malloc(
- sizeof(VkDescriptorSet) * DESCRIPTOR_POOL_STARTING_SIZE);
-
- VULKAN_INTERNAL_AllocateDescriptorSets(
- renderer,
- descriptorSetPool->descriptorPools[0],
- descriptorSetPool->descriptorSetLayout,
- DESCRIPTOR_POOL_STARTING_SIZE,
- descriptorSetPool->inactiveDescriptorSets);
-}
-
-static bool VULKAN_INTERNAL_InitializeGraphicsPipelineResourceLayout(
- VulkanRenderer *renderer,
- VulkanShader *vertexShader,
- VulkanShader *fragmentShader,
- VulkanGraphicsPipelineResourceLayout *pipelineResourceLayout)
-{
- VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE + MAX_STORAGE_TEXTURES_PER_STAGE + MAX_STORAGE_BUFFERS_PER_STAGE];
- VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo;
- VkDescriptorSetLayout descriptorSetLayouts[4];
- VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo;
- DescriptorSetPool *descriptorSetPool;
+ VkDescriptorPoolSize descriptorPoolSizes[
+ MAX_TEXTURE_SAMPLERS_PER_STAGE +
+ MAX_STORAGE_TEXTURES_PER_STAGE +
+ MAX_STORAGE_BUFFERS_PER_STAGE +
+ MAX_COMPUTE_WRITE_TEXTURES +
+ MAX_COMPUTE_WRITE_BUFFERS +
+ MAX_UNIFORM_BUFFERS_PER_STAGE];
+ VkDescriptorPoolCreateInfo descriptorPoolInfo;
+ VkDescriptorPool pool;
VkResult vulkanResult;
- Uint32 i;
-
- pipelineResourceLayout->vertexSamplerCount = vertexShader->numSamplers;
- pipelineResourceLayout->vertexStorageTextureCount = vertexShader->numStorageTextures;
- pipelineResourceLayout->vertexStorageBufferCount = vertexShader->numStorageBuffers;
- pipelineResourceLayout->vertexUniformBufferCount = vertexShader->numUniformBuffers;
- pipelineResourceLayout->fragmentSamplerCount = fragmentShader->numSamplers;
- pipelineResourceLayout->fragmentStorageTextureCount = fragmentShader->numStorageTextures;
- pipelineResourceLayout->fragmentStorageBufferCount = fragmentShader->numStorageBuffers;
- pipelineResourceLayout->fragmentUniformBufferCount = fragmentShader->numUniformBuffers;
-
- // Vertex Resources
-
- descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
- descriptorSetLayoutCreateInfo.pNext = NULL;
- descriptorSetLayoutCreateInfo.flags = 0;
- descriptorSetLayoutCreateInfo.pBindings = NULL;
- descriptorSetLayoutCreateInfo.bindingCount =
- vertexShader->numSamplers +
- vertexShader->numStorageTextures +
- vertexShader->numStorageBuffers;
-
- descriptorSetPool = &pipelineResourceLayout->descriptorSetPools[0];
-
- descriptorSetPool->descriptorInfoCount = descriptorSetLayoutCreateInfo.bindingCount;
- descriptorSetPool->descriptorInfos = NULL;
-
- if (descriptorSetLayoutCreateInfo.bindingCount > 0) {
- descriptorSetPool->descriptorInfos = SDL_malloc(
- descriptorSetPool->descriptorInfoCount * sizeof(VulkanDescriptorInfo));
-
- for (i = 0; i < vertexShader->numSamplers; i += 1) {
- descriptorSetLayoutBindings[i].binding = i;
- descriptorSetLayoutBindings[i].descriptorCount = 1;
- descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
- descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
-
- descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_VERTEX_BIT;
- }
-
- for (i = vertexShader->numSamplers; i < vertexShader->numSamplers + vertexShader->numStorageTextures; i += 1) {
- descriptorSetLayoutBindings[i].binding = i;
- descriptorSetLayoutBindings[i].descriptorCount = 1;
- descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
- descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
-
- descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_VERTEX_BIT;
- }
-
- for (i = vertexShader->numSamplers + vertexShader->numStorageTextures; i < descriptorSetLayoutCreateInfo.bindingCount; i += 1) {
- descriptorSetLayoutBindings[i].binding = i;
- descriptorSetLayoutBindings[i].descriptorCount = 1;
- descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
- descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
-
- descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_VERTEX_BIT;
- }
-
- descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings;
+ // Category 1
+ for (Uint32 i = 0; i < descriptorSetLayout->samplerCount; i += 1) {
+ descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
}
- vulkanResult = renderer->vkCreateDescriptorSetLayout(
- renderer->logicalDevice,
- &descriptorSetLayoutCreateInfo,
- NULL,
- &descriptorSetPool->descriptorSetLayout);
-
- descriptorSetLayouts[0] = descriptorSetPool->descriptorSetLayout;
-
- if (vulkanResult != VK_SUCCESS) {
- LogVulkanResultAsError("vkCreateDescriptorSetLayout", vulkanResult);
- return false;
+ for (Uint32 i = descriptorSetLayout->samplerCount; i < descriptorSetLayout->samplerCount + descriptorSetLayout->storageTextureCount; i += 1) {
+ descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
}
- // Vertex UBOs
-
- descriptorSetPool = &pipelineResourceLayout->descriptorSetPools[1];
-
- descriptorSetLayoutCreateInfo.bindingCount = pipelineResourceLayout->vertexUniformBufferCount;
- descriptorSetLayoutCreateInfo.pBindings = NULL;
-
- descriptorSetPool->descriptorInfoCount = descriptorSetLayoutCreateInfo.bindingCount;
- descriptorSetPool->descriptorInfos = NULL;
-
- if (descriptorSetLayoutCreateInfo.bindingCount > 0) {
- descriptorSetPool->descriptorInfos = SDL_malloc(
- descriptorSetPool->descriptorInfoCount * sizeof(VulkanDescriptorInfo));
+ for (Uint32 i = descriptorSetLayout->samplerCount + descriptorSetLayout->storageTextureCount; i < descriptorSetLayout->samplerCount + descriptorSetLayout->storageTextureCount + descriptorSetLayout->storageBufferCount; i += 1) {
+ descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ descriptorPoolSizes[i].descriptorCount = DESCRIPTOR
(Patch may be truncated, please check the link at the top of this post.)