floooh / sokol

minimal cross-platform standalone C headers
https://floooh.github.io/sokol-html5
zlib License
6.83k stars 480 forks source link

sokol_app: turning off vsync ? #292

Open septag opened 4 years ago

septag commented 4 years ago

Hi, Can I turn off vsync ? :) because according to what I'm seeing, the swap_interval defaults to 1 if we set it to 0.

floooh commented 4 years ago

Hmm, no this isn't supported unfortunately, it would be hard to do on all platforms. For instance MTKView only has a preferredFramesPerSecond method (https://developer.apple.com/documentation/metalkit/mtkview/1536027-preferredframespersecond?language=objc). Setting this to zero will simply never call the frame callback, and setting it to a very high value (e.g. 1000) will clamp at the display refresh rate.

Similar problem on the web platform most likely.

These APIs are basically also the reason why there is this swap_interval member instead of a simple vsync flag.

septag commented 4 years ago

ouch! so as a workaround, how about changing the swap_interval to an enum value:

typedef enum sg_swap_interval {
  SG_SWAPINTERVAL_DEFAULT = 0,
  SG_SWAPINTERVAL_ONE = 1,
  SG_SWAPINTERVAL_TWO = 2,
  SG_SWAPINTERVAL_FOUR = 4,
  SG_SWAPINTERVAL_EIGHT = 8,
  SG_SWAPINTERVAL_NOSYNC = 0x7fffffff // or something
} sg_swap_interval ;

So default would be ONE, and NOSYNC would set it to 0 for the platforms that support this behavior. As for metal and the web that you mentioned, we could divide it by the refresh rate of the display, and of course make an exception for NOSYNC option (right now you are doing the same in metal but shouldn't we query the refresh rate instead of hard coded 60 ?)

floooh commented 4 years ago

Yeah a special value for "no sync" might work, I wouldn't use a new enum type though, just a special constant for "NOSYNC", and it would be need to be ignored on some platforms (but swap_interval is also not guaranteed to work, so I guess that's ok).

shouldn't we query the refresh rate instead of hard coded 60

Yes, on the macOS code path that would definitely make sense, there seems to be a CGDisplayModeGetRefreshRate() function.

I don't think there's a way to query the display refresh rate on the web though. Only way is to measure the time between calls to the frame callback and round to the closest "likely" refresh rate (I'm currently adding a function to sokol_time.h for that).

septag commented 4 years ago

yeah. constants would work pretty well too, it's your call.

Refresh rate would also make sense on iOS, cuz ipad pro is 120hz

would you like me to submit a PR for this ? because I can happily do that. (however I'm not familiar with web platforms)

lithiumtoast commented 4 years ago

For Metal, why not use CAMetalLayer.displaySyncEnabled?

floooh commented 4 years ago

would you like me to submit a PR for this ?

I'm terribly behind on PRs and open issues. Let's discuss at a later time again :)

@lithiumtoast: sokol_app.h is using the higher level MTKView which takes care of the entire frame loop and presentation, I'm not sure if it's possible to access the CAMetalLayer owned by the MTKView (and if yes, whether it's "legal" to poke around in it).

lithiumtoast commented 4 years ago

I don't think it is possible but it's possible to ditch MTKView and use CAMetalLayer directly with a NSView for macOS and a UIView for iOS. I do this myself when using SDL with sokol_gfx.

lithiumtoast commented 4 years ago

@iryont Did you read the Apple docs on CAMetalLayer? There are also some docs on best practices with how to use drawable. You may also want to try presentsWithTransaction.

@floooh Sorry, you can access the CAMetalLayer from MTKView but I don't know how "legal" this is.

CAMetalLayer* layer = self.layer;
layer.displaySyncEnabled = NO;
edubart commented 2 years ago

I've also felt the need to disable vertical synchronization for benchmarking purposes, my workaround at the moment is to use the following after initializing (Linux only):

#ifdef _SAPP_LINUX
    /* Disable swap interval */
    _sapp_glx_swapinterval(0);
#endif
cloudhead commented 9 months ago

Also interested in this, unless there's a way to reduce latency as much as disabling vsync, without disabling vsync :)

lou256 commented 9 months ago

I would also really appreciate if this was added, working on an app where I need vsync off to minimise latency and screen tearing isn't really a concern, seems harder to do this on mac os I guess...