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

Isolate source of vsync lag under Linux #104

Closed
kcgen opened this issue Dec 26, 2019 · 19 comments · Fixed by #1158
Closed

Isolate source of vsync lag under Linux #104

kcgen opened this issue Dec 26, 2019 · 19 comments · Fixed by #1158
Labels
bug Something isn't working Linux Issues related to GNU/Linux

Comments

@kcgen
Copy link
Member

kcgen commented Dec 26, 2019

Vsync causes frame stuttering and audio-drop outs when backed by SDL2's hardware accelerated backends such as opengl and opengles2. This is true for:

  • fullscreen and windowed modes
  • resolutions ranging from original (postage-stamp) to hardware-scaled 1080p
  • output modes texture(nb) and opengl(nb)
  • aspect correction on or off
  • scaler disabled or enabled (such as none, normal2x, or normal3x)

The only way vsync = true becomes useable is to avoid hardware acceleration such as using output = surface or renderer = software.

The following steps reproduce the issue on Linux x86-64, and include a pre-configured dosbox.conf.

Copy & paste:

cd /dev/shm
wget "https://github.com/dreamer/dosbox-staging/files/4000936/Jazz.Jackrabbit.Holiday.Hare.1995.zip" \
    -q -O - | busybox unzip -
cd "Jazz Jackrabbit Holiday Hare 1995"
wget "https://github.com/dreamer/dosbox-staging/suites/377829540/artifacts/876301" \
    -q -O tmp.zip \
    && unzip -p tmp.zip | xz -dc | tar -xv --strip 1 \
    && rm tmp.zip
./dosbox jazz.exe

Jazz Jackrabbit Holiday Hare 1995.zip

@kcgen kcgen added the bug Something isn't working label Dec 26, 2019
@dreamer
Copy link
Member

dreamer commented Dec 26, 2019

I can reproduce the issue on my laptop. Interestingly, I see another issue, that might be related:

I changed the configuration to:

vsync = false
fullresolution = desktop
…
aspect = true

to test how the game is supposed to behave - and in-game, aspect = true is lost. Loading screen before map is ok, but in-game it's disabled and game uses resolution 320x203. When game is started with aspect=false, the resolution is 320x199.

[edit]
Oh, and back when I was testing on Windows 10 I saw no performance issues related to vsync - I was testing Rertro City Rampage 486. I will be able to test more with Windows 10 after holidays.

@kcgen
Copy link
Member Author

kcgen commented Dec 26, 2019

Thanks for testing on your side; rules out something wonky with my Xorg and direct-rendering configuration.

Very interesting that aspect correction isn't performed. Jazz Jackrabbit is unique in that it deliberately drops to a custom resolution (320x199 instead of 200) so it can run the display at 60hz instead of 70hz.

Jazz Jackrabbit doesn't use aspect correction; hmm (maybe DOSBox auto-disables aspect correct for these custom VGA modes? Or maybe this is a bug in DOSBox and the custom mode or resolution is throwing off that aspect calculation? interesting stuff. I need to dig more into SVN now too!)

At least vsync is good on the Windows side. If someone out there owns an Apple OS X machine, please chime in if you can. We can help you build and run tests.

When I read the SDL guide for moving from 1.2 to 2.0, some of the patterns (ie: blitting and the sequence of new 2.0 function calls) don't jive with our code, some of which seems to still use the 1.2 approach and function calls (will write more details in the next day or so) so I'm hoping once we try these "standard" 2.0 call patterns, we might fix vsync too.

@dreamer
Copy link
Member

dreamer commented Dec 26, 2019

I just wrote long posts on Vogons asking for testing and asking NY00123 about cooperation. Hopefully someone will respond… Later I'll write a post on some dosbox-related subreddits - hopefully it'll bring in more testers as well.

Jazz using custom resolution to trigger refresh rates… that's interesting - I am 100% sure I've seen this issue in other game as well (Chamber of the Sci-Mutant Priestess), but I couldn't reproduce it today.

@kcgen
Copy link
Member Author

kcgen commented Dec 26, 2019

@dreamer
Copy link
Member

dreamer commented Dec 27, 2019

Small update: on my laptop I can't get rid of screen tearing (in any app at all) under X11 - I need to use Wayland for that, so I wanted to make sure this problem is not related to X11. It's not - I managed to start dosbox-staging as purely Wayland app this way:

SDL_VIDEODRIVER=wayland ./src/dosbox <args>

Overall the results are: dosbox starts and games are playable, but there are many tiny (unrelated) issues.

With vsync on - there's no difference, same slowdowns as under X11 with vsync on
With vsync off - I think I saw some screen tearing, but it was much, much harder to notice than with X11. I would be useful to have some kind of DOS exec to dedicated to testing tearing, like https://www.youtube.com/watch?v=MfL_JkcEFbE

@kcgen
Copy link
Member Author

kcgen commented Dec 28, 2019

Whoa - SDL2 supports wayland without X11; amazing!
I ripped that video to AVI and found our master branch wasn't compatible with QuickView (throws a codec initialization error, but older DOSBox binaries work fine).

I eventually turned it into a testcase (on the in-progress kc/coverage-1 branch) and used bisect run until it landed on SVN commit 4301; you'll see a PM in vogons to yourself, QBix, and jmarsh. I'm reluctant to drop a bug in SF at this point in case the change was deliberate and QuickView is merely a non-game casualty.

But yes; that video works great for seeing tearing! Much easier than trying to watch the scrolling horizontal background while simultaneously not dying in a platformer game. Alternatives are cracktros (where usually only small objects or text are scrolling - also hard to see tiny tears). Demos are probably the best option; I need to start combing through those too.

In the meantime, I'll tidy up the coverage branch for a PR; I'd like steadily add many tests that hit most of DOSBox's functionality.

@kcgen
Copy link
Member Author

kcgen commented Jan 2, 2020

Potential fix is outside SDL2 and DOSBox - assuming your laptop is using an Intel GPU:

Add this block to /etc/X11/xorg.conf.d/20-intel.conf

Section "Device"
   Identifier  "Intel Graphics"
   Driver      "intel"
   Option      "TripleBuffer" "true"
   Option      "TearFree"     "true"
   Option      "DRI"          "false"
EndSection

(I rebooted to fully reset my video driver & GPU, but restarting X11 should be fine)

I previously was using TearFree and TripleBuffer but surprisingly those didn't take effect until I disabled DRI! With these three set, Jazz plays buttery smooth (full/window, opengl/texture, vsync on/off).

Curious what you see on your side.

@grapeli
Copy link

grapeli commented Jan 2, 2020

This configuration change doesn't make sense. Global DRI disable is unacceptable. TripleBuffer is also enabled by default.

You will achieve the same effect in this way:
dri_driver=unknown ./dosbox (equally absurd)
or unfortunately turning vertical refresh off
vblank_mode=0 ./dosbox
https://dri.freedesktop.org/wiki/ConfigurationOptions/

More tips used for specific applications can be found in this file - /usr/share/drirc.d/00-mesa-defaults.conf.

@kcgen
Copy link
Member Author

kcgen commented Jan 2, 2020

Thanks @grapeli!

I agree. Whether it makes sense or not, the configuration eliminates the stuttering. I'm not saying it's a solution or a good one.. just that it's interesting that tweaking the intel driver alone is sufficient to result in smooth tear-free play (without any adjustment to SDL2 or DOSBox's rendering settings).

We still don't know if the problem exists in SDL2 itself or how the new DOSBox SDL2 code is configuring SDL2. I hope the latter is true and we can entirely solve it in DOSBox.

This area of driver/software interaction appears to be quite a mess after reading https://wiki.archlinux.org/index.php/Intel_graphics#Troubleshooting It's my hope that we simply use the most bullet-proof SDL2 calls in some "best practices" way, and get the best cross-section of compatibility.

Fully agree global settings are far worse than per-application, and I appreciate seeing your suggestions that we can control it locally (as a temporary work-around?). Another question I have is regarding DRI.. are DRI2 and 3 still enabled? From what I can see DRI1 always had issues with vsync and tearing.

Also, does disabling DRI simply mean that SDL2 is forced to use a software (non-hardware accelerated) backend, in which case we're simply using software rendering again which we know isn't affected by this bug?

@kcgen kcgen changed the title Hardware-accelerated Vsync lags under SDL2 on Linux x86-64 and Linux-ARM Isolate source of vsync lag under Linux Feb 4, 2020
@kcgen kcgen added the Linux Issues related to GNU/Linux label Feb 4, 2020
@dreamer
Copy link
Member

dreamer commented Feb 12, 2020

With shader support merged in, we need some re-tests to see how vsync problem was affected.

@GranMinigun
Copy link
Contributor

GranMinigun commented Feb 12, 2020

Menu (and also after-play DOS screen) in HH95 is still affected. Gameplay seems to be fine though. Pixel dissolve in Catacomb 3-D doesn't slow down anymore nevermind, it is still slow; seems I've missed something while testing. Moving cursor lightning fast in Master of Orion 2 still affects performance. Crusader shows slow down in the very beginning of intro cinematic: it's fading from black per-line.
Superscape Benchmark, while able to output hundreds of frames, crawls down to mere 40FPS with vsync on. Frame pacing is very inconsistent. Same could be said for other apps and games though (Quake).
Makes me wonder, how exactly vsync works in our case. Could it be a problem with how DOSBox rasterizes image? (Just thinking out loud.)

@AaronBPaden
Copy link

So I've recently purchased a freesync display, and I've noticed a couple of things.

Generally, vsync works fine with variable refresh, though it doesn't hold the native refresh rate of 70hz or whatever as you'd hope. It jumps all over the place. Anyway, there is a bug where some applications cause the display to get stuck in 60hz unless I turn the monitor off and back on again. At 60hz, I get the issue described here. Were you testing on a 60hz display for both Windows and Linux, @krcroft?

The second thing I notice is that refresh actually still varies if you turn vsync off. Maybe I misunderstood, but I would expect my display to hold 144hz with vsync off. I read somewhere on the internet somewhere once that variable refresh requires vsync to be on, so it must be true. I wonder if dosbox isn't getting unredirected on gnome, now that it isn't using exclusive fullscreen. Does/should dosbox set _NET_WM_BYPASS_COMPOSITOR on x11?

@kcgen
Copy link
Member Author

kcgen commented Feb 19, 2020

Menu (and also after-play DOS screen) in HH95 is still affected. Gameplay seems to be fine though.

Yes; it's as if the video mode plays a role in exasperating vsync; and HH's menu-mode feels like one of those fast demo-scene modes compared to the in-game-mode, which feels more "normal". That's just me guessing though; I'm not sure how to diagnose this though.

Pixel dissolve in Catacomb 3-D doesn't slow down anymore nevermind, it is still slow; seems I've missed something while testing. Moving cursor lightning fast in Master of Orion 2 still affects performance. Crusader shows slow down in the very beginning of intro cinematic: it's fading from black per-line.

Wow; nice testing! You've found a bunch of corner cases. Is there any overlap with these that also cause degraded behavior with SVN? If so, perhaps some of the issue lies outside of SDL and in pure-DOSBox code.

Superscape Benchmark, while able to output hundreds of frames, crawls down to mere 40FPS with vsync on. Frame pacing is very inconsistent. Same could be said for other apps and games though (Quake).
Makes me wonder, how exactly vsync works in our case. Could it be a problem with how DOSBox rasterizes image? (Just thinking out loud.)

I'm not sure; but this is all great information points when someone start digging around in the code.

@kcgen
Copy link
Member Author

kcgen commented Feb 19, 2020

So I've recently purchased a freesync display, and I've noticed a couple of things.

Nice; after 25 years of progress, the LCD panel world can finally match the old CRT's in refresh-rate!

Generally, vsync works fine with variable refresh, though it doesn't hold the native refresh rate of 70hz or whatever as you'd hope. It jumps all over the place.

Are you seeing this subjectively, or is there some driver-overlay that shows the live frame-rate? Just curious; sounds useful!

Anyway, there is a bug where some applications cause the display to get stuck in 60hz unless I turn the monitor off and back on again.

I guess that's Windows/Driver-related (if you're closing DOSBox between programs/games), or are you running DOS games back-to-back within the same DOSBox session?

Were you testing on a 60hz display for both Windows and Linux, @krcroft?

60 Hz: yes; but only under Linux - however both x86_64 (via OpenGL) and on ARM7 (via OpenGLES).

The second thing I notice is that refresh actually still varies if you turn vsync off. Maybe I misunderstood, but I would expect my display to hold 144hz with vsync off.

Is that the case in window-mode and fullscreen? My son has a 144 Hz G-sync monitor, and some older games (when in true full-screen mode) don't behave well, and framerates collapse. But games shown in window-mode (or borderless but windowed-mode) are always locked to the full 144 Hz rate.

Does/should dosbox set _NET_WM_BYPASS_COMPOSITOR on x11?

It looks like SDL2 takes this into account (in SDL2) https://hg.libsdl.org/SDL/file/tip/src/video/x11/SDL_x11window.c#l597

@AaronBPaden
Copy link

Are you seeing this subjectively, or is there some driver-overlay that shows the live frame-rate? Just curious; sounds useful!

This is a feature of the monitor. You can watch the refresh rate update live in the setting panel. It's a bit limited, since it's a single updating number instead of a graph so you can't see change over time, and it's integer only.

You can also get FPS on Linux/Mesa with the environment variable GALLIUM_HUD=fps. The numbers mostly seem to match, except the refresh rate will sometimes jump well over 70 for a second or two (running Quake), while the fps doesn't seem to. Actually, in retrospect, having the refresh rate mimic the refresh rate expected by the game for variable refresh monitors is a completely different feature from vsync, so maybe not appropriate to discuss here. :P

I guess that's Windows/Driver-related (if you're closing DOSBox between programs/games), or are you running DOS games back-to-back within the same DOSBox session?

This is on Linux, and as you described later, only for certain games. Descent rebirth is an example, which is another application still stuck on sdl1. Dosbox-staging using sdl2 doesn't have this particular problem. I just happened to notice because I didn't realize my panel was stuck at 60hz again when I booted up Quake and ended up with crackling audio.

Is that the case in window-mode and fullscreen? My son has a 144 Hz G-sync monitor, and some older games (when in true full-screen mode) don't behave well, and framerates collapse. But games shown in window-mode (or borderless but windowed-mode) are always locked to the full 144 Hz rate.

Looks like Quake running in dosbox-staging with vsync=false in windowed mode is running at 144hz. I may have gotten it backwards before. Gnome is set to 144hz display mode. Maybe dosbox can only have variable refresh because the application is unredirected, which wouldn't be the case for a window.

@GranMinigun
Copy link
Contributor

GranMinigun commented Feb 19, 2020

Generally, vsync works fine with variable refresh, though it doesn't hold the native refresh rate of 70hz or whatever as you'd hope.

Just to clarify: it shouldn't.

If FreeSync or G-Sync is active and framerate stays within display's refresh rate range, then it will always try to keep refresh rate in sync with FPS.

If FPS goes above your maximum refresh rate, then Vsync kicks in: if it's off, then your framerate goes above your refresh rate with possible tearing; when it's on, FPS is clamped to refresh rate.

Now the interesting part: when FPS goes below minimum refresh rate, if you have a G-Sync or FreeSync display with low framerate compensation, then display starts to duplicate output frames to prevent flicker (so for 24 FPS you'll get 48 Hz, for example). But if you have FreeSync display without low framerate compensation, then it stays at its minimum refresh rate and Vsync kicks in.

Is there any overlap with these that also cause degraded behavior with SVN?

I think I remember that Master of Magic had same problem with cursor moving as MOO2 when double buffering was on, but I need to re-check.

But games shown in window-mode (or borderless but windowed-mode) are always locked to the full 144 Hz rate.

G-Sync should have an option for whether refresh rate should be based on compositor or current window. Don't know about FreeSync though.

@GranMinigun
Copy link
Contributor

So, what happened to vsync config setting?

@dreamer
Copy link
Member

dreamer commented Apr 6, 2020

This was new option introduced by SDL2 patch, and in testing we found additional problems during initialization (discussed in #222) - we removed it for now. Properly addressing the problem will probably mean redesign of main dosbox emulation loop, so it's a major development effort.

We'll get back to it after 0.75.0 release - fixing this properly should open the gates for handling adaptive sync as well.

@vanfanel
Copy link

vanfanel commented Apr 7, 2021

What happens here is simply that you are running games that expect a ~70Hz refresh rate (all DOS 640x400 games / 320x200) on a 60Hz display. So that's expected.
Can this option come back, please? It's NOT a problem when using 70Hz modes...

And there's nothing wrong with SDL2, at least with my KMSDRM backend (which allows DOSBOX-staging to run without X11 and without wayland). This is all expected, really. Emulation is being blocked on vsync at a ~60Hz rate, while the games produce samples for 70Hz. No mistery here.

In fact, if you want a simple test that demonstrates what's going on, just:

-Activate VYSNC (I do my own builds so this is not a problem) by sticking an unconditional SDL_RENDERER_PTRESENTVSYNC in SDL_CreateRenderer())

-Load Jazz JackRabbit, which is know to change videomode in-game between menu/animations and the game itself: you will see that there are audio "gaps" on the menu, but not in playing stages.

-Now, set a 70Hz video mode in dosbox.conf (provided your monitor EDID has one: you can find out with cat /sys/class/drm/card1-HDMI-A-1/edid | edid-decode), along with fullscreen=true.
You will see that there are no problems at all on Jazz JackRabbit tittle screen music when you run the game on a 70Hz mode.

So, all in all, please bring vsync setting back. Disabling it makes no sense at all.

kklobe added a commit that referenced this issue Jul 20, 2021
This is a fix for stuttering issues originally observed when vsync
appeared to be force-enabled due to an external monitor connected to a
MacBook Pro, despite the video subsystem being initialized without
vsync.

The fix sets a maximum allowable duration for the rendering calls, which
block when vsync is enabled. Each render call is timed, and if the
duration is too long, we skip the next frame.

This also restores vsync-related .conf settings.

Fixes #104
@kklobe kklobe mentioned this issue Jul 20, 2021
kklobe added a commit that referenced this issue Jul 20, 2021
This is a fix for stuttering issues originally observed when vsync
appeared to be force-enabled due to an external monitor connected to a
MacBook Pro, despite the video subsystem being initialized without
vsync.

The fix sets a maximum allowable duration for the rendering calls, which
block when vsync is enabled. Each render call is timed, and if the
duration is too long, we skip the next frame.

This also restores vsync-related .conf settings.

Fixes #104
kklobe added a commit that referenced this issue Jul 20, 2021
This is a fix for stuttering issues originally observed when vsync
appeared to be force-enabled due to an external monitor connected to a
MacBook Pro, despite the video subsystem being initialized without
vsync.

The fix sets a maximum allowable duration for the rendering calls, which
block when vsync is enabled. Each render call is timed, and if the
duration is too long, we skip the next frame.

This also restores vsync-related .conf settings.

Fixes #104
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Linux Issues related to GNU/Linux
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants