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

Change macOS OpenGL timing to use CVDisplayLink #488

Closed
wants to merge 1 commit into from

Conversation

randrew
Copy link

@randrew randrew commented Feb 26, 2021

When building with SOKOL_GLCORE33 on Mac, this commit adds the CoreVideo to the list of required frameworks: -framework CoreVideo

This replaces the NSTimer with CVDisplayLink for driving the timing of rendering frames with OpenGL on macOS. CVDisplayLink can be used to receive a callback on a separate high-priority thread synchronized with the timing of a display device.

Because sokol_app.h expects the rendering code to run on the main thread, we use: NSObject performSelectorOnMainThread: to trigger our code on the main thread.

Without vertical sync enabled, this will cause tearing. Maybe because both the rendering time of a frame can't be guaranteed to meet the deadline, and maybe also because of the time spent going from one thread to another.

However, it does give a consistent timer, and seems to be an improvement over NSTimer. In my measurements, CPU time waste from the high-frequency NSTimer was reduced.


I believe @floooh has found some issue with resizing the window with this patch. I haven't been able to reproduce that in 10.12, but I also haven't tried very hard.

When building with SOKOL_GLCORE33 on Mac, this commit adds the CoreVideo
to the list of required frameworks: -framework CoreVideo

This replaces the NSTimer with CVDisplayLink for driving the timing of
rendering frames with OpenGL on macOS. CVDisplayLink can be used to
receive a callback on a separate high-priority thread synchronized with
the timing of a display device.

Because sokol_app.h expects the rendering code to run on the main
thread, we use: NSObject performSelectorOnMainThread: to trigger our
code on the main thread.

Without vertical sync enabled, this will cause tearing. Maybe because
both the rendering time of a frame can't be guaranteed to meet the
deadline, and maybe also because of the time spent going from one thread
to another.

However, it does give a consistent timer, and seems to be an improvement
over NSTimer. In my measurements, CPU time waste from the high-frequency
NSTimer was reduced.
@follower
Copy link

follower commented Mar 4, 2021

A short drive-by FYI:

As a result of research related to a CVDisplayLink issue in Godot (quite some time ago), I discovered many implementations miss an important detail which can result in crashes and/or program hangs (connected with system sleep and/or Fast User Switching):

"In macOS 10.4 and later, the display link thread is automatically stopped if the user employs Fast User Switching. The display link is restarted when switching back to the original user."

-- https://developer.apple.com/documentation/corevideo/1457281-cvdisplaylinkstop?language=objc

This means:

  1. The display link may already have been stopped. (Leading to an error on exit.)
  2. The display link may already have been stopped and a different link may have been created. (Leading to a hang during normal program execution because the originally created link disappeared.)

This may not be an issue with your use case but thought I'd at least mention it. :)

Edited:

Add some links with related info:

@randrew
Copy link
Author

randrew commented Mar 5, 2021

Is that true? I slept and and woke my laptop several times, but the thread never died. Apple's documentation seems to indicate that the thread is stopped, but not killed, when switching to another user, and that it is resumed when switching back to the original user.

@floooh
Copy link
Owner

floooh commented May 30, 2021

Closing this, because the multi-window-stuff I'm currently working on in a branch (https://github.com/floooh/sokol/tree/sapp-multiwindow) will use CVDisplayLink both for driving the MTKView and NSOpenGLView (this was the only clean solution I found when rendering in multiple windows with a single sokol-app frame callback). Don't know yet when this will arrive in the master branch, but eventually it will arrive :)

@floooh floooh closed this May 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants