After updating CAMetalLayer.drawableSize, [CAMetalLayer nextDrawable:] frequently takes ~1s

I have a bare-bones Metal app setup where I attach a CAMetalLayer to a window that inherits from a NSWindow with a custom delegate. Everything else is vanilla. I'm also using metal-cpp and metal shader converter.

I'm running into a issue where the application runs fine in the beginning, but once I resize the window, it starts hitching. It turns out that [CAMetalLayer nextDrawable:] frequently (but not always) takes around a full second (plus or minus a few milliseconds) to return once drawableSize has been updated.

I've tried setting allowsNextDrawableTimeout to false which doesn't work; it returns a valid drawable after a second instead of nil. Setting displaySyncEnabled to false reduces the likelihood of this happening to around 50% from 90%+ but does not eliminate it. Setting maximumDrawableCount to 2 or 3 does not seem to make a difference.

By dumping the resource IDs of the returned textures I've noticed something interesting: Before resizing, the layer seems to shuffle between 2 textures or at least 2 resource IDs, but after resizing it starts to create new textures for each returned drawable. Occasionally it seems to reuse a previous resource ID, but it does not seem to have anything to do with whether the method returns quickly or not.

Why does this happen, and how can I fix it? Should I create a new CAMetalLayer when resizing the window instead of updating drawableSize?

Answered by DTS Engineer in 823167022

Hello,

We recommend using CAMetalDisplayLink shown in Achieving smooth frame rates with Metal’s display link.

Hello,

We recommend using CAMetalDisplayLink shown in Achieving smooth frame rates with Metal’s display link.

Thank you for the reply, but having regular 1-second stalls is still highly irregular - the delays are too large IMO to be considered a regular frame pacing issue. Do you have any hypotheses regarding why it might be happening? Are there any requirements to where drawableSize must be updated to avoid these stalls?

Changing drawableSize also seems to somehow disable VSync (or whatever it's called on MacOS). For a very lightweight application, the time it takes for nextDrawable to return goes from ~6-7ms (120fps) to almost zero.

After updating CAMetalLayer.drawableSize, [CAMetalLayer nextDrawable:] frequently takes ~1s
 
 
Q