diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 95913ff..cade7fa 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -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, - ¤tRegion->vulkanBuffer->bufferCreateInfo, - NULL, - ©Buffer - ); - 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, ©ResourceAccessType ); @@ -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, ©ResourceAccessType ); - if (renderer->defragmentedBuffersToDestroyCount >= renderer->defragmentedBuffersToDestroyCapacity) - { - renderer->defragmentedBuffersToDestroyCapacity *= 2; - renderer->defragmentedBuffersToDestroy = SDL_realloc( - renderer->defragmentedBuffersToDestroy, - sizeof(VkBuffer) * renderer->defragmentedBuffersToDestroyCapacity - ); - } + SDL_AtomicIncRef(&newBuffer->referenceCount); + SDL_AtomicIncRef(¤tRegion->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;