[FIXED] Accurate Display.sync()

Started by kappa, February 20, 2012, 22:52:04

Previous topic - Next topic

Simon Felix

We run at 120fps to
a) make our players happy and
b) improve responsiveness

Competitive Tetris is serious business... ;)
Download Cultris II, the fastest Tetris clone from http://gewaltig.net/

princec

But almost every single display out there available except the odd ancient CRT can only do 60Hz...?

Cas :)

CodeBunny

Or 75 fps. I've seen that before. However, people usually have to change monitor settings to enable that, and that usually never happens.

Simon Felix

I first thought too that switching to 60fps should make no difference, since we run the logic at (fixed) 400fps anyway and poll the keyboard more often anyway (Display.processMessages()), not just once per frame. But the game certainly feels more responsive and accurate at 120fps. Did some experiments with our pro-gamers to confirm.

In all cases the lag from "Input -> Rendering -> Screen" should be shorter when you let rendering run more often, in our case half a frame (1/120th).
Download Cultris II, the fastest Tetris clone from http://gewaltig.net/

spasi

Just a heads up, the Nvidia R300 drivers released today should support EXT_swap_control_tear. You can use it by passing -1 to Display.setSwapInterval(). Unfortunately there's no way to detect the presence of a WGL/GLX extension in LWJGL right now, this is something that we plan to fix in 3.0.

EXT_swap_control_tear will synchronize to the monitor refresh rate if rendering is faster and it will swap without synchronization if the frame rate drops below it. Hence you get the best of both worlds and there's no need for Display.sync(). From the spec: "This reduces the visual stutter on late frames and reduces the stall on subsequent frames". I remember John Carmack pushing for this functionality a few years ago, lets hope we'll see support for it from AMD as well. Edit: "Shipping with NVIDIA Forceware 285.62 and AMD Catalyst 11.10 drivers.", it's available on my Radeon and it works great.

princec

Interesting, so that should basically solve the problem of 60fps... 60fps... 60fps... 30fps, where performance suddenly halves? (Or, heh, 45fps, should you perhaps have triple buffering)

Cas :)

spasi

Yes. Nice explanation here, under "Genuinely Smoother Gameplay".

Mickelukas

Quote from: princec on March 22, 2012, 08:33:43
But almost every single display out there available except the odd ancient CRT can only do 60Hz...?

Cas :)

Several new screens do 120Hz to be able to do active shuttering 3D. If you have such a screen I'm guessing that you have a new enough gfx card/driver to support vSyncing though :)

Mike

Obsyd

Tested the new code. It definitely does not eat the cpu as earlier builds do, but it still can do 14% (slowly goes down to 2-4%) on a C2D 3.06Ghz on win7 (2-4% idle). (simple loop,drawing a few triangles) The 2.8.3 display.sync is not as accurate, but it uses only 0-1%.
So this is a step in the right direction :)

CodeBunny

How well does it perform if the game is very CPU-intensive (i.e., already close to 95% or so)? I assume it won't be a problem, just wanting to make sure.

matheus23

Okey, this is completly cracy :D
60.0000 FPS all the time :)
this self-optimizing thing is perfect :)

EDIT: 5% CPU Usage on both cores with an amd athlon 2.55GHz CPU, with only 1 Thread woking at once (but I think thats only because I'm on Archlinux, and linux switches between the cores time to time...)

EDIT2: Idle: ~2% CPU usage.
My github account and currently active project: https://github.com/matheus23/UniverseEngine

Simon Felix

Oh, by the way: I run only the game at 120fps and switch to/from 60fps for the menus. Just in case somebody's looking for test cases... :)
Download Cultris II, the fastest Tetris clone from http://gewaltig.net/

kappa

Display.sync algorithm completely rewritten again (thanks Riven), now works by calculating the average sleep and yield times from the last few frames and adjusts accordingly. Overall much better, uses less yield, more accurate, adapts faster and generally just badass now :)

Do test with the next nightly builds.

Simon Felix

Have thought about using the maximum (instead of average) sleep time? Makes more sense to me.

Pro tip: Store the sum of all elements in addition to the individual values in RunningAvg. Allows to calculate the average in constant time.
Download Cultris II, the fastest Tetris clone from http://gewaltig.net/

kappa

Quote from: dr_evil on March 26, 2012, 19:18:08
Have thought about using the maximum (instead of average) sleep time? Makes more sense to me.
Yup, did try that (see earlier in the thread), however it doesn't work too well as it mostly ends up using yield most of the time, since you can get random spikes with sleep that can be pretty large which mess up the calculation (silly Windows XP can have spikes as large as 60ms). In any event the current method works pretty well and is the most accurate so far.

Quote from: dr_evil on March 26, 2012, 19:18:08
Pro tip: Store the sum of all elements in addition to the individual values in RunningAvg. Allows to calculate the average in constant time.
Yeh, had that in there before but was changed due to the dampening code not working too well, though when benchmarked its pretty insignificant when it comes to overall time spent in sync() (takes maybe a dozen nano's) with most time being spent in the getTime() method. However its a valid optimisation and might be worth tweaking in. Thanks for taking a look.