diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index e0687bb..7a8e6eb 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -695,11 +695,32 @@ static const VulkanResourceAccessInfo AccessMap[RESOURCE_ACCESS_TYPES_COUNT] = /* Memory structures */ -typedef struct VulkanBufferContainer /* cast from Refresh_Buffer */ +/* We use pointer indirection so that defrag can occur without objects + * needing to be aware of the backing buffers changing. + */ +typedef struct VulkanBufferContainer { VulkanBuffer *vulkanBuffer; } VulkanBufferContainer; +/* CpuBuffers consist of multiple backing buffer containers so that data transfers + * can occur safely without the client having to explicitly manage transfer timing. + */ +typedef struct VulkanCpuBufferContainer /* cast from Refresh_CpuBuffer */ +{ + uint32_t sizeInBytes; + VulkanBufferContainer *activeBuffer; + + /* These are all the buffers that have been used by this container. + * If a buffer is bound and then updated with Discard, a new buffer + * will be added to this list. + * These can be reused after they are submitted and command processing is complete. + */ + uint32_t bufferCapacity; + uint32_t bufferCount; + VulkanBufferContainer **backingBuffers; +} VulkanCpuBufferContainer; + struct VulkanBuffer { VkBuffer buffer; @@ -711,10 +732,13 @@ struct VulkanBuffer uint8_t requireHostVisible; uint8_t preferDeviceLocal; uint8_t requireHostLocal; + uint8_t preserveContentsOnDefrag; SDL_atomic_t referenceCount; /* Tracks command buffer usage */ VulkanBufferContainer *container; + + uint8_t markedForDestroy; /* so that defrag doesn't double-free */ }; typedef enum VulkanUniformBufferType @@ -802,6 +826,8 @@ struct VulkanTexture SDL_atomic_t referenceCount; VulkanTextureContainer *container; + + uint8_t markedForDestroy; /* so that defrag doesn't double-free */ }; typedef struct VulkanRenderTarget @@ -3248,6 +3274,28 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier( /* Resource tracking */ +#define ADD_TO_ARRAY_UNIQUE(resource, type, array, count, capacity) \ + uint32_t i; \ + \ + for (i = 0; i < commandBuffer->count; i += 1) \ + { \ + if (commandBuffer->array[i] == resource) \ + { \ + return; \ + } \ + } \ + \ + if (commandBuffer->count == commandBuffer->capacity) \ + { \ + commandBuffer->capacity += 1; \ + commandBuffer->array = SDL_realloc( \ + commandBuffer->array, \ + commandBuffer->capacity * sizeof(type) \ + ); \ + } \ + commandBuffer->array[commandBuffer->count] = resource; \ + commandBuffer->count += 1; + #define TRACK_RESOURCE(resource, type, array, count, capacity) \ uint32_t i; \ \ @@ -3269,10 +3317,8 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier( } \ commandBuffer->array[commandBuffer->count] = resource; \ commandBuffer->count += 1; \ - \ SDL_AtomicIncRef(&resource->referenceCount); - static void VULKAN_INTERNAL_TrackBuffer( VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer, @@ -3391,7 +3437,7 @@ static void VULKAN_INTERNAL_TrackCopiedTexture( VulkanCommandBuffer *commandBuffer, VulkanTexture *texture ) { - TRACK_RESOURCE( + ADD_TO_ARRAY_UNIQUE( texture, VulkanTexture*, copiedTextures, @@ -3406,7 +3452,7 @@ static void VULKAN_INTERNAL_TrackCopiedBuffer( VulkanCommandBuffer *commandBuffer, VulkanBuffer *buffer ) { - TRACK_RESOURCE( + ADD_TO_ARRAY_UNIQUE( buffer, VulkanBuffer*, copiedGpuBuffers, @@ -4145,7 +4191,8 @@ static VulkanBuffer* VULKAN_INTERNAL_CreateBuffer( uint8_t requireHostVisible, uint8_t requireHostLocal, uint8_t preferDeviceLocal, - uint8_t dedicatedAllocation + uint8_t dedicatedAllocation, + uint8_t preserveContentsOnDefrag ) { VulkanBuffer* buffer; VkResult vulkanResult; @@ -4160,6 +4207,8 @@ static VulkanBuffer* VULKAN_INTERNAL_CreateBuffer( buffer->requireHostVisible = requireHostVisible; buffer->requireHostLocal = requireHostLocal; buffer->preferDeviceLocal = preferDeviceLocal; + buffer->preserveContentsOnDefrag = preserveContentsOnDefrag; + buffer->markedForDestroy = 0; bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferCreateInfo.pNext = NULL; @@ -4277,6 +4326,7 @@ static VulkanUniformBufferObject* VULKAN_INTERNAL_CreateUniformBufferObject( 1, 0, 1, + 1, 1 ); @@ -4321,12 +4371,17 @@ static VulkanUniformBufferObject* VULKAN_INTERNAL_CreateUniformBufferObject( return uniformBufferObject; } -/* Buffer indirection so we can cleanly defrag GpuBuffers */ +/* Indirection so we can cleanly defrag buffers */ static VulkanBufferContainer* VULKAN_INTERNAL_CreateBufferContainer( VulkanRenderer *renderer, uint32_t sizeInBytes, VulkanResourceAccessType resourceAccessType, - VkBufferUsageFlags usageFlags + VkBufferUsageFlags usageFlags, + uint8_t requireHostVisible, + uint8_t requireHostLocal, + uint8_t preferDeviceLocal, + uint8_t dedicatedAllocation, + uint8_t preserveContentsOnDefrag ) { VulkanBufferContainer* bufferContainer; VulkanBuffer* buffer; @@ -4339,10 +4394,11 @@ static VulkanBufferContainer* VULKAN_INTERNAL_CreateBufferContainer( sizeInBytes, resourceAccessType, usageFlags, - 0, - 0, - 1, - 0 + requireHostVisible, + requireHostLocal, + preferDeviceLocal, + dedicatedAllocation, + preserveContentsOnDefrag ); if (buffer == NULL) @@ -5413,6 +5469,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( texture->isCube = 0; texture->is3D = 0; + texture->markedForDestroy = 0; if (isCube) { @@ -6812,20 +6869,26 @@ static Refresh_GpuBuffer* VULKAN_CreateGpuBuffer( (VulkanRenderer*) driverData, sizeInBytes, resourceAccessType, - vulkanUsageFlags + vulkanUsageFlags, + 0, + 0, + 1, + 0, + 1 ); } static Refresh_CpuBuffer* VULKAN_CreateCpuBuffer( Refresh_Renderer *driverData, - uint32_t sizeInBytes, - void **pDataPtr + uint32_t sizeInBytes ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VkBufferUsageFlags vulkanUsageFlags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + VulkanCpuBufferContainer *bufferContainer = (VulkanCpuBufferContainer*) SDL_malloc(sizeof(VulkanCpuBufferContainer)); - VulkanBuffer *vulkanBuffer = VULKAN_INTERNAL_CreateBuffer( + bufferContainer->sizeInBytes = sizeInBytes; + bufferContainer->activeBuffer = VULKAN_INTERNAL_CreateBufferContainer( renderer, sizeInBytes, RESOURCE_ACCESS_NONE, @@ -6833,12 +6896,18 @@ static Refresh_CpuBuffer* VULKAN_CreateCpuBuffer( 1, 1, 0, - 1 + 0, + 0 ); - *pDataPtr = vulkanBuffer->usedRegion->allocation->mapPointer; + bufferContainer->bufferCapacity = 1; + bufferContainer->bufferCount = 1; + bufferContainer->backingBuffers = SDL_malloc( + bufferContainer->bufferCapacity * sizeof(VulkanBufferContainer*) + ); + bufferContainer->backingBuffers[0] = bufferContainer->activeBuffer; - return (Refresh_CpuBuffer*) vulkanBuffer; + return (Refresh_CpuBuffer*) bufferContainer; } /* Setters */ @@ -7169,6 +7238,8 @@ static void VULKAN_INTERNAL_QueueDestroyTexture( VulkanRenderer *renderer, VulkanTexture *vulkanTexture ) { + if (vulkanTexture->markedForDestroy) { return; } + SDL_LockMutex(renderer->disposeLock); EXPAND_ARRAY_IF_NEEDED( @@ -7184,6 +7255,8 @@ static void VULKAN_INTERNAL_QueueDestroyTexture( ] = vulkanTexture; renderer->texturesToDestroyCount += 1; + vulkanTexture->markedForDestroy = 1; + SDL_UnlockMutex(renderer->disposeLock); } @@ -7232,6 +7305,8 @@ static void VULKAN_INTERNAL_QueueDestroyBuffer( VulkanRenderer *renderer, VulkanBuffer *vulkanBuffer ) { + if (vulkanBuffer->markedForDestroy) { return; } + SDL_LockMutex(renderer->disposeLock); EXPAND_ARRAY_IF_NEEDED( @@ -7247,6 +7322,8 @@ static void VULKAN_INTERNAL_QueueDestroyBuffer( ] = vulkanBuffer; renderer->buffersToDestroyCount += 1; + vulkanBuffer->markedForDestroy = 1; + SDL_UnlockMutex(renderer->disposeLock); } @@ -7262,7 +7339,7 @@ static void VULKAN_QueueDestroyGpuBuffer( VULKAN_INTERNAL_QueueDestroyBuffer(renderer, vulkanBuffer); - /* Containers are just client handles, so we can destroy immediately */ + /* Containers are just client handles, so we can free immediately */ SDL_free(vulkanBufferContainer); SDL_UnlockMutex(renderer->disposeLock); @@ -7273,11 +7350,20 @@ static void VULKAN_QueueDestroyCpuBuffer( Refresh_CpuBuffer *buffer ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer; + VulkanCpuBufferContainer *bufferContainer = (VulkanCpuBufferContainer*) buffer; + uint32_t i; SDL_LockMutex(renderer->disposeLock); - VULKAN_INTERNAL_QueueDestroyBuffer(renderer, vulkanBuffer); + for (i = 0; i < bufferContainer->bufferCount; i += 1) + { + VULKAN_INTERNAL_QueueDestroyBuffer(renderer, bufferContainer->backingBuffers[i]->vulkanBuffer); + SDL_free(bufferContainer->backingBuffers[i]); + } + + /* Containers are just client handles, so we can free immediately */ + SDL_free(bufferContainer->backingBuffers); + SDL_free(bufferContainer); SDL_UnlockMutex(renderer->disposeLock); } @@ -8342,6 +8428,108 @@ static void VULKAN_EndComputePass( vulkanCommandBuffer->currentComputePipeline = NULL; } +static void VULKAN_INTERNAL_DiscardActiveCpuBuffer( + VulkanRenderer *renderer, + VulkanCpuBufferContainer *cpuBufferContainer +) { + VulkanBufferContainer *cpuBuffer; + uint32_t i; + + cpuBufferContainer->activeBuffer->vulkanBuffer->preserveContentsOnDefrag = 0; + + /* If a previously-discarded buffer is available, we can use that. */ + for (i = 0; i < cpuBufferContainer->bufferCount; i += 1) + { + cpuBuffer = cpuBufferContainer->backingBuffers[i]; + if (SDL_AtomicGet(&cpuBuffer->vulkanBuffer->referenceCount) == 0) + { + cpuBufferContainer->activeBuffer = cpuBuffer; + return; + } + } + + /* No buffer is available, generate a new one. */ + cpuBufferContainer->activeBuffer = VULKAN_INTERNAL_CreateBufferContainer( + renderer, + cpuBufferContainer->sizeInBytes, + RESOURCE_ACCESS_NONE, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + 1, + 1, + 0, + 0, + 0 + ); + + EXPAND_ARRAY_IF_NEEDED( + cpuBufferContainer->backingBuffers, + VulkanBufferContainer*, + cpuBufferContainer->bufferCount + 1, + cpuBufferContainer->bufferCapacity, + cpuBufferContainer->bufferCapacity * 2 + ); + + cpuBufferContainer->backingBuffers[ + cpuBufferContainer->bufferCount + ] = cpuBufferContainer->activeBuffer; + cpuBufferContainer->bufferCount += 1; +} + +static void VULKAN_SetData( + Refresh_Renderer *driverData, + void* data, + Refresh_CpuBuffer *cpuBuffer, + Refresh_BufferCopy *copyParams, + Refresh_SetDataOptions option +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCpuBufferContainer *cpuBufferContainer = (VulkanCpuBufferContainer*) cpuBuffer; + VulkanBuffer *vulkanBuffer = cpuBufferContainer->activeBuffer->vulkanBuffer; + + if (option == REFRESH_SETDATAOPTIONS_DISCARD && SDL_AtomicGet(&vulkanBuffer->referenceCount) > 0) + { + VULKAN_INTERNAL_DiscardActiveCpuBuffer( + renderer, + cpuBufferContainer + ); + } + + uint8_t *bufferPointer = + vulkanBuffer->usedRegion->allocation->mapPointer + + vulkanBuffer->usedRegion->resourceOffset + + copyParams->dstOffset; + + SDL_memcpy( + bufferPointer, + ((uint8_t*) data) + copyParams->srcOffset, + copyParams->size + ); +} + +static void VULKAN_GetData( + Refresh_Renderer *driverData, + Refresh_CpuBuffer *cpuBuffer, + void* data, + Refresh_BufferCopy *copyParams +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCpuBufferContainer *cpuBufferContainer = (VulkanCpuBufferContainer*) cpuBuffer; + VulkanBuffer *vulkanBuffer = cpuBufferContainer->activeBuffer->vulkanBuffer; + + uint8_t *bufferPointer = + vulkanBuffer->usedRegion->allocation->mapPointer + + vulkanBuffer->usedRegion->resourceOffset + + copyParams->srcOffset; + + SDL_memcpy( + ((uint8_t*) data) + copyParams->dstOffset, + bufferPointer, + copyParams->size + ); + + vulkanBuffer->preserveContentsOnDefrag = 0; +} + static void VULKAN_BeginCopyPass( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer @@ -8362,7 +8550,7 @@ static void VULKAN_UploadToTexture( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; + VulkanCpuBufferContainer *bufferContainer = (VulkanCpuBufferContainer*) cpuBuffer; VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; VkBufferImageCopy imageCopy; @@ -8370,7 +8558,7 @@ static void VULKAN_UploadToTexture( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - vulkanCpuBuffer + bufferContainer->activeBuffer->vulkanBuffer ); VULKAN_INTERNAL_ImageMemoryBarrier( @@ -8403,14 +8591,14 @@ static void VULKAN_UploadToTexture( renderer->vkCmdCopyBufferToImage( vulkanCommandBuffer->commandBuffer, - vulkanCpuBuffer->buffer, + bufferContainer->activeBuffer->vulkanBuffer->buffer, vulkanTexture->image, AccessMap[vulkanTexture->resourceAccessType].imageLayout, 1, &imageCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanCpuBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBuffer->vulkanBuffer); VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture); } @@ -8424,7 +8612,7 @@ static void VULKAN_UploadToBuffer( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; + VulkanCpuBufferContainer *cpuBufferContainer = (VulkanCpuBufferContainer*) cpuBuffer; VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; VkBufferCopy bufferCopy; @@ -8432,7 +8620,7 @@ static void VULKAN_UploadToBuffer( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - vulkanCpuBuffer + cpuBufferContainer->activeBuffer->vulkanBuffer ); VULKAN_INTERNAL_BufferMemoryBarrier( @@ -8448,13 +8636,13 @@ static void VULKAN_UploadToBuffer( renderer->vkCmdCopyBuffer( vulkanCommandBuffer->commandBuffer, - vulkanCpuBuffer->buffer, + cpuBufferContainer->activeBuffer->vulkanBuffer->buffer, vulkanGpuBuffer->buffer, 1, &bufferCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanCpuBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, cpuBufferContainer->activeBuffer->vulkanBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); } @@ -8469,14 +8657,14 @@ static void VULKAN_DownloadFromTexture( VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; - VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; + VulkanCpuBufferContainer *cpuBufferContainer = (VulkanCpuBufferContainer*) cpuBuffer; VkBufferImageCopy imageCopy; VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - vulkanCpuBuffer + cpuBufferContainer->activeBuffer->vulkanBuffer ); VULKAN_INTERNAL_ImageMemoryBarrier( @@ -8511,14 +8699,16 @@ static void VULKAN_DownloadFromTexture( vulkanCommandBuffer->commandBuffer, vulkanTexture->image, AccessMap[vulkanTexture->resourceAccessType].imageLayout, - vulkanCpuBuffer->buffer, + cpuBufferContainer->activeBuffer->vulkanBuffer->buffer, 1, &imageCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanCpuBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, cpuBufferContainer->activeBuffer->vulkanBuffer); VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture); + + cpuBufferContainer->activeBuffer->vulkanBuffer->preserveContentsOnDefrag = 1; } static void VULKAN_DownloadFromBuffer( @@ -8530,7 +8720,7 @@ static void VULKAN_DownloadFromBuffer( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; + VulkanCpuBufferContainer *cpuBufferContainer = (VulkanCpuBufferContainer*) cpuBuffer; VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; VkBufferCopy bufferCopy; @@ -8538,7 +8728,7 @@ static void VULKAN_DownloadFromBuffer( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - vulkanCpuBuffer + cpuBufferContainer->activeBuffer->vulkanBuffer ); VULKAN_INTERNAL_BufferMemoryBarrier( @@ -8555,14 +8745,16 @@ static void VULKAN_DownloadFromBuffer( renderer->vkCmdCopyBuffer( vulkanCommandBuffer->commandBuffer, vulkanGpuBuffer->buffer, - vulkanCpuBuffer->buffer, + cpuBufferContainer->activeBuffer->vulkanBuffer->buffer, 1, &bufferCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanCpuBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, cpuBufferContainer->activeBuffer->vulkanBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); + + cpuBufferContainer->activeBuffer->vulkanBuffer->preserveContentsOnDefrag = 1; } static void VULKAN_CopyTextureToTexture( @@ -10118,7 +10310,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( currentRegion = allocation->usedRegions[i]; copyResourceAccessType = RESOURCE_ACCESS_NONE; - if (currentRegion->isBuffer) + if (currentRegion->isBuffer && !currentRegion->vulkanBuffer->markedForDestroy) { currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; @@ -10130,7 +10322,8 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( currentRegion->vulkanBuffer->requireHostVisible, currentRegion->vulkanBuffer->requireHostLocal, currentRegion->vulkanBuffer->preferDeviceLocal, - 0 + 0, + currentRegion->vulkanBuffer->preserveContentsOnDefrag ); if (newBuffer == NULL) @@ -10139,43 +10332,47 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( return 0; } - originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType; + /* Copy buffer contents if necessary */ + if (currentRegion->vulkanBuffer->preserveContentsOnDefrag) + { + 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_READ, + currentRegion->vulkanBuffer + ); - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - newBuffer - ); + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + commandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + newBuffer + ); - bufferCopy.srcOffset = 0; - bufferCopy.dstOffset = 0; - bufferCopy.size = currentRegion->resourceSize; + bufferCopy.srcOffset = 0; + bufferCopy.dstOffset = 0; + bufferCopy.size = currentRegion->resourceSize; - renderer->vkCmdCopyBuffer( - commandBuffer->commandBuffer, - currentRegion->vulkanBuffer->buffer, - newBuffer->buffer, - 1, - &bufferCopy - ); + renderer->vkCmdCopyBuffer( + commandBuffer->commandBuffer, + currentRegion->vulkanBuffer->buffer, + newBuffer->buffer, + 1, + &bufferCopy + ); - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - originalResourceAccessType, - newBuffer - ); + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + commandBuffer->commandBuffer, + originalResourceAccessType, + newBuffer + ); - VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, currentRegion->vulkanBuffer); - VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, newBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, currentRegion->vulkanBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, newBuffer); + } /* re-point original container to new buffer */ if (currentRegion->vulkanBuffer->container != NULL) @@ -10189,7 +10386,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( renderer->needDefrag = 1; } - else + else if (!currentRegion->vulkanTexture->markedForDestroy) { newTexture = VULKAN_INTERNAL_CreateTexture( renderer,