implement buffer defrag
continuous-integration/drone/push Build is failing Details

pull/41/head
cosmonaut 2023-05-15 11:34:57 -07:00
parent 746ad10c7b
commit 19ebe7284d
1 changed files with 98 additions and 106 deletions

View File

@ -689,7 +689,12 @@ static const VulkanResourceAccessInfo AccessMap[RESOURCE_ACCESS_TYPES_COUNT] =
/* Memory structures */ /* Memory structures */
struct VulkanBuffer /* cast from Refresh_Buffer */ typedef struct VulkanBufferContainer /* cast from Refresh_Buffer */
{
VulkanBuffer *vulkanBuffer;
} VulkanBufferContainer;
struct VulkanBuffer
{ {
VkBuffer buffer; VkBuffer buffer;
VkDeviceSize size; VkDeviceSize size;
@ -698,6 +703,8 @@ struct VulkanBuffer /* cast from Refresh_Buffer */
VkBufferUsageFlags usage; VkBufferUsageFlags usage;
SDL_atomic_t referenceCount; /* Tracks command buffer usage */ SDL_atomic_t referenceCount; /* Tracks command buffer usage */
VulkanBufferContainer *container;
}; };
typedef struct VulkanUniformBufferPool VulkanUniformBufferPool; typedef struct VulkanUniformBufferPool VulkanUniformBufferPool;
@ -1752,6 +1759,10 @@ typedef struct VulkanRenderer
uint32_t buffersToDestroyCount; uint32_t buffersToDestroyCount;
uint32_t buffersToDestroyCapacity; uint32_t buffersToDestroyCapacity;
VulkanBufferContainer **bufferContainersToDestroy;
uint32_t bufferContainersToDestroyCount;
uint32_t bufferContainersToDestroyCapacity;
VulkanSampler **samplersToDestroy; VulkanSampler **samplersToDestroy;
uint32_t samplersToDestroyCount; uint32_t samplersToDestroyCount;
uint32_t samplersToDestroyCapacity; uint32_t samplersToDestroyCapacity;
@ -3086,8 +3097,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
VulkanMemoryAllocation *allocation; VulkanMemoryAllocation *allocation;
uint32_t allocationIndexToDefrag; uint32_t allocationIndexToDefrag;
VulkanMemoryUsedRegion *currentRegion; VulkanMemoryUsedRegion *currentRegion;
VulkanMemoryUsedRegion *newRegion; VulkanBuffer* newBuffer;
VkBuffer copyBuffer;
VkBufferCopy bufferCopy; VkBufferCopy bufferCopy;
VkImage copyImage; VkImage copyImage;
VkImageCopy *imageCopyRegions; VkImageCopy *imageCopyRegions;
@ -3101,7 +3111,6 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
VulkanResourceAccessType copyResourceAccessType = RESOURCE_ACCESS_NONE; VulkanResourceAccessType copyResourceAccessType = RESOURCE_ACCESS_NONE;
VulkanResourceAccessType originalResourceAccessType; VulkanResourceAccessType originalResourceAccessType;
SDL_LockMutex(renderer->commandLock);
SDL_LockMutex(renderer->allocatorLock); SDL_LockMutex(renderer->allocatorLock);
renderer->needDefrag = 0; renderer->needDefrag = 0;
@ -3125,6 +3134,10 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
allocation allocation
); );
/* For each used region in the allocation
* create a new resource, copy the data
* and re-point the resource containers
*/
for (i = 0; i < allocation->usedRegionCount; i += 1) for (i = 0; i < allocation->usedRegionCount; i += 1)
{ {
currentRegion = allocation->usedRegions[i]; currentRegion = allocation->usedRegions[i];
@ -3132,40 +3145,20 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
if (currentRegion->isBuffer) if (currentRegion->isBuffer)
{ {
currentRegion->vulkanBuffer->bufferCreateInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
copyBuffer = VULKAN_INTERNAL_CreateBuffer( // TODO: modify this stuff to change the buffer pointers around
newBuffer = VULKAN_INTERNAL_CreateBuffer(
renderer, renderer,
currentRegion->vulkanBuffer->bufferCreateInfo.size, currentRegion->vulkanBuffer->size,
RESOURCE_ACCESS_NONE, RESOURCE_ACCESS_NONE,
currentRegion->vulkanBuffer->bufferCreateInfo.usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT currentRegion->vulkanBuffer->usage
); );
result = renderer->vkCreateBuffer( if (newBuffer == NULL)
renderer->logicalDevice,
&currentRegion->vulkanBuffer->bufferCreateInfo,
NULL,
&copyBuffer
);
VULKAN_ERROR_CHECK(result, vkCreateBuffer, 0)
if (
VULKAN_INTERNAL_BindMemoryForBuffer(
renderer,
copyBuffer,
currentRegion->resourceSize,
currentRegion->vulkanBuffer->preferDeviceLocal,
0,
&newRegion
) != 1)
{ {
/* Out of memory, abort */ Refresh_LogError("Failed to create defrag buffer!");
renderer->vkDestroyBuffer( return 0;
renderer->logicalDevice,
copyBuffer,
NULL
);
break;
} }
originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType; originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType;
@ -3180,7 +3173,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
VULKAN_INTERNAL_BufferMemoryBarrier( VULKAN_INTERNAL_BufferMemoryBarrier(
renderer, renderer,
RESOURCE_ACCESS_TRANSFER_WRITE, RESOURCE_ACCESS_TRANSFER_WRITE,
copyBuffer, newBuffer,
&copyResourceAccessType &copyResourceAccessType
); );
@ -3191,7 +3184,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
renderer->vkCmdCopyBuffer( renderer->vkCmdCopyBuffer(
commandBuffer->commandBuffer, commandBuffer->commandBuffer,
currentRegion->vulkanBuffer->buffer, currentRegion->vulkanBuffer->buffer,
copyBuffer, newBuffer->buffer,
1, 1,
&bufferCopy &bufferCopy
); );
@ -3199,45 +3192,18 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
VULKAN_INTERNAL_BufferMemoryBarrier( VULKAN_INTERNAL_BufferMemoryBarrier(
renderer, renderer,
originalResourceAccessType, originalResourceAccessType,
copyBuffer, newBuffer,
&copyResourceAccessType &copyResourceAccessType
); );
if (renderer->defragmentedBuffersToDestroyCount >= renderer->defragmentedBuffersToDestroyCapacity) SDL_AtomicIncRef(&newBuffer->referenceCount);
{ SDL_AtomicIncRef(&currentRegion->vulkanBuffer->referenceCount);
renderer->defragmentedBuffersToDestroyCapacity *= 2;
renderer->defragmentedBuffersToDestroy = SDL_realloc(
renderer->defragmentedBuffersToDestroy,
sizeof(VkBuffer) * renderer->defragmentedBuffersToDestroyCapacity
);
}
if (renderer->usedRegionsToDestroyCount >= renderer->usedRegionsToDestroyCapacity) /* re-point original container to new buffer */
{ newBuffer->container = currentRegion->vulkanBuffer->container;
renderer->usedRegionsToDestroyCapacity *= 2; newBuffer->container->vulkanBuffer = newBuffer;
renderer->usedRegionsToDestroy = SDL_realloc(
renderer->usedRegionsToDestroy,
sizeof(VulkanMemoryUsedRegion*) * renderer->usedRegionsToDestroyCapacity
);
}
renderer->defragmentedBuffersToDestroy[ VULKAN_INTERNAL_QueueDestroyBuffer(renderer, currentRegion->vulkanBuffer);
renderer->defragmentedBuffersToDestroyCount
] = currentRegion->vulkanBuffer->buffer;
renderer->defragmentedBuffersToDestroyCount += 1;
renderer->usedRegionsToDestroy[
renderer->usedRegionsToDestroyCount
] = currentRegion;
renderer->usedRegionsToDestroyCount += 1;
newRegion->isBuffer = 1;
newRegion->vulkanBuffer = currentRegion->vulkanBuffer;
newRegion->vulkanBuffer->usedRegion = newRegion; /* lol */
newRegion->vulkanBuffer->buffer = copyBuffer;
newRegion->vulkanBuffer->resourceAccessType = copyResourceAccessType;
renderer->needDefrag = 1; renderer->needDefrag = 1;
} }
@ -3461,7 +3427,6 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
renderer->defragTimer = 0; renderer->defragTimer = 0;
SDL_UnlockMutex(renderer->commandLock);
SDL_UnlockMutex(renderer->allocatorLock); SDL_UnlockMutex(renderer->allocatorLock);
return 1; return 1;
@ -5825,7 +5790,7 @@ static void VULKAN_DrawPrimitivesIndirect(
) { ) {
VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanRenderer* renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer; VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer;
VkDescriptorSet descriptorSets[4]; VkDescriptorSet descriptorSets[4];
uint32_t dynamicOffsets[2]; uint32_t dynamicOffsets[2];
@ -7344,6 +7309,7 @@ static Refresh_Buffer* VULKAN_CreateBuffer(
Refresh_BufferUsageFlags usageFlags, Refresh_BufferUsageFlags usageFlags,
uint32_t sizeInBytes uint32_t sizeInBytes
) { ) {
VulkanBufferContainer* bufferContainer;
VulkanBuffer* buffer; VulkanBuffer* buffer;
VulkanResourceAccessType resourceAccessType; VulkanResourceAccessType resourceAccessType;
VkBufferUsageFlags vulkanUsageFlags = VkBufferUsageFlags vulkanUsageFlags =
@ -7391,6 +7357,11 @@ static Refresh_Buffer* VULKAN_CreateBuffer(
return NULL; return NULL;
} }
bufferContainer = SDL_malloc(sizeof(VulkanBufferContainer*));
bufferContainer->vulkanBuffer = buffer;
buffer->container = bufferContainer;
return (Refresh_Buffer*) buffer; return (Refresh_Buffer*) buffer;
} }
@ -7964,7 +7935,7 @@ static void VULKAN_SetBufferData(
) { ) {
VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanRenderer* renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer* vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanCommandBuffer* vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBuffer* vulkanBuffer = (VulkanBuffer*) buffer; VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer;
VulkanTransferBuffer* transferBuffer; VulkanTransferBuffer* transferBuffer;
uint8_t* transferBufferPointer; uint8_t* transferBufferPointer;
VkBufferCopy bufferCopy; VkBufferCopy bufferCopy;
@ -7983,8 +7954,8 @@ static void VULKAN_SetBufferData(
} }
transferBufferPointer = transferBufferPointer =
transferBuffer->buffer->allocation->mapPointer + transferBuffer->buffer->usedRegion->allocation->mapPointer +
transferBuffer->buffer->offset + transferBuffer->buffer->usedRegion->resourceOffset +
transferBuffer->offset; transferBuffer->offset;
SDL_memcpy( SDL_memcpy(
@ -8392,13 +8363,13 @@ static void VULKAN_GetBufferData(
void *data, void *data,
uint32_t dataLengthInBytes uint32_t dataLengthInBytes
) { ) {
VulkanBuffer* vulkanBuffer = (VulkanBuffer*) buffer; VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer;
uint8_t *dataPtr = (uint8_t*) data; uint8_t *dataPtr = (uint8_t*) data;
uint8_t *mapPointer; uint8_t *mapPointer;
mapPointer = mapPointer =
vulkanBuffer->allocation->mapPointer + vulkanBuffer->usedRegion->allocation->mapPointer +
vulkanBuffer->offset; vulkanBuffer->usedRegion->resourceOffset;
SDL_memcpy( SDL_memcpy(
dataPtr, dataPtr,
@ -8416,7 +8387,7 @@ static void VULKAN_CopyTextureToBuffer(
VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanTexture *vulkanTexture = (VulkanTexture*) textureSlice->texture; VulkanTexture *vulkanTexture = (VulkanTexture*) textureSlice->texture;
VulkanBuffer* vulkanBuffer = (VulkanBuffer*) buffer; VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer;
VulkanResourceAccessType prevResourceAccess; VulkanResourceAccessType prevResourceAccess;
VkBufferImageCopy imageCopy; VkBufferImageCopy imageCopy;
@ -8529,13 +8500,10 @@ static void VULKAN_QueueDestroySampler(
SDL_UnlockMutex(renderer->disposeLock); SDL_UnlockMutex(renderer->disposeLock);
} }
static void VULKAN_QueueDestroyBuffer( static void VULKAN_INTERNAL_QueueDestroyBuffer(
Refresh_Renderer *driverData, VulkanRenderer *renderer,
Refresh_Buffer *buffer VulkanBuffer *vulkanBuffer
) { ) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer;
SDL_LockMutex(renderer->disposeLock); SDL_LockMutex(renderer->disposeLock);
EXPAND_ARRAY_IF_NEEDED( EXPAND_ARRAY_IF_NEEDED(
@ -8554,6 +8522,34 @@ static void VULKAN_QueueDestroyBuffer(
SDL_UnlockMutex(renderer->disposeLock); SDL_UnlockMutex(renderer->disposeLock);
} }
static void VULKAN_QueueDestroyBuffer(
Refresh_Renderer *driverData,
Refresh_Buffer *buffer
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanBufferContainer *vulkanBufferContainer = (VulkanBufferContainer*) buffer;
VulkanBuffer *vulkanBuffer = vulkanBufferContainer->vulkanBuffer;
SDL_LockMutex(renderer->disposeLock);
VULKAN_INTERNAL_QueueDestroyBuffer(renderer, vulkanBuffer);
EXPAND_ARRAY_IF_NEEDED(
renderer->bufferContainersToDestroy,
VulkanBufferContainer *,
renderer->bufferContainersToDestroyCount + 1,
renderer->bufferContainersToDestroyCapacity,
renderer->bufferContainersToDestroyCapacity * 2
)
renderer->bufferContainersToDestroy[
renderer->bufferContainersToDestroyCount
] = vulkanBufferContainer;
renderer->bufferContainersToDestroyCount += 1;
SDL_UnlockMutex(renderer->disposeLock);
}
static void VULKAN_QueueDestroyShaderModule( static void VULKAN_QueueDestroyShaderModule(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
Refresh_ShaderModule *shaderModule Refresh_ShaderModule *shaderModule
@ -9392,7 +9388,7 @@ static void VULKAN_BindVertexBuffers(
for (i = 0; i < bindingCount; i += 1) for (i = 0; i < bindingCount; i += 1)
{ {
currentVulkanBuffer = (VulkanBuffer*) pBuffers[i]; currentVulkanBuffer = ((VulkanBufferContainer*) pBuffers[i])->vulkanBuffer;
buffers[i] = currentVulkanBuffer->buffer; buffers[i] = currentVulkanBuffer->buffer;
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer);
} }
@ -9417,7 +9413,7 @@ static void VULKAN_BindIndexBuffer(
) { ) {
VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanRenderer* renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBuffer* vulkanBuffer = (VulkanBuffer*) buffer; VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer;
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer);
@ -9501,7 +9497,7 @@ static void VULKAN_BindComputeBuffers(
for (i = 0; i < computePipeline->pipelineLayout->bufferDescriptorSetCache->bindingCount; i += 1) for (i = 0; i < computePipeline->pipelineLayout->bufferDescriptorSetCache->bindingCount; i += 1)
{ {
currentVulkanBuffer = (VulkanBuffer*) pBuffers[i]; currentVulkanBuffer = ((VulkanBufferContainer*) pBuffers[i])->vulkanBuffer;
descriptorBufferInfos[i].buffer = currentVulkanBuffer->buffer; descriptorBufferInfos[i].buffer = currentVulkanBuffer->buffer;
descriptorBufferInfos[i].offset = 0; descriptorBufferInfos[i].offset = 0;
@ -10217,14 +10213,20 @@ static void VULKAN_INTERNAL_PerformPendingDestroys(
} }
} }
/* containers are not vulkan resources, so no need for ref counting */
for (i = renderer->bufferContainersToDestroyCount - 1; i >= 0; i -= 1)
{
SDL_free(renderer->bufferContainersToDestroy[i]);
renderer->bufferContainersToDestroyCount -= 1;
}
for (i = renderer->buffersToDestroyCount - 1; i >= 0; i -= 1) for (i = renderer->buffersToDestroyCount - 1; i >= 0; i -= 1)
{ {
if (SDL_AtomicGet(&renderer->buffersToDestroy[i]->referenceCount) == 0) if (SDL_AtomicGet(&renderer->buffersToDestroy[i]->referenceCount) == 0)
{ {
VULKAN_INTERNAL_DestroyBuffer( VULKAN_INTERNAL_DestroyBuffer(
renderer, renderer,
renderer->buffersToDestroy[i] renderer->buffersToDestroy[i]);
);
renderer->buffersToDestroy[i] = renderer->buffersToDestroy[renderer->buffersToDestroyCount - 1]; renderer->buffersToDestroy[i] = renderer->buffersToDestroy[renderer->buffersToDestroyCount - 1];
renderer->buffersToDestroyCount -= 1; renderer->buffersToDestroyCount -= 1;
@ -11009,9 +11011,6 @@ static uint8_t VULKAN_INTERNAL_IsDeviceSuitable(
static void VULKAN_INTERNAL_GetPhysicalDeviceProperties( static void VULKAN_INTERNAL_GetPhysicalDeviceProperties(
VulkanRenderer *renderer VulkanRenderer *renderer
) { ) {
VkDeviceSize deviceLocalHeapSize;
int32_t i;
renderer->physicalDeviceDriverProperties.sType = renderer->physicalDeviceDriverProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR; VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
renderer->physicalDeviceDriverProperties.pNext = NULL; renderer->physicalDeviceDriverProperties.pNext = NULL;
@ -11030,21 +11029,6 @@ static void VULKAN_INTERNAL_GetPhysicalDeviceProperties(
renderer->physicalDevice, renderer->physicalDevice,
&renderer->memoryProperties &renderer->memoryProperties
); );
deviceLocalHeapSize = 0;
for (i = 0; i < renderer->memoryProperties.memoryHeapCount; i += 1)
{
if ( renderer->memoryProperties.memoryHeaps[i].flags &
VK_MEMORY_HEAP_DEVICE_LOCAL_BIT )
{
if (renderer->memoryProperties.memoryHeaps[i].size > deviceLocalHeapSize)
{
deviceLocalHeapSize = renderer->memoryProperties.memoryHeaps[i].size;
}
}
}
renderer->maxDeviceLocalHeapUsage = deviceLocalHeapSize;
} }
static uint8_t VULKAN_INTERNAL_DeterminePhysicalDevice( static uint8_t VULKAN_INTERNAL_DeterminePhysicalDevice(
@ -11861,6 +11845,14 @@ static Refresh_Device* VULKAN_CreateDevice(
renderer->buffersToDestroyCapacity renderer->buffersToDestroyCapacity
); );
renderer->bufferContainersToDestroyCapacity = 16;
renderer->bufferContainersToDestroyCount = 0;
renderer->bufferContainersToDestroy = SDL_malloc(
sizeof(VulkanBufferContainer *) *
renderer->bufferContainersToDestroyCapacity
);
renderer->samplersToDestroyCapacity = 16; renderer->samplersToDestroyCapacity = 16;
renderer->samplersToDestroyCount = 0; renderer->samplersToDestroyCount = 0;