libretro / ludo

A libretro frontend written in golang
https://ludo.libretro.com/
GNU General Public License v3.0
595 stars 68 forks source link

Dropping frames or jerky video at high refresh rates #344

Open schrock opened 4 years ago

schrock commented 4 years ago

OS: Windows 10

Regardless of whether I'm running in windowed mode or fullscreen, the video appears to be jerky or dropping frames. Based on my experience with Retroarch, my guess is this has something to do with the monitor refresh rate synchronization, or something similar. Does Ludo sync the emulation speed to the monitor refresh rate, or does it use an independent frame rate that has to be configured to match the monitor, similar to Retroarch?

kivutar commented 4 years ago

Ludo is based on the monitor refresh rate. The implementation is based on GLFW. If your GPU driver doesn't have vsync enabled, it might have some problems synchronizing.

Also, games are paced based on the audio being played in a blocking way. If the audio driver is misconfigured, it can also block the emulation, but then you should be able to hear that the audio is not played properly.

schrock commented 4 years ago

There's definitely something up. I did some more intensive testing, comparing Ludo to Retroarch. Ludo is definitely dropping frames. Retroarch, on the other hand, is buttery smooth.

I don't know if this may have something to do with it, but I am using a 144 Hz GSync monitor. While in Ludo or Retroarch, it seems like GSync is properly engaged and the monitor is outputting 60 frames per second, though it varies a bit. I turned off GSync and just ran the monitor at its max refresh rate (144 Hz), and the results were the same in both Ludo and Retroarch.

kivutar commented 4 years ago

We have to check issues with GLFW 3.3 and 144Hz GSync then

kivutar commented 4 years ago

Maybe duplicate of https://github.com/libretro/ludo/issues/237

johnnyq commented 4 years ago

im still experiencing this although not as bad as initially. Testing with LudOS on pi3 and 4

iiiGerardoiii commented 4 years ago

I'm experiencing some constant stuttering on 144hz monitor as well.

I recorded my monitor in slow-mo to notice the "stuttering", with 60fps motion in the background for comparison: https://a.pomf.cat/tkfhnu.mp4

Apologies for shaky camera

johnnyq commented 4 years ago

@iiiGerardoiii Great Video for diagnostic purposes. I'm def not experiencing anything like that. Mine is maybe a frame skip in between but you would have to have a trained eye. It may be as @kivutar said possible issues with GLFW 3.3 and 144Hz Gsync.

schrock commented 4 years ago

More testing has revealed that the issue does not seem to be the use of GSync, but rather high refresh rates. I turned off GSync and ran Ludo in windowed mode with fixed refresh rates of 144 Hz, 120 Hz, and 60 Hz. Both 144 Hz and 120 Hz dropped frames, but 60 Hz was buttery smooth.

Unfortunately, I am unable to test 60 Hz in fullscreen mode. Even if I set the refresh rate to 60 Hz in the Nvidia control panel, it seems that Ludo automatically switches to the highest available refresh rate in fullscreen mode.

Until the issue with high refresh rates is resolved, you might want to consider implementing an option in the settings menu to change the fullscreen refresh rate as a workaround/hotfix.

kivutar commented 4 years ago

We can add a Swap Interval option, to swap every 2 vblank on 120Hz screens. But it won't work on 144Hz. And it's a bit cryptic for the user too.

According to GLFW:

SwapInterval sets the swap interval for the current context, i.e. the number of screen updates to wait before swapping the buffers of a window and returning from SwapBuffers. This is sometimes called 'vertical synchronization', 'vertical retrace synchronization' or 'vsync'.

Contexts that support either of the WGL_EXT_swap_control_tear and GLX_EXT_swap_control_tear extensions also accept negative swap intervals, which allow the driver to swap even if a frame arrives a little bit late. You can check for the presence of these extensions using ExtensionSupported. For more information about swap tearing, see the extension specifications.

Some GPU drivers do not honor the requested swap interval, either because of user settings that override the request or due to bugs in the driver.

And right now we're hardcoding this to 1.

schrock commented 4 years ago

Given that the guiding principle behind Ludo seems to be giving the user an easier setup experience, I think it might be worthwhile to implement the following logic:

Alternatively, we could implement a fullscreen resolution and refresh rate option in the settings. Currently, it uses the highest available resolution and refresh rate.

kivutar commented 4 years ago

But first we need to make sure that swap interval 2 is a valid workaround. Can you compile Ludo to test?

kivutar commented 4 years ago

We could also try forcing GLFW_REFRESH_RATE to 60 and see if it helps.

johnnyq commented 4 years ago

@kivutar I think forcing the refresh rate to 60Hz should work great lets give it a shot!!

kivutar commented 3 years ago

Sadly I only have 60Hz screens at home

kivutar commented 3 years ago

OK I think we simply need to implement dynamic rate control to fix this.

https://near.sh/articles/audio/dynamic-rate-control

johnnyq commented 2 years ago

Id agree