From 74112396ec529bcbeb5e25ee39d3d45bd351fd40 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Mon, 15 May 2023 16:39:02 -0700 Subject: [PATCH] implement texture container and defrag --- src/Refresh_Driver_Vulkan.c | 823 +++++++++++++--------------- src/Refresh_Driver_Vulkan_vkfuncs.h | 1 + 2 files changed, 383 insertions(+), 441 deletions(-) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index cade7fa..f92b2a2 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -702,6 +702,9 @@ struct VulkanBuffer VulkanResourceAccessType resourceAccessType; VkBufferUsageFlags usage; + uint8_t preferDeviceLocal; + uint8_t isTransferBuffer; + SDL_atomic_t referenceCount; /* Tracks command buffer usage */ VulkanBufferContainer *container; @@ -772,6 +775,11 @@ typedef struct VulkanShaderModule SDL_atomic_t referenceCount; } VulkanShaderModule; +typedef struct VulkanTextureContainer /* Cast from Refresh_Texture */ +{ + VulkanTexture *vulkanTexture; +} VulkanTextureContainer; + struct VulkanTexture { VulkanMemoryUsedRegion *usedRegion; @@ -796,6 +804,8 @@ struct VulkanTexture struct VulkanTexture *msaaTex; SDL_atomic_t referenceCount; + + VulkanTextureContainer *container; }; typedef struct VulkanRenderTarget @@ -1759,10 +1769,6 @@ 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; @@ -1804,6 +1810,7 @@ typedef struct VulkanRenderer /* Forward declarations */ +static uint8_t VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer); static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer); static void VULKAN_UnclaimWindow(Refresh_Renderer *driverData, void *windowHandle); static void VULKAN_Wait(Refresh_Renderer *driverData); @@ -1869,7 +1876,7 @@ static inline void LogVulkanResultAsWarn( #define VULKAN_ERROR_CHECK(res, fn, ret) \ if (res != VK_SUCCESS) \ { \ - FNA3D_LogError("%s %s", #fn, VkErrorMessages(res)); \ + Refresh_LogError("%s %s", #fn, VkErrorMessages(res)); \ return ret; \ } @@ -2346,6 +2353,35 @@ static void VULKAN_INTERNAL_RemoveMemoryUsedRegion( SDL_UnlockMutex(renderer->allocatorLock); } +static uint8_t VULKAN_INTERNAL_FindMemoryType( + VulkanRenderer *renderer, + uint32_t typeFilter, + VkMemoryPropertyFlags requiredProperties, + VkMemoryPropertyFlags ignoredProperties, + uint32_t *memoryTypeIndex +) { + uint32_t i; + + for (i = *memoryTypeIndex; i < renderer->memoryProperties.memoryTypeCount; i += 1) + { + if ( (typeFilter & (1 << i)) && + (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties && + (renderer->memoryProperties.memoryTypes[i].propertyFlags & ignoredProperties) == 0 ) + { + *memoryTypeIndex = i; + return 1; + } + } + + Refresh_LogWarn( + "Failed to find memory type %X, required %X, ignored %X", + typeFilter, + requiredProperties, + ignoredProperties + ); + return 0; +} + static uint8_t VULKAN_INTERNAL_FindBufferMemoryRequirements( VulkanRenderer *renderer, VkBuffer buffer, @@ -2536,7 +2572,7 @@ static uint8_t VULKAN_INTERNAL_AllocateMemory( SDL_free(allocation); - FNA3D_LogWarn("vkAllocateMemory: %s", VkErrorMessages(result)); + Refresh_LogWarn("vkAllocateMemory: %s", VkErrorMessages(result)); return 0; } @@ -2656,7 +2692,7 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( if ( (buffer == VK_NULL_HANDLE && image == VK_NULL_HANDLE) || (buffer != VK_NULL_HANDLE && image != VK_NULL_HANDLE) ) { - FNA3D_LogError("BindResourceMemory must be given either a VulkanBuffer or a VulkanTexture"); + Refresh_LogError("BindResourceMemory must be given either a VulkanBuffer or a VulkanTexture"); return 0; } @@ -2778,7 +2814,7 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( SDL_UnlockMutex(renderer->allocatorLock); /* Responsibility of the caller to handle being out of memory */ - FNA3D_LogWarn("Failed to allocate memory!"); + Refresh_LogWarn("Failed to allocate memory!"); return 2; } @@ -2914,10 +2950,10 @@ static uint8_t VULKAN_INTERNAL_BindMemoryForImage( if (isRenderTarget) { - FNA3D_LogWarn("RenderTarget is allocated in host memory, pre-allocate your targets!"); + Refresh_LogWarn("RenderTarget is allocated in host memory, pre-allocate your targets!"); } - FNA3D_LogWarn("Out of device local memory, falling back to host memory"); + Refresh_LogWarn("Out of device local memory, falling back to host memory"); while (VULKAN_INTERNAL_FindImageMemoryRequirements( renderer, @@ -3028,7 +3064,7 @@ static uint8_t VULKAN_INTERNAL_BindMemoryForBuffer( /* Follow-up for the warning logged by FindMemoryType */ if (!renderer->unifiedMemoryWarning) { - FNA3D_LogWarn("No unified memory found, falling back to host memory"); + Refresh_LogWarn("No unified memory found, falling back to host memory"); renderer->unifiedMemoryWarning = 1; } @@ -3090,348 +3126,6 @@ static uint8_t VULKAN_INTERNAL_FindAllocationToDefragment( return 0; } -static uint8_t VULKAN_INTERNAL_DefragmentMemory( - VulkanRenderer *renderer -) { - VulkanMemorySubAllocator allocator; - VulkanMemoryAllocation *allocation; - uint32_t allocationIndexToDefrag; - VulkanMemoryUsedRegion *currentRegion; - VulkanBuffer* newBuffer; - VkBufferCopy bufferCopy; - VkImage copyImage; - VkImageCopy *imageCopyRegions; - VkImageAspectFlags aspectFlags; - VulkanCommandBuffer *commandBuffer; - VkCommandBufferBeginInfo beginInfo; - VkPipelineStageFlags waitFlags = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; - VkSubmitInfo submitInfo; - VkResult result; - uint32_t i, level; - VulkanResourceAccessType copyResourceAccessType = RESOURCE_ACCESS_NONE; - VulkanResourceAccessType originalResourceAccessType; - - SDL_LockMutex(renderer->allocatorLock); - - renderer->needDefrag = 0; - - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - beginInfo.pNext = NULL; - beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - beginInfo.pInheritanceInfo = NULL; - - commandBuffer = VULKAN_AcquireCommandBuffer((Refresh_Renderer *) renderer); - - if (VULKAN_INTERNAL_FindAllocationToDefragment( - renderer, - &allocator, - &allocationIndexToDefrag - )) { - allocation = allocator.allocations[allocationIndexToDefrag]; - - VULKAN_INTERNAL_MakeMemoryUnavailable( - renderer, - 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]; - copyResourceAccessType = RESOURCE_ACCESS_NONE; - - if (currentRegion->isBuffer) - { - currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; - - // TODO: modify this stuff to change the buffer pointers around - newBuffer = VULKAN_INTERNAL_CreateBuffer( - renderer, - currentRegion->vulkanBuffer->size, - RESOURCE_ACCESS_NONE, - currentRegion->vulkanBuffer->usage - ); - - if (newBuffer == NULL) - { - Refresh_LogError("Failed to create defrag buffer!"); - return 0; - } - - originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType; - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - RESOURCE_ACCESS_TRANSFER_READ, - currentRegion->vulkanBuffer->buffer, - ¤tRegion->vulkanBuffer->resourceAccessType - ); - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - RESOURCE_ACCESS_TRANSFER_WRITE, - newBuffer, - ©ResourceAccessType - ); - - bufferCopy.srcOffset = 0; - bufferCopy.dstOffset = 0; - bufferCopy.size = currentRegion->resourceSize; - - renderer->vkCmdCopyBuffer( - commandBuffer->commandBuffer, - currentRegion->vulkanBuffer->buffer, - newBuffer->buffer, - 1, - &bufferCopy - ); - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - originalResourceAccessType, - newBuffer, - ©ResourceAccessType - ); - - SDL_AtomicIncRef(&newBuffer->referenceCount); - SDL_AtomicIncRef(¤tRegion->vulkanBuffer->referenceCount); - - /* re-point original container to new buffer */ - newBuffer->container = currentRegion->vulkanBuffer->container; - newBuffer->container->vulkanBuffer = newBuffer; - - VULKAN_INTERNAL_QueueDestroyBuffer(renderer, currentRegion->vulkanBuffer); - - renderer->needDefrag = 1; - } - else - { - result = renderer->vkCreateImage( - renderer->logicalDevice, - ¤tRegion->vulkanTexture->imageCreateInfo, - NULL, - ©Image - ); - - VULKAN_ERROR_CHECK(result, vkCreateImage, 0) - - if (VULKAN_INTERNAL_BindMemoryForImage( - renderer, - copyImage, - 0, - &newRegion - ) != 1) - { - /* Out of memory, abort */ - renderer->vkDestroyImage( - renderer->logicalDevice, - copyImage, - NULL - ); - - break; - } - - if (IsDepthFormat(currentRegion->vulkanTexture->surfaceFormat)) - { - aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT; - - if (DepthFormatContainsStencil(currentRegion->vulkanTexture->surfaceFormat)) - { - aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - } - else - { - aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; - } - - originalResourceAccessType = currentRegion->vulkanTexture->resourceAccessType; - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_READ, - aspectFlags, - 0, - currentRegion->vulkanTexture->layerCount, - 0, - currentRegion->vulkanTexture->levelCount, - 0, - currentRegion->vulkanTexture->image, - ¤tRegion->vulkanTexture->resourceAccessType - ); - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - aspectFlags, - 0, - currentRegion->vulkanTexture->layerCount, - 0, - currentRegion->vulkanTexture->levelCount, - 0, - copyImage, - ©ResourceAccessType - ); - - imageCopyRegions = SDL_stack_alloc(VkImageCopy, currentRegion->vulkanTexture->levelCount); - - for (level = 0; level < currentRegion->vulkanTexture->levelCount; level += 1) - { - imageCopyRegions[level].srcOffset.x = 0; - imageCopyRegions[level].srcOffset.y = 0; - imageCopyRegions[level].srcOffset.z = 0; - imageCopyRegions[level].srcSubresource.aspectMask = aspectFlags; - imageCopyRegions[level].srcSubresource.baseArrayLayer = 0; - imageCopyRegions[level].srcSubresource.layerCount = currentRegion->vulkanTexture->layerCount; - imageCopyRegions[level].srcSubresource.mipLevel = level; - imageCopyRegions[level].extent.width = SDL_max(1, currentRegion->vulkanTexture->dimensions.width >> level); - imageCopyRegions[level].extent.height = SDL_max(1, currentRegion->vulkanTexture->dimensions.height >> level); - imageCopyRegions[level].extent.depth = currentRegion->vulkanTexture->depth; - imageCopyRegions[level].dstOffset.x = 0; - imageCopyRegions[level].dstOffset.y = 0; - imageCopyRegions[level].dstOffset.z = 0; - imageCopyRegions[level].dstSubresource.aspectMask = aspectFlags; - imageCopyRegions[level].dstSubresource.baseArrayLayer = 0; - imageCopyRegions[level].dstSubresource.layerCount = currentRegion->vulkanTexture->layerCount; - imageCopyRegions[level].dstSubresource.mipLevel = level; - } - - renderer->vkCmdCopyImage( - commandBuffer->commandBuffer, - currentRegion->vulkanTexture->image, - AccessMap[currentRegion->vulkanTexture->resourceAccessType].imageLayout, - copyImage, - AccessMap[copyResourceAccessType].imageLayout, - currentRegion->vulkanTexture->levelCount, - imageCopyRegions - ); - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - originalResourceAccessType, - aspectFlags, - 0, - currentRegion->vulkanTexture->layerCount, - 0, - currentRegion->vulkanTexture->levelCount, - 0, - copyImage, - ©ResourceAccessType - ); - - SDL_stack_free(imageCopyRegions); - - if (renderer->defragmentedImagesToDestroyCount >= renderer->defragmentedImagesToDestroyCapacity) - { - renderer->defragmentedImagesToDestroyCapacity *= 2; - renderer->defragmentedImagesToDestroy = SDL_realloc( - renderer->defragmentedImagesToDestroy, - sizeof(VkImage) * renderer->defragmentedImagesToDestroyCapacity - ); - } - - if (renderer->defragmentedImageViewsToDestroyCount >= renderer->defragmentedImageViewsToDestroyCapacity) - { - renderer->defragmentedImageViewsToDestroyCapacity *= 2; - renderer->defragmentedImageViewsToDestroy = SDL_realloc( - renderer->defragmentedImageViewsToDestroy, - sizeof(VkImageView) * renderer->defragmentedImageViewsToDestroyCapacity - ); - } - - if (renderer->usedRegionsToDestroyCount >= renderer->usedRegionsToDestroyCapacity) - { - renderer->usedRegionsToDestroyCapacity *= 2; - renderer->usedRegionsToDestroy = SDL_realloc( - renderer->usedRegionsToDestroy, - sizeof(VulkanMemoryUsedRegion*) * renderer->usedRegionsToDestroyCapacity - ); - } - - renderer->defragmentedImagesToDestroy[ - renderer->defragmentedImagesToDestroyCount - ] = currentRegion->vulkanTexture->image; - - renderer->defragmentedImagesToDestroyCount += 1; - - renderer->defragmentedImageViewsToDestroy[ - renderer->defragmentedImageViewsToDestroyCount - ] = currentRegion->vulkanTexture->view; - - renderer->defragmentedImageViewsToDestroyCount += 1; - - renderer->usedRegionsToDestroy[ - renderer->usedRegionsToDestroyCount - ] = currentRegion; - - renderer->usedRegionsToDestroyCount += 1; - - currentRegion->vulkanTexture->viewCreateInfo.image = copyImage; - - renderer->vkCreateImageView( - renderer->logicalDevice, - ¤tRegion->vulkanTexture->viewCreateInfo, - NULL, - ¤tRegion->vulkanTexture->view - ); - - newRegion->isBuffer = 0; - - newRegion->vulkanTexture = currentRegion->vulkanTexture; - newRegion->vulkanTexture->usedRegion = newRegion; /* lol */ - newRegion->vulkanTexture->image = copyImage; - newRegion->vulkanTexture->resourceAccessType = copyResourceAccessType; - - renderer->needDefrag = 1; - } - } - } - - renderer->vkEndCommandBuffer( - renderer->defragCommandBufferContainer->commandBuffer - ); - - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.pNext = NULL; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &renderer->defragCommandBufferContainer->commandBuffer; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = &renderer->defragSemaphore; - submitInfo.pWaitDstStageMask = &waitFlags; - submitInfo.signalSemaphoreCount = 0; - submitInfo.pSignalSemaphores = NULL; - - result = renderer->vkResetFences( - renderer->logicalDevice, - 1, - &renderer->defragCommandBufferContainer->inFlightFence - ); - VULKAN_ERROR_CHECK(result, vkResetFences, 0) - - result = renderer->vkQueueSubmit( - renderer->unifiedQueue, - 1, - &submitInfo, - renderer->defragCommandBufferContainer->inFlightFence - ); - VULKAN_ERROR_CHECK(result, vkQueueSubmit, 0) - - renderer->currentCommandBufferContainer = NULL; - renderer->numActiveCommands = 0; - - renderer->defragTimer = 0; - - SDL_UnlockMutex(renderer->allocatorLock); - - return 1; -} - /* Memory Barriers */ static void VULKAN_INTERNAL_BufferMemoryBarrier( @@ -3782,7 +3476,7 @@ static void VULKAN_INTERNAL_RemoveRenderTargetsContainingTexture( { hash = &renderer->renderTargetHashArray.elements[i].key; - if ((VulkanTexture*) hash->texture == texture) + if (hash->texture == texture) { VULKAN_INTERNAL_RemoveFramebuffersContainingView( renderer, @@ -4407,7 +4101,9 @@ static VulkanBuffer* VULKAN_INTERNAL_CreateBuffer( VulkanRenderer *renderer, VkDeviceSize size, VulkanResourceAccessType resourceAccessType, - VkBufferUsageFlags usage + VkBufferUsageFlags usage, + uint8_t preferDeviceLocal, + uint8_t isTransferBuffer ) { VulkanBuffer* buffer; VkResult vulkanResult; @@ -4419,6 +4115,8 @@ static VulkanBuffer* VULKAN_INTERNAL_CreateBuffer( buffer->size = size; buffer->resourceAccessType = resourceAccessType; buffer->usage = usage; + buffer->preferDeviceLocal = preferDeviceLocal; + buffer->isTransferBuffer = isTransferBuffer; bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferCreateInfo.pNext = NULL; @@ -4437,8 +4135,6 @@ static VulkanBuffer* VULKAN_INTERNAL_CreateBuffer( ); VULKAN_ERROR_CHECK(vulkanResult, vkCreateBuffer, 0) - buffer->bufferCreateInfo = bufferCreateInfo; - bindResult = VULKAN_INTERNAL_BindMemoryForBuffer( renderer, buffer->buffer, @@ -4569,7 +4265,9 @@ static uint8_t VULKAN_INTERNAL_CreateUniformBuffer( renderer, UBO_BUFFER_SIZE, resourceAccessType, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + 0, + 0 ); if (buffer->vulkanBuffer == NULL) @@ -4658,7 +4356,9 @@ static VulkanUniformBuffer* VULKAN_INTERNAL_CreateDummyUniformBuffer( renderer, UBO_BUFFER_SIZE, resourceAccessType, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + 0, + 0 ); buffer->offset = 0; @@ -5313,9 +5013,7 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( swapchainData->textures[i].resourceAccessType = RESOURCE_ACCESS_NONE; /* Swapchain memory is managed by the driver */ - swapchainData->textures[i].allocation = NULL; - swapchainData->textures[i].offset = 0; - swapchainData->textures[i].memorySize = 0; + swapchainData->textures[i].usedRegion = NULL; swapchainData->textures[i].dimensions = swapchainData->extent; swapchainData->textures[i].format = swapchainData->swapchainFormat; @@ -5988,9 +5686,6 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( ); VULKAN_ERROR_CHECK(vulkanResult, vkCreateImage, 0) - texture->isRenderTarget = isRenderTarget; - texture->imageCreateInfo = imageCreateInfo; - bindResult = VULKAN_INTERNAL_BindMemoryForImage( renderer, texture->image, @@ -6005,7 +5700,8 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( texture->image, NULL); - return bindResult; + Refresh_LogError("Unable to bind memory for texture!"); + return NULL; } texture->usedRegion->vulkanTexture = texture; /* lol */ @@ -6046,7 +5742,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( { LogVulkanResultAsError("vkCreateImageView", vulkanResult); Refresh_LogError("Failed to create texture image view"); - return 0; + return NULL; } texture->dimensions.width = width; @@ -6205,7 +5901,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = (VulkanTexture*) colorAttachmentInfos[i].texture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; if (texture->msaaTex != NULL) { @@ -6328,7 +6024,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( } else { - texture = (VulkanTexture*) depthStencilAttachmentInfo->texture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; attachmentDescriptions[attachmentDescriptionCount].flags = 0; attachmentDescriptions[attachmentDescriptionCount].format = texture->format; @@ -7222,7 +6918,8 @@ static Refresh_Texture* VULKAN_CreateTexture( VkImageAspectFlags imageAspectFlags; uint8_t isDepthFormat = IsRefreshDepthFormat(textureCreateInfo->format); VkFormat format; - VulkanTexture *result; + VulkanTextureContainer *container; + VulkanTexture *vulkanTexture; if (isDepthFormat) { @@ -7267,7 +6964,7 @@ static Refresh_Texture* VULKAN_CreateTexture( imageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; } - result = VULKAN_INTERNAL_CreateTexture( + vulkanTexture = VULKAN_INTERNAL_CreateTexture( renderer, textureCreateInfo->width, textureCreateInfo->height, @@ -7283,11 +6980,11 @@ static Refresh_Texture* VULKAN_CreateTexture( ); /* create the MSAA texture for color attachments, if needed */ - if ( result != NULL && + if ( vulkanTexture != NULL && !isDepthFormat && textureCreateInfo->sampleCount > REFRESH_SAMPLECOUNT_1 ) { - result->msaaTex = VULKAN_INTERNAL_CreateTexture( + vulkanTexture->msaaTex = VULKAN_INTERNAL_CreateTexture( renderer, textureCreateInfo->width, textureCreateInfo->height, @@ -7301,7 +6998,11 @@ static Refresh_Texture* VULKAN_CreateTexture( ); } - return (Refresh_Texture*) result; + container = SDL_malloc(sizeof(VulkanTextureContainer)); + container->vulkanTexture = vulkanTexture; + vulkanTexture->container = container; + + return (Refresh_Texture*) container; } static Refresh_Buffer* VULKAN_CreateBuffer( @@ -7348,7 +7049,9 @@ static Refresh_Buffer* VULKAN_CreateBuffer( (VulkanRenderer*)driverData, sizeInBytes, resourceAccessType, - vulkanUsageFlags + vulkanUsageFlags, + 1, + 0 ); if (buffer == NULL) @@ -7357,9 +7060,8 @@ static Refresh_Buffer* VULKAN_CreateBuffer( return NULL; } - bufferContainer = SDL_malloc(sizeof(VulkanBufferContainer*)); + bufferContainer = SDL_malloc(sizeof(VulkanBufferContainer)); bufferContainer->vulkanBuffer = buffer; - buffer->container = bufferContainer; return (Refresh_Buffer*) buffer; @@ -7407,7 +7109,9 @@ static VulkanTransferBuffer* VULKAN_INTERNAL_AcquireTransferBuffer( renderer, size, RESOURCE_ACCESS_TRANSFER_READ_WRITE, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + 1, + 1 ); if (transferBuffer == NULL) @@ -7439,7 +7143,7 @@ static void VULKAN_SetTextureData( uint32_t dataLengthInBytes ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanTexture *vulkanTexture = (VulkanTexture*) textureSlice->texture; + VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanTransferBuffer *transferBuffer; VkBufferImageCopy imageCopy; @@ -7465,8 +7169,8 @@ static void VULKAN_SetTextureData( } stagingBufferPointer = - transferBuffer->buffer->allocation->mapPointer + - transferBuffer->buffer->offset + + transferBuffer->buffer->usedRegion->allocation->mapPointer + + transferBuffer->buffer->usedRegion->resourceOffset + transferBuffer->offset; SDL_memcpy( @@ -7553,7 +7257,7 @@ static void VULKAN_SetTextureDataYUV( uint32_t dataLength ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanTexture *tex = (VulkanTexture*) y; + VulkanTexture *tex = ((VulkanTextureContainer*) y)->vulkanTexture; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*)commandBuffer; VulkanTransferBuffer *transferBuffer; @@ -7576,8 +7280,8 @@ static void VULKAN_SetTextureDataYUV( } stagingBufferPointer = - transferBuffer->buffer->allocation->mapPointer + - transferBuffer->buffer->offset + + transferBuffer->buffer->usedRegion->allocation->mapPointer + + transferBuffer->buffer->usedRegion->resourceOffset + transferBuffer->offset; /* Initialize values that are the same for Y, U, and V */ @@ -7660,7 +7364,7 @@ static void VULKAN_SetTextureDataYUV( imageCopy.bufferOffset = transferBuffer->offset + yDataLength; - tex = (VulkanTexture*) u; + tex = ((VulkanTextureContainer*) u)->vulkanTexture; SDL_memcpy( stagingBufferPointer + yDataLength, @@ -7715,7 +7419,7 @@ static void VULKAN_SetTextureDataYUV( imageCopy.bufferOffset = transferBuffer->offset + yDataLength + uvDataLength; - tex = (VulkanTexture*) v; + tex = ((VulkanTextureContainer*) v)->vulkanTexture; SDL_memcpy( stagingBufferPointer + yDataLength + uvDataLength, @@ -7778,8 +7482,8 @@ static void VULKAN_INTERNAL_BlitImage( VkFilter filter ) { VkImageBlit blit; - VulkanTexture *sourceTexture = (VulkanTexture*) sourceTextureSlice->texture; - VulkanTexture *destinationTexture = (VulkanTexture*) destinationTextureSlice->texture; + VulkanTexture *sourceTexture = ((VulkanTextureContainer*) sourceTextureSlice->texture)->vulkanTexture; + VulkanTexture *destinationTexture = ((VulkanTextureContainer*) destinationTextureSlice->texture)->vulkanTexture; VulkanResourceAccessType originalSourceAccessType = sourceTexture->resourceAccessType; @@ -7919,7 +7623,7 @@ static void VULKAN_INTERNAL_SetBufferData( uint32_t dataLength ) { SDL_memcpy( - vulkanBuffer->allocation->mapPointer + vulkanBuffer->offset + offsetInBytes, + vulkanBuffer->usedRegion->allocation->mapPointer + vulkanBuffer->usedRegion->resourceOffset + offsetInBytes, data, dataLength ); @@ -8295,7 +7999,7 @@ static void VULKAN_BindVertexSamplers( for (i = 0; i < samplerCount; i += 1) { - currentTexture = (VulkanTexture*) pTextures[i]; + currentTexture = ((VulkanTextureContainer*) pTextures[i])->vulkanTexture; currentSampler = (VulkanSampler*) pSamplers[i]; descriptorImageInfos[i].imageView = currentTexture->view; descriptorImageInfos[i].sampler = currentSampler->sampler; @@ -8338,7 +8042,7 @@ static void VULKAN_BindFragmentSamplers( for (i = 0; i < samplerCount; i += 1) { - currentTexture = (VulkanTexture*) pTextures[i]; + currentTexture = ((VulkanTextureContainer*) pTextures[i])->vulkanTexture; currentSampler = (VulkanSampler*) pSamplers[i]; descriptorImageInfos[i].imageView = currentTexture->view; descriptorImageInfos[i].sampler = currentSampler->sampler; @@ -8386,7 +8090,7 @@ static void VULKAN_CopyTextureToBuffer( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *vulkanTexture = (VulkanTexture*) textureSlice->texture; + VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer; VulkanResourceAccessType prevResourceAccess; @@ -8454,13 +8158,10 @@ static void VULKAN_CopyTextureToBuffer( VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); } -static void VULKAN_QueueDestroyTexture( - Refresh_Renderer *driverData, - Refresh_Texture *texture +static void VULKAN_INTERNAL_QueueDestroyTexture( + VulkanRenderer *renderer, + VulkanTexture *vulkanTexture ) { - VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanTexture* vulkanTexture = (VulkanTexture*) texture; - SDL_LockMutex(renderer->disposeLock); EXPAND_ARRAY_IF_NEEDED( @@ -8471,12 +8172,32 @@ static void VULKAN_QueueDestroyTexture( renderer->texturesToDestroyCapacity * 2 ) - renderer->texturesToDestroy[renderer->texturesToDestroyCount] = vulkanTexture; + renderer->texturesToDestroy[ + renderer->texturesToDestroyCount + ] = vulkanTexture; renderer->texturesToDestroyCount += 1; SDL_UnlockMutex(renderer->disposeLock); } +static void VULKAN_QueueDestroyTexture( + Refresh_Renderer *driverData, + Refresh_Texture *texture +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer *)texture; + VulkanTexture *vulkanTexture = vulkanTextureContainer->vulkanTexture; + + SDL_LockMutex(renderer->disposeLock); + + VULKAN_INTERNAL_QueueDestroyTexture(renderer, vulkanTexture); + + /* Containers are just client handles, so we can destroy immediately */ + SDL_free(vulkanTextureContainer); + + SDL_UnlockMutex(renderer->disposeLock); +} + static void VULKAN_QueueDestroySampler( Refresh_Renderer *driverData, Refresh_Sampler *sampler @@ -8534,18 +8255,8 @@ static void VULKAN_QueueDestroyBuffer( 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; + /* Containers are just client handles, so we can destroy immediately */ + SDL_free(vulkanBufferContainer); SDL_UnlockMutex(renderer->disposeLock); } @@ -8637,7 +8348,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - hash.colorTargetDescriptions[i].format = ((VulkanTexture*) colorAttachmentInfos[i].texture)->format; + hash.colorTargetDescriptions[i].format = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture->format; hash.colorTargetDescriptions[i].clearColor = colorAttachmentInfos[i].clearColor; hash.colorTargetDescriptions[i].loadOp = colorAttachmentInfos[i].loadOp; hash.colorTargetDescriptions[i].storeOp = colorAttachmentInfos[i].storeOp; @@ -8646,7 +8357,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( hash.colorAttachmentSampleCount = REFRESH_SAMPLECOUNT_1; if (colorAttachmentCount > 0) { - texture = (VulkanTexture*) colorAttachmentInfos[0].texture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[0].texture)->vulkanTexture; if (texture->msaaTex != NULL) { hash.colorAttachmentSampleCount = texture->msaaTex->sampleCount; @@ -8665,7 +8376,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( } else { - hash.depthStencilTargetDescription.format = ((VulkanTexture*) depthStencilAttachmentInfo->texture)->format; + hash.depthStencilTargetDescription.format = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture->format; hash.depthStencilTargetDescription.loadOp = depthStencilAttachmentInfo->loadOp; hash.depthStencilTargetDescription.storeOp = depthStencilAttachmentInfo->storeOp; hash.depthStencilTargetDescription.stencilLoadOp = depthStencilAttachmentInfo->stencilLoadOp; @@ -8735,7 +8446,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = (VulkanTexture*) colorAttachmentInfos[i].texture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, @@ -8771,7 +8482,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( } else { - texture = (VulkanTexture*) depthStencilAttachmentInfo->texture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, texture, @@ -8804,7 +8515,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = (VulkanTexture*) colorAttachmentInfos[i].texture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, @@ -8838,7 +8549,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( if (depthStencilAttachmentInfo != NULL) { - texture = (VulkanTexture*) depthStencilAttachmentInfo->texture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, texture, @@ -8983,7 +8694,7 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = (VulkanTexture*) colorAttachmentInfos[i].texture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; w = texture->dimensions.width >> colorAttachmentInfos[i].level; h = texture->dimensions.height >> colorAttachmentInfos[i].level; @@ -9000,7 +8711,7 @@ static void VULKAN_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { - texture = (VulkanTexture*) depthStencilAttachmentInfo->texture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; w = texture->dimensions.width >> depthStencilAttachmentInfo->level; h = texture->dimensions.height >> depthStencilAttachmentInfo->level; @@ -9041,7 +8752,7 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = (VulkanTexture*) colorAttachmentInfos[i].texture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; VULKAN_INTERNAL_ImageMemoryBarrier( renderer, @@ -9068,7 +8779,7 @@ static void VULKAN_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { - texture = (VulkanTexture*) depthStencilAttachmentInfo->texture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; depthAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT; if (IsStencilFormat(texture->format)) @@ -9108,7 +8819,7 @@ static void VULKAN_BeginRenderPass( clearValues[i].color.float32[2] = colorAttachmentInfos[i].clearColor.z; clearValues[i].color.float32[3] = colorAttachmentInfos[i].clearColor.w; - texture = (VulkanTexture*) colorAttachmentInfos[i].texture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; if (texture->msaaTex != NULL) { clearValues[i+1].color.float32[0] = colorAttachmentInfos[i].clearColor.x; @@ -9150,13 +8861,13 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { vulkanCommandBuffer->renderPassColorTargetTextures[i] = - (VulkanTexture*) colorAttachmentInfos[i].texture; + ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; } vulkanCommandBuffer->renderPassColorTargetCount = colorAttachmentCount; if (depthStencilAttachmentInfo != NULL) { - vulkanCommandBuffer->renderPassDepthTexture = (VulkanTexture*) depthStencilAttachmentInfo->texture; + vulkanCommandBuffer->renderPassDepthTexture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; } /* Set sensible default viewport state */ @@ -9555,7 +9266,7 @@ static void VULKAN_BindComputeTextures( for (i = 0; i < computePipeline->pipelineLayout->imageDescriptorSetCache->bindingCount; i += 1) { - currentTexture = (VulkanTexture*) pTextures[i]; + currentTexture = ((VulkanTextureContainer*) pTextures[i])->vulkanTexture; descriptorImageInfos[i].imageView = currentTexture->view; descriptorImageInfos[i].sampler = VK_NULL_HANDLE; descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; @@ -10213,13 +9924,6 @@ 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) @@ -10624,6 +10328,251 @@ static void VULKAN_Submit( SDL_UnlockMutex(renderer->submitLock); } +static uint8_t VULKAN_INTERNAL_DefragmentMemory( + VulkanRenderer *renderer +) { + VulkanMemorySubAllocator allocator; + VulkanMemoryAllocation *allocation; + uint32_t allocationIndexToDefrag; + VulkanMemoryUsedRegion *currentRegion; + VulkanBuffer* newBuffer; + VulkanTexture* newTexture; + VkBufferCopy bufferCopy; + VkImageCopy *imageCopyRegions; + VkImageAspectFlags aspectFlags; + VulkanCommandBuffer *commandBuffer; + VkCommandBufferBeginInfo beginInfo; + VkPipelineStageFlags waitFlags = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + uint32_t i, level; + VulkanResourceAccessType copyResourceAccessType = RESOURCE_ACCESS_NONE; + VulkanResourceAccessType originalResourceAccessType; + + SDL_LockMutex(renderer->allocatorLock); + + renderer->needDefrag = 0; + + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.pNext = NULL; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + beginInfo.pInheritanceInfo = NULL; + + commandBuffer = (VulkanCommandBuffer*) VULKAN_AcquireCommandBuffer((Refresh_Renderer *) renderer); + + if (VULKAN_INTERNAL_FindAllocationToDefragment( + renderer, + &allocator, + &allocationIndexToDefrag + )) { + allocation = allocator.allocations[allocationIndexToDefrag]; + + VULKAN_INTERNAL_MakeMemoryUnavailable( + renderer, + 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]; + copyResourceAccessType = RESOURCE_ACCESS_NONE; + + if (currentRegion->isBuffer) + { + currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; + + newBuffer = VULKAN_INTERNAL_CreateBuffer( + renderer, + currentRegion->vulkanBuffer->size, + RESOURCE_ACCESS_NONE, + currentRegion->vulkanBuffer->usage, + currentRegion->vulkanBuffer->preferDeviceLocal, + currentRegion->vulkanBuffer->isTransferBuffer + ); + + if (newBuffer == NULL) + { + Refresh_LogError("Failed to create defrag buffer!"); + return 0; + } + + originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType; + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + commandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + currentRegion->vulkanBuffer + ); + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + commandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + newBuffer + ); + + bufferCopy.srcOffset = 0; + bufferCopy.dstOffset = 0; + bufferCopy.size = currentRegion->resourceSize; + + renderer->vkCmdCopyBuffer( + commandBuffer->commandBuffer, + currentRegion->vulkanBuffer->buffer, + newBuffer->buffer, + 1, + &bufferCopy + ); + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + commandBuffer->commandBuffer, + originalResourceAccessType, + newBuffer + ); + + VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, currentRegion->vulkanBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, newBuffer); + + /* re-point original container to new buffer */ + newBuffer->container = currentRegion->vulkanBuffer->container; + newBuffer->container->vulkanBuffer = newBuffer; + currentRegion->vulkanBuffer->container = NULL; + + VULKAN_INTERNAL_QueueDestroyBuffer(renderer, currentRegion->vulkanBuffer); + + renderer->needDefrag = 1; + } + else + { + newTexture = VULKAN_INTERNAL_CreateTexture( + renderer, + currentRegion->vulkanTexture->dimensions.width, + currentRegion->vulkanTexture->dimensions.height, + currentRegion->vulkanTexture->depth, + currentRegion->vulkanTexture->isCube, + currentRegion->vulkanTexture->levelCount, + currentRegion->vulkanTexture->sampleCount, + currentRegion->vulkanTexture->format, + currentRegion->vulkanTexture->aspectFlags, + currentRegion->vulkanTexture->usageFlags + ); + + if (newTexture == NULL) + { + Refresh_LogError("Failed to create defrag texture!"); + return 0; + } + + originalResourceAccessType = currentRegion->vulkanTexture->resourceAccessType; + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + commandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + aspectFlags, + 0, + currentRegion->vulkanTexture->layerCount, + 0, + currentRegion->vulkanTexture->levelCount, + 0, + currentRegion->vulkanTexture->image, + ¤tRegion->vulkanTexture->resourceAccessType + ); + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + commandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + aspectFlags, + 0, + currentRegion->vulkanTexture->layerCount, + 0, + currentRegion->vulkanTexture->levelCount, + 0, + newTexture->image, + ©ResourceAccessType + ); + + imageCopyRegions = SDL_stack_alloc(VkImageCopy, currentRegion->vulkanTexture->levelCount); + + for (level = 0; level < currentRegion->vulkanTexture->levelCount; level += 1) + { + imageCopyRegions[level].srcOffset.x = 0; + imageCopyRegions[level].srcOffset.y = 0; + imageCopyRegions[level].srcOffset.z = 0; + imageCopyRegions[level].srcSubresource.aspectMask = aspectFlags; + imageCopyRegions[level].srcSubresource.baseArrayLayer = 0; + imageCopyRegions[level].srcSubresource.layerCount = currentRegion->vulkanTexture->layerCount; + imageCopyRegions[level].srcSubresource.mipLevel = level; + imageCopyRegions[level].extent.width = SDL_max(1, currentRegion->vulkanTexture->dimensions.width >> level); + imageCopyRegions[level].extent.height = SDL_max(1, currentRegion->vulkanTexture->dimensions.height >> level); + imageCopyRegions[level].extent.depth = currentRegion->vulkanTexture->depth; + imageCopyRegions[level].dstOffset.x = 0; + imageCopyRegions[level].dstOffset.y = 0; + imageCopyRegions[level].dstOffset.z = 0; + imageCopyRegions[level].dstSubresource.aspectMask = aspectFlags; + imageCopyRegions[level].dstSubresource.baseArrayLayer = 0; + imageCopyRegions[level].dstSubresource.layerCount = currentRegion->vulkanTexture->layerCount; + imageCopyRegions[level].dstSubresource.mipLevel = level; + } + + renderer->vkCmdCopyImage( + commandBuffer->commandBuffer, + currentRegion->vulkanTexture->image, + AccessMap[currentRegion->vulkanTexture->resourceAccessType].imageLayout, + newTexture->image, + AccessMap[copyResourceAccessType].imageLayout, + currentRegion->vulkanTexture->levelCount, + imageCopyRegions + ); + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + commandBuffer->commandBuffer, + originalResourceAccessType, + aspectFlags, + 0, + currentRegion->vulkanTexture->layerCount, + 0, + currentRegion->vulkanTexture->levelCount, + 0, + newTexture->image, + ©ResourceAccessType + ); + + SDL_stack_free(imageCopyRegions); + + VULKAN_INTERNAL_TrackTexture(renderer, commandBuffer, currentRegion->vulkanTexture); + VULKAN_INTERNAL_TrackTexture(renderer, commandBuffer, newTexture); + + /* re-point original container to new texture */ + newTexture->container = currentRegion->vulkanTexture->container; + newTexture->container->vulkanTexture = newTexture; + currentRegion->vulkanTexture->container = NULL; + + VULKAN_INTERNAL_QueueDestroyTexture(renderer, currentRegion->vulkanTexture); + + renderer->needDefrag = 1; + } + } + } + + VULKAN_Submit( + (Refresh_Renderer*) renderer, + 1, + (Refresh_CommandBuffer**) &commandBuffer + ); + + renderer->defragTimer = 0; + + SDL_UnlockMutex(renderer->allocatorLock); + + return 1; +} + /* Device instantiation */ static inline uint8_t VULKAN_INTERNAL_SupportsExtension( @@ -11845,14 +11794,6 @@ 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; diff --git a/src/Refresh_Driver_Vulkan_vkfuncs.h b/src/Refresh_Driver_Vulkan_vkfuncs.h index 69f06ea..47749ff 100644 --- a/src/Refresh_Driver_Vulkan_vkfuncs.h +++ b/src/Refresh_Driver_Vulkan_vkfuncs.h @@ -89,6 +89,7 @@ VULKAN_DEVICE_FUNCTION(BaseVK, void, vkCmdClearDepthStencilImage, (VkCommandBuff VULKAN_DEVICE_FUNCTION(BaseVK, void, vkCmdCopyBuffer, (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions)) VULKAN_DEVICE_FUNCTION(BaseVK, void, vkCmdCopyBufferToImage, (VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy *pRegions)) VULKAN_DEVICE_FUNCTION(BaseVK, void, vkCmdCopyImageToBuffer, (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions)) +VULKAN_DEVICE_FUNCTION(BaseVK, void, vkCmdCopyImage, (VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions)) VULKAN_DEVICE_FUNCTION(BaseVK, void, vkCmdDispatch, (VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)) VULKAN_DEVICE_FUNCTION(BaseVK, void, vkCmdDraw, (VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)) VULKAN_DEVICE_FUNCTION(BaseVK, void, vkCmdDrawIndexed, (VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance))