Support frame-multiplying to work around VRR/high-refresh monitor limitations
Are you using the latest DOSBox Staging version?
- [x] I have checked and I'm using the latest release.
Different version than latest?
No response
What operating system are you using?
Linux x86
If other OS or Linux, please describe
Debian 13 Testing, latest stable MESA 25.0.2, several different Wayland compositors, be it wlroors-based and "standalone"
Are you running DOSBox Staging on a native OS?
- [x] I am running Staging on a native OS
Relevant hardware info
Ryzen 7 8700G with RDNA3 graphics and 32GB of DDR5 RAM
Have you checked that no other similar issue already exists?
- [x] I have searched and have not found similar issues.
A clear and concise description of what the bug is
Setting host_rate = 120 + vsync = on when a ~120Hz physical video mode is in use in the host machine, dosbox-staging should run with a ~120 Hz vertical video rate, but it runs at the same rate than dos_rate instead.
What should happen: setting/forcing host_rate = 120 + vsync = on when a ~120Hz physical video mode is in use, dosbox-staging should effectively refresh the screen ~120 times per second, independently from dos_rate.
Currently, the ONLY way to get dosbox-staging to output 120 FPS (=do 120 frame swaps per seconds) is to force dos_rate = 120 and presentation_mode = cfr. That's not correct. Forcing the dos_rate to achieve ~120 FPS should not be needed.
In a nutshell, host_rate = 120 + vsync = on should result in 120 FPS being produced, even if internal DOS rate is still whatever the DOS program wants it to be.
Using different presentation_mode values makes no difference: only forcing dos_rate to 120 and setting presentation_mode to cfr makes effect, but that's not a solution because a 120 dos_rate naturally makes the games unplayable fast, as expected.
This is not related to the environment: the fact that GNU/Linux and/or Wayland is used here is not really relevant, this issue has to do with how dosbox-staging does frame swaps internally using the SDL2/OpenGL functions (ie: how many times per second it requests frame swaps) in relation to the host_rate option. That doesn't have anything to do with the underlying OS or windowing system.
Related issue
- https://github.com/dosbox-staging/dosbox-staging/issues/4227
Steps to reproduce the behaviour
Explain in detail how to reproduce the bug. Assume no familiarity with the software.
- Set a physical ~120Hz video mode on the host machine.
- Set
host_rate = 120in dosbox-staging.conf - Launch a DOS game/program (no matter which one) or simply a DOS session using dosbox-staging
- Turn on your display overlay to watch the vertical video rate / vfreq (or use whatever means you want in software, like mangohud, etc). You will see it matches the INTERNAL
dos_rateinstead of the forcedhost_ratevalue.
Download URL of affected game or software
No game needed, just run a plain DOS session to see how the parameter is ignored.
Your configuration
Provide a log
https://gist.github.com/vanfanel/a82fdfa4e893295056e82f0a219efb82
Code of conduct and contributing guidelines
- [x] Yes, I agree.
I'm a bit confused... You raised this ticket in 2021, didn't you? https://github.com/dosbox-staging/dosbox-staging/issues/953
This is what you asked for in that ticket (quoting your words):
A config parameter to specify the refresh rate of the emulated VGA graphics. It could simply be called "refresh_rate =", setting it to "auto" would use the default refresh rate and setting it to "host" would use the host's refresh rate.
Well, that's what host_rate does. It controls how the refresh rate of the emulated VGA adapter is determined. It doesn't try to change the refresh rate of your monitor or desktop--although I'd agree we could make that distinction a bit clearer in the config setting's description.
dosbox-staging should run with a ~120 Hz vertical video rate, but it runs at the same rate than dos_rate instead.
Yes, because you forced dos_rate. So... don't force dos_rate? 😆
You will see it matches the INTERNAL dos_rate instead of the forced host_rate value.
Again, leave dos_rate alone then. If you set dos_rate, that's the rate you'll get.
This is not related to the environment: the fact that GNU/Linux and/or Wayland is used here is not really relevant, this issue has to do with how dosbox-staging does frame swaps internally using the SDL2/OpenGL functions (ie: how many times per second it requests frame swaps) in relation to the host_rate option. That doesn't have anything to do with the underlying OS or windowing system
Not true. The environment plays a huge role and effectively every single presentation mode / vsync / VRR change needs to be tested on all three OSes (Windows, macOS, Linux) as they have very different behaviour. Speaking from experience.
Anyway, this is a huge can of worms.
TL;DR We don't support frame doubling at the host rate like you think we do (present 60 Hz content at 120 Hz, or 180 Hz, etc.)
I can confirm this behaviour. I will test it on Windows also and let you know.
Well, that's what
host_ratedoes. It controls how the refresh rate of the emulated VGA adapter is determined. It doesn't try to change the refresh rate of your monitor or desktop--although I'd agree we could make that distinction a bit clearer in the config setting's description.
But that's wrong, at least in the naming (my fault from 2021 I guess?): host_rate should control the external framerate, NOT the internal VGA adapter rate. The VGA adapter rate should be controlled with dos_rate (and it is! dos_rate does what it's supposed to do, but not host_rate).
dosbox-staging should run with a ~120 Hz vertical video rate, but it runs at the same rate than dos_rate instead.
Yes, because you forced
dos_rate. So... don't forcedos_rate? 😆
That was part of my experiments. I don't want to change dos_rate at all.
The environment plays a huge role and effectively every single presentation mode / vsync / VRR change needs to be tested on all three OSes (Windows, macOS, Linux) as they have very different behaviour. Speaking from experience.
Are you setting the presentation mode somewhere in the code? Unless you are doing so, up-to-date Wayland compositors use mailbox by default, and I am sure modern Winblows matches that default (wouldn't touch a Win system with a 10mts pole, but that's a different story).
TL;DR We don't support frame doubling at the host rate like you think we do (present 60 Hz content at 120 Hz, or 180 Hz, etc.)
...and that's why it's impossible to have perfectly smooth scrolls with VRR on Jazz, Superfrog, etc.: it's physically impossible to have it in VRR equipment unless you let the host graphics run at full refresh rate and duplicate frames. VRR does not work like "do ~60 frame swaps per second on a ~120 Hz display and we get perfect scrolls magically". It needs the emulator to be VSYNC-ed (this would lead to producing ~120FPS) and still run at ~60FPS internally.
Should I open a ticked for doubling at the host rate then?
I already have those games running perfectly on RA, FPGA, etc.. my only intention here is to help improving dosbox-staging so it does justice to those games, which is perfectly possible, and I see it has many options already to achieve this, it's just that some of them don't do what they should do.
These are SDL2+GL games that run perfectly well while obeying the host refresh rate of ~120Hz. They show perfectly smooth framerates by: 1) Swapping the video buffers ~120 times per second 2) Running internally at 60 FPS. In other words, they use VRR as intended (they let SDL2/GL do it, to be precise):
I am sure the dosbox-staging code can be easily modified to do the same. If it was my own code, I would do it.
Can you at least give me a hand on where to look? Since I do my own builds here, it should be relatively easy, and we can fight the can of worms that way :)
Also, as @GuerreroNinja said, the same problem can also be seen on Windows, so it's no doubt internal to how staging manages the external/internal rates.
VRR does not work like "do ~60 frame swaps per second on a ~120 Hz display and we get perfect scrolls magically".
But that's exactly how VRR is supposed to work, the refresh rate is in sync with the frame rate. My display is set to 240 Hz, and the OSD shows a refresh rate that's constantly changing with the rendered FPS. If I disable VRR, it will always show 240 Hz.
The 70.1 Hz in your first photo is the intended behavior of a VRR display.
I'm using Windows 10 and VRR in DOSBox Staging is working perfectly with the default settings.
VRR does not work like "do ~60 frame swaps per second on a ~120 Hz display and we get perfect scrolls magically".
But that's exactly how VRR is supposed to work, the refresh rate is in sync with the frame rate. My display is set to 240 Hz, and the OSD shows a refresh rate that's constantly changing with the rendered FPS. If I disable VRR, it will always show 240 Hz.
The 70.1 Hz in your first photo is the intended behavior of a VRR display.
I'm using Windows 10 and VRR in DOSBox Staging is working perfectly with the default settings.
Are you sure of that?
A very simple test is run Superfrog and observe how the frog blinks when it falls from the sky as first level starts: that blinking should be perfectly regular. On dosbox-staging, no matter what, it is not. We also have other Windows users confirming that.
Now, do the same test on RetroArch dosbox with VSYNC ON you will see how it's perfect. Same in real hardware on a CRT, and same on ao486 (FPGA 486 computer implementation on the MiSTer).
@vanfanel Okay, I just remembered the lack of proper VRR range support on a lot of monitors—that explains the whole thing perfectly.
So a monitor that has proper support for VRR has a usable VRR range of 30-144 Hz or 30-360 Hz or something similar. This means if the FPS drops down to 30 FPS, you'll still get perfect vsync.
Now, the problem is that many manufacturers half-ass things to save costs, and it's usually the low FPS limit of the VRR range that suffers. So some cheaper implementations might only go down to 48 Hz, and in your case, the monitor probably can't even go down to 60 Hz reliably! That's pretty shit, but it's what it is.
Some manufacturers employ tricks, like the Low Framerate Compensation (LFC) trick of the "FreeSync Premium" capable monitors. That's basically only supporting a narrow VRR range of something like 70-120 Hz, then doubling up frames when the input falls below 70 FPS. Kind of a hack, and it's amusing they market it to you as "Premium" 🤣
But apparently, that tech is not half bad: https://forums.blurbusters.com/viewtopic.php?t=11520
The results of Nvidia's 2019 testing of 536 VRR-capable monitors paints a pretty sad picture—only 5% (23 models) made the cut that support the 60-144 Hz range properly, which is actually a quite modest range. As mentioned, better monitors have a much lower low cap than 60 Hz!
So @vanfanel, first of all, don't make the mistake assuming everybody has the same monitor as you 😆 @vladkosi most likely has a better model that can sync down to 60 Hz at least.
When shopping around for a new monitor you're intending to use with emulators, don't buy anything that cannot go down to 48 Hz at least.
Now, you can work around these limitations at the software side by doubling up the frames, even if you don't have LFC and a FreeSync "Premium" (big LOL 🤣) monitor. So yeah, maybe RetroArch does that.
Now on to your specific points:
-
dos_ratedoes what it says on the tin—forces the specified Hz for the video mode at the emulated video card level, no matter what. - Yeah, I too think
host_rateis confusing.presentation_ratewould be a lot better; I think I'll rename it. - We could add a "soft-LFC" option to double/triple the presentation rate. Probably we'd need to add a config option that specifies a low threshold for the frame-multiplication (off by default). E.g. you might wanna force a 60 Hz DOS game to run at 360 Hz on a high-refresh monitor.
In a nutshell, host_rate = 120 + vsync = on should result in 120 FPS being produced, even if internal DOS rate is still whatever the DOS program wants it to be.
That's also reasonable, and I agree with you. If the actual refresh rate is higher than the DOS-side refresh rate, we should start presenting duplicate frames. I though that worked with the stock settings, but maybe it doesn't if you specify exact rates with host_rate = 120. Renaming it to presentation_rate = 120 would also make everything a lot clearer: we present at 120 Hz, no matter what.
Can you at least give me a hand on where to look? Since I do my own builds here, it should be relatively easy, and we can fight the can of worms that way :)
Maybe try increasing the low cap of the duplicate frame presentation threshold (we could in theory make this configurable): https://github.com/dosbox-staging/dosbox-staging/blob/main/src/gui/sdlmain.cpp#L1103
Maye the "interpolating VRR" path we did for macOS is applicable to your scenario? Try forcing that. https://github.com/dosbox-staging/dosbox-staging/blob/4fdb359b778e06a16123d5341e4cf210301dd1e0/include/vga.h#L148-L150
Have a look at this too: https://github.com/dosbox-staging/dosbox-staging/blob/main/src/gui/sdlmain.cpp#L362-L454
Unless you are doing so, up-to-date Wayland compositors use mailbox by default, and I am sure modern Winblows matches that default (wouldn't touch a Win system with a 10mts pole, but that's a different story).
If we do any changes to this area based on your experimentations, putting your aversions aside and testing the feature on Windows too with your particular VRR-challenged (😄) monitor would greatly increase the chance of the changes being accepted. We don't wanna play whack-a-mole with the VRR/vsync stuff, so testing both on Linux and Windows with your monitor would be highly advantageous.
VRR range might be the issue, my display starts at 48 Hz.
I've just tested Superfrog, Jazz Jackrabbit and Epic Pinball. They look perfectly smooth, identical to any other emulator or game that's running at 60 FPS.
VRR range might be the issue, my display starts at 48 Hz.
I've just tested Superfrog, Jazz Jackrabbit and Epic Pinball. They look perfectly smooth, identical to any other emulator or game that's running at 60 FPS.
Thanks for confirming!
@vanfanel Okay, I just remembered the lack of proper VRR range support on a lot of monitors—that explains the whole thing perfectly.
So a monitor that has proper support for VRR has a usable VRR range of 30-144 Hz or 30-360 Hz or something similar. This means if the FPS drops down to 30 FPS, you'll still get perfect vsync.
This explains a lot about VRR implementations and related artifacts/problems. In my case, I can confirm that ROG Ally shows a perfect smooth scrolling in RA/MAME arcade emulation without vsync on, i.e. pure VRR sync, no matter the refresh (tested from 49Hz to 72Hz). However, my gaming monitor (HP Omen 27s) shows almost imperceptible stuttering in some games (not all). For example, in Demon's World (55Hz) the background shows some blinking in some elements like windows, but the scrolling is smooth as butter. Does this make sense? Well, there is some kind of black magic happening in the video+LCD panel, I am sure, because ROG Ally does it right with the same parameters in RA. This shows that VRR is very hardware dependent, as mentioned before.
@johnnovak Yes, I think you are totally right on this: the problem here is my monitor VRR range, possibly starting around 70Hz: that explains why 70Hz games look perfectly smooth while ~60Hz ones don't. Thanks to everyone else involved in this thread, really. Bringing light to this issue is proving to be a teamwork! Of course the definitive solution is going to be getting myself a proper VRR monitor starting at 48Hz... but while that happens, let's try to workaround the issue by implementing your suggestions.
Now let's go with your suggestions:
-
I have tried setting
constexpr uint16_t MinRateHz = 70;in https://github.com/dosbox-staging/dosbox-staging/blob/main/src/gui/sdlmain.cpp#L1103 instead of the default 10. That should make any game with less than 70Hz get framedoubled presentation, right? For example, with ~60Hz games dosbox should be sending 120FPS with this modification. It doesn't seem to be the case, even with that, dosbox-staging is still sending ~60fps to the display in 60Hz games. Maybe I understood this wrong? -
I also tried forcing
constexpr auto InterpolatingVrrMinRateHz = 120;in https://github.com/dosbox-staging/dosbox-staging/blob/main/src/gui/sdlmain.cpp#L1103 I am also getting ~60FPS in 60Hz games, shouldn't that produce interpolated 120FPS? Maybe I am understanding that wrong too?
@vanfanel Yeah, I'm intending to add support for frame-doubling at some point, but not now. Then I'll take a deep dive into that code (I did not write it originally). Until then, just play around with the code and let us know if you found something interesting or got something working 😄
@vanfanel Yeah, I'm intending to add support for frame-doubling at some point, but not now. Then I'll take a deep dive into that code (I did not write it originally). Until then, just play around with the code and let us know if you found something interesting or got something working 😄
Ok! Good to hear that. I'll tell you if I get frame-doubling working somehow, but I doubt it. When you do that deep-dive, please tell me so I can test it on my displays. Since most modern displays don't really do proper 60Hz VRR as you said, I think it's a good thing to have.
My monitor, for example, reports on it's EDID that it SHOULD be able to do as low as 48 Hz VRR:
Display Range Limits:
Monitor ranges (Bare Limits): 48-146 Hz V, 180-180 kHz H, max dotclock 340 MHz
Display Product Name: 'XG2401 SERIES'
...But I suppose it's lying. Or, well, doing it wrong, which makes it unsuitable for dosbox-staging unless I stick to 70Hz software. I was about to edit it's EDID, but I guess I can save that effort since it's already reporting a fake 48 Hz lower limit :(
@vladkosi What's your display, please? I may get one like yours :)
You can still try lowering the VRR limit to 30 Hz: https://forums.blurbusters.com/viewtopic.php?t=13250
Or maybe rasing it above 60 Hz will work.
My display is Alienware AW2523HF.
@vanfanel, i checked the specs of the xg2401, and it reports 144Hz is possible with a display port connection. I'm guessing you're using HDMI, which is limited to 120Hz.
Tom's hardware did a thorough review complete with testing the different vsync settings: smartsync vs freesync, the different input lag settings, and different response time settings.
https://www.tomshardware.com/reviews/viewsonic-xg2401-24-inch-freesync-monitor,4504-3.html
"AMD FreeSync is off by default so you'll have to check this box during the XG2401's initial setup. First however, you need to visit the Setup menu and enable DisplayPort 1.2"
"make sure to turn on DP 1.2 and FreeSync and set your video driver to 144Hz"
(They also have recommended settings for the input and lag settings).
So it looks like DP is needed to use FreeSync. If 48 Hz is the VRR lower bound then, then I have no doubt that with FreeSync enabled (and the drivers set to use it), it will correctly lock onto the 60 Hz game and sync the rate to that speed.
But without FreeSync, my hunch is the the monitor is essentially running as a high refresh rate 120 Hz display, but without freesync's ability to lock onto slower rates.
But why are 70 Hz games a lot better than 60 Hz? If I had to guess, the panel is physically syncing in the 144 Hz range, but HDMI's bandwidth limit caps out at 120Hz 1080p. So it could be that 70 Hz games just line up very close to the panels natural rate a lot better than 60 Hz.
Once Freesync is enabled with video drivers supporting it, then it will unlock the panels ability to sync and lock onto rates fully between the 48 to 144 Hz range.
Just a guess :-)
@vladkosi Thanks! Seems to be a good monitor if I can't get the XG2401 to properly sync to ~60Hz dosbox-staging.
About your suggestion for lowering the VRR lower limit to 30 Hz as in https://forums.blurbusters.com/viewtopic.php?t=13250 ...it seems to be using something called CRU which is a Windows thing. I am a Linux-only user. Do you happen to know what this CRU thing does? Does it override EDID under the hood?
@interloper98 I am, in fact, using the XG2401 monitor via DisplayPort. It DOES support 144Hz, but by default Wayland (WLroots) sets a 119 Hz mode by default since that's the "preferred" mode according to wlr-randr. Setting the 144 Hz mode doesn't make any difference for this issue.
Also, FreeSync is active both on Wayland (as reported by wlr-randr again) and on the monitor.
Do you happen to know what this CRU thing does? Does it override EDID under the hood?
https://www.monitortests.com/forum/Thread-Custom-Resolution-Utility-CRU
"CRU creates software EDID overrides in the registry and does not modify the hardware."
Ok, that's good @vanfanel!
Does the XG2401 do the LFC multiplier stuff below 48 Hz that @johnnovak mentioned?
Was thinking it could be verified by forcing the DOS rate into that LFC zone with "dos_rate = 40" (or 35), and then see if a game like SuperFrog looks smooth (ofcourse, it will be in slow-motion, but at least it's one way to check LFC).
Ok, that's good @vanfanel!
Does the XG2401 do the LFC multiplier stuff below 48 Hz that @johnnovak mentioned?
I'm trying to do so. Currently I have to figure out how to fill the empty Range Limits fields on the AW EDID Editor, any help with that is welcome:
Was thinking it could be verified by forcing the DOS rate into that LFC zone with
"dos_rate = 40"(or 35), and then see if a game like SuperFrog looks smooth (ofcourse, it will be in slow-motion, but at least it's one way to check LFC).
Yes, I set dos_rate=30 and presentation_mode=cfr, and frame pacing is correct. Even at 40 and 50 it is correct. (Of course it's slow-mo as you said).
Well, I can now set the VRR range of the monitor to whatever I want. I even set it to 100-120Hz so LFC kicks in with 60FPS (the monitor overlay reports constant 119.98Hz for ~60Hz content if I do so), but games are still not smooth as in dosbox-core (RA): Superfrog blinking isn't good, scrolls have micro-stuttering, etc.
I guess duplicate-frames is needed in dosbox-staging to achieve this on some Freesync monitors after all, no way around it.
If someone has a VRR Range suggestion to make (I already did 30-120, 70-120, etc) please tell me. A new monitor (Alienware AW2523HF, same as @vladkosi has) is coming tomorrow anyway.
Well, I can now set the VRR range of the monitor to whatever I want. I even set it to 100-120Hz so LFC kicks in with 60FPS (the monitor overlay reports constant 119.98Hz for ~60Hz content if I do so), but games are still not smooth as in dosbox-core (RA): Superfrog blinking isn't good, scrolls have micro-stuttering, etc.
So what did you change exactly? Some monitor or driver settings?
Well, I can now set the VRR range of the monitor to whatever I want. I even set it to 100-120Hz so LFC kicks in with 60FPS (the monitor overlay reports constant 119.98Hz for ~60Hz content if I do so), but games are still not smooth as in dosbox-core (RA): Superfrog blinking isn't good, scrolls have micro-stuttering, etc.
So what did you change exactly? Some monitor or driver settings?
In GNU/Linux it's very easy to retrieve a monitor EDID, since it lives in /sys/class/drm/card0-DP-1/edid, then edit it at will (I finally did it using hexedit directly instead of broken desktop software), then fix the checksum of the blocks, concat them and presto, you can set whatever you want for your monitor resolutions, frequencies... sky is the limit :)
Then, you can tell the kernel to load whatever EDID file you want with the likes of drm.edid_firmware=DP-1:edid/edid2.bin, and finally you can confirm that the new EDID is in use with edid-decode /sys/class/drm/card0-DP-1/edid.
And of course that reflects on the monitor overlay. Here's SuperFrog with the monitor running at 119.98Hz, by setting the lower VRR range limit to 100, which forces LFC to kick-in and make it run at 120Hz (but then again, dosbox-staging needs the frame duplication feature because the game runs at ~60Hz without it anyway, so it's not smooth with this EDID trickery):
Ok, saying monitor driver config would've sufficed 😏
After getting an AW2523HF monitor, I can see that it makes exactly the same thing that my Viewsonic monitors do: -If I set a physical video 60Hz mode, ~60Hz games like Superfrog are totally smooth (=smooth scrolls, regular flog blinking with no "solid" frames in-between during the blinking). -If I set a physical video 120Hz mode, ~60Hz games like Superfrog show microstuttering, unless I force dos_rate & host_rate to be 60. -Same with 70Hz games with smooth sroll (Lemmings 2): they are only microstutter-free if I set a 70hz mode.
So no, the monitor wasn't the problem. AW2523HF doesn't bring anything new to the table.
Standalone MAME is always smooth at any physical refresh rate, even with games that have exotic refresh rates like Mortal Kombat, Caveman Ninja, etc. In other words, MAME does VRR right.
So no, the monitor wasn't the problem. AW2523HF doesn't bring anything new to the table.
Well, @vladkosi has the same as monitor as you now @vanfanel, and he's reporting 100% smooth scrolling and perfect sync in all games on Windows with VRR enabled in Staging.
So any of the following is possible:
- Some driver / OS misconfiguration on your end.
- Monitor firmware differences.
- VRR works perfectly on Windows but is slightly broken on Linux.
- X11 vs Wayland differences as @interloper98 mentioned.
Also, are you testing your new monitor with stock settings? Undo all your tweaking, make sure all presentation settings are on their defaults. VRR should just work out of the box with the stock config, no tweaking should be required. In particular, do NOT set vsync in Staging, neither force it at the driver / OS level.
In other words, MAME does VRR right.
MAME is a different emulator... Console games are very different, etc...
I am using the monitor at default settings. Dosbox-staging is also using all video settings default values, except fullscreen.
I have also tried X11, no difference.
My conclusion is that the effect is so subtle that not everybody sees it: indeed, if I didn't pay attention I could say that games are smooth. But not "as smooth as with plain VSYNC".
I've been investigating and VSYNC is supposed to offer more "continuous" framerate vs VRR/AdaptiveSync anyway (https://arxiv.org/abs/2306.01691), so I'm probably being too picky here. But it seems that the repeated frames feature will overcome this small difference, since apparently that's also what MAME does (hence why no matter the game, I always get ~119FPS on the monitor overlay with MAME and perfectly smooth movement).
This is what ChatGPT says about using VRR with emulators, and it seems to nail what I am seeing on every VRR-capable monitor I try: "Modern 3D games often have fluctuating frame times due to real-time rendering complexity. VRR helps by synchronizing the refresh rate of the monitor to the actual frame delivery, reducing screen tearing and stuttering. However, in 2D emulated games, frame times are often fixed (~60 FPS for console games, ~70 FPS for DOS games). VRR’s dynamic adjustments can introduce micro-stuttering if the frame pacing isn’t perfectly stable. Classic 2D games, especially those with smooth side-scrolling, rely on precise, evenly spaced frame updates. With V-Sync ON at a fixed refresh rate (e.g., 60Hz for a 60FPS game), the timing is locked and produces a perfectly smooth scroll. But with VRR, even if the FPS stays constant, the refresh rate may slightly fluctuate (e.g., 59.9Hz → 60.1Hz), leading to subtle inconsistencies in motion."
Those "subtle inconsistencies" are what I am seeing. Not everybody will see them, but I do.
BTW, when I say MAME does "the right thing" it's because MAME is a very valid example here: MAME does NOT emulate consoles only, it emulates a myriad or arcade systems with very exotic refresh rates... so it has to deal with different framerates waaaay more than dosbox, that's for sure :)
(I would also like to note that it's possible to achieve VSYNC-level of scrolling/refresh perfection in DOS ~60Hz games using dosbox-staging with VRR if the screen refresh is capped to 60Hz. Same for ~70Hz games and capping refresh rate to 70Hz, etc. This proves the point I exposed about slight framerate fluctuation causing the microstuttering I see. But in the end, that's a workaround: frame-repeating is the way to properly "fix" it).
My conclusion is that the effect is so subtle that not everybody sees it: indeed, if I didn't pay attention I could say that games are smooth. But not "as smooth as with plain VSYNC".
Indeed, I think it's a general VRR issue. The quality between the VRR implementations seems to vary a lot between different monitors.
I've been investigating and VSYNC is supposed to offer more "continuous" framerate vs VRR/AdaptiveSync anyway (https://arxiv.org/abs/2306.01691), so I'm probably being too picky here.
Yes, I think so too 😏
This is what ChatGPT says about using VRR with emulators
Great! The plagiarism generator managed to find some useful comment made by a real human 😆 Maybe link the citation sources next time to, so we can read the real answer 😛
Plagiarism generator said: But with VRR, even if the FPS stays constant, the refresh rate may slightly fluctuate (e.g., 59.9Hz → 60.1Hz), leading to subtle inconsistencies in motion.
Yeah, I'd say that's a less than perfect VRR implementation.
BTW, when I say MAME does "the right thing" it's because MAME is a very valid example here: MAME does NOT emulate consoles only, it emulates a myriad or arcade systems with very exotic refresh rates... so it has to deal with different framerates waaaay more than dosbox, that's for sure :)
You are sure about a lot of things 😆 Well, maybe don't be so sure 😄 Watch a few DOS demos, like Show by Majic 12. That switches between non-standard refresh rates like crazy. But yeah, games do that less often, but some still do (e.g., check out the intro of Pinball Fantasies; it's crazy what they're doing there).
If you think there aren't lots of weird custom resolutions in DOS games, check out this table I compiled a while ago (doesn't include refresh rates, though, but those are all over the map too—anything goes):
https://github.com/dosbox-staging/dosbox-staging/wiki/Video-emulation-tests#summary-of-dos-video-modes
But in the end, that's a workaround: frame-repeating is the way to properly "fix" it
How do you know that? Your workaround involves basically artifically "fixing" the refresh rate to a constant value, which won't work with games that switch between refresh rates a lot.
If we start sending every frame twice, and if there is a legit frame presentation evenness problem in Staging, we'd be making the problem worse because the jitter would be doubled, right? It would be still VRR with a slight jitter in the pacing, just at 2x the original rate. Frame-doubling would achieve different results than your workaround.
Not saying there isn't a legitimate problem here, but investigating this will need to wait until one of the core devs gets a VRR -capable monitor (like me, one day 😄). Otherwise, it's impractical to investigate this and rely on other people reports whether some change "improved" things or not. And as you correctly said, different people have different sensitivity to these issues. I grew up with the Commodore 64 and the Amiga 500 on real CRTs, so I definitely can tell when smooth scrolling is 100% smooth (and forced vsync guarantees that too if the emulated refresh rate is forced to the exact same FPS, as you correctly said).
@johnnovak My proposed fix is not about sending every frame twice. It's like this: Always swap frames (that means swapping as many times per second as possible, NOT limited to DOS rate), but only upload new frames when available. If no new frame is available, then draw the same frame.
That's how it's done in both MAME and JollyGood and it works around the natural VRR limitations.
But as I said, it's not a "fix", nothing is "broken" here. I'd call it an improvement instead.
@johnnovak My proposed fix is not about sending every frame twice. It's like this: Always swap frames (that means swapping as many times per second as possible, NOT limited to DOS rate), but only upload new frames when available. If no new frame is available, then draw the same frame.
What determines "as many times per second as possible"? You're confused about VRR... With VRR, you send a frame whenever there is a new frame. That's it. What even is "as many times per second as possible" on a VRR monitor? The highest FPS of the VRR range? So on a 360 Hz max monitor 360 FPS? I don't understand what you're saying.
What you described is exactly what the VFR presentation mode in Staging already does. But that will never give you smooth scrolling... E.g., if you set your monitor to fixed 70 Hz, or 80 Hz, or whatever, then keep sending frames at 70 Hz, 80 Hz, etc. for a 60 Hz DOS game, that will result in a lot of stutter. That's because the 60 Hz frame rate and whatever your actual refresh rate is, so 70 Hz, 80 Hz, etc. don't line up. You need to send 60 Hz content exactly at 60 Hz intervals (or even multiples, so 120, 180, 240, etc.) to get 100% smooth scrolling.
Again, only solvable with VRR in the generic case. You don't quite seem to understand how VRR works and what it tries to solve.
That's how it's done in both MAME and JollyGood and it works around the natural VRR limitations.
I very much doubt that as it doesn't make sense. VRR is VRR, sending frames at a fixed rate is different.
But as I said, it's not a "fix", nothing is "broken" here. I'd call it an improvement instead.
Yeah, I don't think anything is broken here either.
Frame-multiplying (so sending everything twice, or thrice) can be helpful on VRR monitors that do a shit job close to the lower end of the VRR range. So it's a useful workaround for those less-than-perfect VRR monitors that work "on paper" in say the 48 to 160 Hz range or whatever, but in practice sync a lot better to say 120 Hz content than 60 Hz content. It's an implementation deficiency of certain VRR monitors (probably most), and a frame-multiplying feature would help with that in a practical sense. Probably that is what MAME is doing.
Update: Also verify in the logs that Staging sets CFR presentation mode on your VRR monitor with stock settings, and that it does NOT auto-enable vsync. If it doesn't that's a problem. In that case try setting presentation_mode = cfr and by all means set vsync = off.
@johnnovak I understand what VRR does to try and solve the variable framerate problem. But the way that's done, small fluctiations on the frametimes is what cause the slight stuttering I am seeing that is not present with traditional vsync + 60 fps game + 60 hz video mode.
There's how it's done in jollygood: in jgrf.c, lines 839 to 861, notice what it's passed into jgrf_video_render(), it will tell the GL backend to either update the framebuffer or not:
https://gitlab.com/jgemu/jgrf/-/blob/master/src/video_gl.c#L362
(That is also part of how input lag is avoided, because the SDL event loop is going to run and perform the input state changes regardless of whether a frame of emulation was executed or not).