libretro / RetroArch

Cross-platform, sophisticated frontend for the libretro API. Licensed GPLv3.
http://www.libretro.com
GNU General Public License v3.0
9.85k stars 1.78k forks source link

Monitor refresh rate environment callback - Good for Variable Sync? (Request) #4934

Closed Tatsuya79 closed 6 years ago

Tatsuya79 commented 7 years ago

Request to implement an environment callback that would set the frontend’s refresh rate to the same value as the ‘core’ refresh rate.

Ex. Sharp x68000 has different refresh modes, 55.45Hz and 61.46Hz. If I launch them on my 60Hz monitor, 1st mode will have stutters, 2nd sound crackling and pitch issue.

I make 2 resolutions with those refresh rates in my GPU panel (they work). But Retroarch still stays at 60Hz when launching those games.

I need to manually change video_refresh_rate = "61.46" in my retroarch.cfg or core override to make my monitor switch to the corresponding display mode on core launch.

It would be useful to pass the core ideal refresh rate to the effective frontend monitor refresh rate. Perhaps make an option in video settings for that. That could also make it a "one click" activate G-Sync/Freesync refresh mode if I understand it correctly.

Also keep in mind some games start in one refresh mode and then switch to a different one later.

inactive123 commented 7 years ago

@aliaspider @Themaister What is your take on this? I'm trying to gather feedback from people who might be vaguely knowledgeable about the specific needs of G-Sync/Freesync users, and who would be able to determine if an environment callback that caters to this kind of thing would make sense.

andres-asm commented 7 years ago

Why would you need a new callback? The core can already change av info at runtime. As far as I see what's needed is for the cores to use set_av_info and the front-end needs to be able to query the driver for valid resolutions and switch, accordingly.

It already allows switching res but it doesn't include refresh rate in the process.

On Thu, May 18, 2017, 6:38 AM Twinaphex notifications@github.com wrote:

@aliaspider https://github.com/aliaspider @Themaister https://github.com/themaister What is your take on this? I'm trying to gather feedback from people who might be vaguely knowledgeable about the specific needs of G-Sync/Freesync users, and who would be able to determine if an environment callback that caters to this kind of thing would make sense.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/libretro/RetroArch/issues/4934#issuecomment-302379320, or mute the thread https://github.com/notifications/unsubscribe-auth/ABpC0IsvmNHPHzinYLKczPQi4SCKDtxfks5r7C2XgaJpZM4NfE7b .

Tatsuya79 commented 7 years ago

Indeed, just using the fps value in av_info and applying it as monitor refresh rate would do that.

blurbusters commented 6 years ago

--crossposted from #1633 as this pertinent info will help here too--

I am trying to help a user fix microstutter during variable refresh rate, and I have given them recommendations: https://forums.blurbusters.com/viewtopic.php?f=5&t=3903&p=31050#p31050

However, it is also the emulator author's responsibility to improve framepacing as much as possible, to minimize VRR microstutter.

This is what I have advised to the user, but I am cross-posting here because too many emulators fail in properly implementing VRR support. Many are already good (perhaps yours is) but I'm posting here as a public education notice.

Decision matrix: -- First, try the recommendations in Issue #1633 at RetroArch's bug tracker. If this suceeds, then you're finished, the emulator frame pacing issue is fixed. -- Failing that, try removing your framerate throttle, and use RTSS to throttle your emulator. If this succeeds, then the emulator's frame pacing is confirmed defective, and the emulator authors should read the below paragraph.

[FOR SOFTWARE DEVELOPERS] Skip this paragraph if you don't know how to develop software. NOTE: This is for other creators who visits Blur Busters Forums -- including emulator programmers / app developers / authors, please pay attention to your emulator's framepacing issues -- you want sub-millisecond timing accuracy in executing pageflips such as Direct3D Present() calls and such to avoid microstutters on VRR displays. A 1ms error in framepacing accuracy means a 1-screenwidth-per-second space shooter scroller or Super Mario scroller, will end up having a 1/1000 screenwidth microstutter (equivalent to 2 pixelwidths on a 1920x1080 display). This type of microstutter from 1ms framepacing error is noticeable when framepacing errors happens at regular intervals. For proper fluidity on VRR displays, your refresh cycles is controlled by the exact timing of the pageflip. So.....when you're in VSYNC OFF mode or VRR mode please use microsecond clocks for timing your framebuffer flips in your emulator source code!. This will reduce microstutter issues for software-triggered display refresh cycles (which is what GSYNC and FreeSync essentially is) especially for strongly fixed-Hz content such as videos and emulators. Basically when programming for a VRR display, you're now doing the equivalent of software-based VSYNC ON that's lower lag than waiting for a monitor's next fixed refresh cycle (for a non-VRR display). To successfully display fixed-Hz material (emulators, videos, etc) in a way that is as microstutter-free as true VSYNC ON, but without lag of VSYNC ON, you have to have really pristine framepacing accuracy. Do not use uncompensated millisecond-accurate timers, you may have to intentionally do a micro-busywait loop (a few tens or hundreds microseconds) within your timer event, to intentionally re-align your next frame buffer pageflip to a more exact interval since the last framebuffer flip (record a microsecond timestamp everytime you do a framebuffer flip, and align the next framebuffer flip as exactly as your software allows you to -- timer events add microstutter for fixed-Hz material on VRR displays, so pad the beginning of your timer event routine with a micro-busywait since last event, if you're using a timer event). RTSS does this sort of pageflip accuracy magic already. It's not rocket science. You might be using another method. But if you're using a timer event as your framepacing method....Then trigger your timer event approximately 1ms early and do a micro-busywait to microsecond accuracy. Timer jitter gone. No more microstutter. Problem solved. PC games don't have to worry about this as much as their framerates are designed to fluctuate, but emulators & videos are not designed to, so you have to improve your framepacing programming game, to the microseconds level in your own app/software that you create. [/FOR SOFTWARE DEVELOPERS]

(Direct quote from Blur Busters Forums)

If microsecond-accurate framerate throttling does not yet exist in RetroArch, it is an easy fix. Please open a new issue here on this system, for the good of other VRR users. It is a pervasive problem with approximately 50% of emulators, and it's amazing how big a difference a single microsecond actually is -- but it makes sense because VRR (FreeSync, GSYNC) hands over refresh cycle trigger to a software clock instead of a hardware refresh rate.

If you are doing render-and-flip all at once -- then frame rendertime fluctuation issues will cause microstutter issues when mapping an emulated fixed Hz to a VRR display. Separate your rendering from your frame flipping, instead of "render-and-flip" all at once. Basically render, then micro-busywait, then framebuffer flip (microsecond-aligned to previous flip). You may want a configurable margin (e.g. 1ms, 2ms) depending on emulator, as your padding for rendertime variances.

Many developers are unaware that the exact time of framebuffer flip immediately triggers refresh cycles (photons hitting eyeballs) when it comes to a variable refresh rate display. Your computer just (essentially) commanded a VRR monitor, "display the frame NOW" when your app executes glutSwapBuffers() or Present() or whatever. Imperfect software timers equals microstutter! So... Wisely wield your new-found power of directly commanding refresh cycles :)

If RetroArch already has microsecond-accurate frame throttling, so truly appreciated. If RetroArch does not have (best-effort) microsecond-accurate frame throttling, fix it, pretty-pretty-please.
G-SYNC and FreeSync users thank you very much for reading this public service notice --

Cheers, Mark Rejhon Founder, Blur Busters & TestUFO

P.S. TIP: VRR is good for video too. 48fps film, 59.94fps, 60fps, 120fps, 18fps, 23.97fps, 24fps, 25fps, whatever. Please verify your video players in RetroArch is fully VRR compatible. Many players configured into fullscreen mode automatically work with VRR (e.g. SMPlayer) but many video player authors unaware of VRR accidentally (in good intentions) mess things up when trying to improve things for a fixed-Hz monitor. Authors are unaware of how VRR works. VRR friendly video is easier than most think: It's simply executing frame pageflips at intervals as exactly-as-possible to the frame's timecode as possible -- and letting the VRR do the magic for you.

P.S. TIP 2: A 144Hz or 240Hz VRR Monitor is an excellent way of reducing 60Hz emulator lag. Occasionally, in certain cases, the lag savings is so huge that it can actually sometimes get less input lag than the original emulated machine connected to a slow-scanning 60Hz display. This is made possible because the individual refresh cycles are scanned-out in 1/144sec (for 144Hz VRR) or 1/240sec (for 240Hz VRR). So your 60Hz frame appears sooner than on many 60Hz displays, even though you're only running at 60fps on a high-Hz VRR display. Basically, perfect ultrasmooth 60Hz VSYNC ON appearance with most of the low-lag benefits of 144Hz/240Hz VSYNC OFF. The VRR trick for emulators (that has good frame pacing), can compensate a huge amount for emulator lag, and is part of why VRR is getting popular with emulator users as a lag-reducing technique.

Tatsuya79 commented 6 years ago

Closing this as a g-sync monitor I'm testing doesn't take the monitor refresh setting into consideration (it won't force a refresh RA is asking for).