From 627662f002149da383b62cf010ad13df8717c25d Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Thu, 13 Apr 2023 17:10:32 +0100 Subject: [PATCH] Fix #106704: Resolve flashing Metal viewport Previous fix to resolve GPU hang which could occur in the Metal backend caused additional flickering to occur as as side effect, due to removal of required execution dependencies in certain places. This patch resolves both problems by only removing the GPU hang dependency stall when additional synchronization primitives are used along-side the global sync primitive. Authored by Apple: Michael Parkin-White --- source/blender/gpu/metal/mtl_context.mm | 10 ---------- source/blender/gpu/metal/mtl_state.mm | 13 +++++++++++++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/source/blender/gpu/metal/mtl_context.mm b/source/blender/gpu/metal/mtl_context.mm index a89b1562396..e24dd0bcae8 100644 --- a/source/blender/gpu/metal/mtl_context.mm +++ b/source/blender/gpu/metal/mtl_context.mm @@ -2191,16 +2191,6 @@ void present(MTLRenderPassDescriptor *blit_descriptor, id cmdbuf = [ctx->queue commandBuffer]; MTLCommandBufferManager::num_active_cmd_bufs++; - if (MTLCommandBufferManager::sync_event != nil) { - /* Release synchronization primitive for current frame to avoid cross-frame dependencies. - * We require MTLEvents to ensure correct ordering of workload submissions within a frame, - * however, we should not create long chains of dependencies spanning several drawables as any - * temporary stalls can then trigger erroneous GPU timeouts in non-dependent submissions. */ - [MTLCommandBufferManager::sync_event release]; - MTLCommandBufferManager::sync_event = nil; - MTLCommandBufferManager::event_signal_val = 0; - } - /* Do Present Call and final Blit to MTLDrawable. */ id enc = [cmdbuf renderCommandEncoderWithDescriptor:blit_descriptor]; [enc setRenderPipelineState:blit_pso]; diff --git a/source/blender/gpu/metal/mtl_state.mm b/source/blender/gpu/metal/mtl_state.mm index a9f11a970d9..5f570625ff1 100644 --- a/source/blender/gpu/metal/mtl_state.mm +++ b/source/blender/gpu/metal/mtl_state.mm @@ -607,6 +607,19 @@ void MTLFence::wait() return; } + /* Note(#106431 #106704): `sync_event` is a global cross-context synchronization primitive used + * to ensure GPU workloads execute in the correct order across contexts. + * + * To prevent unexpected GPU stalls, this needs to be reset when used along side explicit + * synchronization. Previously this was handled during frame boundaries, however, to eliminate + * situational flickering (#106704), only reset this during the cases where we are waiting on + * synchronization primitives. */ + if (MTLCommandBufferManager::sync_event != nil) { + [MTLCommandBufferManager::sync_event release]; + MTLCommandBufferManager::sync_event = nil; + MTLCommandBufferManager::event_signal_val = 0; + } + if (signalled_) { MTLContext *ctx = MTLContext::get(); BLI_assert(ctx); -- 2.30.2