Răsfoiți Sursa

gpu: Metal fence fixes

(cherry picked from commit 3561f81400fd8cbf74290dabd1440569b46440ae)
Caleb Cornett 2 săptămâni în urmă
părinte
comite
6c10cdb6eb
1 a modificat fișierele cu 14 adăugiri și 27 ștergeri
  1. 14 27
      src/gpu/metal/SDL_gpu_metal.m

+ 14 - 27
src/gpu/metal/SDL_gpu_metal.m

@@ -448,8 +448,7 @@ typedef struct MetalTextureContainer
 
 
 typedef struct MetalFence
 typedef struct MetalFence
 {
 {
-    // can be NULL if the command buffer was recycled
-    MetalCommandBuffer *commandBuffer;
+    id<MTLCommandBuffer> commandBuffer;
     SDL_AtomicInt referenceCount;
     SDL_AtomicInt referenceCount;
 } MetalFence;
 } MetalFence;
 
 
@@ -2131,7 +2130,7 @@ static bool METAL_INTERNAL_AcquireFence(
 
 
     // Associate the fence with the command buffer
     // Associate the fence with the command buffer
     commandBuffer->fence = fence;
     commandBuffer->fence = fence;
-    fence->commandBuffer = commandBuffer;
+    fence->commandBuffer = commandBuffer->handle;
     (void)SDL_AtomicIncRef(&commandBuffer->fence->referenceCount);
     (void)SDL_AtomicIncRef(&commandBuffer->fence->referenceCount);
 
 
     return true;
     return true;
@@ -3401,6 +3400,7 @@ static void METAL_ReleaseFence(
     SDL_GPUFence *fence)
     SDL_GPUFence *fence)
 {
 {
     MetalFence *metalFence = (MetalFence *)fence;
     MetalFence *metalFence = (MetalFence *)fence;
+    metalFence->commandBuffer = nil;
     if (SDL_AtomicDecRef(&metalFence->referenceCount)) {
     if (SDL_AtomicDecRef(&metalFence->referenceCount)) {
         METAL_INTERNAL_ReleaseFenceToPool(
         METAL_INTERNAL_ReleaseFenceToPool(
             (MetalRenderer *)driverData,
             (MetalRenderer *)driverData,
@@ -3512,8 +3512,6 @@ static void METAL_INTERNAL_CleanCommandBuffer(
         METAL_ReleaseFence(
         METAL_ReleaseFence(
             (SDL_GPURenderer *)renderer,
             (SDL_GPURenderer *)renderer,
             (SDL_GPUFence *)commandBuffer->fence);
             (SDL_GPUFence *)commandBuffer->fence);
-    } else {
-        commandBuffer->fence->commandBuffer = NULL;
     }
     }
 
 
     // Return command buffer to pool
     // Return command buffer to pool
@@ -3587,11 +3585,7 @@ static void METAL_INTERNAL_PerformPendingDestroys(
 static bool METAL_INTERNAL_IsFenceBusy(
 static bool METAL_INTERNAL_IsFenceBusy(
         MetalFence *fence
         MetalFence *fence
 ) {
 ) {
-    if (!fence->commandBuffer) {
-        return false; // command buffer was recycled
-    }
-
-    MTLCommandBufferStatus status = fence->commandBuffer->handle.status;
+    MTLCommandBufferStatus status = fence->commandBuffer.status;
     return status == MTLCommandBufferStatusCommitted || status == MTLCommandBufferStatusScheduled;
     return status == MTLCommandBufferStatusCommitted || status == MTLCommandBufferStatusScheduled;
 }
 }
 
 
@@ -3607,25 +3601,19 @@ static bool METAL_WaitForFences(
         if (waitAll) {
         if (waitAll) {
             for (Uint32 i = 0; i < numFences; i += 1) {
             for (Uint32 i = 0; i < numFences; i += 1) {
                 MetalFence *fence = (MetalFence *)fences[i];
                 MetalFence *fence = (MetalFence *)fences[i];
-                if (METAL_INTERNAL_IsFenceBusy(fence)) {
-                    [fence->commandBuffer->handle waitUntilCompleted];
-                }
+                [fence->commandBuffer waitUntilCompleted];
             }
             }
         } else {
         } else {
-            dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
-            for (Uint32 i = 0; i < numFences; i += 1) {
-                MetalFence *fence = (MetalFence *)fences[i];
-                // command buffer has completed and been recycled
-                if(!fence->commandBuffer)
-                    return true;
-
-                // even if it's completed, the handle will call back straight away
-                [fence->commandBuffer->handle addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
-                    dispatch_semaphore_signal(semaphore);
-                }];
+            bool waiting = true;
+            while (waiting) {
+                for (Uint32 i = 0; i < numFences; i += 1) {
+                    MetalFence *fence = (MetalFence *)fences[i];
+                    if (!METAL_INTERNAL_IsFenceBusy(fence)) {
+                        waiting = false;
+                        break;
+                    }
+                }
             }
             }
-
-            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
         }
         }
 
 
         METAL_INTERNAL_PerformPendingDestroys(renderer);
         METAL_INTERNAL_PerformPendingDestroys(renderer);
@@ -4119,7 +4107,6 @@ static bool METAL_Submit(
 
 
         // Check if we can perform any cleanups
         // Check if we can perform any cleanups
         for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
         for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
-
             if (!METAL_INTERNAL_IsFenceBusy(renderer->submittedCommandBuffers[i]->fence)) {
             if (!METAL_INTERNAL_IsFenceBusy(renderer->submittedCommandBuffers[i]->fence)) {
                 METAL_INTERNAL_CleanCommandBuffer(
                 METAL_INTERNAL_CleanCommandBuffer(
                     renderer,
                     renderer,