diff --git a/impeller/renderer/backend/metal/surface_mtl.mm b/impeller/renderer/backend/metal/surface_mtl.mm index 117ef36ab13e9..b84f3a144058d 100644 --- a/impeller/renderer/backend/metal/surface_mtl.mm +++ b/impeller/renderer/backend/metal/surface_mtl.mm @@ -266,14 +266,29 @@ - (void)flutterPrepareForPresent:(nonnull id)commandBuffer; flutterPrepareForPresent:command_buffer]; } + // Intel iOS simulators do not seem to give backpressure on Metal drawable + // aquisition, which can result in Impeller running head of the GPU + // workload by dozens of frames. Slow this process down by blocking + // on submit until the last command buffer is at least scheduled. +#if defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64) + constexpr bool alwaysWaitForScheduling = true; +#else + constexpr bool alwaysWaitForScheduling = false; +#endif // defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64) + // If the threads have been merged, or there is a pending frame capture, // then block on cmd buffer scheduling to ensure that the // transaction/capture work correctly. if ([[NSThread currentThread] isMainThread] || - [[MTLCaptureManager sharedCaptureManager] isCapturing]) { + [[MTLCaptureManager sharedCaptureManager] isCapturing] || + alwaysWaitForScheduling) { TRACE_EVENT0("flutter", "waitUntilScheduled"); [command_buffer commit]; +#if defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64) + [command_buffer waitUntilCompleted]; +#else [command_buffer waitUntilScheduled]; +#endif // defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64) [drawable_ present]; } else { // The drawable may come from a FlutterMetalLayer, so it can't be