From 9a29f763e1ce9eb0442b997fc34a97bd98268309 Mon Sep 17 00:00:00 2001 From: William Horvath Date: Sat, 29 Aug 2026 17:06:19 +0900 Subject: [PATCH] d3d12: Read the fence in SubmitAndAcquireFence while submitLock is held Once the lock is released, another thread can clean up the completed command buffer, return it to the pool and resubmit it with a different fence before we read d3d12CommandBuffer->inFlightFence, handing the caller a fence it doesn't own (or NULL). (cherry picked from commit f443c429c667b752e2809efbdc7315bd4d7f90df) --- src/gpu/d3d12/SDL_gpu_d3d12.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/gpu/d3d12/SDL_gpu_d3d12.c b/src/gpu/d3d12/SDL_gpu_d3d12.c index 43015c820d..d172c945ca 100644 --- a/src/gpu/d3d12/SDL_gpu_d3d12.c +++ b/src/gpu/d3d12/SDL_gpu_d3d12.c @@ -7957,8 +7957,9 @@ static bool D3D12_INTERNAL_CleanCommandBuffer( return true; } -static bool D3D12_Submit( - SDL_GPUCommandBuffer *commandBuffer) +static bool D3D12_INTERNAL_Submit( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUFence **fence) { D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer; D3D12Renderer *renderer = d3d12CommandBuffer->renderer; @@ -8036,6 +8037,12 @@ static bool D3D12_Submit( return false; } + // Return the fence while submitLock is held, another thread could + // recycle this command buffer as soon as the lock is released. + if (fence) { + *fence = (SDL_GPUFence *)d3d12CommandBuffer->inFlightFence; + } + // Mark that a fence should be signaled after command list execution res = ID3D12CommandQueue_Signal( renderer->commandQueue, @@ -8134,15 +8141,22 @@ static bool D3D12_Submit( return result; } +static bool D3D12_Submit( + SDL_GPUCommandBuffer *commandBuffer) +{ + return D3D12_INTERNAL_Submit(commandBuffer, NULL); +} + static SDL_GPUFence *D3D12_SubmitAndAcquireFence( SDL_GPUCommandBuffer *commandBuffer) { D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer; + SDL_GPUFence *fence = NULL; d3d12CommandBuffer->autoReleaseFence = false; - if (!D3D12_Submit(commandBuffer)) { + if (!D3D12_INTERNAL_Submit(commandBuffer, &fence)) { return NULL; } - return (SDL_GPUFence *)d3d12CommandBuffer->inFlightFence; + return fence; } static bool D3D12_Cancel(