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

Pull Request: https://projects.blender.org/blender/blender/pulls/106914
This commit is contained in:
Jason Fielder
2023-04-14 07:54:08 +02:00
committed by Jeroen Bakker
parent dc1b36f288
commit 2745cacd95
2 changed files with 13 additions and 10 deletions

View File

@@ -2191,16 +2191,6 @@ void present(MTLRenderPassDescriptor *blit_descriptor,
id<MTLCommandBuffer> 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<MTLRenderCommandEncoder> enc = [cmdbuf renderCommandEncoderWithDescriptor:blit_descriptor];
[enc setRenderPipelineState:blit_pso];

View File

@@ -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);