implement SetData and GetData

pull/50/head
cosmonaut 2024-02-21 23:11:15 -08:00
parent 0c095fa56d
commit 6674076423
1 changed files with 269 additions and 72 deletions

View File

@ -695,11 +695,32 @@ static const VulkanResourceAccessInfo AccessMap[RESOURCE_ACCESS_TYPES_COUNT] =
/* Memory structures */ /* 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; VulkanBuffer *vulkanBuffer;
} VulkanBufferContainer; } 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 struct VulkanBuffer
{ {
VkBuffer buffer; VkBuffer buffer;
@ -711,10 +732,13 @@ struct VulkanBuffer
uint8_t requireHostVisible; uint8_t requireHostVisible;
uint8_t preferDeviceLocal; uint8_t preferDeviceLocal;
uint8_t requireHostLocal; uint8_t requireHostLocal;
uint8_t preserveContentsOnDefrag;
SDL_atomic_t referenceCount; /* Tracks command buffer usage */ SDL_atomic_t referenceCount; /* Tracks command buffer usage */
VulkanBufferContainer *container; VulkanBufferContainer *container;
uint8_t markedForDestroy; /* so that defrag doesn't double-free */
}; };
typedef enum VulkanUniformBufferType typedef enum VulkanUniformBufferType
@ -802,6 +826,8 @@ struct VulkanTexture
SDL_atomic_t referenceCount; SDL_atomic_t referenceCount;
VulkanTextureContainer *container; VulkanTextureContainer *container;
uint8_t markedForDestroy; /* so that defrag doesn't double-free */
}; };
typedef struct VulkanRenderTarget typedef struct VulkanRenderTarget
@ -3248,6 +3274,28 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier(
/* Resource tracking */ /* 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) \ #define TRACK_RESOURCE(resource, type, array, count, capacity) \
uint32_t i; \ uint32_t i; \
\ \
@ -3269,10 +3317,8 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier(
} \ } \
commandBuffer->array[commandBuffer->count] = resource; \ commandBuffer->array[commandBuffer->count] = resource; \
commandBuffer->count += 1; \ commandBuffer->count += 1; \
\
SDL_AtomicIncRef(&resource->referenceCount); SDL_AtomicIncRef(&resource->referenceCount);
static void VULKAN_INTERNAL_TrackBuffer( static void VULKAN_INTERNAL_TrackBuffer(
VulkanRenderer *renderer, VulkanRenderer *renderer,
VulkanCommandBuffer *commandBuffer, VulkanCommandBuffer *commandBuffer,
@ -3391,7 +3437,7 @@ static void VULKAN_INTERNAL_TrackCopiedTexture(
VulkanCommandBuffer *commandBuffer, VulkanCommandBuffer *commandBuffer,
VulkanTexture *texture VulkanTexture *texture
) { ) {
TRACK_RESOURCE( ADD_TO_ARRAY_UNIQUE(
texture, texture,
VulkanTexture*, VulkanTexture*,
copiedTextures, copiedTextures,
@ -3406,7 +3452,7 @@ static void VULKAN_INTERNAL_TrackCopiedBuffer(
VulkanCommandBuffer *commandBuffer, VulkanCommandBuffer *commandBuffer,
VulkanBuffer *buffer VulkanBuffer *buffer
) { ) {
TRACK_RESOURCE( ADD_TO_ARRAY_UNIQUE(
buffer, buffer,
VulkanBuffer*, VulkanBuffer*,
copiedGpuBuffers, copiedGpuBuffers,
@ -4145,7 +4191,8 @@ static VulkanBuffer* VULKAN_INTERNAL_CreateBuffer(
uint8_t requireHostVisible, uint8_t requireHostVisible,
uint8_t requireHostLocal, uint8_t requireHostLocal,
uint8_t preferDeviceLocal, uint8_t preferDeviceLocal,
uint8_t dedicatedAllocation uint8_t dedicatedAllocation,
uint8_t preserveContentsOnDefrag
) { ) {
VulkanBuffer* buffer; VulkanBuffer* buffer;
VkResult vulkanResult; VkResult vulkanResult;
@ -4160,6 +4207,8 @@ static VulkanBuffer* VULKAN_INTERNAL_CreateBuffer(
buffer->requireHostVisible = requireHostVisible; buffer->requireHostVisible = requireHostVisible;
buffer->requireHostLocal = requireHostLocal; buffer->requireHostLocal = requireHostLocal;
buffer->preferDeviceLocal = preferDeviceLocal; buffer->preferDeviceLocal = preferDeviceLocal;
buffer->preserveContentsOnDefrag = preserveContentsOnDefrag;
buffer->markedForDestroy = 0;
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferCreateInfo.pNext = NULL; bufferCreateInfo.pNext = NULL;
@ -4277,6 +4326,7 @@ static VulkanUniformBufferObject* VULKAN_INTERNAL_CreateUniformBufferObject(
1, 1,
0, 0,
1, 1,
1,
1 1
); );
@ -4321,12 +4371,17 @@ static VulkanUniformBufferObject* VULKAN_INTERNAL_CreateUniformBufferObject(
return uniformBufferObject; return uniformBufferObject;
} }
/* Buffer indirection so we can cleanly defrag GpuBuffers */ /* Indirection so we can cleanly defrag buffers */
static VulkanBufferContainer* VULKAN_INTERNAL_CreateBufferContainer( static VulkanBufferContainer* VULKAN_INTERNAL_CreateBufferContainer(
VulkanRenderer *renderer, VulkanRenderer *renderer,
uint32_t sizeInBytes, uint32_t sizeInBytes,
VulkanResourceAccessType resourceAccessType, VulkanResourceAccessType resourceAccessType,
VkBufferUsageFlags usageFlags VkBufferUsageFlags usageFlags,
uint8_t requireHostVisible,
uint8_t requireHostLocal,
uint8_t preferDeviceLocal,
uint8_t dedicatedAllocation,
uint8_t preserveContentsOnDefrag
) { ) {
VulkanBufferContainer* bufferContainer; VulkanBufferContainer* bufferContainer;
VulkanBuffer* buffer; VulkanBuffer* buffer;
@ -4339,10 +4394,11 @@ static VulkanBufferContainer* VULKAN_INTERNAL_CreateBufferContainer(
sizeInBytes, sizeInBytes,
resourceAccessType, resourceAccessType,
usageFlags, usageFlags,
0, requireHostVisible,
0, requireHostLocal,
1, preferDeviceLocal,
0 dedicatedAllocation,
preserveContentsOnDefrag
); );
if (buffer == NULL) if (buffer == NULL)
@ -5413,6 +5469,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture(
texture->isCube = 0; texture->isCube = 0;
texture->is3D = 0; texture->is3D = 0;
texture->markedForDestroy = 0;
if (isCube) if (isCube)
{ {
@ -6812,20 +6869,26 @@ static Refresh_GpuBuffer* VULKAN_CreateGpuBuffer(
(VulkanRenderer*) driverData, (VulkanRenderer*) driverData,
sizeInBytes, sizeInBytes,
resourceAccessType, resourceAccessType,
vulkanUsageFlags vulkanUsageFlags,
0,
0,
1,
0,
1
); );
} }
static Refresh_CpuBuffer* VULKAN_CreateCpuBuffer( static Refresh_CpuBuffer* VULKAN_CreateCpuBuffer(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
uint32_t sizeInBytes, uint32_t sizeInBytes
void **pDataPtr
) { ) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VkBufferUsageFlags vulkanUsageFlags = VkBufferUsageFlags vulkanUsageFlags =
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; 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, renderer,
sizeInBytes, sizeInBytes,
RESOURCE_ACCESS_NONE, RESOURCE_ACCESS_NONE,
@ -6833,12 +6896,18 @@ static Refresh_CpuBuffer* VULKAN_CreateCpuBuffer(
1, 1,
1, 1,
0, 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 */ /* Setters */
@ -7169,6 +7238,8 @@ static void VULKAN_INTERNAL_QueueDestroyTexture(
VulkanRenderer *renderer, VulkanRenderer *renderer,
VulkanTexture *vulkanTexture VulkanTexture *vulkanTexture
) { ) {
if (vulkanTexture->markedForDestroy) { return; }
SDL_LockMutex(renderer->disposeLock); SDL_LockMutex(renderer->disposeLock);
EXPAND_ARRAY_IF_NEEDED( EXPAND_ARRAY_IF_NEEDED(
@ -7184,6 +7255,8 @@ static void VULKAN_INTERNAL_QueueDestroyTexture(
] = vulkanTexture; ] = vulkanTexture;
renderer->texturesToDestroyCount += 1; renderer->texturesToDestroyCount += 1;
vulkanTexture->markedForDestroy = 1;
SDL_UnlockMutex(renderer->disposeLock); SDL_UnlockMutex(renderer->disposeLock);
} }
@ -7232,6 +7305,8 @@ static void VULKAN_INTERNAL_QueueDestroyBuffer(
VulkanRenderer *renderer, VulkanRenderer *renderer,
VulkanBuffer *vulkanBuffer VulkanBuffer *vulkanBuffer
) { ) {
if (vulkanBuffer->markedForDestroy) { return; }
SDL_LockMutex(renderer->disposeLock); SDL_LockMutex(renderer->disposeLock);
EXPAND_ARRAY_IF_NEEDED( EXPAND_ARRAY_IF_NEEDED(
@ -7247,6 +7322,8 @@ static void VULKAN_INTERNAL_QueueDestroyBuffer(
] = vulkanBuffer; ] = vulkanBuffer;
renderer->buffersToDestroyCount += 1; renderer->buffersToDestroyCount += 1;
vulkanBuffer->markedForDestroy = 1;
SDL_UnlockMutex(renderer->disposeLock); SDL_UnlockMutex(renderer->disposeLock);
} }
@ -7262,7 +7339,7 @@ static void VULKAN_QueueDestroyGpuBuffer(
VULKAN_INTERNAL_QueueDestroyBuffer(renderer, vulkanBuffer); 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_free(vulkanBufferContainer);
SDL_UnlockMutex(renderer->disposeLock); SDL_UnlockMutex(renderer->disposeLock);
@ -7273,11 +7350,20 @@ static void VULKAN_QueueDestroyCpuBuffer(
Refresh_CpuBuffer *buffer Refresh_CpuBuffer *buffer
) { ) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer; VulkanCpuBufferContainer *bufferContainer = (VulkanCpuBufferContainer*) buffer;
uint32_t i;
SDL_LockMutex(renderer->disposeLock); 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); SDL_UnlockMutex(renderer->disposeLock);
} }
@ -8342,6 +8428,108 @@ static void VULKAN_EndComputePass(
vulkanCommandBuffer->currentComputePipeline = NULL; 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( static void VULKAN_BeginCopyPass(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer Refresh_CommandBuffer *commandBuffer
@ -8362,7 +8550,7 @@ static void VULKAN_UploadToTexture(
) { ) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; VulkanCpuBufferContainer *bufferContainer = (VulkanCpuBufferContainer*) cpuBuffer;
VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture;
VkBufferImageCopy imageCopy; VkBufferImageCopy imageCopy;
@ -8370,7 +8558,7 @@ static void VULKAN_UploadToTexture(
renderer, renderer,
vulkanCommandBuffer->commandBuffer, vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_READ, RESOURCE_ACCESS_TRANSFER_READ,
vulkanCpuBuffer bufferContainer->activeBuffer->vulkanBuffer
); );
VULKAN_INTERNAL_ImageMemoryBarrier( VULKAN_INTERNAL_ImageMemoryBarrier(
@ -8403,14 +8591,14 @@ static void VULKAN_UploadToTexture(
renderer->vkCmdCopyBufferToImage( renderer->vkCmdCopyBufferToImage(
vulkanCommandBuffer->commandBuffer, vulkanCommandBuffer->commandBuffer,
vulkanCpuBuffer->buffer, bufferContainer->activeBuffer->vulkanBuffer->buffer,
vulkanTexture->image, vulkanTexture->image,
AccessMap[vulkanTexture->resourceAccessType].imageLayout, AccessMap[vulkanTexture->resourceAccessType].imageLayout,
1, 1,
&imageCopy &imageCopy
); );
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanCpuBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBuffer->vulkanBuffer);
VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture);
VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture); VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture);
} }
@ -8424,7 +8612,7 @@ static void VULKAN_UploadToBuffer(
) { ) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; VulkanCpuBufferContainer *cpuBufferContainer = (VulkanCpuBufferContainer*) cpuBuffer;
VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer;
VkBufferCopy bufferCopy; VkBufferCopy bufferCopy;
@ -8432,7 +8620,7 @@ static void VULKAN_UploadToBuffer(
renderer, renderer,
vulkanCommandBuffer->commandBuffer, vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_READ, RESOURCE_ACCESS_TRANSFER_READ,
vulkanCpuBuffer cpuBufferContainer->activeBuffer->vulkanBuffer
); );
VULKAN_INTERNAL_BufferMemoryBarrier( VULKAN_INTERNAL_BufferMemoryBarrier(
@ -8448,13 +8636,13 @@ static void VULKAN_UploadToBuffer(
renderer->vkCmdCopyBuffer( renderer->vkCmdCopyBuffer(
vulkanCommandBuffer->commandBuffer, vulkanCommandBuffer->commandBuffer,
vulkanCpuBuffer->buffer, cpuBufferContainer->activeBuffer->vulkanBuffer->buffer,
vulkanGpuBuffer->buffer, vulkanGpuBuffer->buffer,
1, 1,
&bufferCopy &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);
VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer);
} }
@ -8469,14 +8657,14 @@ static void VULKAN_DownloadFromTexture(
VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture;
VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; VulkanCpuBufferContainer *cpuBufferContainer = (VulkanCpuBufferContainer*) cpuBuffer;
VkBufferImageCopy imageCopy; VkBufferImageCopy imageCopy;
VULKAN_INTERNAL_BufferMemoryBarrier( VULKAN_INTERNAL_BufferMemoryBarrier(
renderer, renderer,
vulkanCommandBuffer->commandBuffer, vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_WRITE, RESOURCE_ACCESS_TRANSFER_WRITE,
vulkanCpuBuffer cpuBufferContainer->activeBuffer->vulkanBuffer
); );
VULKAN_INTERNAL_ImageMemoryBarrier( VULKAN_INTERNAL_ImageMemoryBarrier(
@ -8511,14 +8699,16 @@ static void VULKAN_DownloadFromTexture(
vulkanCommandBuffer->commandBuffer, vulkanCommandBuffer->commandBuffer,
vulkanTexture->image, vulkanTexture->image,
AccessMap[vulkanTexture->resourceAccessType].imageLayout, AccessMap[vulkanTexture->resourceAccessType].imageLayout,
vulkanCpuBuffer->buffer, cpuBufferContainer->activeBuffer->vulkanBuffer->buffer,
1, 1,
&imageCopy &imageCopy
); );
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanCpuBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, cpuBufferContainer->activeBuffer->vulkanBuffer);
VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture);
VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture); VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture);
cpuBufferContainer->activeBuffer->vulkanBuffer->preserveContentsOnDefrag = 1;
} }
static void VULKAN_DownloadFromBuffer( static void VULKAN_DownloadFromBuffer(
@ -8530,7 +8720,7 @@ static void VULKAN_DownloadFromBuffer(
) { ) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; VulkanCpuBufferContainer *cpuBufferContainer = (VulkanCpuBufferContainer*) cpuBuffer;
VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer;
VkBufferCopy bufferCopy; VkBufferCopy bufferCopy;
@ -8538,7 +8728,7 @@ static void VULKAN_DownloadFromBuffer(
renderer, renderer,
vulkanCommandBuffer->commandBuffer, vulkanCommandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_WRITE, RESOURCE_ACCESS_TRANSFER_WRITE,
vulkanCpuBuffer cpuBufferContainer->activeBuffer->vulkanBuffer
); );
VULKAN_INTERNAL_BufferMemoryBarrier( VULKAN_INTERNAL_BufferMemoryBarrier(
@ -8555,14 +8745,16 @@ static void VULKAN_DownloadFromBuffer(
renderer->vkCmdCopyBuffer( renderer->vkCmdCopyBuffer(
vulkanCommandBuffer->commandBuffer, vulkanCommandBuffer->commandBuffer,
vulkanGpuBuffer->buffer, vulkanGpuBuffer->buffer,
vulkanCpuBuffer->buffer, cpuBufferContainer->activeBuffer->vulkanBuffer->buffer,
1, 1,
&bufferCopy &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);
VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer);
cpuBufferContainer->activeBuffer->vulkanBuffer->preserveContentsOnDefrag = 1;
} }
static void VULKAN_CopyTextureToTexture( static void VULKAN_CopyTextureToTexture(
@ -10118,7 +10310,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
currentRegion = allocation->usedRegions[i]; currentRegion = allocation->usedRegions[i];
copyResourceAccessType = RESOURCE_ACCESS_NONE; copyResourceAccessType = RESOURCE_ACCESS_NONE;
if (currentRegion->isBuffer) if (currentRegion->isBuffer && !currentRegion->vulkanBuffer->markedForDestroy)
{ {
currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
@ -10130,7 +10322,8 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
currentRegion->vulkanBuffer->requireHostVisible, currentRegion->vulkanBuffer->requireHostVisible,
currentRegion->vulkanBuffer->requireHostLocal, currentRegion->vulkanBuffer->requireHostLocal,
currentRegion->vulkanBuffer->preferDeviceLocal, currentRegion->vulkanBuffer->preferDeviceLocal,
0 0,
currentRegion->vulkanBuffer->preserveContentsOnDefrag
); );
if (newBuffer == NULL) if (newBuffer == NULL)
@ -10139,43 +10332,47 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
return 0; return 0;
} }
originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType; /* Copy buffer contents if necessary */
if (currentRegion->vulkanBuffer->preserveContentsOnDefrag)
{
originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType;
VULKAN_INTERNAL_BufferMemoryBarrier( VULKAN_INTERNAL_BufferMemoryBarrier(
renderer, renderer,
commandBuffer->commandBuffer, commandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_READ, RESOURCE_ACCESS_TRANSFER_READ,
currentRegion->vulkanBuffer currentRegion->vulkanBuffer
); );
VULKAN_INTERNAL_BufferMemoryBarrier( VULKAN_INTERNAL_BufferMemoryBarrier(
renderer, renderer,
commandBuffer->commandBuffer, commandBuffer->commandBuffer,
RESOURCE_ACCESS_TRANSFER_WRITE, RESOURCE_ACCESS_TRANSFER_WRITE,
newBuffer newBuffer
); );
bufferCopy.srcOffset = 0; bufferCopy.srcOffset = 0;
bufferCopy.dstOffset = 0; bufferCopy.dstOffset = 0;
bufferCopy.size = currentRegion->resourceSize; bufferCopy.size = currentRegion->resourceSize;
renderer->vkCmdCopyBuffer( renderer->vkCmdCopyBuffer(
commandBuffer->commandBuffer, commandBuffer->commandBuffer,
currentRegion->vulkanBuffer->buffer, currentRegion->vulkanBuffer->buffer,
newBuffer->buffer, newBuffer->buffer,
1, 1,
&bufferCopy &bufferCopy
); );
VULKAN_INTERNAL_BufferMemoryBarrier( VULKAN_INTERNAL_BufferMemoryBarrier(
renderer, renderer,
commandBuffer->commandBuffer, commandBuffer->commandBuffer,
originalResourceAccessType, originalResourceAccessType,
newBuffer newBuffer
); );
VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, currentRegion->vulkanBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, currentRegion->vulkanBuffer);
VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, newBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, newBuffer);
}
/* re-point original container to new buffer */ /* re-point original container to new buffer */
if (currentRegion->vulkanBuffer->container != NULL) if (currentRegion->vulkanBuffer->container != NULL)
@ -10189,7 +10386,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
renderer->needDefrag = 1; renderer->needDefrag = 1;
} }
else else if (!currentRegion->vulkanTexture->markedForDestroy)
{ {
newTexture = VULKAN_INTERNAL_CreateTexture( newTexture = VULKAN_INTERNAL_CreateTexture(
renderer, renderer,