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 */
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,6 +10332,9 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
return 0;
}
/* Copy buffer contents if necessary */
if (currentRegion->vulkanBuffer->preserveContentsOnDefrag)
{
originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType;
VULKAN_INTERNAL_BufferMemoryBarrier(
@ -10176,6 +10372,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
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,