Feature: configurable refresh-rate and change default to 60fps #8680
Motivation / Problem
While working on OpenGL for SDL, I noticed a few things with the video driver that stood out. It made me wonder if they could be changed .. and so I tried them out. These combined with OpenGL give to me a much better experience with SDL.
While doing SDL, I found that doing all drivers is pretty easy if (and this is a big if)
There are several, rather unrelated, changes in this PR, but combined gives a good total experience.
There is one TODO in the code, as it depends on another PR to be merged first (startup-configuration-entries).
And as you can see in the diff, there is a lot of duplication between the drivers now. We could abstract this, but I was unsure we should go that route. They are the same now, as we worked a lot on them lately, but there is no guarantee that works in the future. So I left that out for now .. but creating a "base" driver with the mainloop in there is very much possible.
Tested it on SDL2, SDL1, Allegro, Cocoa, Win32, dedicated server and emscripten; they all work as I would expect.
What issues does this solve?
Checklist for review
Some things are not automated, and forgotten often. This list is a reminder for the reviewers.
The text was updated successfully, but these errors were encountered:
Adding to _realtime_ticks in a random place is a bit of a hack, and by using modern C++, we can avoid this hack.
On all OSes we tested the std::chrono::steady_clock is of a high enough resolution to do millisecond measurements, which is all we need. By accident, this fixes a Win32 driver bug, where we would never hit our targets, as the resolution of the clock was too low to do accurate millisecond measurements with (it was ~16ms resolution instead).
During fast-forward, the game was drawing as fast as it could. This means that the fast-forward was limited also by how fast we could draw, something that people in general don't expect. To give an extreme case, if you are fully zoomed out on a busy map, fast-forward would be mostly limited because of the time it takes to draw the screen. By decoupling the draw-tick and game-tick, we can keep the pace of the draw-tick the same while speeding up the game-tick. To use the extreme case as example again, if you are fully zoomed out now, the screen only redraws 33.33 times per second, fast-forwarding or not. This means fast-forward is much more likely to go at the same speed, no matter what you are looking at.
Before, every next frame was calculated from the current time. If for some reason the current frame was drifting a bit, the next would too, and the next more, etc etc. This meant we rarely hit the targets we would like, like 33.33fps. Instead, allow video-drivers to drift slightly, and schedule the next frame based on the time the last should have happened. Only if the drift gets too much, that deadlines are missed for longer period of times, schedule the next frame based on the current time. This makes the FPS a lot smoother, as sleeps aren't as exact as you might think.
Sleep for 1ms (which is always (a lot) more than 1ms) is just randomly guessing and hoping you hit your deadline, give or take. But given we can calculate when our next frame is happening, we can just sleep for that exact amount. As these values are often a bit larger, it is also more likely the OS can schedule us back in close to our requested target. This means it is more likely we hit our deadlines, which makes the FPS a lot more stable.
Most modern games run on 60 fps, and for good reason. This gives a much smoother experiences. As some people have monitors that can do 144Hz or even 240Hz, allow people to configure the refresh rate. Of course, the higher you set the value, the more time the game spends on drawing pixels instead of simulating the game, which has an effect on simulation speed. The simulation will still always run at 33.33 fps, and is not influences by this setting.
… that shouldn't be closed yet The higher your refresh-rate, the more likely this is. Mostly you notice this when creating a new game or when abandoning a game. This is a bit of a hack to keep the old behaviour, as before this patch the game was already freezing your mouse while it was changing game-mode, and it does this too after this patch. Just now it freezes too a few frames earlier, to prevent not drawing windows people still expect to see.