From bcb4d0a905dc71bf576cd58b0b0fe6d80e7170ed Mon Sep 17 00:00:00 2001 From: Acaki Date: Wed, 20 Aug 2025 01:50:27 +0800 Subject: [PATCH] fix: attempt to fix occasional video freeze with metal renderer --- VoidLink/Metal/MetalVideoRenderer.m | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/VoidLink/Metal/MetalVideoRenderer.m b/VoidLink/Metal/MetalVideoRenderer.m index 10cf81fe..f7e1a449 100644 --- a/VoidLink/Metal/MetalVideoRenderer.m +++ b/VoidLink/Metal/MetalVideoRenderer.m @@ -650,9 +650,14 @@ CFStringRef __currentColorSpace; [commandBuffer addCompletedHandler:^(id cb) { dispatch_semaphore_signal(block_semaphore); - const CFTimeInterval GPUTime = cb.GPUEndTime - cb.GPUStartTime; - const double alpha = 0.25f; - self->_averageGPUTime = (GPUTime * alpha) + (self->_averageGPUTime * (1.0 - alpha)); + if (cb.error) { + // Request IDR frame to recover from rendering error + LiRequestIdrFrame(); + } else { + const CFTimeInterval GPUTime = cb.GPUEndTime - cb.GPUStartTime; + const double alpha = 0.25f; + self->_averageGPUTime = (GPUTime * alpha) + (self->_averageGPUTime * (1.0 - alpha)); + } // Free textures after completion of rendering for (size_t i = 0; i < planes; i++) { @@ -677,7 +682,15 @@ CFStringRef __currentColorSpace; // by any stage in the Metal pipeline (CPU, GPU, Metal, Drivers, etc.). if (!self.isStopping) { dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)); // 100ms - dispatch_semaphore_wait(_inFlightSemaphore, timeout); + long result = dispatch_semaphore_wait(_inFlightSemaphore, timeout); + if (result != 0) { + // Timeout occurred - this is the main cause of video freezes + // Signal the semaphore to unblock potentially stuck frames + for (NSUInteger i = 0; i < MaxFramesInFlight; i++) { + dispatch_semaphore_signal(_inFlightSemaphore); + } + LiRequestIdrFrame(); // Request recovery + } } }