|
|
@@ -500,6 +500,7 @@ struct VulkanMemoryAllocation
|
|
|
VkDeviceSize usedSpace;
|
|
|
Uint8 *mapPointer;
|
|
|
SDL_Mutex *memoryLock;
|
|
|
+ SDL_AtomicInt referenceCount; // Used to avoid defrag races
|
|
|
};
|
|
|
|
|
|
typedef struct VulkanMemoryAllocator
|
|
|
@@ -1040,10 +1041,18 @@ typedef struct VulkanCommandBuffer
|
|
|
Sint32 usedBufferCount;
|
|
|
Sint32 usedBufferCapacity;
|
|
|
|
|
|
+ VulkanBuffer **buffersUsedInPendingTransfers;
|
|
|
+ Sint32 buffersUsedInPendingTransfersCount;
|
|
|
+ Sint32 buffersUsedInPendingTransfersCapacity;
|
|
|
+
|
|
|
VulkanTexture **usedTextures;
|
|
|
Sint32 usedTextureCount;
|
|
|
Sint32 usedTextureCapacity;
|
|
|
|
|
|
+ VulkanTexture **texturesUsedInPendingTransfers;
|
|
|
+ Sint32 texturesUsedInPendingTransfersCount;
|
|
|
+ Sint32 texturesUsedInPendingTransfersCapacity;
|
|
|
+
|
|
|
VulkanSampler **usedSamplers;
|
|
|
Sint32 usedSamplerCount;
|
|
|
Sint32 usedSamplerCapacity;
|
|
|
@@ -1205,6 +1214,10 @@ struct VulkanRenderer
|
|
|
SDL_Mutex *descriptorSetLayoutFetchLock;
|
|
|
SDL_Mutex *windowLock;
|
|
|
|
|
|
+ // We don't want transfer commands to block each other,
|
|
|
+ // but we want all transfers to block during defrag.
|
|
|
+ SDL_RWLock *defragLock;
|
|
|
+
|
|
|
Uint8 defragInProgress;
|
|
|
|
|
|
VulkanMemoryAllocation **allocationsToDefrag;
|
|
|
@@ -1836,6 +1849,8 @@ static Uint8 VULKAN_INTERNAL_AllocateMemory(
|
|
|
allocation->freeRegionCount = 0;
|
|
|
allocation->freeRegionCapacity = 1;
|
|
|
|
|
|
+ SDL_SetAtomicInt(&allocation->referenceCount, 0);
|
|
|
+
|
|
|
allocation->allocator = allocator;
|
|
|
|
|
|
result = renderer->vkAllocateMemory(
|
|
|
@@ -2373,7 +2388,7 @@ static Uint8 VULKAN_INTERNAL_BindMemoryForBuffer(
|
|
|
|
|
|
// Resource tracking
|
|
|
|
|
|
-#define TRACK_RESOURCE(resource, type, array, count, capacity) \
|
|
|
+#define TRACK_RESOURCE(resource, type, array, count, capacity, refcountvar) \
|
|
|
for (Sint32 i = commandBuffer->count - 1; i >= 0; i -= 1) { \
|
|
|
if (commandBuffer->array[i] == resource) { \
|
|
|
return; \
|
|
|
@@ -2388,7 +2403,8 @@ static Uint8 VULKAN_INTERNAL_BindMemoryForBuffer(
|
|
|
} \
|
|
|
commandBuffer->array[commandBuffer->count] = resource; \
|
|
|
commandBuffer->count += 1; \
|
|
|
- SDL_AtomicIncRef(&resource->referenceCount);
|
|
|
+ SDL_AtomicIncRef(&refcountvar)
|
|
|
+
|
|
|
|
|
|
static void VULKAN_INTERNAL_TrackBuffer(
|
|
|
VulkanCommandBuffer *commandBuffer,
|
|
|
@@ -2399,7 +2415,23 @@ static void VULKAN_INTERNAL_TrackBuffer(
|
|
|
VulkanBuffer *,
|
|
|
usedBuffers,
|
|
|
usedBufferCount,
|
|
|
- usedBufferCapacity)
|
|
|
+ usedBufferCapacity,
|
|
|
+ buffer->referenceCount);
|
|
|
+}
|
|
|
+
|
|
|
+// Use this function when a GPU buffer is part of a transfer operation.
|
|
|
+// Note that this isn't for transfer buffers, those don't need to refcount their allocations.
|
|
|
+static void VULKAN_INTERNAL_TrackBufferTransfer(
|
|
|
+ VulkanCommandBuffer *commandBuffer,
|
|
|
+ VulkanBuffer *buffer)
|
|
|
+{
|
|
|
+ TRACK_RESOURCE(
|
|
|
+ buffer,
|
|
|
+ VulkanBuffer *,
|
|
|
+ buffersUsedInPendingTransfers,
|
|
|
+ buffersUsedInPendingTransfersCount,
|
|
|
+ buffersUsedInPendingTransfersCapacity,
|
|
|
+ buffer->usedRegion->allocation->referenceCount);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_INTERNAL_TrackTexture(
|
|
|
@@ -2411,7 +2443,22 @@ static void VULKAN_INTERNAL_TrackTexture(
|
|
|
VulkanTexture *,
|
|
|
usedTextures,
|
|
|
usedTextureCount,
|
|
|
- usedTextureCapacity)
|
|
|
+ usedTextureCapacity,
|
|
|
+ texture->referenceCount);
|
|
|
+}
|
|
|
+
|
|
|
+// Use this when a texture is part of a transfer operation.
|
|
|
+static void VULKAN_INTERNAL_TrackTextureTransfer(
|
|
|
+ VulkanCommandBuffer *commandBuffer,
|
|
|
+ VulkanTexture *texture)
|
|
|
+{
|
|
|
+ TRACK_RESOURCE(
|
|
|
+ texture,
|
|
|
+ VulkanTexture *,
|
|
|
+ texturesUsedInPendingTransfers,
|
|
|
+ texturesUsedInPendingTransfersCount,
|
|
|
+ texturesUsedInPendingTransfersCapacity,
|
|
|
+ texture->usedRegion->allocation->referenceCount);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_INTERNAL_TrackSampler(
|
|
|
@@ -2423,7 +2470,8 @@ static void VULKAN_INTERNAL_TrackSampler(
|
|
|
VulkanSampler *,
|
|
|
usedSamplers,
|
|
|
usedSamplerCount,
|
|
|
- usedSamplerCapacity)
|
|
|
+ usedSamplerCapacity,
|
|
|
+ sampler->referenceCount);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_INTERNAL_TrackGraphicsPipeline(
|
|
|
@@ -2435,7 +2483,8 @@ static void VULKAN_INTERNAL_TrackGraphicsPipeline(
|
|
|
VulkanGraphicsPipeline *,
|
|
|
usedGraphicsPipelines,
|
|
|
usedGraphicsPipelineCount,
|
|
|
- usedGraphicsPipelineCapacity)
|
|
|
+ usedGraphicsPipelineCapacity,
|
|
|
+ graphicsPipeline->referenceCount);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_INTERNAL_TrackComputePipeline(
|
|
|
@@ -2447,7 +2496,8 @@ static void VULKAN_INTERNAL_TrackComputePipeline(
|
|
|
VulkanComputePipeline *,
|
|
|
usedComputePipelines,
|
|
|
usedComputePipelineCount,
|
|
|
- usedComputePipelineCapacity)
|
|
|
+ usedComputePipelineCapacity,
|
|
|
+ computePipeline->referenceCount);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_INTERNAL_TrackFramebuffer(
|
|
|
@@ -2459,7 +2509,8 @@ static void VULKAN_INTERNAL_TrackFramebuffer(
|
|
|
VulkanFramebuffer *,
|
|
|
usedFramebuffers,
|
|
|
usedFramebufferCount,
|
|
|
- usedFramebufferCapacity);
|
|
|
+ usedFramebufferCapacity,
|
|
|
+ framebuffer->referenceCount);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_INTERNAL_TrackUniformBuffer(
|
|
|
@@ -6844,7 +6895,7 @@ static SDL_GPUTexture *VULKAN_CreateTexture(
|
|
|
texture);
|
|
|
VULKAN_INTERNAL_TrackTexture(barrierCommandBuffer, texture);
|
|
|
if (!VULKAN_Submit((SDL_GPUCommandBuffer *)barrierCommandBuffer)) {
|
|
|
- VULKAN_ReleaseTexture((SDL_GPURenderer *)renderer, (SDL_GPUTexture *)container);
|
|
|
+ VULKAN_ReleaseTexture((SDL_GPURenderer *)renderer, (SDL_GPUTexture *)container);
|
|
|
return NULL;
|
|
|
}
|
|
|
}
|
|
|
@@ -8742,8 +8793,9 @@ static void VULKAN_UploadToTexture(
|
|
|
VulkanTextureSubresource *vulkanTextureSubresource;
|
|
|
VkBufferImageCopy imageCopy;
|
|
|
|
|
|
- // Note that the transfer buffer does not need a barrier, as it is synced by the client
|
|
|
+ SDL_LockRWLockForReading(renderer->defragLock);
|
|
|
|
|
|
+ // Note that the transfer buffer does not need a barrier, as it is synced by the client
|
|
|
vulkanTextureSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
|
|
|
renderer,
|
|
|
vulkanCommandBuffer,
|
|
|
@@ -8783,6 +8835,9 @@ static void VULKAN_UploadToTexture(
|
|
|
|
|
|
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
|
|
|
VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, vulkanTextureSubresource->parent);
|
|
|
+ VULKAN_INTERNAL_TrackTextureTransfer(vulkanCommandBuffer, vulkanTextureSubresource->parent);
|
|
|
+
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_UploadToBuffer(
|
|
|
@@ -8797,8 +8852,9 @@ static void VULKAN_UploadToBuffer(
|
|
|
VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)destination->buffer;
|
|
|
VkBufferCopy bufferCopy;
|
|
|
|
|
|
- // Note that the transfer buffer does not need a barrier, as it is synced by the client
|
|
|
+ SDL_LockRWLockForReading(renderer->defragLock);
|
|
|
|
|
|
+ // Note that the transfer buffer does not need a barrier, as it is synced by the client
|
|
|
VulkanBuffer *vulkanBuffer = VULKAN_INTERNAL_PrepareBufferForWrite(
|
|
|
renderer,
|
|
|
vulkanCommandBuffer,
|
|
|
@@ -8806,6 +8862,7 @@ static void VULKAN_UploadToBuffer(
|
|
|
cycle,
|
|
|
VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION);
|
|
|
|
|
|
+
|
|
|
bufferCopy.srcOffset = source->offset;
|
|
|
bufferCopy.dstOffset = destination->offset;
|
|
|
bufferCopy.size = destination->size;
|
|
|
@@ -8825,6 +8882,9 @@ static void VULKAN_UploadToBuffer(
|
|
|
|
|
|
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
|
|
|
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
|
|
|
+ VULKAN_INTERNAL_TrackBufferTransfer(vulkanCommandBuffer, vulkanBuffer);
|
|
|
+
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
}
|
|
|
|
|
|
// Readback
|
|
|
@@ -8840,6 +8900,9 @@ static void VULKAN_DownloadFromTexture(
|
|
|
VulkanTextureSubresource *vulkanTextureSubresource;
|
|
|
VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)destination->transfer_buffer;
|
|
|
VkBufferImageCopy imageCopy;
|
|
|
+
|
|
|
+ SDL_LockRWLockForReading(renderer->defragLock);
|
|
|
+
|
|
|
vulkanTextureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
|
|
|
textureContainer,
|
|
|
source->layer,
|
|
|
@@ -8883,6 +8946,9 @@ static void VULKAN_DownloadFromTexture(
|
|
|
|
|
|
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
|
|
|
VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, vulkanTextureSubresource->parent);
|
|
|
+ VULKAN_INTERNAL_TrackTextureTransfer(vulkanCommandBuffer, vulkanTextureSubresource->parent);
|
|
|
+
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_DownloadFromBuffer(
|
|
|
@@ -8896,8 +8962,9 @@ static void VULKAN_DownloadFromBuffer(
|
|
|
VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)destination->transfer_buffer;
|
|
|
VkBufferCopy bufferCopy;
|
|
|
|
|
|
- // Note that transfer buffer does not need a barrier, as it is synced by the client
|
|
|
+ SDL_LockRWLockForReading(renderer->defragLock);
|
|
|
|
|
|
+ // Note that transfer buffer does not need a barrier, as it is synced by the client
|
|
|
VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
|
|
|
renderer,
|
|
|
vulkanCommandBuffer,
|
|
|
@@ -8923,6 +8990,9 @@ static void VULKAN_DownloadFromBuffer(
|
|
|
|
|
|
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
|
|
|
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, bufferContainer->activeBuffer);
|
|
|
+ VULKAN_INTERNAL_TrackBufferTransfer(vulkanCommandBuffer, bufferContainer->activeBuffer);
|
|
|
+
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_CopyTextureToTexture(
|
|
|
@@ -8940,6 +9010,8 @@ static void VULKAN_CopyTextureToTexture(
|
|
|
VulkanTextureSubresource *dstSubresource;
|
|
|
VkImageCopy imageCopy;
|
|
|
|
|
|
+ SDL_LockRWLockForReading(renderer->defragLock);
|
|
|
+
|
|
|
srcSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
|
|
|
(VulkanTextureContainer *)source->texture,
|
|
|
source->layer,
|
|
|
@@ -9001,6 +9073,10 @@ static void VULKAN_CopyTextureToTexture(
|
|
|
|
|
|
VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcSubresource->parent);
|
|
|
VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstSubresource->parent);
|
|
|
+ VULKAN_INTERNAL_TrackTextureTransfer(vulkanCommandBuffer, srcSubresource->parent);
|
|
|
+ VULKAN_INTERNAL_TrackTextureTransfer(vulkanCommandBuffer, dstSubresource->parent);
|
|
|
+
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_CopyBufferToBuffer(
|
|
|
@@ -9016,6 +9092,8 @@ static void VULKAN_CopyBufferToBuffer(
|
|
|
VulkanBufferContainer *dstContainer = (VulkanBufferContainer *)destination->buffer;
|
|
|
VkBufferCopy bufferCopy;
|
|
|
|
|
|
+ SDL_LockRWLockForReading(renderer->defragLock);
|
|
|
+
|
|
|
VulkanBuffer *dstBuffer = VULKAN_INTERNAL_PrepareBufferForWrite(
|
|
|
renderer,
|
|
|
vulkanCommandBuffer,
|
|
|
@@ -9054,6 +9132,10 @@ static void VULKAN_CopyBufferToBuffer(
|
|
|
|
|
|
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, srcContainer->activeBuffer);
|
|
|
VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, dstBuffer);
|
|
|
+ VULKAN_INTERNAL_TrackBufferTransfer(vulkanCommandBuffer, srcContainer->activeBuffer);
|
|
|
+ VULKAN_INTERNAL_TrackBufferTransfer(vulkanCommandBuffer, dstBuffer);
|
|
|
+
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_GenerateMipmaps(
|
|
|
@@ -9067,8 +9149,10 @@ static void VULKAN_GenerateMipmaps(
|
|
|
VulkanTextureSubresource *dstTextureSubresource;
|
|
|
VkImageBlit blit;
|
|
|
|
|
|
+ SDL_LockRWLockForReading(renderer->defragLock);
|
|
|
+
|
|
|
// Blit each slice sequentially. Barriers, barriers everywhere!
|
|
|
- for (Uint32 layerOrDepthIndex = 0; layerOrDepthIndex < container->header.info.layer_count_or_depth; layerOrDepthIndex += 1)
|
|
|
+ for (Uint32 layerOrDepthIndex = 0; layerOrDepthIndex < container->header.info.layer_count_or_depth; layerOrDepthIndex += 1) {
|
|
|
for (Uint32 level = 1; level < container->header.info.num_levels; level += 1) {
|
|
|
Uint32 layer = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : layerOrDepthIndex;
|
|
|
Uint32 depth = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? layerOrDepthIndex : 0;
|
|
|
@@ -9147,7 +9231,13 @@ static void VULKAN_GenerateMipmaps(
|
|
|
|
|
|
VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcTextureSubresource->parent);
|
|
|
VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstTextureSubresource->parent);
|
|
|
+ VULKAN_INTERNAL_TrackTextureTransfer(vulkanCommandBuffer, srcTextureSubresource->parent);
|
|
|
+ VULKAN_INTERNAL_TrackTextureTransfer(vulkanCommandBuffer, dstTextureSubresource->parent);
|
|
|
+
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_EndCopyPass(
|
|
|
@@ -9357,11 +9447,21 @@ static bool VULKAN_INTERNAL_AllocateCommandBuffer(
|
|
|
commandBuffer->usedBuffers = SDL_malloc(
|
|
|
commandBuffer->usedBufferCapacity * sizeof(VulkanBuffer *));
|
|
|
|
|
|
+ commandBuffer->buffersUsedInPendingTransfersCapacity = 4;
|
|
|
+ commandBuffer->buffersUsedInPendingTransfersCount = 0;
|
|
|
+ commandBuffer->buffersUsedInPendingTransfers = SDL_malloc(
|
|
|
+ commandBuffer->buffersUsedInPendingTransfersCapacity * sizeof(VulkanBuffer *));
|
|
|
+
|
|
|
commandBuffer->usedTextureCapacity = 4;
|
|
|
commandBuffer->usedTextureCount = 0;
|
|
|
commandBuffer->usedTextures = SDL_malloc(
|
|
|
commandBuffer->usedTextureCapacity * sizeof(VulkanTexture *));
|
|
|
|
|
|
+ commandBuffer->texturesUsedInPendingTransfersCapacity = 4;
|
|
|
+ commandBuffer->texturesUsedInPendingTransfersCount = 0;
|
|
|
+ commandBuffer->texturesUsedInPendingTransfers = SDL_malloc(
|
|
|
+ commandBuffer->texturesUsedInPendingTransfersCapacity * sizeof(VulkanTexture *));
|
|
|
+
|
|
|
commandBuffer->usedSamplerCapacity = 4;
|
|
|
commandBuffer->usedSamplerCount = 0;
|
|
|
commandBuffer->usedSamplers = SDL_malloc(
|
|
|
@@ -10430,11 +10530,21 @@ static void VULKAN_INTERNAL_CleanCommandBuffer(
|
|
|
}
|
|
|
commandBuffer->usedBufferCount = 0;
|
|
|
|
|
|
+ for (Sint32 i = 0; i < commandBuffer->buffersUsedInPendingTransfersCount; i += 1) {
|
|
|
+ (void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->usedRegion->allocation->referenceCount);
|
|
|
+ }
|
|
|
+ commandBuffer->buffersUsedInPendingTransfersCount = 0;
|
|
|
+
|
|
|
for (Sint32 i = 0; i < commandBuffer->usedTextureCount; i += 1) {
|
|
|
(void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
|
|
|
}
|
|
|
commandBuffer->usedTextureCount = 0;
|
|
|
|
|
|
+ for (Sint32 i = 0; i < commandBuffer->texturesUsedInPendingTransfersCount; i += 1){
|
|
|
+ (void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->usedRegion->allocation->referenceCount);
|
|
|
+ }
|
|
|
+ commandBuffer->texturesUsedInPendingTransfersCount = 0;
|
|
|
+
|
|
|
for (Sint32 i = 0; i < commandBuffer->usedSamplerCount; i += 1) {
|
|
|
(void)SDL_AtomicDecRef(&commandBuffer->usedSamplers[i]->referenceCount);
|
|
|
}
|
|
|
@@ -10820,8 +10930,30 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|
|
commandBuffer->isDefrag = 1;
|
|
|
|
|
|
SDL_LockMutex(renderer->allocatorLock);
|
|
|
+ SDL_LockRWLockForWriting(renderer->defragLock);
|
|
|
+
|
|
|
+ // Find an allocation that doesn't have any pending transfer operations
|
|
|
+ Sint32 indexToDefrag = -1;
|
|
|
+ for (Sint32 i = renderer->allocationsToDefragCount - 1; i >= 0; i -= 1) {
|
|
|
+ if (SDL_GetAtomicInt(&renderer->allocationsToDefrag[i]->referenceCount) == 0) {
|
|
|
+ indexToDefrag = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- VulkanMemoryAllocation *allocation = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
|
|
|
+ if (indexToDefrag == -1) {
|
|
|
+ // Nothing is available to defrag, but it's not an error
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
+ SDL_UnlockMutex(renderer->allocatorLock);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ VulkanMemoryAllocation *allocation = renderer->allocationsToDefrag[indexToDefrag];
|
|
|
+
|
|
|
+ // Plug the hole
|
|
|
+ if ((Uint32) indexToDefrag != renderer->allocationsToDefragCount - 1) {
|
|
|
+ renderer->allocationsToDefrag[indexToDefrag] = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
|
|
|
+ }
|
|
|
renderer->allocationsToDefragCount -= 1;
|
|
|
|
|
|
/* For each used region in the allocation
|
|
|
@@ -10841,6 +10973,7 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|
|
currentRegion->vulkanBuffer->container != NULL ? currentRegion->vulkanBuffer->container->debugName : NULL);
|
|
|
|
|
|
if (newBuffer == NULL) {
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
SDL_UnlockMutex(renderer->allocatorLock);
|
|
|
SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to allocate defrag buffer!");
|
|
|
return false;
|
|
|
@@ -10906,6 +11039,7 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|
|
¤tRegion->vulkanTexture->container->header.info);
|
|
|
|
|
|
if (newTexture == NULL) {
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
SDL_UnlockMutex(renderer->allocatorLock);
|
|
|
SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to allocate defrag buffer!");
|
|
|
return false;
|
|
|
@@ -10980,6 +11114,7 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ SDL_UnlockRWLock(renderer->defragLock);
|
|
|
SDL_UnlockMutex(renderer->allocatorLock);
|
|
|
|
|
|
return true;
|