Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swap interval ignored on macOS 13 #2249

Open
elmindreda opened this issue Jan 9, 2023 · 12 comments · May be fixed by #2277
Open

Swap interval ignored on macOS 13 #2249

elmindreda opened this issue Jan 9, 2023 · 12 comments · May be fixed by #2277
Labels
bug Bug reports and bugfix pull requests external Issues GLFW cannot reasonably solve macOS OpenGL

Comments

@elmindreda
Copy link
Member

OpenGL swap interval seems to have broken again, as reported in #1990, after having been fixed in 12.1.

@elmindreda elmindreda added bug Bug reports and bugfix pull requests external Issues GLFW cannot reasonably solve labels Jan 9, 2023
@RustyMoyher
Copy link

I just noticed this bug today, since I recently updated to macOS Ventura (13.2). Looking into how SDL handled this issue, it appears they reintroduced their CVDisplayLink code for OpenGL contexts: libsdl-org/SDL#4918

@bandaloo
Copy link

bandaloo commented Feb 4, 2023

discovered this just now. even setting glfwSwapInterval to a ridiculously high number seems to have no effect. not sure of a good workaround for this

edit: using OpenGL ES 2.0 with ANGLE

edit 2: as i'm going to bed, i'm realizing this suggests ANGLE is choosing to target OpenGL under the hood. i think there is a GLFW hint where i can ask it to use Metal. i'll test that tomorrow

@bandaloo
Copy link

bandaloo commented Feb 4, 2023

because glfw 3.4 is not on vcpkg yet, i built it from source to try the init hint:

glfwInitHint(GLFW_ANGLE_PLATFORM_TYPE, GLFW_ANGLE_PLATFORM_TYPE_METAL);

to make extra sure ANGLE wasn't choosing to use OpenGL, i did not include "-framework OpenGL" in target_link_libraries in CMakeLists.txt; only "-framework Cocoa and -framework IOKit" which i need otherwise I'll get linker errors. even with glfwSwapIntervals the loop is still running at hyper speed... like each loop time is a fraction of a millisecond, and is consuming 100% of the CPU.

interestingly, this does not happen when i use OpenGL to the same degree. perhaps this is a bug with the vcpkg unofficial port of ANGLE?

@felipeek
Copy link

On a MacBook Pro 2019 and MacOS Ventura 13.0.1. ---- Using GLFW 3.3.8

When I enable vsync, I am seeing 120 FPS, even though the monitor's refresh rate is 60Hz.

It is also strange that even if I try glfwSwapInterval(2), I still see 120 FPS. In fact, the argument of glfwSwapInterval seems to be meaningless, as I see the same results even with something like glfwSwapInterval(100).

It looks like there is something wrong happening.

@Philanatidae Philanatidae linked a pull request Feb 19, 2023 that will close this issue
@RustyMoyher
Copy link

I've found this to be a somewhat urgent bug for me, so I've created a temporary fork. It's basically GLFW 3.3.8 with most of the changes in #2277 applied to it.

Note: I've broken Windows + Linux builds since I'm only using this for now.

The changes are here: RustyMoyher@7a5a9dc.

Hope anyone else finds this useful!

copybara-service bot pushed a commit to google-deepmind/mujoco_mpc that referenced this issue Mar 13, 2023
OpenGL VSync became broken again in macOS 13 (glfw/glfw#2249). This workaround is similar to glfw/glfw#2277 but is implemented entirely outside of GLFW.

PiperOrigin-RevId: 516320722
Change-Id: Ie49aabd82c469e718c97ea406722fd806fa86688
copybara-service bot pushed a commit to google-deepmind/mujoco that referenced this issue Mar 13, 2023
OpenGL VSync became broken again in macOS 13 (glfw/glfw#2249). This workaround is similar to glfw/glfw#2277 but is implemented entirely outside of GLFW.

PiperOrigin-RevId: 516320722
Change-Id: Ib8a651a942f592c74e00ad3c7b22f2dfd156be5f
@caldog20
Copy link

Are there any updates on when this may get resolved upstream without a fork? I am currently affected by this issue. When setting glfwSwapInterval(0) FPS is mostly unlimited. When setting glfwSwapInterval(1) or any value other than 0 then the FPS is locked around 120fps.

@saran-t
Copy link

saran-t commented Mar 30, 2023

In the meantime, following @RustyMoyher's comment and #2277, I was able to implement a similar workaround externally from GLFW without needing to patch or fork.

See google-deepmind/mujoco@2f0fb1e and google-deepmind/mujoco@81ba9ec.

It does require putting macOS-specific, #ifdef-guarded stuff into your own code though.

@RustyMoyher
Copy link

Update: my attempt at fixing this in my temporary fork of 3.3.8 only partially worked. It still sometimes stutters, though the stutters are infrequent. I'm not sure if I failed to port the changes in #2277 correctly or if there is some kind of race condition in the mutex or something.

I may look into adding an external workaround as @saran-t's suggested.

@Bixilon
Copy link

Bixilon commented Aug 31, 2023

I can confurm this bug on mac os Ventura 13.5.1. i5 2017

@krackers
Copy link

krackers commented Sep 14, 2023

If you look at the display clock (via cvdisplaylink) before and after a call to buffer swap with vsync enabled, you see that every other buffer swap is not blocking properly. But interestingly, if you have a promotion display, I see the reverse scenario, where every vsync blocks properly but the blocking time gives you 60fps instead of 120fps.

Using cvdisplaylink is an ok stopgap, but actually the displaylink callback doesn't trigger at the beginning of vsync, they trigger in the middle of one. See https://thume.ca/2017/12/09/cvdisplaylink-doesnt-link-to-your-display/. This means that you if you try to block on it from a non-displaylink thread (via the technique in the PR) then you are techincally swapping in the middle of a vsync, but the fact that you don't see any tearing probably means osx is doing some additional compositing behind the scenes, so I guess it doesn't matter. But to be proper, you'd probably want to sleep until the next vsync (this is not the same as outTime of the cvdisplaylink callback, because at least in my case outTime is actually 2 frames ahead, not one).

And finally if you swap from within a displaylink thread, you get very interesting behavior where the swap itself appears to take 0 time. I'm guessing somewhere inside quartz apple has a special-case for swapping from a displaylink thread, and they just mark it as deferred until the vsync (because otherwise the fact that displaylink callback is fired in the middle and swap would ordinarily block until vsync would interact badly).

@saran-t
Copy link

saran-t commented Sep 14, 2023

I found that calling glfwSwapBuffers on the DisplayLink thread can lead to sporadic, random crashes (hence google-deepmind/mujoco@81ba9ec).

@krackers
Copy link

I saw that too, with native opengl code (i.e. no glfw abstraction). It's surprising because calling flushBuffer on the displaylink thread is exactly what apple recommended in https://developer.apple.com/library/archive/qa/qa1385/_index.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug reports and bugfix pull requests external Issues GLFW cannot reasonably solve macOS OpenGL
Projects
Status: Now
Development

Successfully merging a pull request may close this issue.

8 participants