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

Add frame presentation modes (#953, #1167, #1197, #1228, #1363, #1159) #1596

Merged
merged 9 commits into from Mar 30, 2022

Conversation

kcgen
Copy link
Member

@kcgen kcgen commented Mar 22, 2022

Background: DOSBox (and thus Staging) presents a new frame to the host at the end of the DOS video mode's vblank period, provided new DOS screen content is present. Satisfying both conditions means the effective frame rate can be as low as 0 FPS (if the screen content isn't changing) and as fast as the DOS rate (often up to ~70 Hz). We'll call this existing presentation mode: Variable Frame Rate or VFR.

This PR adds some more presentation modes:

  • CFR delivers a constant frame rate defined by the emulated DOS rate. Similar to VFR however this presents all frames.
  • Synced CFR delivers a constant frame rate synchronized with the host's refresh rate. It presents only the most recently updated frame when the DOS rate exceeds the host rate.
  • Throttled VFR delivers a variable frame rate up to the DOS rate throttled to the display's rate. It presents only the most recently updated frame when the DOS rate exceeds the host rate.

Given these modes either show duplicate frames or may drop frames, why would we want them?

  • Some displays include a "variable refresh rate" feature that changes the physical refresh rate based on the inbound frame rate. Some models will flicker and dim when fed frame rates that rapidly bobble around and dip. Therefore these displays behave better with constant frame rates.
  • SDL2 on modern desktops and display drivers can effectively enforce vsync (https://user-images.githubusercontent.com/1557255/159196458-6fff6d8c-0b34-4971-aceb-f59a5017e58c.png), which means the host can absorb frames no faster than the display's frame period and will stall the presenter (ie: DOSBox) with more closely spaced framed. For these systems, spacing our frames out to the host's desired pace means we can avoid stalling DOSBox.

By default, this PR inspects real-time conditions and picks the optimal presentation mode and frame period. For power-users, these conditions are configurable:

  • [sdl] presentation_mode = auto / cfr / vfr
  • [sdl] host_rate = auto / sdi / vrr / custom
  • [dosbox] dos_rate = default / host / custom

These are described in the updated config file, which can be written with: Z:\> config -wc.

Contributors to this PR include:

  • @nemo93, who thoroughly reporting several issues regarding dropped and stalled frames.
  • @0mnicydle, @Kappa971 and @shermp who extensively tested and provided feedback during its development.

Linked issues:

@kcgen kcgen added bug Something isn't working regression We broke something 😊 labels Mar 22, 2022
@kcgen kcgen self-assigned this Mar 22, 2022
@kcgen kcgen added this to In progress in 0.79 release via automation Mar 22, 2022
@kcgen
Copy link
Member Author

kcgen commented Mar 22, 2022

For those testing on Linux, I noticed ibus-daemon was able to micro-stall DOSBox Staging (and the gnome-shell) due to an excessive CPU usage bug. You can safely kill/uninstall/delete the ibus daemon to avoid this impact.

@kcgen
Copy link
Member Author

kcgen commented Mar 23, 2022

Comparing main versus the PR on a vsync-enforced 60 Hz system using the same conf setting, running Phil's benchmark.

[sdl]
fullscreen = true
output = opengl
vsync = true
vsync_skip = 0

[render]
scaler = none
glshader = none

[cpu]
core = dynamic
cycles = max

[dosbox]
startup_verbosity = quiet

[mixer]
nosound = true

Doom

2022-03-23_16-38_1

Before:

  • 2022-03-23_16-32_1

After:

  • 2022-03-23_16-31

Chris's 3D Benchmark

2022-03-23_16-38

Before:

  • 2022-03-23_16-32

After:

  • 2022-03-23_16-30

Quake

2022-03-23_16-38_2

Before:

  • 2022-03-23_16-33

After:

  • 2022-03-23_16-28

What's going on here?

The main branch is trying to render all 70 DOS frames/s, but my display is vsync-blocked, so DOSBox repeatedly stalls and then unstalls (it appears like breathing.. faster then slow, fast then slow).

On real hardware, these benchmarks scale with system speed - they're not bottlenecked by vsync. That's how the PR lets them run: by only presenting frames to the host in the fraction of time just before vsync period.

Even thought the host is vsync-blocked at 60 Hz, the PR still lets the DOS side behave as if it's running at a full 70 Hz, despite only ever being able to show 60 FPS.

@kcgen kcgen force-pushed the kc/dropped-frames-fix-3 branch 3 times, most recently from a8f7599 to 75d7535 Compare March 25, 2022 04:35
Copy link
Collaborator

@bmunger bmunger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't see any obvious problems with the code changes. Ran my usual tests of this branch and found no regressions either. Don't have a variable refresh rate monitor, so if there are any issues there I wouldn't be able to test. Overall a very large set of changes. Nice work!

These member variables and functions allow for the setting,
getting, and overriding of the DOS refresh rate.
This is a pre-requisite to moving to period-based
constant and variable frame rate presentation, where time
periods are used to control if presentation is performed.
Fixes a couple uninitialized member warnings.
SDL only provides the host rate as an integer, which is too coarse
for our needs.  This commit adds an enum and functions to refine
the host rate.
These routines perform a single task per backend-method:
     - Surface frame buffer update and presentation
     - Texture frame buffer update and presentation
     - OpenGL frame buffer update and presentation

Four presentation modes are added:
     - CFR: constant frame rate
     - VFR: variable frame rate
     - SYNCED_CFR: constant frame rate at host timing
     - THROTTLED_VFR: variable frame rate not exceeding the
                      host's benchmarked max presentation
                      rate.
This commit calls the setup_presentation_mode() routine
during DOS video mode changes and during fullscreen-to-
window toggles.

These are the points where the properties about both
the DOS and host video modes can change, and therefore
are where we should reassess which presentation mode
to employ.

Finally, the selected presentation mode is call in
GFX_EndUpdate().
@kcgen
Copy link
Member Author

kcgen commented Mar 29, 2022

PRs been up for a week.

If anyone plans to help more with this - be it testing, code review, or general feedback - please let me know!

If not, will plan to merge in the next day or so.

Copy link
Sponsor Collaborator

@Wengier Wengier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a complete refinement over the original one. The code looks good and I do not notice any obvious problems either. I don't personally have a VRR monitor to test though, but it has apparently tested by others who have such a monitor.

@kcgen
Copy link
Member Author

kcgen commented Mar 29, 2022

Thanks for the review, @Wengier !

@kcgen
Copy link
Member Author

kcgen commented Mar 30, 2022

Let's merge ; thanks everyone for all the feedback and help testing this!

@kcgen kcgen merged commit e4e50d3 into main Mar 30, 2022
0.79 release automation moved this from In progress to Done Mar 30, 2022
@kcgen kcgen deleted the kc/dropped-frames-fix-3 branch March 30, 2022 07:16
@kcgen kcgen changed the title Add frame presentation modes (#953, #1167, #1197, #1228, #1363) Add frame presentation modes (#953, #1167, #1197, #1228, #1363, #1159) Apr 4, 2022
@kcgen
Copy link
Member Author

kcgen commented Apr 4, 2022

Fixes #1559

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working regression We broke something 😊
Projects
No open projects
3 participants