mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-06-22 14:01:55 +00:00
gpu: Metal fence fixes
This commit is contained in:
parent
e575093c83
commit
3561f81400
1 changed files with 14 additions and 27 deletions
|
|
@ -454,8 +454,7 @@ typedef struct MetalTextureContainer
|
|||
|
||||
typedef struct MetalFence
|
||||
{
|
||||
// can be NULL if the command buffer was recycled
|
||||
MetalCommandBuffer *commandBuffer;
|
||||
id<MTLCommandBuffer> commandBuffer;
|
||||
SDL_AtomicInt referenceCount;
|
||||
} MetalFence;
|
||||
|
||||
|
|
@ -2137,7 +2136,7 @@ static bool METAL_INTERNAL_AcquireFence(
|
|||
|
||||
// Associate the fence with the command buffer
|
||||
commandBuffer->fence = fence;
|
||||
fence->commandBuffer = commandBuffer;
|
||||
fence->commandBuffer = commandBuffer->handle;
|
||||
(void)SDL_AtomicIncRef(&commandBuffer->fence->referenceCount);
|
||||
|
||||
return true;
|
||||
|
|
@ -3407,6 +3406,7 @@ static void METAL_ReleaseFence(
|
|||
SDL_GPUFence *fence)
|
||||
{
|
||||
MetalFence *metalFence = (MetalFence *)fence;
|
||||
metalFence->commandBuffer = nil;
|
||||
if (SDL_AtomicDecRef(&metalFence->referenceCount)) {
|
||||
METAL_INTERNAL_ReleaseFenceToPool(
|
||||
(MetalRenderer *)driverData,
|
||||
|
|
@ -3518,8 +3518,6 @@ static void METAL_INTERNAL_CleanCommandBuffer(
|
|||
METAL_ReleaseFence(
|
||||
(SDL_GPURenderer *)renderer,
|
||||
(SDL_GPUFence *)commandBuffer->fence);
|
||||
} else {
|
||||
commandBuffer->fence->commandBuffer = NULL;
|
||||
}
|
||||
|
||||
// Return command buffer to pool
|
||||
|
|
@ -3593,11 +3591,7 @@ static void METAL_INTERNAL_PerformPendingDestroys(
|
|||
static bool METAL_INTERNAL_IsFenceBusy(
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -3613,25 +3607,19 @@ static bool METAL_WaitForFences(
|
|||
if (waitAll) {
|
||||
for (Uint32 i = 0; i < numFences; i += 1) {
|
||||
MetalFence *fence = (MetalFence *)fences[i];
|
||||
if (METAL_INTERNAL_IsFenceBusy(fence)) {
|
||||
[fence->commandBuffer->handle waitUntilCompleted];
|
||||
}
|
||||
[fence->commandBuffer waitUntilCompleted];
|
||||
}
|
||||
} 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);
|
||||
|
|
@ -4125,7 +4113,6 @@ static bool METAL_Submit(
|
|||
|
||||
// Check if we can perform any cleanups
|
||||
for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
|
||||
|
||||
if (!METAL_INTERNAL_IsFenceBusy(renderer->submittedCommandBuffers[i]->fence)) {
|
||||
METAL_INTERNAL_CleanCommandBuffer(
|
||||
renderer,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue