Muryan

Using Metal in macOS Screen Savers

Posted 17th November 2018

In my last post I was glowing in my praise for Apple’s Metal technology. Since then my love affair with Metal has cooled just a little. The underlying technology is great, but I just couldn’t get the recommended way of handling Metal graphics (MTKView) to play nice in a screen saver. It works fine in normal apps such the test harness I use for Ephemeral development, but there’s something about living inside a screen saver that makes it exhibit some odd behaviour, primarily visual glitches on start up.

So I ended up dropping down one level in the technology stack, getting rid of MTKView in favour of using CAMetalLayer and CVDisplayLink. Now I have a Metal screen saver that is free of glitches, and works exactly the way I want it to. Despite the switch in technology the bulk of my code didn’t need to change, which was a relief. And for a bonus I’m now using the new timer to run the OpenGL/OpenCL variant of Ephemeral, which is now drawing more smoothly than ever before.

There’s one more issue with Metal that’s cost me a huge amount of time, which is a rare problem which causes visual corruptions. The symptom is that every second frame of animation is garbled, but only ever when running from System Preferences in preview mode. I tried everything I could think of to fix it, but just couldn’t get it to go away.

And then I had the idea of looking at Metal screen savers written by other developers. I found three, and managed to get all of them to draw with the same style of corruption. So I think I can put this down to a problem with macOS: it seems very unlikely to me that all these Metal-based screen savers, independently created by different developers and using different methods for drawing, contain the exact same bug. Coupled with occasional visual corruptions I see on the macOS lock screen and desktop, and I feel even more certain that macOS that’s at fault.

With all that out of the way, the new Metal version of Ephemeral is almost ready to go…