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 */
struct VulkanBuffer /* cast from Refresh_Buffer */
typedef struct VulkanBufferContainer /* cast from Refresh_Buffer */
{
VulkanBuffer *vulkanBuffer;
} VulkanBufferContainer;
struct VulkanBuffer
{
VkBuffer buffer;
VkDeviceSize size;
@ -698,6 +703,8 @@ struct VulkanBuffer /* cast from Refresh_Buffer */
VkBufferUsageFlags usage;
SDL_atomic_t referenceCount; /* Tracks command buffer usage */
VulkanBufferContainer *container;
};
typedef struct VulkanUniformBufferPool VulkanUniformBufferPool;
@ -1752,6 +1759,10 @@ typedef struct VulkanRenderer
uint32_t buffersToDestroyCount;
uint32_t buffersToDestroyCapacity;
VulkanBufferContainer **bufferContainersToDestroy;
uint32_t bufferContainersToDestroyCount;
uint32_t bufferContainersToDestroyCapacity;
VulkanSampler **samplersToDestroy;
uint32_t samplersToDestroyCount;
uint32_t samplersToDestroyCapacity;
@ -3086,8 +3097,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
VulkanMemoryAllocation *allocation;
uint32_t allocationIndexToDefrag;
VulkanMemoryUsedRegion *currentRegion;
VulkanMemoryUsedRegion *newRegion;
VkBuffer copyBuffer;
VulkanBuffer* newBuffer;
VkBufferCopy bufferCopy;
VkImage copyImage;
VkImageCopy *imageCopyRegions;
@ -3101,7 +3111,6 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
VulkanResourceAccessType copyResourceAccessType = RESOURCE_ACCESS_NONE;
VulkanResourceAccessType originalResourceAccessType;
SDL_LockMutex(renderer->commandLock);
SDL_LockMutex(renderer->allocatorLock);
renderer->needDefrag = 0;
@ -3125,6 +3134,10 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
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)
{
currentRegion = allocation->usedRegions[i];
@ -3132,40 +3145,20 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
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,
currentRegion->vulkanBuffer->bufferCreateInfo.size,
currentRegion->vulkanBuffer->size,
RESOURCE_ACCESS_NONE,
currentRegion->vulkanBuffer->bufferCreateInfo.usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT
currentRegion->vulkanBuffer->usage
);
result = renderer->vkCreateBuffer(
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)
if (newBuffer == NULL)
{
/* Out of memory, abort */
renderer->vkDestroyBuffer(
renderer->logicalDevice,
copyBuffer,
NULL
);
break;
Refresh_LogError("Failed to create defrag buffer!");
return 0;
}
originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType;
@ -3180,7 +3173,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
RESOURCE_ACCESS_TRANSFER_WRITE,
copyBuffer,
newBuffer,
&copyResourceAccessType
);
@ -3191,7 +3184,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
renderer->vkCmdCopyBuffer(
commandBuffer->commandBuffer,
currentRegion->vulkanBuffer->buffer,
copyBuffer,
newBuffer->buffer,
1,
&bufferCopy
);
@ -3199,45 +3192,18 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
VULKAN_INTERNAL_BufferMemoryBarrier(
renderer,
originalResourceAccessType,
copyBuffer,
newBuffer,
&copyResourceAccessType
);
if (renderer->defragmentedBuffersToDestroyCount >= renderer->defragmentedBuffersToDestroyCapacity)
{
renderer->defragmentedBuffersToDestroyCapacity *= 2;
renderer->defragmentedBuffersToDestroy = SDL_realloc(
renderer->defragmentedBuffersToDestroy,
sizeof(VkBuffer) * renderer->defragmentedBuffersToDestroyCapacity
);
}
SDL_AtomicIncRef(&newBuffer->referenceCount);
SDL_AtomicIncRef(&currentRegion->vulkanBuffer->referenceCount);
if (renderer->usedRegionsToDestroyCount >= renderer->usedRegionsToDestroyCapacity)
{
renderer->usedRegionsToDestroyCapacity *= 2;
renderer->usedRegionsToDestroy = SDL_realloc(
renderer->usedRegionsToDestroy,
sizeof(VulkanMemoryUsedRegion*) * renderer->usedRegionsToDestroyCapacity
);
}
/* re-point original container to new buffer */
newBuffer->container = currentRegion->vulkanBuffer->container;
newBuffer->container->vulkanBuffer = newBuffer;
renderer->defragmentedBuffersToDestroy[
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;
VULKAN_INTERNAL_QueueDestroyBuffer(renderer, currentRegion->vulkanBuffer);
renderer->needDefrag = 1;
}
@ -3461,7 +3427,6 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
renderer->defragTimer = 0;
SDL_UnlockMutex(renderer->commandLock);
SDL_UnlockMutex(renderer->allocatorLock);
return 1;
@ -5825,7 +5790,7 @@ static void VULKAN_DrawPrimitivesIndirect(
) {
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer;
VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer;
VkDescriptorSet descriptorSets[4];
uint32_t dynamicOffsets[2];
@ -7344,6 +7309,7 @@ static Refresh_Buffer* VULKAN_CreateBuffer(
Refresh_BufferUsageFlags usageFlags,
uint32_t sizeInBytes
) {
VulkanBufferContainer* bufferContainer;
VulkanBuffer* buffer;
VulkanResourceAccessType resourceAccessType;
VkBufferUsageFlags vulkanUsageFlags =
@ -7391,6 +7357,11 @@ static Refresh_Buffer* VULKAN_CreateBuffer(
return NULL;
}
bufferContainer = SDL_malloc(sizeof(VulkanBufferContainer*));
bufferContainer->vulkanBuffer = buffer;
buffer->container = bufferContainer;
return (Refresh_Buffer*) buffer;
}
@ -7964,7 +7935,7 @@ static void VULKAN_SetBufferData(
) {
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer* vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBuffer* vulkanBuffer = (VulkanBuffer*) buffer;
VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer;
VulkanTransferBuffer* transferBuffer;
uint8_t* transferBufferPointer;
VkBufferCopy bufferCopy;
@ -7983,8 +7954,8 @@ static void VULKAN_SetBufferData(
}
transferBufferPointer =
transferBuffer->buffer->allocation->mapPointer +
transferBuffer->buffer->offset +
transferBuffer->buffer->usedRegion->allocation->mapPointer +
transferBuffer->buffer->usedRegion->resourceOffset +
transferBuffer->offset;
SDL_memcpy(
@ -8392,13 +8363,13 @@ static void VULKAN_GetBufferData(
void *data,
uint32_t dataLengthInBytes
) {
VulkanBuffer* vulkanBuffer = (VulkanBuffer*) buffer;
VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer;
uint8_t *dataPtr = (uint8_t*) data;
uint8_t *mapPointer;
mapPointer =
vulkanBuffer->allocation->mapPointer +
vulkanBuffer->offset;
vulkanBuffer->usedRegion->allocation->mapPointer +
vulkanBuffer->usedRegion->resourceOffset;
SDL_memcpy(
dataPtr,
@ -8416,7 +8387,7 @@ static void VULKAN_CopyTextureToBuffer(
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanTexture *vulkanTexture = (VulkanTexture*) textureSlice->texture;
VulkanBuffer* vulkanBuffer = (VulkanBuffer*) buffer;
VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer;
VulkanResourceAccessType prevResourceAccess;
VkBufferImageCopy imageCopy;
@ -8529,13 +8500,10 @@ static void VULKAN_QueueDestroySampler(
SDL_UnlockMutex(renderer->disposeLock);
}
static void VULKAN_QueueDestroyBuffer(
Refresh_Renderer *driverData,
Refresh_Buffer *buffer
static void VULKAN_INTERNAL_QueueDestroyBuffer(
VulkanRenderer *renderer,
VulkanBuffer *vulkanBuffer
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer;
SDL_LockMutex(renderer->disposeLock);
EXPAND_ARRAY_IF_NEEDED(
@ -8554,6 +8522,34 @@ static void VULKAN_QueueDestroyBuffer(
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(
Refresh_Renderer *driverData,
Refresh_ShaderModule *shaderModule
@ -9392,7 +9388,7 @@ static void VULKAN_BindVertexBuffers(
for (i = 0; i < bindingCount; i += 1)
{
currentVulkanBuffer = (VulkanBuffer*) pBuffers[i];
currentVulkanBuffer = ((VulkanBufferContainer*) pBuffers[i])->vulkanBuffer;
buffers[i] = currentVulkanBuffer->buffer;
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer);
}
@ -9417,7 +9413,7 @@ static void VULKAN_BindIndexBuffer(
) {
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBuffer* vulkanBuffer = (VulkanBuffer*) buffer;
VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->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)
{
currentVulkanBuffer = (VulkanBuffer*) pBuffers[i];
currentVulkanBuffer = ((VulkanBufferContainer*) pBuffers[i])->vulkanBuffer;
descriptorBufferInfos[i].buffer = currentVulkanBuffer->buffer;
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)
{
if (SDL_AtomicGet(&renderer->buffersToDestroy[i]->referenceCount) == 0)
{
VULKAN_INTERNAL_DestroyBuffer(
renderer,
renderer->buffersToDestroy[i]
);
renderer->buffersToDestroy[i]);
renderer->buffersToDestroy[i] = renderer->buffersToDestroy[renderer->buffersToDestroyCount - 1];
renderer->buffersToDestroyCount -= 1;
@ -11009,9 +11011,6 @@ static uint8_t VULKAN_INTERNAL_IsDeviceSuitable(
static void VULKAN_INTERNAL_GetPhysicalDeviceProperties(
VulkanRenderer *renderer
) {
VkDeviceSize deviceLocalHeapSize;
int32_t i;
renderer->physicalDeviceDriverProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
renderer->physicalDeviceDriverProperties.pNext = NULL;
@ -11030,21 +11029,6 @@ static void VULKAN_INTERNAL_GetPhysicalDeviceProperties(
renderer->physicalDevice,
&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(
@ -11861,6 +11845,14 @@ static Refresh_Device* VULKAN_CreateDevice(
renderer->buffersToDestroyCapacity
);
renderer->bufferContainersToDestroyCapacity = 16;
renderer->bufferContainersToDestroyCount = 0;
renderer->bufferContainersToDestroy = SDL_malloc(
sizeof(VulkanBufferContainer *) *
renderer->bufferContainersToDestroyCapacity
);
renderer->samplersToDestroyCapacity = 16;
renderer->samplersToDestroyCount = 0;