From c696e93180a7a57991161798400adc7c05af0d8b Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+thatcosmonaut@users.noreply.github.com> 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 bd3910bd7b..5803a7aedc 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,