From a3d69ace213d7b835a6c3c4e4a02fdd896a568d3 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 16 Feb 2024 17:27:33 -0800 Subject: [PATCH] rework uniform buffer implementation as a ring buffer --- src/Refresh_Driver_Vulkan.c | 700 +++++++----------------------------- 1 file changed, 125 insertions(+), 575 deletions(-) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 1083fb8..00bcd2c 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -715,16 +715,6 @@ struct VulkanBuffer VulkanBufferContainer *container; }; -typedef struct VulkanUniformBufferPool VulkanUniformBufferPool; - -typedef struct VulkanUniformBuffer -{ - VulkanUniformBufferPool *pool; - VkDeviceSize poolOffset; /* memory offset relative to the pool buffer */ - VkDeviceSize offset; /* based on uniform pushes */ - VkDescriptorSet descriptorSet; -} VulkanUniformBuffer; - typedef enum VulkanUniformBufferType { UNIFORM_BUFFER_VERTEX, @@ -747,20 +737,16 @@ typedef struct VulkanUniformDescriptorPool uint32_t availableDescriptorSetCount; } VulkanUniformDescriptorPool; -/* This is actually just one buffer that we carve slices out of. */ -struct VulkanUniformBufferPool +/* Uniform buffers are just one buffer that we carve slices out of. */ +typedef struct VulkanUniformBufferObject { VulkanUniformBufferType type; - VulkanUniformDescriptorPool descriptorPool; + VkDescriptorSet descriptorSet; VulkanBuffer *buffer; - VkDeviceSize nextAvailableOffset; - SDL_mutex *lock; + uint32_t currentOffset; uint8_t *mapPointer; /* uniform buffers are permanently mapped */ - - VulkanUniformBuffer **availableBuffers; - uint32_t availableBufferCount; - uint32_t availableBufferCapacity; -}; + SDL_mutex *lock; +} VulkanUniformBufferObject; /* Renderer Structure */ @@ -1557,19 +1543,11 @@ typedef struct VulkanCommandBuffer uint32_t renderPassColorTargetCount; VulkanTexture *renderPassDepthTexture; /* can be NULL */ - VulkanUniformBuffer *vertexUniformBuffer; - VulkanUniformBuffer *fragmentUniformBuffer; - VulkanUniformBuffer *computeUniformBuffer; - VkDescriptorSet vertexSamplerDescriptorSet; /* updated by BindVertexSamplers */ VkDescriptorSet fragmentSamplerDescriptorSet; /* updated by BindFragmentSamplers */ VkDescriptorSet bufferDescriptorSet; /* updated by BindComputeBuffers */ VkDescriptorSet imageDescriptorSet; /* updated by BindComputeTextures */ - VulkanUniformBuffer **boundUniformBuffers; - uint32_t boundUniformBufferCount; - uint32_t boundUniformBufferCapacity; - DescriptorSetData *boundDescriptorSetDatas; uint32_t boundDescriptorSetDataCount; uint32_t boundDescriptorSetDataCapacity; @@ -1763,19 +1741,14 @@ typedef struct VulkanRenderer VkDescriptorSet emptyComputeBufferDescriptorSet; VkDescriptorSet emptyComputeImageDescriptorSet; - VulkanUniformBufferPool *vertexUniformBufferPool; - VulkanUniformBufferPool *fragmentUniformBufferPool; - VulkanUniformBufferPool *computeUniformBufferPool; + VulkanUniformBufferObject *vertexUniformBufferObject; + VulkanUniformBufferObject *fragmentUniformBufferObject; + VulkanUniformBufferObject *computeUniformBufferObject; VkDescriptorSetLayout vertexUniformDescriptorSetLayout; VkDescriptorSetLayout fragmentUniformDescriptorSetLayout; VkDescriptorSetLayout computeUniformDescriptorSetLayout; - VulkanBuffer *dummyBuffer; - VulkanUniformBuffer *dummyVertexUniformBuffer; - VulkanUniformBuffer *dummyFragmentUniformBuffer; - VulkanUniformBuffer *dummyComputeUniformBuffer; - VkDeviceSize minUBOAlignment; /* Some drivers don't support D16 for some reason. Fun! */ @@ -3612,7 +3585,6 @@ static void VULKAN_INTERNAL_DestroyCommandPool( SDL_free(commandBuffer->presentDatas); SDL_free(commandBuffer->waitSemaphores); SDL_free(commandBuffer->signalSemaphores); - SDL_free(commandBuffer->boundUniformBuffers); SDL_free(commandBuffer->boundDescriptorSetDatas); SDL_free(commandBuffer->boundComputeBuffers); SDL_free(commandBuffer->boundComputeTextures); @@ -4213,24 +4185,30 @@ static uint8_t VULKAN_INTERNAL_AddUniformDescriptorPool( return 1; } -static VulkanUniformBufferPool* VULKAN_INTERNAL_CreateUniformBufferPool( +static VulkanUniformBufferObject* VULKAN_INTERNAL_CreateUniformBufferObject( VulkanRenderer *renderer, VulkanUniformBufferType uniformBufferType ) { - VulkanUniformBufferPool* uniformBufferPool = SDL_malloc(sizeof(VulkanUniformBufferPool)); + VulkanUniformBufferObject* uniformBufferObject = SDL_malloc(sizeof(VulkanUniformBufferObject)); VulkanResourceAccessType resourceAccessType; + VkDescriptorSetLayout descriptorSetLayout; + VkWriteDescriptorSet writeDescriptorSet; + VkDescriptorBufferInfo descriptorBufferInfo; if (uniformBufferType == UNIFORM_BUFFER_VERTEX) { resourceAccessType = RESOURCE_ACCESS_VERTEX_SHADER_READ_UNIFORM_BUFFER; + descriptorSetLayout = renderer->vertexUniformDescriptorSetLayout; } else if (uniformBufferType == UNIFORM_BUFFER_FRAGMENT) { resourceAccessType = RESOURCE_ACCESS_FRAGMENT_SHADER_READ_UNIFORM_BUFFER; + descriptorSetLayout = renderer->fragmentUniformDescriptorSetLayout; } else if (uniformBufferType == UNIFORM_BUFFER_COMPUTE) { resourceAccessType = RESOURCE_ACCESS_COMPUTE_SHADER_READ_UNIFORM_BUFFER; + descriptorSetLayout = renderer->computeUniformDescriptorSetLayout; } else { @@ -4238,59 +4216,66 @@ static VulkanUniformBufferPool* VULKAN_INTERNAL_CreateUniformBufferPool( return 0; } - uniformBufferPool->buffer = VULKAN_INTERNAL_CreateBuffer( + /* Allocate backing buffer */ + uniformBufferObject->buffer = VULKAN_INTERNAL_CreateBuffer( renderer, UBO_BUFFER_SIZE, resourceAccessType, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 1, - 0, + 1, 1 ); - uniformBufferPool->nextAvailableOffset = 0; + uniformBufferObject->lock = SDL_CreateMutex(); - uniformBufferPool->type = uniformBufferType; - uniformBufferPool->lock = SDL_CreateMutex(); + uniformBufferObject->currentOffset = 0; + uniformBufferObject->type = uniformBufferType; - uniformBufferPool->availableBufferCapacity = 16; - uniformBufferPool->availableBufferCount = 0; - uniformBufferPool->availableBuffers = SDL_malloc(uniformBufferPool->availableBufferCapacity * sizeof(VulkanUniformBuffer*)); + /* Allocate a descriptor set for the uniform buffer */ + VULKAN_INTERNAL_AllocateDescriptorSets( + renderer, + renderer->defaultDescriptorPool, + descriptorSetLayout, + 1, + &uniformBufferObject->descriptorSet + ); - uniformBufferPool->descriptorPool.availableDescriptorSetCount = 0; - uniformBufferPool->descriptorPool.descriptorPoolCount = 0; - uniformBufferPool->descriptorPool.descriptorPools = NULL; + /* Update the descriptor set for the first and last time! */ + descriptorBufferInfo.buffer = uniformBufferObject->buffer->buffer; + descriptorBufferInfo.offset = 0; + descriptorBufferInfo.range = VK_WHOLE_SIZE; + writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeDescriptorSet.pNext = NULL; + writeDescriptorSet.descriptorCount = 1; + writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + writeDescriptorSet.dstArrayElement = 0; + writeDescriptorSet.dstBinding = 0; + writeDescriptorSet.dstSet = uniformBufferObject->descriptorSet; + writeDescriptorSet.pBufferInfo = &descriptorBufferInfo; + writeDescriptorSet.pImageInfo = NULL; + writeDescriptorSet.pTexelBufferView = NULL; + + renderer->vkUpdateDescriptorSets( + renderer->logicalDevice, + 1, + &writeDescriptorSet, + 0, + NULL + ); + + /* Permanently map the memory */ renderer->vkMapMemory( renderer->logicalDevice, - uniformBufferPool->buffer->usedRegion->allocation->memory, + uniformBufferObject->buffer->usedRegion->allocation->memory, 0, VK_WHOLE_SIZE, 0, - (void**) &uniformBufferPool->mapPointer + (void**) &uniformBufferObject->mapPointer ); - VULKAN_INTERNAL_AddUniformDescriptorPool(renderer, &uniformBufferPool->descriptorPool); - - return uniformBufferPool; -} - -static void VULKAN_INTERNAL_BindUniformBuffer( - VulkanRenderer *renderer, - VulkanCommandBuffer *commandBuffer, - VulkanUniformBuffer *uniformBuffer -) { - if (commandBuffer->boundUniformBufferCount >= commandBuffer->boundUniformBufferCapacity) - { - commandBuffer->boundUniformBufferCapacity *= 2; - commandBuffer->boundUniformBuffers = SDL_realloc( - commandBuffer->boundUniformBuffers, - sizeof(VulkanUniformBuffer*) * commandBuffer->boundUniformBufferCapacity - ); - } - - commandBuffer->boundUniformBuffers[commandBuffer->boundUniformBufferCount] = uniformBuffer; - commandBuffer->boundUniformBufferCount += 1; + return uniformBufferObject; } /* Buffer indirection so we can cleanly defrag */ @@ -4329,244 +4314,19 @@ static VulkanBufferContainer* VULKAN_INTERNAL_CreateBufferContainer( return (VulkanBufferContainer*) bufferContainer; } -static uint8_t VULKAN_INTERNAL_CreateUniformBuffer( +static void VULKAN_INTERNAL_DestroyUniformBufferObject( VulkanRenderer *renderer, - VulkanUniformBufferPool *bufferPool + VulkanUniformBufferObject *uniformBufferObject ) { - VkDescriptorSetLayout descriptorSetLayout; - - if (bufferPool->type == UNIFORM_BUFFER_VERTEX) - { - descriptorSetLayout = renderer->vertexUniformDescriptorSetLayout; - } - else if (bufferPool->type == UNIFORM_BUFFER_FRAGMENT) - { - descriptorSetLayout = renderer->fragmentUniformDescriptorSetLayout; - } - else if (bufferPool->type == UNIFORM_BUFFER_COMPUTE) - { - descriptorSetLayout = renderer->computeUniformDescriptorSetLayout; - } - else - { - Refresh_LogError("Unrecognized uniform buffer type!"); - return 0; - } - - VulkanUniformBuffer *uniformBuffer = SDL_malloc(sizeof(VulkanUniformBuffer)); - uniformBuffer->pool = bufferPool; - uniformBuffer->poolOffset = bufferPool->nextAvailableOffset; - uniformBuffer->offset = 0; - - bufferPool->nextAvailableOffset += VULKAN_INTERNAL_NextHighestAlignment(UBO_SECTION_SIZE, renderer->minUBOAlignment); - - if (bufferPool->nextAvailableOffset >= UBO_BUFFER_SIZE) - { - Refresh_LogError("Uniform buffer overflow!"); - SDL_free(uniformBuffer); - return 0; - } - - /* Allocate a descriptor set for the uniform buffer */ - - if (bufferPool->descriptorPool.availableDescriptorSetCount == 0) - { - if (!VULKAN_INTERNAL_AddUniformDescriptorPool( - renderer, - &bufferPool->descriptorPool - )) { - Refresh_LogError("Failed to add uniform descriptor pool!"); - SDL_free(uniformBuffer); - return 0; - } - } - - if (!VULKAN_INTERNAL_AllocateDescriptorSets( - renderer, - bufferPool->descriptorPool.descriptorPools[bufferPool->descriptorPool.descriptorPoolCount - 1], - descriptorSetLayout, - 1, - &uniformBuffer->descriptorSet - )) { - Refresh_LogError("Failed to allocate uniform descriptor set!"); - return 0; - } - - bufferPool->descriptorPool.availableDescriptorSetCount -= 1; - - if (bufferPool->availableBufferCount >= bufferPool->availableBufferCapacity) - { - bufferPool->availableBufferCapacity *= 2; - - bufferPool->availableBuffers = SDL_realloc( - bufferPool->availableBuffers, - sizeof(VulkanUniformBuffer*) * bufferPool->availableBufferCapacity - ); - } - - bufferPool->availableBuffers[bufferPool->availableBufferCount] = uniformBuffer; - bufferPool->availableBufferCount += 1; - - return 1; -} - -static VulkanUniformBuffer* VULKAN_INTERNAL_CreateDummyUniformBuffer( - VulkanRenderer *renderer, - VulkanUniformBufferType uniformBufferType -) { - VkDescriptorSetLayout descriptorSetLayout; - VkWriteDescriptorSet writeDescriptorSet; - VkDescriptorBufferInfo descriptorBufferInfo; - - if (uniformBufferType == UNIFORM_BUFFER_VERTEX) - { - descriptorSetLayout = renderer->vertexUniformDescriptorSetLayout; - } - else if (uniformBufferType == UNIFORM_BUFFER_FRAGMENT) - { - descriptorSetLayout = renderer->fragmentUniformDescriptorSetLayout; - } - else if (uniformBufferType == UNIFORM_BUFFER_COMPUTE) - { - descriptorSetLayout = renderer->computeUniformDescriptorSetLayout; - } - else - { - Refresh_LogError("Unrecognized uniform buffer type!"); - return NULL; - } - - VulkanUniformBuffer *uniformBuffer = SDL_malloc(sizeof(VulkanUniformBuffer)); - uniformBuffer->poolOffset = 0; - uniformBuffer->offset = 0; - - /* Allocate a descriptor set for the uniform buffer */ - - VULKAN_INTERNAL_AllocateDescriptorSets( - renderer, - renderer->defaultDescriptorPool, - descriptorSetLayout, - 1, - &uniformBuffer->descriptorSet - ); - - /* Update the descriptor set for the first and last time! */ - - descriptorBufferInfo.buffer = renderer->dummyBuffer->buffer; - descriptorBufferInfo.offset = 0; - descriptorBufferInfo.range = VK_WHOLE_SIZE; - - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.pNext = NULL; - writeDescriptorSet.descriptorCount = 1; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - writeDescriptorSet.dstArrayElement = 0; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.dstSet = uniformBuffer->descriptorSet; - writeDescriptorSet.pBufferInfo = &descriptorBufferInfo; - writeDescriptorSet.pImageInfo = NULL; - writeDescriptorSet.pTexelBufferView = NULL; - - renderer->vkUpdateDescriptorSets( - renderer->logicalDevice, - 1, - &writeDescriptorSet, - 0, - NULL - ); - - uniformBuffer->pool = NULL; /* No pool because this is a dummy */ - - return uniformBuffer; -} - -static void VULKAN_INTERNAL_DestroyUniformBufferPool( - VulkanRenderer *renderer, - VulkanUniformBufferPool *uniformBufferPool -) { - uint32_t i; - - for (i = 0; i < uniformBufferPool->descriptorPool.descriptorPoolCount; i += 1) - { - renderer->vkDestroyDescriptorPool( - renderer->logicalDevice, - uniformBufferPool->descriptorPool.descriptorPools[i], - NULL - ); - } - SDL_free(uniformBufferPool->descriptorPool.descriptorPools); - - /* This is always destroyed after submissions, so all buffers are available */ - for (i = 0; i < uniformBufferPool->availableBufferCount; i += 1) - { - SDL_free(uniformBufferPool->availableBuffers[i]); - } - renderer->vkUnmapMemory( renderer->logicalDevice, - uniformBufferPool->buffer->usedRegion->allocation->memory + uniformBufferObject->buffer->usedRegion->allocation->memory ); - VULKAN_INTERNAL_DestroyBuffer(renderer, uniformBufferPool->buffer); + VULKAN_INTERNAL_DestroyBuffer(renderer, uniformBufferObject->buffer); - SDL_DestroyMutex(uniformBufferPool->lock); - SDL_free(uniformBufferPool->availableBuffers); - SDL_free(uniformBufferPool); -} - -static VulkanUniformBuffer* VULKAN_INTERNAL_AcquireUniformBufferFromPool( - VulkanRenderer *renderer, - VulkanUniformBufferPool *bufferPool, - VkDeviceSize blockSize -) { - VkWriteDescriptorSet writeDescriptorSet; - VkDescriptorBufferInfo descriptorBufferInfo; - - SDL_LockMutex(bufferPool->lock); - - if (bufferPool->availableBufferCount == 0) - { - if (!VULKAN_INTERNAL_CreateUniformBuffer(renderer, bufferPool)) - { - SDL_UnlockMutex(bufferPool->lock); - Refresh_LogError("Failed to create uniform buffer!"); - return NULL; - } - } - - VulkanUniformBuffer *uniformBuffer = bufferPool->availableBuffers[bufferPool->availableBufferCount - 1]; - bufferPool->availableBufferCount -= 1; - - SDL_UnlockMutex(bufferPool->lock); - - uniformBuffer->offset = 0; - - /* Update the descriptor set with the correct range */ - - descriptorBufferInfo.buffer = uniformBuffer->pool->buffer->buffer; - descriptorBufferInfo.offset = uniformBuffer->poolOffset; - descriptorBufferInfo.range = blockSize; - - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.pNext = NULL; - writeDescriptorSet.descriptorCount = 1; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - writeDescriptorSet.dstArrayElement = 0; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.dstSet = uniformBuffer->descriptorSet; - writeDescriptorSet.pBufferInfo = &descriptorBufferInfo; - writeDescriptorSet.pImageInfo = NULL; - writeDescriptorSet.pTexelBufferView = NULL; - - renderer->vkUpdateDescriptorSets( - renderer->logicalDevice, - 1, - &writeDescriptorSet, - 0, - NULL - ); - - return uniformBuffer; + SDL_DestroyMutex(uniformBufferObject->lock); + SDL_free(uniformBufferObject); } /* Swapchain */ @@ -5211,12 +4971,6 @@ static void VULKAN_DestroyDevice( SDL_free(renderer->submittedCommandBuffers); - VULKAN_INTERNAL_DestroyBuffer(renderer, renderer->dummyBuffer); - - SDL_free(renderer->dummyVertexUniformBuffer); - SDL_free(renderer->dummyFragmentUniformBuffer); - SDL_free(renderer->dummyComputeUniformBuffer); - for (i = 0; i < renderer->fencePool.availableFenceCount; i += 1) { renderer->vkDestroyFence(renderer->logicalDevice, renderer->fencePool.availableFences[i], NULL); @@ -5361,9 +5115,9 @@ static void VULKAN_DestroyDevice( NULL ); - VULKAN_INTERNAL_DestroyUniformBufferPool(renderer, renderer->vertexUniformBufferPool); - VULKAN_INTERNAL_DestroyUniformBufferPool(renderer, renderer->fragmentUniformBufferPool); - VULKAN_INTERNAL_DestroyUniformBufferPool(renderer, renderer->computeUniformBufferPool); + VULKAN_INTERNAL_DestroyUniformBufferObject(renderer, renderer->vertexUniformBufferObject); + VULKAN_INTERNAL_DestroyUniformBufferObject(renderer, renderer->fragmentUniformBufferObject); + VULKAN_INTERNAL_DestroyUniformBufferObject(renderer, renderer->computeUniformBufferObject); for (i = 0; i < renderer->framebufferHashArray.count; i += 1) { @@ -5460,8 +5214,8 @@ static void VULKAN_DrawInstancedPrimitives( descriptorSets[0] = vulkanCommandBuffer->vertexSamplerDescriptorSet; descriptorSets[1] = vulkanCommandBuffer->fragmentSamplerDescriptorSet; - descriptorSets[2] = vulkanCommandBuffer->vertexUniformBuffer->descriptorSet; - descriptorSets[3] = vulkanCommandBuffer->fragmentUniformBuffer->descriptorSet; + descriptorSets[2] = renderer->vertexUniformBufferObject->descriptorSet; + descriptorSets[3] = renderer->fragmentUniformBufferObject->descriptorSet; dynamicOffsets[0] = vertexParamOffset; dynamicOffsets[1] = fragmentParamOffset; @@ -5527,8 +5281,8 @@ static void VULKAN_DrawPrimitives( descriptorSets[0] = vulkanCommandBuffer->vertexSamplerDescriptorSet; descriptorSets[1] = vulkanCommandBuffer->fragmentSamplerDescriptorSet; - descriptorSets[2] = vulkanCommandBuffer->vertexUniformBuffer->descriptorSet; - descriptorSets[3] = vulkanCommandBuffer->fragmentUniformBuffer->descriptorSet; + descriptorSets[2] = renderer->vertexUniformBufferObject->descriptorSet; + descriptorSets[3] = renderer->fragmentUniformBufferObject->descriptorSet; dynamicOffsets[0] = vertexParamOffset; dynamicOffsets[1] = fragmentParamOffset; @@ -5574,8 +5328,8 @@ static void VULKAN_DrawPrimitivesIndirect( descriptorSets[0] = vulkanCommandBuffer->vertexSamplerDescriptorSet; descriptorSets[1] = vulkanCommandBuffer->fragmentSamplerDescriptorSet; - descriptorSets[2] = vulkanCommandBuffer->vertexUniformBuffer->descriptorSet; - descriptorSets[3] = vulkanCommandBuffer->fragmentUniformBuffer->descriptorSet; + descriptorSets[2] = renderer->vertexUniformBufferObject->descriptorSet; + descriptorSets[3] = renderer->fragmentUniformBufferObject->descriptorSet; dynamicOffsets[0] = vertexParamOffset; dynamicOffsets[1] = fragmentParamOffset; @@ -7057,15 +6811,14 @@ static Refresh_CpuBuffer* VULKAN_CreateCpuBuffer( /* Setters */ static void VULKAN_INTERNAL_SetUniformBufferData( - VulkanUniformBuffer *uniformBuffer, + VulkanUniformBufferObject *uniformBufferObject, void* data, uint32_t dataLength ) { uint8_t *dst = - uniformBuffer->pool->mapPointer + - uniformBuffer->pool->buffer->usedRegion->resourceOffset + - uniformBuffer->poolOffset + - uniformBuffer->offset; + uniformBufferObject->mapPointer + + uniformBufferObject->buffer->usedRegion->resourceOffset + + uniformBufferObject->currentOffset; SDL_memcpy( dst, @@ -7085,45 +6838,30 @@ static uint32_t VULKAN_PushVertexShaderUniforms( VulkanGraphicsPipeline* graphicsPipeline = vulkanCommandBuffer->currentGraphicsPipeline; uint32_t offset; - if (graphicsPipeline == NULL) - { - Refresh_LogError("Cannot push uniforms if a pipeline is not bound!"); - return 0; - } - if (graphicsPipeline->vertexUniformBlockSize == 0) { Refresh_LogError("Bound pipeline's vertex stage does not declare uniforms!"); return 0; } - if ( - vulkanCommandBuffer->vertexUniformBuffer->offset + - graphicsPipeline->vertexUniformBlockSize >= - UBO_SECTION_SIZE - ) { - /* We're out of space in this buffer, bind the old one and acquire a new one */ - VULKAN_INTERNAL_BindUniformBuffer( - renderer, - vulkanCommandBuffer, - vulkanCommandBuffer->vertexUniformBuffer - ); - vulkanCommandBuffer->vertexUniformBuffer = VULKAN_INTERNAL_AcquireUniformBufferFromPool( - renderer, - renderer->vertexUniformBufferPool, - graphicsPipeline->vertexUniformBlockSize - ); + SDL_LockMutex(renderer->vertexUniformBufferObject->lock); + + if (renderer->vertexUniformBufferObject->currentOffset + dataLengthInBytes >= UBO_BUFFER_SIZE) + { + renderer->vertexUniformBufferObject->currentOffset = 0; } - offset = vulkanCommandBuffer->vertexUniformBuffer->offset; + offset = renderer->vertexUniformBufferObject->currentOffset; VULKAN_INTERNAL_SetUniformBufferData( - vulkanCommandBuffer->vertexUniformBuffer, + renderer->vertexUniformBufferObject, data, dataLengthInBytes ); - vulkanCommandBuffer->vertexUniformBuffer->offset += graphicsPipeline->vertexUniformBlockSize; + renderer->vertexUniformBufferObject->currentOffset += graphicsPipeline->vertexUniformBlockSize; + + SDL_UnlockMutex(renderer->vertexUniformBufferObject->lock); return offset; } @@ -7139,33 +6877,30 @@ static uint32_t VULKAN_PushFragmentShaderUniforms( VulkanGraphicsPipeline* graphicsPipeline = vulkanCommandBuffer->currentGraphicsPipeline; uint32_t offset; - if ( - vulkanCommandBuffer->fragmentUniformBuffer->offset + - graphicsPipeline->fragmentUniformBlockSize >= - UBO_SECTION_SIZE - ) { - /* We're out of space in this buffer, bind the old one and acquire a new one */ - VULKAN_INTERNAL_BindUniformBuffer( - renderer, - vulkanCommandBuffer, - vulkanCommandBuffer->fragmentUniformBuffer - ); - vulkanCommandBuffer->fragmentUniformBuffer = VULKAN_INTERNAL_AcquireUniformBufferFromPool( - renderer, - renderer->fragmentUniformBufferPool, - graphicsPipeline->fragmentUniformBlockSize - ); + if (graphicsPipeline->fragmentUniformBlockSize == 0) + { + Refresh_LogError("Bound pipeline's fragment stage does not declare uniforms!"); + return 0; } - offset = vulkanCommandBuffer->fragmentUniformBuffer->offset; + SDL_LockMutex(renderer->fragmentUniformBufferObject->lock); + + if (renderer->fragmentUniformBufferObject->currentOffset + dataLengthInBytes >= UBO_BUFFER_SIZE) + { + renderer->fragmentUniformBufferObject->currentOffset = 0; + } + + offset = renderer->fragmentUniformBufferObject->currentOffset; VULKAN_INTERNAL_SetUniformBufferData( - vulkanCommandBuffer->fragmentUniformBuffer, + renderer->fragmentUniformBufferObject, data, dataLengthInBytes ); - vulkanCommandBuffer->fragmentUniformBuffer->offset += graphicsPipeline->fragmentUniformBlockSize; + renderer->fragmentUniformBufferObject->currentOffset += graphicsPipeline->fragmentUniformBlockSize; + + SDL_UnlockMutex(renderer->fragmentUniformBufferObject->lock); return offset; } @@ -7181,33 +6916,30 @@ static uint32_t VULKAN_PushComputeShaderUniforms( VulkanComputePipeline* computePipeline = vulkanCommandBuffer->currentComputePipeline; uint32_t offset; - if ( - vulkanCommandBuffer->computeUniformBuffer->offset + - computePipeline->uniformBlockSize >= - UBO_SECTION_SIZE - ) { - /* We're out of space in this buffer, bind the old one and acquire a new one */ - VULKAN_INTERNAL_BindUniformBuffer( - renderer, - vulkanCommandBuffer, - vulkanCommandBuffer->computeUniformBuffer - ); - vulkanCommandBuffer->computeUniformBuffer = VULKAN_INTERNAL_AcquireUniformBufferFromPool( - renderer, - renderer->computeUniformBufferPool, - computePipeline->uniformBlockSize - ); + if (computePipeline->uniformBlockSize == 0) + { + Refresh_LogError("Bound pipeline's compute stage does not declare uniforms!"); + return 0; } - offset = vulkanCommandBuffer->computeUniformBuffer->offset; + SDL_LockMutex(renderer->computeUniformBufferObject->lock); + + if (renderer->computeUniformBufferObject->currentOffset + dataLengthInBytes >= UBO_BUFFER_SIZE) + { + renderer->computeUniformBufferObject->currentOffset = 0; + } + + offset = renderer->computeUniformBufferObject->currentOffset; VULKAN_INTERNAL_SetUniformBufferData( - vulkanCommandBuffer->computeUniformBuffer, + renderer->computeUniformBufferObject, data, dataLengthInBytes ); - vulkanCommandBuffer->computeUniformBuffer->offset += computePipeline->uniformBlockSize; + renderer->computeUniformBufferObject->currentOffset += computePipeline->uniformBlockSize; + + SDL_UnlockMutex(renderer->computeUniformBufferObject->lock); return offset; } @@ -8195,28 +7927,6 @@ static void VULKAN_EndRenderPass( vulkanCommandBuffer->commandBuffer ); - if ( vulkanCommandBuffer->vertexUniformBuffer != renderer->dummyVertexUniformBuffer && - vulkanCommandBuffer->vertexUniformBuffer != NULL - ) { - VULKAN_INTERNAL_BindUniformBuffer( - renderer, - vulkanCommandBuffer, - vulkanCommandBuffer->vertexUniformBuffer - ); - } - vulkanCommandBuffer->vertexUniformBuffer = NULL; - - if ( vulkanCommandBuffer->fragmentUniformBuffer != renderer->dummyFragmentUniformBuffer && - vulkanCommandBuffer->fragmentUniformBuffer != NULL - ) { - VULKAN_INTERNAL_BindUniformBuffer( - renderer, - vulkanCommandBuffer, - vulkanCommandBuffer->fragmentUniformBuffer - ); - } - vulkanCommandBuffer->fragmentUniformBuffer = NULL; - /* If the render targets can be sampled, transition them to sample layout */ for (i = 0; i < vulkanCommandBuffer->renderPassColorTargetCount; i += 1) { @@ -8292,52 +8002,6 @@ static void VULKAN_BindGraphicsPipeline( VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanGraphicsPipeline* pipeline = (VulkanGraphicsPipeline*) graphicsPipeline; - if ( vulkanCommandBuffer->vertexUniformBuffer != renderer->dummyVertexUniformBuffer && - vulkanCommandBuffer->vertexUniformBuffer != NULL - ) { - VULKAN_INTERNAL_BindUniformBuffer( - renderer, - vulkanCommandBuffer, - vulkanCommandBuffer->vertexUniformBuffer - ); - } - - if (pipeline->vertexUniformBlockSize == 0) - { - vulkanCommandBuffer->vertexUniformBuffer = renderer->dummyVertexUniformBuffer; - } - else - { - vulkanCommandBuffer->vertexUniformBuffer = VULKAN_INTERNAL_AcquireUniformBufferFromPool( - renderer, - renderer->vertexUniformBufferPool, - pipeline->vertexUniformBlockSize - ); - } - - if ( vulkanCommandBuffer->fragmentUniformBuffer != renderer->dummyFragmentUniformBuffer && - vulkanCommandBuffer->fragmentUniformBuffer != NULL - ) { - VULKAN_INTERNAL_BindUniformBuffer( - renderer, - vulkanCommandBuffer, - vulkanCommandBuffer->fragmentUniformBuffer - ); - } - - if (pipeline->fragmentUniformBlockSize == 0) - { - vulkanCommandBuffer->fragmentUniformBuffer = renderer->dummyFragmentUniformBuffer; - } - else - { - vulkanCommandBuffer->fragmentUniformBuffer = VULKAN_INTERNAL_AcquireUniformBufferFromPool( - renderer, - renderer->fragmentUniformBufferPool, - pipeline->fragmentUniformBlockSize - ); - } - /* bind dummy sets if necessary */ if (pipeline->pipelineLayout->vertexSamplerDescriptorSetCache == NULL) { @@ -8446,7 +8110,7 @@ static void VULKAN_BindComputePipeline( VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanComputePipeline *vulkanComputePipeline = (VulkanComputePipeline*) computePipeline; - /* bind dummy sets */ + /* bind dummy sets if necessary */ if (vulkanComputePipeline->pipelineLayout->bufferDescriptorSetCache == NULL) { vulkanCommandBuffer->bufferDescriptorSet = renderer->emptyComputeBufferDescriptorSet; @@ -8457,15 +8121,6 @@ static void VULKAN_BindComputePipeline( vulkanCommandBuffer->imageDescriptorSet = renderer->emptyComputeImageDescriptorSet; } - if ( vulkanCommandBuffer->computeUniformBuffer != renderer->dummyComputeUniformBuffer && - vulkanCommandBuffer->computeUniformBuffer != NULL - ) { - VULKAN_INTERNAL_BindUniformBuffer( - renderer, - vulkanCommandBuffer, - vulkanCommandBuffer->computeUniformBuffer - ); - } renderer->vkCmdBindPipeline( vulkanCommandBuffer->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, @@ -8474,19 +8129,6 @@ static void VULKAN_BindComputePipeline( vulkanCommandBuffer->currentComputePipeline = vulkanComputePipeline; - if (vulkanComputePipeline->uniformBlockSize == 0) - { - vulkanCommandBuffer->computeUniformBuffer = renderer->dummyComputeUniformBuffer; - } - else - { - vulkanCommandBuffer->computeUniformBuffer = VULKAN_INTERNAL_AcquireUniformBufferFromPool( - renderer, - renderer->computeUniformBufferPool, - vulkanComputePipeline->uniformBlockSize - ); - } - VULKAN_INTERNAL_TrackComputePipeline(renderer, vulkanCommandBuffer, vulkanComputePipeline); } @@ -8606,7 +8248,7 @@ static void VULKAN_DispatchCompute( descriptorSets[0] = vulkanCommandBuffer->bufferDescriptorSet; descriptorSets[1] = vulkanCommandBuffer->imageDescriptorSet; - descriptorSets[2] = vulkanCommandBuffer->computeUniformBuffer->descriptorSet; + descriptorSets[2] = renderer->computeUniformBufferObject->descriptorSet; renderer->vkCmdBindDescriptorSets( vulkanCommandBuffer->commandBuffer, @@ -8692,17 +8334,6 @@ static void VULKAN_EndComputePass( } } - if ( vulkanCommandBuffer->computeUniformBuffer != renderer->dummyComputeUniformBuffer && - vulkanCommandBuffer->computeUniformBuffer != NULL) - { - VULKAN_INTERNAL_BindUniformBuffer( - renderer, - vulkanCommandBuffer, - vulkanCommandBuffer->computeUniformBuffer - ); - } - - vulkanCommandBuffer->computeUniformBuffer = NULL; vulkanCommandBuffer->currentComputePipeline = NULL; } @@ -9459,14 +9090,6 @@ static void VULKAN_INTERNAL_AllocateCommandBuffers( commandBuffer->signalSemaphoreCapacity * sizeof(VkSemaphore) ); - /* Bound buffer tracking */ - - commandBuffer->boundUniformBufferCapacity = 16; - commandBuffer->boundUniformBufferCount = 0; - commandBuffer->boundUniformBuffers = SDL_malloc( - commandBuffer->boundUniformBufferCapacity * sizeof(VulkanUniformBuffer*) - ); - /* Descriptor set tracking */ commandBuffer->boundDescriptorSetDataCapacity = 16; @@ -9656,10 +9279,6 @@ static Refresh_CommandBuffer* VULKAN_AcquireCommandBuffer( commandBuffer->currentComputePipeline = NULL; commandBuffer->currentGraphicsPipeline = NULL; - commandBuffer->vertexUniformBuffer = NULL; - commandBuffer->fragmentUniformBuffer = NULL; - commandBuffer->computeUniformBuffer = NULL; - commandBuffer->renderPassColorTargetCount = 0; commandBuffer->autoReleaseFence = 1; @@ -10152,7 +9771,6 @@ static void VULKAN_INTERNAL_CleanCommandBuffer( VulkanCommandBuffer *commandBuffer ) { uint32_t i; - VulkanUniformBuffer *uniformBuffer; DescriptorSetData *descriptorSetData; if (commandBuffer->autoReleaseFence) @@ -10165,29 +9783,6 @@ static void VULKAN_INTERNAL_CleanCommandBuffer( commandBuffer->inFlightFence = VK_NULL_HANDLE; } - /* Bound uniform buffers are now available */ - - for (i = 0; i < commandBuffer->boundUniformBufferCount; i += 1) - { - uniformBuffer = commandBuffer->boundUniformBuffers[i]; - - SDL_LockMutex(uniformBuffer->pool->lock); - if (uniformBuffer->pool->availableBufferCount == uniformBuffer->pool->availableBufferCapacity) - { - uniformBuffer->pool->availableBufferCapacity *= 2; - uniformBuffer->pool->availableBuffers = SDL_realloc( - uniformBuffer->pool->availableBuffers, - uniformBuffer->pool->availableBufferCapacity * sizeof(VulkanUniformBuffer*) - ); - } - - uniformBuffer->pool->availableBuffers[uniformBuffer->pool->availableBufferCount] = uniformBuffer; - uniformBuffer->pool->availableBufferCount += 1; - SDL_UnlockMutex(uniformBuffer->pool->lock); - } - - commandBuffer->boundUniformBufferCount = 0; - /* Bound descriptor sets are now available */ for (i = 0; i < commandBuffer->boundDescriptorSetDataCount; i += 1) @@ -11958,64 +11553,19 @@ static Refresh_Device* VULKAN_CreateDevice( &renderer->emptyComputeImageDescriptorSet ); - /* Dummy Uniform Buffers */ + /* Initialize uniform buffer objects */ - renderer->dummyBuffer = VULKAN_INTERNAL_CreateBuffer( - renderer, - 16, - RESOURCE_ACCESS_GENERAL, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - 0, - 0, - 1 - ); - - renderer->dummyVertexUniformBuffer = VULKAN_INTERNAL_CreateDummyUniformBuffer( + renderer->vertexUniformBufferObject = VULKAN_INTERNAL_CreateUniformBufferObject( renderer, UNIFORM_BUFFER_VERTEX ); - if (renderer->dummyVertexUniformBuffer == NULL) - { - Refresh_LogError("Failed to create dummy vertex uniform buffer!"); - return NULL; - } - - renderer->dummyFragmentUniformBuffer = VULKAN_INTERNAL_CreateDummyUniformBuffer( + renderer->fragmentUniformBufferObject = VULKAN_INTERNAL_CreateUniformBufferObject( renderer, UNIFORM_BUFFER_FRAGMENT ); - if (renderer->dummyFragmentUniformBuffer == NULL) - { - Refresh_LogError("Failed to create dummy fragment uniform buffer!"); - return NULL; - } - - renderer->dummyComputeUniformBuffer = VULKAN_INTERNAL_CreateDummyUniformBuffer( - renderer, - UNIFORM_BUFFER_COMPUTE - ); - - if (renderer->dummyComputeUniformBuffer == NULL) - { - Refresh_LogError("Failed to create dummy compute uniform buffer!"); - return NULL; - } - - /* Initialize uniform buffer pools */ - - renderer->vertexUniformBufferPool = VULKAN_INTERNAL_CreateUniformBufferPool( - renderer, - UNIFORM_BUFFER_VERTEX - ); - - renderer->fragmentUniformBufferPool = VULKAN_INTERNAL_CreateUniformBufferPool( - renderer, - UNIFORM_BUFFER_FRAGMENT - ); - - renderer->computeUniformBufferPool = VULKAN_INTERNAL_CreateUniformBufferPool( + renderer->computeUniformBufferObject = VULKAN_INTERNAL_CreateUniformBufferObject( renderer, UNIFORM_BUFFER_COMPUTE );