[SDL2] No renderer vsync on macOS Mojave?

For the 2D render API, yes, but apps using OpenGL still suffer. I’m looking at playing with Apple’s DisplayLink API to see if we can get vsync working on GL again.

Adding some observations since I upgraded to MacOS Mojave and working on a game that uses OpenGL.

I was getting the black OpenGL window, but upgraded to 2.0.9 and works fine. (Thanks!!!)

Now contending with a lack of vertical sync on Mac. I did some tests with a testbed app…

  1. Drawing just a few polygons means the app can easily hit 300+fps. Turning vertical sync on/off has no effect.

  2. Just a few polygons with a SDL_Delay(1000/60) runs at 50fps, no frame drops.

  3. (the interesting case) If I throw 100x the polygons then the app “runs” at 30fps but I’m getting some serious frame skip/drop with it only showing every 2nd/3rd/4th frame so it looks like it’s running 10fps or less.

Is there something going on under the Mac hood causing frame drops when the rendering gets heavy that anyone else aware of?

No problems on any other platform (Win, iOS).

Additional…

I turned off rendering some background buildings and now I’m not getting any frame drops. So there’s definitely some threshold of drawing stuff that triggers Mac OpenGL to start tripping over itself and start dropping bunches of frames.

As a short term development only hack fix it’s fine, but obviously not a long term release option.

My (current, possibly incorrect) understanding is OpenGL+vsync is broken in Mojave. Vsync for Metal works, but the “swap interval” API in NSOpenGLContext just doesn’t work. We might be able to fake this ourselves with CVDisplayLink, but I haven’t tried yet.

So OpenGL is the default on macOS when you are creating a renderer, then? I’m not selecting the OpenGL driver intentionally at all, and I still get no vsync after setting up the renderer (used with a streamed texture as the framebuffer, and the vsync flag).

So far, even in 2.0.9. In 2.0.10, we’ll likely make Metal the default (and fallback to OpenGL on older macOS releases). Alex has done a ton of work on the Metal renderer, and I think it’s pretty solid now.

Do you happen to know whether Metal has any equivalent to OpenGL’s ‘glLogicOp’ functionality? I need to be able to set AND, OR and XOR plotting modes which for the moment forces me to use OpenGL irrespective of the merits of any other renderers.

I think there’s just one or two things missing before I’d consider it production-ready: we don’t have a LockTexture implementation yet, and UpdateTexture can replace the texture in a previous frame if you do it too quickly. I have ideas for both of those though, hopefully they’ll get resolved Soon™. :slight_smile:

Metal doesn’t have an equivalent to glLogicOp: https://openradar.appspot.com/34763016

On iOS it could theoretically be implemented via a custom shader (due to iOS’ ability to have fully programmable blending), but not on macOS.

What are you using it for? I wonder if there’s a different solution to the problem you’re trying to solve.

My app is an interpreter for the BBC BASIC programming language. BBC BASIC supports OR, AND and XOR plotting via the GCOL statement, which is commonly found in programs written in that language.

The only alternative to using glLogicOp() would be to read the display buffer with SDL_RenderReadPixels(), modify the pixels myself, and then write the buffer back. But I would expect that to be far too slow.

This is good to hear. I’m doing a game that does a lot of its own drawing and then uses the accelerated renderer to put that on the screen, and it’ll be nice to have LockTexture working in Metal.

FWIW can I emphasise how important it is to me to find a workaround. I can’t use Metal, for the reasons I explained, so I’m completely dependent on continued support for OpenGL via SDL2 on MacOS. Some people have expressed the opinion that, having been deprecated, OpenGL will inevitably be removed completely; but we don’t know that and I wouldn’t want it to be used as an excuse for not solving the vsync problem.

If you really need it fixed you should probably file a bug with Apple using their radar bug tracker.

Ryan said earlier in the thread that he was following it up with Apple. But continuing to pursue a workaround in SDL seems sensible as well.

I wonder if one workaround to get VSYNC working with OpenGL rendering could be achieved by using Metal as only the final buffer render by following the Mixing Metal and OpenGL documentation. Not sure it would help anything, but might allow OpenGL-specific stuff to work while possibly rendering as if using Metal such that VSYNC would work (Mojave build w/XCode 10 - or probably more accurately 10.14 frameworks).

The best paths forward of course are to get Apple to fix the issue and default to full Metal rendering, but maybe for those who require OpenGL with the presumption Apple never fixes it … ?

https://developer.apple.com/documentation/metal/mixing_metal_and_opengl_rendering_in_a_view?language=objc

I haven’t yet ‘upgraded’ to Mojave so cannot confirm this for myself, but a report received from a user states that my app (which is currently 32-bit and built on MacOS Snow Leopard!) runs at a solid 60 fps, which suggests to me that vSync is actually working. I suppose it’s possible that it’s broken only for 64-bit builds (and of course MacOS is dropping support for 32-bit apps soon) but this observation is at least ‘interesting’.

@rtrussell I believe the issue exists in the 10.14 frameworks/SDK since vsync works fine when building on Mojave with XCode 9.4.1 (10.13 SDK) and running the game .app on Mojave. Both builds are 64-bit, so while it is the case that it’s only the 64-bit builds are broken, that might be due to the 10.14 SDK not being available for 32-bit. I haven’t yet tried building with XCode10 & 10.14 SDK on High Sierra and then running that product .app on Mojave, but probably not worth the effort at this point.

You make a good point that the smarter workaround is to probably just use Xcode 9.x until Metal is fully supported (or for all games that require supporting OpenGL on Mac).

(aside: I couldn’t quickly get Xcode 10 to build w/10.13 SDK to test that combo, granted I put in a minimal effort)

I can confirm that if you compile an SDL2.0.9 program with XCode 9 (on High SIerra) instead of XCode 10 (on Mojave), renderer vsync will work properly in macOS Mojave!

1 Like

This commit should make vsync work on Mojave, compiled with Xcode 10…

…as an added bonus, it should give you adaptive vsync (it does vsync if you beat the swap interval, but swap immediately if you were late) on the mac, which we never had before. That’s enabled by calling SDL_GL_SetSwapInterval(-1). Linux and Windows already have adaptive vsync, if it’s supported at the driver level, but this patch manages it inside SDL with a little help from CVDisplayLink.

Please test this (on both Xcode 9 and 10, Mojave or not)!

Thanks!

I don’t have Xcode 9 on my machine, but with Xcode 10 on Mojave this works. Don’t have an adaptive sync monitor, so I can’t test that part.