rework uniform buffer implementation as a ring buffer

pull/50/head
cosmonaut 2024-02-16 17:27:33 -08:00
parent 4ed50a96c9
commit a3d69ace21
1 changed files with 125 additions and 575 deletions

View File

@ -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
);