MTKView, presentDrawable afterMinimumDuration seems flakey...

I downloaded this sample:

https://developer.apple.com/documentation/metal/basic_tasks_and_concepts/using_metal_to_draw_a_view_s_contents?preferredLanguage=occ

I commented out this line in AAPLViewController.mm

//    _view.enableSetNeedsDisplay = YES;

I modified the presentDrawable line in AAPLRenderer.mm to add afterMinimumDuration:

    [commandBuffer presentDrawable:drawable afterMinimumDuration:1.0/60];

I then added a presentedHandler before the above line that records the time between successive presents.

Most of the time it correctly reports 0.166667s. However, about every dozen or so frames (it varies) it seems to present a frame early with an internal of 0.0083333333s followed by the next frame after around 0.24s.

Is this expected behaviour, I was hoping that afterMinimumDuration would specifically make things consistent. Why would it present a frame early?

This is on a new MacBook Pro 16 running latest macOS Monterrey, and the sample project upgraded to have a minimum deployment target of 11.0. Xcode latest public release 13.1.

Replies

I concur

Did you find any solution to this?

My answer doesn't include code, but I believe it will be helpful as I spent 3 days before I figured it out.

You need to use a semaphore to control access to the "in-flight" frames, and the maximum of the "in-flight" frames should be equal to 3 (because MTKView uses triple buffering).

To find out how to do this correctly is easy. Start a new "Game" project in xcode, and select the framework "Metal" (not "SceneKit" or "SpriteKit"), and you can skip tests generation. Then you can find the relevant code in the "Renderer.swift" file (or whatever language you selected).

I commented out all the "cube rotation" rendering in the default project, and just left the drawable presentation. The glitch disappeared at 60 FPS when the window is maximised (or not). Additionally I tried rendering the full video sample with graphics at 120 FPS (by setting preferredFrameRate on the view), and it works marvellously. You can enable metal information display in the options to see that there is no fluctuation if frame rate. Well, there is, but not glitchy anymore.

I'm using MacBook Pro M2.