skullernet / q2pro

Enhanced Quake 2 client and server
GNU General Public License v2.0
248 stars 87 forks source link

Reducing mouse lag with vertical sync #24

Open ghost opened 11 years ago

ghost commented 11 years ago

I'm curious to know if there is anything that can be done to help reduce the amount of mouse lag / input latency that occurs when v-sync is enabled.

I like the effect dynamic lighting has when v-sync is enabled, but the the mouse lag is very noticeable and makes it difficult to make fast movements. On the other hand, when v-sync is disabled, fast dynamic lighting effects such as the flash from the Machinegun become ruined by screen tearing.

One trick that seems to work is by setting the maxfps just under the monitor refresh rate. In my case setting the maxfps to 58 on my 60Hz monitor appears to eliminate the lag when v-sync is on and keeps the dynamic flash effects looking smooth, but obviously some frame dropping is occurring. The only conclusion I can come up with is that by setting the maxfps to 58, it's no longer being rounded to 62.5, which is above the monitor refresh rate, but this is only a guess - I'm not particularly knowledgeable in this area.

skullernet commented 11 years ago

It is true manual synchronization of SwapBuffers calls to vertical refresh by means of raw frametime measurement does not work well. Call SwapBuffers too early and it blocks. Call it too late and miss a frame update. There needs to be a way for single threaded application to query if previously issued SwapBuffers has completed and it is safe to issue new drawing commands.

I've researched this topic in the past and came to conclusion there is no universal solution to this problem right now. OpenGL implementation deficiencies prevent such automatic synchronization from working correctly on all systems.

Ironically, situation in this area is better on Linux/GLX than on Windows/WGL. On Linux, many video drivers support handy GLX_SGI_video_sync extension that allows applications to directly query video sync counter. Q2PRO already successfully uses it to perform automatic synchronization of rendering fps when ‘cl_async’ is set to 2. It works well with NVidia proprietary drivers and Intel open source drivers on various hardware, and I think should work with AMD/ATI open source drivers.

On Windows, there is no direct analogue to this extension. OpenGL registry lists WGL_OML_sync_control that has similar purpose, but no vendors actually support it.

Another possibility is using GL_ARB_sync, which is more generic and cross-platform solution. It should be possible to install a sync fence after SwapBuffers and then querying it for completion. The problem is that actual vendor support for this extension seems to be very shaky despite it being advertised, for older hardware at least. Among several machines I've tested, I only got it working correctly on a computer with NVidia GTX 650 card, in both Windows 7 and Linux. On previous generations of NVidia GPUs it didn't synchronize correctly even with the same drivers version, and Intel HD graphics drivers simply crashed whenever attempt to use GL_ARB_sync was made.

If GL_ARB_sync worked for most hardware it would be an ideal cross-platform solution. But right now I guess it is too early to become enabling on this feature. Anyway, I've created an ‘arb-sync’ branch that includes experimental support for GL_ARB_sync. Feel free to try if it works for you. If supported on your system, setting ‘cl_async’ to 2 should enable automatic synchronization of rendering fps (‘r_maxfps’ is ignored in this case).

ghost commented 11 years ago

Thank you for the detailed explanation, and for the initial progress you've already made.

I've just built and tested the arb-sync branch and it appears to work very well with cl_async 2 enabled on my NVIDIA 8800 GT card. The motion is very smooth, dynamic lights aren't being affected by screen tearing and input latency is significantly reduced to the point of being barely noticeable.

That's a shame to hear about the lacking hardware / driver support on Windows, but hopefully this situation will continue to improve over time.

jdolan commented 11 years ago

Ely, just buy a 120Hz monitor. Problem solved ;)

PaulKlumpp commented 11 years ago

Wish it was that easy as buying a new monitor. ;) Ghosting (rendering slower than HZ, vsync off) or tearing (rendering half-way done, vsync off) will always occur when not rendering is not synced with HZ. Yep, I know that you know that as well. ;) I just wanted to explain for this thread and for historic purposes of this issue.

2013/4/8 Jay Dolan notifications@github.com

Ely, just buy a 120Hz monitor. Problem solved ;)

— Reply to this email directly or view it on GitHubhttps://github.com/AndreyNazarov/q2pro/issues/24#issuecomment-16052463 .

Calinou commented 6 days ago

With a VRR display, V-Sync enabled and FPS cap below the monitor refresh rate, you can get the best of both worlds (no tearing and low input lag). This doesn't need anything game-specific, so this can probably be closed now. VRR displays literally didn't exist when this issue was opened :slightly_smiling_face:

The only limitation is that r_maxfps in Q2PRO is limited to integer milliseconds per frame value (e.g. you can limit to 111 FPS or 125 FPS, but not 117 FPS which would be optimal for a 120 Hz display). It would be interesting to look into lifting this limitation, but I'm not sure if it's technically feasible (id Tech 3 has struggled with this for decades).