Răsfoiți Sursa

metal: 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 metalCommandBuffer->fence, handing the caller a
fence it doesn't own.
William Horvath 3 săptămâni în urmă
părinte
comite
10309e3240
1 a modificat fișierele cu 18 adăugiri și 4 ștergeri
  1. 18 4
      src/gpu/metal/SDL_gpu_metal.m

+ 18 - 4
src/gpu/metal/SDL_gpu_metal.m

@@ -4069,8 +4069,9 @@ static bool METAL_SetAllowedFramesInFlight(
 
 
 // Submission
 // Submission
 
 
-static bool METAL_Submit(
-    SDL_GPUCommandBuffer *commandBuffer)
+static bool METAL_INTERNAL_Submit(
+    SDL_GPUCommandBuffer *commandBuffer,
+    SDL_GPUFence **fence)
 {
 {
     @autoreleasepool {
     @autoreleasepool {
         MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
         MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
@@ -4083,6 +4084,12 @@ static bool METAL_Submit(
             return false;
             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 *)metalCommandBuffer->fence;
+        }
+
         // Enqueue present requests, if applicable
         // Enqueue present requests, if applicable
         for (Uint32 i = 0; i < metalCommandBuffer->windowDataCount; i += 1) {
         for (Uint32 i = 0; i < metalCommandBuffer->windowDataCount; i += 1) {
             MetalWindowData *windowData = metalCommandBuffer->windowDatas[i];
             MetalWindowData *windowData = metalCommandBuffer->windowDatas[i];
@@ -4129,15 +4136,22 @@ static bool METAL_Submit(
     }
     }
 }
 }
 
 
+static bool METAL_Submit(
+    SDL_GPUCommandBuffer *commandBuffer)
+{
+    return METAL_INTERNAL_Submit(commandBuffer, NULL);
+}
+
 static SDL_GPUFence *METAL_SubmitAndAcquireFence(
 static SDL_GPUFence *METAL_SubmitAndAcquireFence(
     SDL_GPUCommandBuffer *commandBuffer)
     SDL_GPUCommandBuffer *commandBuffer)
 {
 {
     MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
     MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    SDL_GPUFence *fence = NULL;
     metalCommandBuffer->autoReleaseFence = false;
     metalCommandBuffer->autoReleaseFence = false;
-    if (!METAL_Submit(commandBuffer)) {
+    if (!METAL_INTERNAL_Submit(commandBuffer, &fence)) {
         return NULL;
         return NULL;
     }
     }
-    return (SDL_GPUFence *)metalCommandBuffer->fence;
+    return fence;
 }
 }
 
 
 static bool METAL_Cancel(
 static bool METAL_Cancel(