Uniform buffers are now slices of dedicated allocs (#48)
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This should fix an issue where draw calls could flicker if a defrag was in progress and a uniform buffer was being used. Uniform buffer "pools" are now just a single dedicated VulkanBuffer, and the uniform buffer objects are offsets into that buffer. Reviewed-on: #48pull/49/head
parent
b72b0b5fde
commit
7297eba889
|
@ -79,7 +79,8 @@ typedef struct VulkanExtensions
|
||||||
#define ALLOCATION_INCREMENT 16000000 /* 16MB */
|
#define ALLOCATION_INCREMENT 16000000 /* 16MB */
|
||||||
#define TRANSFER_BUFFER_STARTING_SIZE 8000000 /* 8MB */
|
#define TRANSFER_BUFFER_STARTING_SIZE 8000000 /* 8MB */
|
||||||
#define POOLED_TRANSFER_BUFFER_SIZE 16000000 /* 16MB */
|
#define POOLED_TRANSFER_BUFFER_SIZE 16000000 /* 16MB */
|
||||||
#define UBO_BUFFER_SIZE 16000 /* 16KB */
|
#define UBO_BUFFER_SIZE 16000000 /* 16MB */
|
||||||
|
#define UBO_SECTION_SIZE 4000 /* 4KB */
|
||||||
#define DESCRIPTOR_POOL_STARTING_SIZE 128
|
#define DESCRIPTOR_POOL_STARTING_SIZE 128
|
||||||
#define DEFRAG_TIME 200
|
#define DEFRAG_TIME 200
|
||||||
#define WINDOW_DATA "Refresh_VulkanWindowData"
|
#define WINDOW_DATA "Refresh_VulkanWindowData"
|
||||||
|
@ -719,8 +720,8 @@ typedef struct VulkanUniformBufferPool VulkanUniformBufferPool;
|
||||||
typedef struct VulkanUniformBuffer
|
typedef struct VulkanUniformBuffer
|
||||||
{
|
{
|
||||||
VulkanUniformBufferPool *pool;
|
VulkanUniformBufferPool *pool;
|
||||||
VulkanBufferContainer *vulkanBufferContainer; /* use container to avoid defrag issues */
|
VkDeviceSize poolOffset; /* memory offset relative to the pool buffer */
|
||||||
VkDeviceSize offset;
|
VkDeviceSize offset; /* based on uniform pushes */
|
||||||
VkDescriptorSet descriptorSet;
|
VkDescriptorSet descriptorSet;
|
||||||
} VulkanUniformBuffer;
|
} VulkanUniformBuffer;
|
||||||
|
|
||||||
|
@ -746,10 +747,13 @@ typedef struct VulkanUniformDescriptorPool
|
||||||
uint32_t availableDescriptorSetCount;
|
uint32_t availableDescriptorSetCount;
|
||||||
} VulkanUniformDescriptorPool;
|
} VulkanUniformDescriptorPool;
|
||||||
|
|
||||||
|
/* This is actually just one buffer that we carve slices out of. */
|
||||||
struct VulkanUniformBufferPool
|
struct VulkanUniformBufferPool
|
||||||
{
|
{
|
||||||
VulkanUniformBufferType type;
|
VulkanUniformBufferType type;
|
||||||
VulkanUniformDescriptorPool descriptorPool;
|
VulkanUniformDescriptorPool descriptorPool;
|
||||||
|
VulkanBuffer *buffer;
|
||||||
|
VkDeviceSize nextAvailableOffset;
|
||||||
SDL_mutex *lock;
|
SDL_mutex *lock;
|
||||||
|
|
||||||
VulkanUniformBuffer **availableBuffers;
|
VulkanUniformBuffer **availableBuffers;
|
||||||
|
@ -1776,6 +1780,8 @@ typedef struct VulkanRenderer
|
||||||
VkDescriptorSetLayout vertexUniformDescriptorSetLayout;
|
VkDescriptorSetLayout vertexUniformDescriptorSetLayout;
|
||||||
VkDescriptorSetLayout fragmentUniformDescriptorSetLayout;
|
VkDescriptorSetLayout fragmentUniformDescriptorSetLayout;
|
||||||
VkDescriptorSetLayout computeUniformDescriptorSetLayout;
|
VkDescriptorSetLayout computeUniformDescriptorSetLayout;
|
||||||
|
|
||||||
|
VulkanBuffer *dummyBuffer;
|
||||||
VulkanUniformBuffer *dummyVertexUniformBuffer;
|
VulkanUniformBuffer *dummyVertexUniformBuffer;
|
||||||
VulkanUniformBuffer *dummyFragmentUniformBuffer;
|
VulkanUniformBuffer *dummyFragmentUniformBuffer;
|
||||||
VulkanUniformBuffer *dummyComputeUniformBuffer;
|
VulkanUniformBuffer *dummyComputeUniformBuffer;
|
||||||
|
@ -4197,6 +4203,36 @@ static VulkanUniformBufferPool* VULKAN_INTERNAL_CreateUniformBufferPool(
|
||||||
VulkanUniformBufferType uniformBufferType
|
VulkanUniformBufferType uniformBufferType
|
||||||
) {
|
) {
|
||||||
VulkanUniformBufferPool* uniformBufferPool = SDL_malloc(sizeof(VulkanUniformBufferPool));
|
VulkanUniformBufferPool* uniformBufferPool = SDL_malloc(sizeof(VulkanUniformBufferPool));
|
||||||
|
VulkanResourceAccessType resourceAccessType;
|
||||||
|
|
||||||
|
if (uniformBufferType == UNIFORM_BUFFER_VERTEX)
|
||||||
|
{
|
||||||
|
resourceAccessType = RESOURCE_ACCESS_VERTEX_SHADER_READ_UNIFORM_BUFFER;
|
||||||
|
}
|
||||||
|
else if (uniformBufferType == UNIFORM_BUFFER_FRAGMENT)
|
||||||
|
{
|
||||||
|
resourceAccessType = RESOURCE_ACCESS_FRAGMENT_SHADER_READ_UNIFORM_BUFFER;
|
||||||
|
}
|
||||||
|
else if (uniformBufferType == UNIFORM_BUFFER_COMPUTE)
|
||||||
|
{
|
||||||
|
resourceAccessType = RESOURCE_ACCESS_COMPUTE_SHADER_READ_UNIFORM_BUFFER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Refresh_LogError("Unrecognized uniform buffer type!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uniformBufferPool->buffer = VULKAN_INTERNAL_CreateBuffer(
|
||||||
|
renderer,
|
||||||
|
UBO_BUFFER_SIZE,
|
||||||
|
resourceAccessType,
|
||||||
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
uniformBufferPool->nextAvailableOffset = 0;
|
||||||
|
|
||||||
uniformBufferPool->type = uniformBufferType;
|
uniformBufferPool->type = uniformBufferType;
|
||||||
uniformBufferPool->lock = SDL_CreateMutex();
|
uniformBufferPool->lock = SDL_CreateMutex();
|
||||||
|
@ -4230,12 +4266,6 @@ static void VULKAN_INTERNAL_BindUniformBuffer(
|
||||||
|
|
||||||
commandBuffer->boundUniformBuffers[commandBuffer->boundUniformBufferCount] = uniformBuffer;
|
commandBuffer->boundUniformBuffers[commandBuffer->boundUniformBufferCount] = uniformBuffer;
|
||||||
commandBuffer->boundUniformBufferCount += 1;
|
commandBuffer->boundUniformBufferCount += 1;
|
||||||
|
|
||||||
VULKAN_INTERNAL_TrackBuffer(
|
|
||||||
renderer,
|
|
||||||
commandBuffer,
|
|
||||||
uniformBuffer->vulkanBufferContainer->vulkanBuffer
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Buffer indirection so we can cleanly defrag */
|
/* Buffer indirection so we can cleanly defrag */
|
||||||
|
@ -4304,22 +4334,18 @@ static uint8_t VULKAN_INTERNAL_CreateUniformBuffer(
|
||||||
|
|
||||||
VulkanUniformBuffer *uniformBuffer = SDL_malloc(sizeof(VulkanUniformBuffer));
|
VulkanUniformBuffer *uniformBuffer = SDL_malloc(sizeof(VulkanUniformBuffer));
|
||||||
uniformBuffer->pool = bufferPool;
|
uniformBuffer->pool = bufferPool;
|
||||||
uniformBuffer->vulkanBufferContainer = VULKAN_INTERNAL_CreateBufferContainer(
|
uniformBuffer->poolOffset = bufferPool->nextAvailableOffset;
|
||||||
renderer,
|
uniformBuffer->offset = 0;
|
||||||
UBO_BUFFER_SIZE,
|
|
||||||
resourceAccessType,
|
|
||||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
if (uniformBuffer->vulkanBufferContainer == NULL)
|
bufferPool->nextAvailableOffset += UBO_SECTION_SIZE;
|
||||||
|
|
||||||
|
if (bufferPool->nextAvailableOffset >= UBO_BUFFER_SIZE)
|
||||||
{
|
{
|
||||||
Refresh_LogError("Failed to create buffer for uniform buffer!");
|
Refresh_LogError("Uniform buffer overflow!");
|
||||||
|
SDL_free(uniformBuffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uniformBuffer->offset = 0;
|
|
||||||
|
|
||||||
/* Allocate a descriptor set for the uniform buffer */
|
/* Allocate a descriptor set for the uniform buffer */
|
||||||
|
|
||||||
if (bufferPool->descriptorPool.availableDescriptorSetCount == 0)
|
if (bufferPool->descriptorPool.availableDescriptorSetCount == 0)
|
||||||
|
@ -4329,6 +4355,7 @@ static uint8_t VULKAN_INTERNAL_CreateUniformBuffer(
|
||||||
&bufferPool->descriptorPool
|
&bufferPool->descriptorPool
|
||||||
)) {
|
)) {
|
||||||
Refresh_LogError("Failed to add uniform descriptor pool!");
|
Refresh_LogError("Failed to add uniform descriptor pool!");
|
||||||
|
SDL_free(uniformBuffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4393,15 +4420,7 @@ static VulkanUniformBuffer* VULKAN_INTERNAL_CreateDummyUniformBuffer(
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanUniformBuffer *uniformBuffer = SDL_malloc(sizeof(VulkanUniformBuffer));
|
VulkanUniformBuffer *uniformBuffer = SDL_malloc(sizeof(VulkanUniformBuffer));
|
||||||
uniformBuffer->pool = NULL;
|
uniformBuffer->poolOffset = 0;
|
||||||
uniformBuffer->vulkanBufferContainer = VULKAN_INTERNAL_CreateBufferContainer(
|
|
||||||
renderer,
|
|
||||||
1,
|
|
||||||
resourceAccessType,
|
|
||||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
|
|
||||||
uniformBuffer->offset = 0;
|
uniformBuffer->offset = 0;
|
||||||
|
|
||||||
/* Allocate a descriptor set for the uniform buffer */
|
/* Allocate a descriptor set for the uniform buffer */
|
||||||
|
@ -4416,7 +4435,7 @@ static VulkanUniformBuffer* VULKAN_INTERNAL_CreateDummyUniformBuffer(
|
||||||
|
|
||||||
/* Update the descriptor set for the first and last time! */
|
/* Update the descriptor set for the first and last time! */
|
||||||
|
|
||||||
descriptorBufferInfo.buffer = uniformBuffer->vulkanBufferContainer->vulkanBuffer->buffer;
|
descriptorBufferInfo.buffer = renderer->dummyBuffer->buffer;
|
||||||
descriptorBufferInfo.offset = 0;
|
descriptorBufferInfo.offset = 0;
|
||||||
descriptorBufferInfo.range = VK_WHOLE_SIZE;
|
descriptorBufferInfo.range = VK_WHOLE_SIZE;
|
||||||
|
|
||||||
|
@ -4463,11 +4482,11 @@ static void VULKAN_INTERNAL_DestroyUniformBufferPool(
|
||||||
/* This is always destroyed after submissions, so all buffers are available */
|
/* This is always destroyed after submissions, so all buffers are available */
|
||||||
for (i = 0; i < uniformBufferPool->availableBufferCount; i += 1)
|
for (i = 0; i < uniformBufferPool->availableBufferCount; i += 1)
|
||||||
{
|
{
|
||||||
VULKAN_INTERNAL_DestroyBuffer(renderer, uniformBufferPool->availableBuffers[i]->vulkanBufferContainer->vulkanBuffer);
|
|
||||||
SDL_free(uniformBufferPool->availableBuffers[i]->vulkanBufferContainer);
|
|
||||||
SDL_free(uniformBufferPool->availableBuffers[i]);
|
SDL_free(uniformBufferPool->availableBuffers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VULKAN_INTERNAL_DestroyBuffer(renderer, uniformBufferPool->buffer);
|
||||||
|
|
||||||
SDL_DestroyMutex(uniformBufferPool->lock);
|
SDL_DestroyMutex(uniformBufferPool->lock);
|
||||||
SDL_free(uniformBufferPool->availableBuffers);
|
SDL_free(uniformBufferPool->availableBuffers);
|
||||||
SDL_free(uniformBufferPool);
|
SDL_free(uniformBufferPool);
|
||||||
|
@ -4502,8 +4521,8 @@ static VulkanUniformBuffer* VULKAN_INTERNAL_AcquireUniformBufferFromPool(
|
||||||
|
|
||||||
/* Update the descriptor set with the correct range */
|
/* Update the descriptor set with the correct range */
|
||||||
|
|
||||||
descriptorBufferInfo.buffer = uniformBuffer->vulkanBufferContainer->vulkanBuffer->buffer;
|
descriptorBufferInfo.buffer = uniformBuffer->pool->buffer->buffer;
|
||||||
descriptorBufferInfo.offset = 0;
|
descriptorBufferInfo.offset = uniformBuffer->poolOffset;
|
||||||
descriptorBufferInfo.range = blockSize;
|
descriptorBufferInfo.range = blockSize;
|
||||||
|
|
||||||
writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
|
@ -5183,13 +5202,7 @@ static void VULKAN_DestroyDevice(
|
||||||
|
|
||||||
SDL_free(renderer->submittedCommandBuffers);
|
SDL_free(renderer->submittedCommandBuffers);
|
||||||
|
|
||||||
VULKAN_INTERNAL_DestroyBuffer(renderer, renderer->dummyVertexUniformBuffer->vulkanBufferContainer->vulkanBuffer);
|
VULKAN_INTERNAL_DestroyBuffer(renderer, renderer->dummyBuffer);
|
||||||
VULKAN_INTERNAL_DestroyBuffer(renderer, renderer->dummyFragmentUniformBuffer->vulkanBufferContainer->vulkanBuffer);
|
|
||||||
VULKAN_INTERNAL_DestroyBuffer(renderer, renderer->dummyComputeUniformBuffer->vulkanBufferContainer->vulkanBuffer);
|
|
||||||
|
|
||||||
SDL_free(renderer->dummyVertexUniformBuffer->vulkanBufferContainer);
|
|
||||||
SDL_free(renderer->dummyFragmentUniformBuffer->vulkanBufferContainer);
|
|
||||||
SDL_free(renderer->dummyComputeUniformBuffer->vulkanBufferContainer);
|
|
||||||
|
|
||||||
SDL_free(renderer->dummyVertexUniformBuffer);
|
SDL_free(renderer->dummyVertexUniformBuffer);
|
||||||
SDL_free(renderer->dummyFragmentUniformBuffer);
|
SDL_free(renderer->dummyFragmentUniformBuffer);
|
||||||
|
@ -7815,7 +7828,7 @@ static uint32_t VULKAN_PushVertexShaderUniforms(
|
||||||
if (
|
if (
|
||||||
vulkanCommandBuffer->vertexUniformBuffer->offset +
|
vulkanCommandBuffer->vertexUniformBuffer->offset +
|
||||||
graphicsPipeline->vertexUniformBlockSize >=
|
graphicsPipeline->vertexUniformBlockSize >=
|
||||||
UBO_BUFFER_SIZE
|
UBO_SECTION_SIZE
|
||||||
) {
|
) {
|
||||||
/* We're out of space in this buffer, bind the old one and acquire a new one */
|
/* We're out of space in this buffer, bind the old one and acquire a new one */
|
||||||
VULKAN_INTERNAL_BindUniformBuffer(
|
VULKAN_INTERNAL_BindUniformBuffer(
|
||||||
|
@ -7833,8 +7846,8 @@ static uint32_t VULKAN_PushVertexShaderUniforms(
|
||||||
offset = vulkanCommandBuffer->vertexUniformBuffer->offset;
|
offset = vulkanCommandBuffer->vertexUniformBuffer->offset;
|
||||||
|
|
||||||
VULKAN_INTERNAL_SetBufferData(
|
VULKAN_INTERNAL_SetBufferData(
|
||||||
vulkanCommandBuffer->vertexUniformBuffer->vulkanBufferContainer->vulkanBuffer,
|
vulkanCommandBuffer->vertexUniformBuffer->pool->buffer,
|
||||||
vulkanCommandBuffer->vertexUniformBuffer->offset,
|
vulkanCommandBuffer->vertexUniformBuffer->poolOffset + vulkanCommandBuffer->vertexUniformBuffer->offset,
|
||||||
data,
|
data,
|
||||||
dataLengthInBytes
|
dataLengthInBytes
|
||||||
);
|
);
|
||||||
|
@ -7859,7 +7872,7 @@ static uint32_t VULKAN_PushFragmentShaderUniforms(
|
||||||
if (
|
if (
|
||||||
vulkanCommandBuffer->fragmentUniformBuffer->offset +
|
vulkanCommandBuffer->fragmentUniformBuffer->offset +
|
||||||
graphicsPipeline->fragmentUniformBlockSize >=
|
graphicsPipeline->fragmentUniformBlockSize >=
|
||||||
UBO_BUFFER_SIZE
|
UBO_SECTION_SIZE
|
||||||
) {
|
) {
|
||||||
/* We're out of space in this buffer, bind the old one and acquire a new one */
|
/* We're out of space in this buffer, bind the old one and acquire a new one */
|
||||||
VULKAN_INTERNAL_BindUniformBuffer(
|
VULKAN_INTERNAL_BindUniformBuffer(
|
||||||
|
@ -7877,8 +7890,8 @@ static uint32_t VULKAN_PushFragmentShaderUniforms(
|
||||||
offset = vulkanCommandBuffer->fragmentUniformBuffer->offset;
|
offset = vulkanCommandBuffer->fragmentUniformBuffer->offset;
|
||||||
|
|
||||||
VULKAN_INTERNAL_SetBufferData(
|
VULKAN_INTERNAL_SetBufferData(
|
||||||
vulkanCommandBuffer->fragmentUniformBuffer->vulkanBufferContainer->vulkanBuffer,
|
vulkanCommandBuffer->fragmentUniformBuffer->pool->buffer,
|
||||||
vulkanCommandBuffer->fragmentUniformBuffer->offset,
|
vulkanCommandBuffer->fragmentUniformBuffer->poolOffset + vulkanCommandBuffer->fragmentUniformBuffer->offset,
|
||||||
data,
|
data,
|
||||||
dataLengthInBytes
|
dataLengthInBytes
|
||||||
);
|
);
|
||||||
|
@ -7902,7 +7915,7 @@ static uint32_t VULKAN_PushComputeShaderUniforms(
|
||||||
if (
|
if (
|
||||||
vulkanCommandBuffer->computeUniformBuffer->offset +
|
vulkanCommandBuffer->computeUniformBuffer->offset +
|
||||||
computePipeline->uniformBlockSize >=
|
computePipeline->uniformBlockSize >=
|
||||||
UBO_BUFFER_SIZE
|
UBO_SECTION_SIZE
|
||||||
) {
|
) {
|
||||||
/* We're out of space in this buffer, bind the old one and acquire a new one */
|
/* We're out of space in this buffer, bind the old one and acquire a new one */
|
||||||
VULKAN_INTERNAL_BindUniformBuffer(
|
VULKAN_INTERNAL_BindUniformBuffer(
|
||||||
|
@ -7920,8 +7933,8 @@ static uint32_t VULKAN_PushComputeShaderUniforms(
|
||||||
offset = vulkanCommandBuffer->computeUniformBuffer->offset;
|
offset = vulkanCommandBuffer->computeUniformBuffer->offset;
|
||||||
|
|
||||||
VULKAN_INTERNAL_SetBufferData(
|
VULKAN_INTERNAL_SetBufferData(
|
||||||
vulkanCommandBuffer->computeUniformBuffer->vulkanBufferContainer->vulkanBuffer,
|
vulkanCommandBuffer->computeUniformBuffer->pool->buffer,
|
||||||
vulkanCommandBuffer->computeUniformBuffer->offset,
|
vulkanCommandBuffer->computeUniformBuffer->poolOffset + vulkanCommandBuffer->computeUniformBuffer->offset,
|
||||||
data,
|
data,
|
||||||
dataLengthInBytes
|
dataLengthInBytes
|
||||||
);
|
);
|
||||||
|
@ -11992,6 +12005,15 @@ static Refresh_Device* VULKAN_CreateDevice(
|
||||||
|
|
||||||
/* Dummy Uniform Buffers */
|
/* Dummy Uniform Buffers */
|
||||||
|
|
||||||
|
renderer->dummyBuffer = VULKAN_INTERNAL_CreateBuffer(
|
||||||
|
renderer,
|
||||||
|
1,
|
||||||
|
RESOURCE_ACCESS_GENERAL,
|
||||||
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
renderer->dummyVertexUniformBuffer = VULKAN_INTERNAL_CreateDummyUniformBuffer(
|
renderer->dummyVertexUniformBuffer = VULKAN_INTERNAL_CreateDummyUniformBuffer(
|
||||||
renderer,
|
renderer,
|
||||||
UNIFORM_BUFFER_VERTEX
|
UNIFORM_BUFFER_VERTEX
|
||||||
|
|
Loading…
Reference in New Issue