fixed-size transfer pool
continuous-integration/drone/push Build is passing Details

pull/41/head
cosmonaut 2023-05-16 18:20:43 -07:00
parent 45b71bd63d
commit 994f5dc0b9
1 changed files with 111 additions and 3 deletions

View File

@ -75,6 +75,7 @@ static uint32_t deviceExtensionCount = SDL_arraysize(deviceExtensionNames);
#define MAX_ALLOCATION_SIZE 256000000 /* 256MB */ #define MAX_ALLOCATION_SIZE 256000000 /* 256MB */
#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 UBO_BUFFER_SIZE 16000 /* 16KB */ #define UBO_BUFFER_SIZE 16000 /* 16KB */
#define DESCRIPTOR_POOL_STARTING_SIZE 128 #define DESCRIPTOR_POOL_STARTING_SIZE 128
#define WINDOW_DATA "Refresh_VulkanWindowData" #define WINDOW_DATA "Refresh_VulkanWindowData"
@ -1516,8 +1517,18 @@ typedef struct VulkanTransferBuffer
{ {
VulkanBuffer* buffer; VulkanBuffer* buffer;
VkDeviceSize offset; VkDeviceSize offset;
uint8_t fromPool;
} VulkanTransferBuffer; } VulkanTransferBuffer;
typedef struct VulkanTransferBufferPool
{
SDL_mutex *lock;
VulkanTransferBuffer **availableBuffers;
uint32_t availableBufferCount;
uint32_t availableBufferCapacity;
} VulkanTransferBufferPool;
typedef struct VulkanCommandPool VulkanCommandPool; typedef struct VulkanCommandPool VulkanCommandPool;
typedef struct VulkanCommandBuffer typedef struct VulkanCommandBuffer
@ -1723,6 +1734,8 @@ typedef struct VulkanRenderer
uint32_t submittedCommandBufferCount; uint32_t submittedCommandBufferCount;
uint32_t submittedCommandBufferCapacity; uint32_t submittedCommandBufferCapacity;
VulkanTransferBufferPool transferBufferPool;
CommandPoolHashTable commandPoolHashTable; CommandPoolHashTable commandPoolHashTable;
DescriptorSetLayoutHashTable descriptorSetLayoutHashTable; DescriptorSetLayoutHashTable descriptorSetLayoutHashTable;
GraphicsPipelineLayoutHashTable graphicsPipelineLayoutHashTable; GraphicsPipelineLayoutHashTable graphicsPipelineLayoutHashTable;
@ -5151,6 +5164,15 @@ static void VULKAN_DestroyDevice(
SDL_free(renderer->dummyFragmentUniformBuffer); SDL_free(renderer->dummyFragmentUniformBuffer);
SDL_free(renderer->dummyComputeUniformBuffer); SDL_free(renderer->dummyComputeUniformBuffer);
for (i = 0; i < renderer->transferBufferPool.availableBufferCount; i += 1)
{
VULKAN_INTERNAL_DestroyBuffer(renderer, renderer->transferBufferPool.availableBuffers[i]->buffer);
SDL_free(renderer->transferBufferPool.availableBuffers[i]);
}
SDL_free(renderer->transferBufferPool.availableBuffers);
SDL_DestroyMutex(renderer->transferBufferPool.lock);
for (i = 0; i < NUM_COMMAND_POOL_BUCKETS; i += 1) for (i = 0; i < NUM_COMMAND_POOL_BUCKETS; i += 1)
{ {
commandPoolHashArray = renderer->commandPoolHashTable.buckets[i]; commandPoolHashArray = renderer->commandPoolHashTable.buckets[i];
@ -7099,6 +7121,40 @@ static VulkanTransferBuffer* VULKAN_INTERNAL_AcquireTransferBuffer(
} }
} }
/* Nothing fits, can we get a transfer buffer from the pool? */
SDL_LockMutex(renderer->transferBufferPool.lock);
for (i = 0; i < renderer->transferBufferPool.availableBufferCount; i += 1)
{
transferBuffer = renderer->transferBufferPool.availableBuffers[i];
offset = transferBuffer->offset + alignment - (transferBuffer->offset % alignment);
if (offset + requiredSize <= transferBuffer->buffer->size)
{
if (commandBuffer->transferBufferCount == commandBuffer->transferBufferCapacity)
{
commandBuffer->transferBufferCapacity *= 2;
commandBuffer->transferBuffers = SDL_realloc(
commandBuffer->transferBuffers,
commandBuffer->transferBufferCapacity * sizeof(VulkanTransferBuffer*)
);
}
commandBuffer->transferBuffers[commandBuffer->transferBufferCount] = transferBuffer;
commandBuffer->transferBufferCount += 1;
renderer->transferBufferPool.availableBuffers[i] = renderer->transferBufferPool.availableBuffers[renderer->transferBufferPool.availableBufferCount - 1];
renderer->transferBufferPool.availableBufferCount -= 1;
SDL_UnlockMutex(renderer->transferBufferPool.lock);
transferBuffer->offset = offset;
return transferBuffer;
}
}
SDL_UnlockMutex(renderer->transferBufferPool.lock);
/* Nothing fits, so let's create a new transfer buffer */ /* Nothing fits, so let's create a new transfer buffer */
size = TRANSFER_BUFFER_STARTING_SIZE; size = TRANSFER_BUFFER_STARTING_SIZE;
@ -7118,10 +7174,12 @@ static VulkanTransferBuffer* VULKAN_INTERNAL_AcquireTransferBuffer(
1, 1,
1 1
); );
transferBuffer->fromPool = 0;
if (transferBuffer->buffer == NULL) if (transferBuffer->buffer == NULL)
{ {
Refresh_LogError("Failed to allocate transfer buffer!"); Refresh_LogError("Failed to allocate transfer buffer!");
SDL_free(transferBuffer);
return NULL; return NULL;
} }
@ -10040,9 +10098,22 @@ static void VULKAN_INTERNAL_CleanCommandBuffer(
for (i = 0; i < commandBuffer->transferBufferCount; i += 1) for (i = 0; i < commandBuffer->transferBufferCount; i += 1)
{ {
VULKAN_INTERNAL_QueueDestroyBuffer(renderer, commandBuffer->transferBuffers[i]->buffer); if (commandBuffer->transferBuffers[i]->fromPool)
SDL_free(commandBuffer->transferBuffers[i]); {
commandBuffer->transferBuffers[i] = NULL; SDL_LockMutex(renderer->transferBufferPool.lock);
commandBuffer->transferBuffers[i]->offset = 0;
renderer->transferBufferPool.availableBuffers[renderer->transferBufferPool.availableBufferCount] = commandBuffer->transferBuffers[i];
renderer->transferBufferPool.availableBufferCount += 1;
SDL_UnlockMutex(renderer->transferBufferPool.lock);
}
else
{
VULKAN_INTERNAL_QueueDestroyBuffer(renderer, commandBuffer->transferBuffers[i]->buffer);
SDL_free(commandBuffer->transferBuffers[i]);
commandBuffer->transferBuffers[i] = NULL;
}
} }
commandBuffer->transferBufferCount = 0; commandBuffer->transferBufferCount = 0;
@ -11392,6 +11463,9 @@ static Refresh_Device* VULKAN_CreateDevice(
/* Variables: Image Format Detection */ /* Variables: Image Format Detection */
VkImageFormatProperties imageFormatProperties; VkImageFormatProperties imageFormatProperties;
/* Variables: Transfer buffer init */
VulkanTransferBuffer *transferBuffer;
SDL_memset(renderer, '\0', sizeof(VulkanRenderer)); SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
renderer->debugMode = debugMode; renderer->debugMode = debugMode;
@ -11774,6 +11848,40 @@ static Refresh_Device* VULKAN_CreateDevice(
renderer->renderTargetHashArray.count = 0; renderer->renderTargetHashArray.count = 0;
renderer->renderTargetHashArray.capacity = 0; renderer->renderTargetHashArray.capacity = 0;
/* Initialize transfer buffer pool */
renderer->transferBufferPool.lock = SDL_CreateMutex();
renderer->transferBufferPool.availableBufferCapacity = 4;
renderer->transferBufferPool.availableBufferCount = 0;
renderer->transferBufferPool.availableBuffers = SDL_malloc(
renderer->transferBufferPool.availableBufferCapacity * sizeof(VulkanTransferBuffer*)
);
for (i = 0; i < renderer->transferBufferPool.availableBufferCapacity; i += 1)
{
transferBuffer = SDL_malloc(sizeof(VulkanTransferBuffer));
transferBuffer->offset = 0;
transferBuffer->fromPool = 1;
transferBuffer->buffer = VULKAN_INTERNAL_CreateBuffer(
renderer,
POOLED_TRANSFER_BUFFER_SIZE,
RESOURCE_ACCESS_TRANSFER_READ_WRITE,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1,
1
);
if (transferBuffer->buffer == NULL)
{
Refresh_LogError("Failed to allocate transfer buffer!");
SDL_free(transferBuffer);
}
renderer->transferBufferPool.availableBuffers[i] = transferBuffer;
renderer->transferBufferPool.availableBufferCount += 1;
}
/* Some drivers don't support D16, so we have to fall back to D32. */ /* Some drivers don't support D16, so we have to fall back to D32. */
vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties( vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties(