From c696e93180a7a57991161798400adc7c05af0d8b Mon Sep 17 00:00:00 2001
From: Evan Hemsley <[EMAIL REDACTED]>
Date: Wed, 19 Mar 2025 13:32:14 -0700
Subject: [PATCH] GPU Vulkan: Fix render pass race (#12587)
---
src/gpu/vulkan/SDL_gpu_vulkan.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c
index bd3910bd7ba0d..5803a7aedc7d9 100644
--- a/src/gpu/vulkan/SDL_gpu_vulkan.c
+++ b/src/gpu/vulkan/SDL_gpu_vulkan.c
@@ -1175,6 +1175,7 @@ struct VulkanRenderer
SDL_Mutex *submitLock;
SDL_Mutex *acquireCommandBufferLock;
SDL_Mutex *acquireUniformBufferLock;
+ SDL_Mutex *renderPassFetchLock;
SDL_Mutex *framebufferFetchLock;
SDL_Mutex *windowLock;
@@ -4889,6 +4890,7 @@ static void VULKAN_DestroyDevice(
SDL_DestroyMutex(renderer->submitLock);
SDL_DestroyMutex(renderer->acquireCommandBufferLock);
SDL_DestroyMutex(renderer->acquireUniformBufferLock);
+ SDL_DestroyMutex(renderer->renderPassFetchLock);
SDL_DestroyMutex(renderer->framebufferFetchLock);
SDL_DestroyMutex(renderer->windowLock);
@@ -7034,12 +7036,15 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
key.depthStencilTargetDescription.stencilStoreOp = depthStencilTargetInfo->stencil_store_op;
}
+ SDL_LockMutex(renderer->renderPassFetchLock);
+
bool result = SDL_FindInHashTable(
renderer->renderPassHashTable,
(const void *)&key,
(const void **)&renderPassWrapper);
if (result) {
+ SDL_UnlockMutex(renderer->renderPassFetchLock);
return renderPassWrapper->handle;
}
@@ -7050,6 +7055,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
depthStencilTargetInfo);
if (renderPassHandle == VK_NULL_HANDLE) {
+ SDL_UnlockMutex(renderer->renderPassFetchLock);
return VK_NULL_HANDLE;
}
@@ -7065,6 +7071,8 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
(const void *)allocedKey,
(const void *)renderPassWrapper, true);
+ SDL_UnlockMutex(renderer->renderPassFetchLock);
+
return renderPassHandle;
}
@@ -7133,9 +7141,8 @@ static VulkanFramebuffer *VULKAN_INTERNAL_FetchFramebuffer(
(const void *)&key,
(const void **)&vulkanFramebuffer);
- SDL_UnlockMutex(renderer->framebufferFetchLock);
-
if (findResult) {
+ SDL_UnlockMutex(renderer->framebufferFetchLock);
return vulkanFramebuffer;
}
@@ -7203,19 +7210,18 @@ static VulkanFramebuffer *VULKAN_INTERNAL_FetchFramebuffer(
FramebufferHashTableKey *allocedKey = SDL_malloc(sizeof(FramebufferHashTableKey));
SDL_memcpy(allocedKey, &key, sizeof(FramebufferHashTableKey));
- SDL_LockMutex(renderer->framebufferFetchLock);
-
SDL_InsertIntoHashTable(
renderer->framebufferHashTable,
(const void *)allocedKey,
(const void *)vulkanFramebuffer, true);
- SDL_UnlockMutex(renderer->framebufferFetchLock);
} else {
SDL_free(vulkanFramebuffer);
+ SDL_UnlockMutex(renderer->framebufferFetchLock);
CHECK_VULKAN_ERROR_AND_RETURN(result, vkCreateFramebuffer, NULL);
}
+ SDL_UnlockMutex(renderer->framebufferFetchLock);
return vulkanFramebuffer;
}
@@ -11607,6 +11613,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
renderer->submitLock = SDL_CreateMutex();
renderer->acquireCommandBufferLock = SDL_CreateMutex();
renderer->acquireUniformBufferLock = SDL_CreateMutex();
+ renderer->renderPassFetchLock = SDL_CreateMutex();
renderer->framebufferFetchLock = SDL_CreateMutex();
renderer->windowLock = SDL_CreateMutex();
@@ -11668,7 +11675,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
renderer->renderPassHashTable = SDL_CreateHashTable(
0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
- true, // thread-safe
+ false, // manually synchronized due to timing
VULKAN_INTERNAL_RenderPassHashFunction,
VULKAN_INTERNAL_RenderPassHashKeyMatch,
VULKAN_INTERNAL_RenderPassHashDestroy,