I'm still trying to figure out the best route here.
I should say the standard presentDrawable approach is usually described as "present as soon as possible" which also sounds like what I want, but in reality it seems to mean "present as soon as possible after all the other frames in the queue have been presented".
From my investigations so far it seems likely that CAMetalLayer has some logic to handle pacing, but I haven't seen that described anywhere either in docs or WWDC talks and I'm struggling to figure out the logic it's using.
For example if you look at https://developer.apple.com/videos/play/wwdc2019/606/ at 6:30 - the focus is on the command encoder for a future frame blocking on waitNextDrawable for a full frame, and how offscreen draws could be dispatched ahead.
But for me there's an unanswered frame pacing question here too - the orange surface stays on the display for 2 frame periods, even though the following frame (shown in green in the Instruments trace) is fully complete well in advance of the swap interval where we'd expect it to display. It's as if some component (likely CAMetalLayer) has decided that a future frame has missed some submission deadline and so responds by delaying the presentation of the next one in the queue, even though it's ready to go.
I think with CAMetalLayer I might just end up triggering rendering the following frame on the presentedHandler callback of the previous one rather than using CADisplayLink / MTLView at all. That way I can hopefully keep maximumDrawableCount at 3 so waitForNextDrawable should always be non-blocking, and guarantee presenting on the following VSYNC, but I don't want to be fighting against internal opaque CAMetalLayer logic that decides I'm not submitting frames fast enough to keep a full drawable queue.
I'd love to understand more about all this - any references greatly appreciated!
Topic:
Graphics & Games
SubTopic:
General
Tags: