Re: Emulating GSync at fixed refresh rate? [triple buffer]

Talk about NVIDIA G-SYNC, a variable refresh rate (VRR) technology. G-SYNC eliminates stutters, tearing, and reduces input lag. List of G-SYNC Monitors.
User avatar
RealNC
Site Admin
Posts: 3757
Joined: 24 Dec 2013, 18:32
Contact:

Re: Emulating GSync at fixed refresh rate? [triple buffer]

Post by RealNC » 29 Jan 2014, 13:55

I did a small experiment today. As we all know, tearing is the result of sending a new frame to the monitor when it's not yet finished displaying the previous frame that was sent. So I thought, what if we match the frequency at which we sent frames exactly to the monitor's refresh rate, and time it in such a way that each frame is sent at the exact right moment?

There's an engine that allows fine frame capping. The Source engine. In this case, Gold Source. So I fired up Counter-Strike Condition Zero and played around with fps_max (with V-Sync disabled, of course.) The sweet spot for my monitor seems to be 59.5055 FPS (yes, you can use floats as values.) With that value, the tearing line always stays on the same spot. I then made two key binds for 59.5055 and 59.6. So I set 59.6, observe the tearing line moving upwards, and when it's at the top of the screen, I press the key for 59.5055. Now the tearing line is out of view and doesn't come back. I get zero input lag and no tearing.

With newer games this doesn't work for long, since there can be stutters (when loading new assets and such) which will destroy the timing and the tearing line can then move to a visible spot again. But with old games such as Gold Source ones (like CS 1.6 and CS CZ), this works for quite a long period of time. At least in Linux. In Windows it appears that the timing is destroyed more often.

This made me wonder though if it would be possible for a rendering engine to do that on its own. That is, turning V-Sync off and manually time everything in such a way that the tearing line isn't visible. Could the monitor's vblank signal be utilized for this but without actually doing full V-Sync?
SteamGitHubStack Overflow
The views and opinions expressed in my posts are my own and do not necessarily reflect the official policy or position of Blur Busters.

User avatar
Chief Blur Buster
Site Admin
Posts: 11653
Joined: 05 Dec 2013, 15:44
Location: Toronto / Hamilton, Ontario, Canada
Contact:

Re: Emulating G-Sync at fixed refresh rate [low-lag VSYNC ON

Post by Chief Blur Buster » 29 Jan 2014, 14:08

Emulating variable GSYNC is impossible --
Just try eliminating stutter/tearing during varying 40fps-through-60fps -- you cannot with this method.
However, your approach is still good, called "Just in time VSYNC", as long as frame rates are consistent.
RealNC wrote:Now the tearing line is out of view and doesn't come back.
That sounds like some stage (e.g. game or drivers) is doing some form of adaptive VSYNC, or a harmonic effect in the game engine that is keeping the tearline between refreshes. Normally, when a tearline slowly rolls, it will come back at the opposite end of the screen shortly.

We are already talking about this idea.
You should see "Just In Time VSYNC" in the Area 51:
ezQuake: Just In Time VSYNC

RealNC wrote:This made me wonder though if it would be possible for a rendering engine to do that on its own. That is, turning V-Sync off and manually time everything in such a way that the tearing line isn't visible. Could the monitor's vblank signal be utilized for this but without actually doing full V-Sync?
Yes. ezQuake can do this already.
And twilen says his WinUAE emulator has an adjustment setting that allows you to do this (render immediately before blanking interval).

It's simply letting the software steer the tearline up/and down. Looking in your Custom resolution Utility (NVIDIA or ToastyX) for 1080p@120Hz, you see a 135KHz horizontal scanrate. That means one row of pixels takes 1/135,000th of a second for the GPU to transmit to a display (scan-out from computer to display, transmitting pixels at the dotclock rate, one pixel per dotclock tick). Delay 1/135,000th of a second before presenting a new framebuffer, and the tearline will be downwards one pixel than otherwise. Do enough delays, and you can steer the tearline accurately. But that's simplistic. Easier is you can use Direct3D RasterStatus.ScanLine() to find where the position of the tearline will be (assuming immediate page flip of an already-rendered frame buffer), and compute your future delay loop accordingly. Or if you know you render frames at 500fps, then simply do a busywait until ScanLine() hits approximately 800, then read keyboard/mouse input, render the new game frame in 280/135,000ths of a second (about 2 millisecond), and finally flip to the new frame while the tearline is hidden between refreshes. The problem is sometimes you take longer than expected to render, and sometimes you overshoot, and get tearing near the top edge of the next frame. You can do adaptive algorithms (e.g. running history of the last few frames) to compute what number to wait for RasterStatus.ScanLine(), before reading input and rendering the next frame before the current refresh finishes (e.g. RasterStatus.ScanLine resets to 0). You can also use RasterStatus.InVBlank to help you too, as well, but you want to start rendering before you hit VBlank, so...

Alternatively, instead of reading ScanLine, you can also keep track of the amount of time between refreshes (know the current refresh rate or know how rapidly Direct3D Present() is occuring during VSYNC ON). Knowing the time between refreshes and when the last blanking interval was, you can wait until you think you're "about 75% of the time to the next blanking interval". Then begin reading input, and then do a Present() in VSYNC ON mode. That lowers the lag between input (mouse/keyboard) and the output (display). The name of the game is to make Present() return in the shortest possible time during VSYNC ON mode (e.g. minimum possible waiting for VBlank) by timing the Present() as close as possible to VBlank, but not overshooting. But, one problem, the lack of a safety margin for GPU render fluctuations, means you can miss the current VBlank and cause a full frame of latency. There's a more forgivign method; use game-driven adaptive VSYNC which would have lower latency than driver-driven adaptive VSYNC. It is more challenging, but it can be done. You use VSYNC OFF, and try to flip while the known tearline position will be hidden in the blanking interval between refreshes. Aaron Hightower (AAhigh here) did this when he programmed the San Francisco Rush 2049 coin-op arcade game. When the graphics slowed down a bit, tearing sometimes briefly showed up at the top edge of the screen (due to long GPU render time) before "bouncing" back off the top edge when GPU rendertime fell back.

One of the several approaches above, is what some software ezQuake and WinUAE (command line option) is able to do. This is simply software-based low-latency adaptive VSYNC (with a low-latency fully-capped out frame rate, something harder to do via drivers) -- A few smart programmers are already doing what you're describing.

This concept is easier for somebody who's successfully mastered the art of rasters See Raster Interrupt Veterans, but a modern programmer (who's never worked in the Golden Days of Ataris and Commodore 64s) can familiarize themselves by watching high speed videos of CRTs refreshing and LCDs refreshing, and understanding the concept of the horizontal scanrate, which is exactly the position where the tearline will be.

This isn't GSYNC because it's impossible to emulate with a fixed refresh rate, but simply a low-latency game-driven adaptive VSYNC ON.
Head of Blur Busters - BlurBusters.com | TestUFO.com | Follow @BlurBusters on Twitter

Image
Forum Rules wrote:  1. Rule #1: Be Nice. This is published forum rule #1. Even To Newbies & People You Disagree With!
  2. Please report rule violations If you see a post that violates forum rules, then report the post.
  3. ALWAYS respect indie testers here. See how indies are bootstrapping Blur Busters research!

User avatar
RealNC
Site Admin
Posts: 3757
Joined: 24 Dec 2013, 18:32
Contact:

Re: Emulating G-Sync at fixed refresh rate [low-lag VSYNC ON

Post by RealNC » 29 Jan 2014, 15:59

Chief Blur Buster wrote:
RealNC wrote:Now the tearing line is out of view and doesn't come back.
That sounds like some stage (e.g. game or drivers) is doing some form of adaptive VSYNC, or a harmonic effect in the game engine that is keeping the tearline between refreshes. Normally, when a tearline slowly rolls, it will come back at the opposite end of the screen shortly.
I stop the "rolling" of the tear line by pressing the other key when it reaches the top. I have one key to start the rolling and one to stop it. That allows me to control the position of the tear line. It's still there, but at the very top (or bottom, or jittering between top and bottom) of the screen and stays there. It looks like what is described in this thread:

http://forums.blurbusters.com/viewtopic.php?f=5&t=208

The "Just In Time VSYNC" thread is about rendering at the last possible time before vblank. What I'm describing here is similar, but instead of trying to time the rendering time, I propose rendering as usual without writing any hairy prediction code and only timing the page flip itself and dropping all frames that were rendered between the previous vblank and the new one. For example:

Code: Select all

render frame 1
render frame 2
render part of frame 3
vblank
flip to frame 2 - frame 1 is never displayed, frame 3 isn't ready
render the rest of frame 3
    (we don't want to skip this and go directly for frame 4, since if several
    frames take longer than the vblank interval, we're f****d)
render frame 4
vblank
flip to frame 4 (frame 3 is never displayed)
etc.
Of course this only works in cases where FPS is at least as high as vertical refresh rate. If you drop below, you're forced to either tear or not flip (display the previous frame again.) Triple buffering would defeat the purpose of this idea.

(My original post was a method to manually induce the above behavior to the Gold Source engine.)

So in effect, the engine can render at, say, 120FPS and display without tearing on a 60Hz monitor. Currently, what seems to happen with the majority of existing games engines, is that V-Sync actually caps FPS to the refresh rate. And, as if this wasn't bad enough, they send the previous frame to the monitor rather than the latest one, doubling input lag (for example fps_max > Hz with V-Sync on in Source games induces this behavior; which is the default, even. Very bad.) I don't see a reason to actually do that and it appears to be the main reason for V-Sync input lag.

Does that make sense to anyone? :P
SteamGitHubStack Overflow
The views and opinions expressed in my posts are my own and do not necessarily reflect the official policy or position of Blur Busters.

User avatar
Chief Blur Buster
Site Admin
Posts: 11653
Joined: 05 Dec 2013, 15:44
Location: Toronto / Hamilton, Ontario, Canada
Contact:

Re: Emulating G-Sync at fixed refresh rate [low-lag VSYNC ON

Post by Chief Blur Buster » 29 Jan 2014, 16:25

RealNC wrote:Does that make sense to anyone? :P
What you just described is low-latency triple buffering, isn't it?
Head of Blur Busters - BlurBusters.com | TestUFO.com | Follow @BlurBusters on Twitter

Image
Forum Rules wrote:  1. Rule #1: Be Nice. This is published forum rule #1. Even To Newbies & People You Disagree With!
  2. Please report rule violations If you see a post that violates forum rules, then report the post.
  3. ALWAYS respect indie testers here. See how indies are bootstrapping Blur Busters research!

User avatar
RealNC
Site Admin
Posts: 3757
Joined: 24 Dec 2013, 18:32
Contact:

Re: Emulating G-Sync at fixed refresh rate [low-lag VSYNC ON

Post by RealNC » 29 Jan 2014, 16:29

Chief Blur Buster wrote:
RealNC wrote:Does that make sense to anyone? :P
What you just described is low-latency triple buffering, isn't it?
Hm, I didn't know this existed as I never saw a game actually doing this. If I enable V-Sync, games will cap to 60 and that's the end of it.

Do you know of any engines currently that do this?
SteamGitHubStack Overflow
The views and opinions expressed in my posts are my own and do not necessarily reflect the official policy or position of Blur Busters.

User avatar
Chief Blur Buster
Site Admin
Posts: 11653
Joined: 05 Dec 2013, 15:44
Location: Toronto / Hamilton, Ontario, Canada
Contact:

Re: Emulating G-Sync at fixed refresh rate [low-lag VSYNC ON

Post by Chief Blur Buster » 29 Jan 2014, 16:31

There are many triple buffer algorithms, and some games used the algorithm you describe, as a low-latency triple buffering. I remember at least some games on my 3Dfx Voodoo did things this way more than 10 years ago.

Render Buffer -- frame being rendered, repeatedly replaces frame in waiting buffer when done
Waiting Buffer -- freshest completed rendered frame, which will be flipped at vsync
Front Buffer -- frame being displayed

I forgot which was called the "Back Buffer", but this is the proper low latency triple buffer architecture. When you enabled "Triple Buffering" on a Voodoo2 card in Year 1999, it behaved like this. IMHO, Microsoft messed ability to do proper low latency triple buffering with Direct3D. Old-school developers have been rueing this ever since.

NOTE: You can get microstutters with this triplebuffering algorithm due to the continually varying times between frame render times and the VSYNC. The microstutters go down the higher the framerate you go, at the formula of 1/fps. The maximum stutter amplitude (amount an edge apparently vibrates during stutter) translates to the pixel step between frames. Which means at 200fps, the microstutter amplitude is 1/200ths the motionspeed (e.g. 5 pixel amplitude of stutter (vibrating edge) at 1000 pixels/second. Assuming game motion is 'perfect', the number of stutters per second will be a function of the harmonic between frame rate and refresh rate (e.g. triple buffered 63fps at 60Hz would have 3 microstutters per second).

Mental Note: Hmmm, eventually, I should create an article/post about stutter frequencies and stutter amplitudes, because I've got a good mathematical understanding of stutters under various conditions (double buffered, low-latency triple buffered, VSYNC ON, VSYNC OFF, framerate versus refresh rate) assuming 'perfect' game fluidity (no game-induced fluidity issue) and the rest is caused by harmonics of the way the frames are displayed. This is reliably reproduced when running old game engines on newer systems (e.g. old Quake engine, old Source Engine) because they run so fast that the stutter harmonics are easy for me to predict in advance.
Head of Blur Busters - BlurBusters.com | TestUFO.com | Follow @BlurBusters on Twitter

Image
Forum Rules wrote:  1. Rule #1: Be Nice. This is published forum rule #1. Even To Newbies & People You Disagree With!
  2. Please report rule violations If you see a post that violates forum rules, then report the post.
  3. ALWAYS respect indie testers here. See how indies are bootstrapping Blur Busters research!

User avatar
Chief Blur Buster
Site Admin
Posts: 11653
Joined: 05 Dec 2013, 15:44
Location: Toronto / Hamilton, Ontario, Canada
Contact:

Re: Emulating GSync at fixed refresh rate [triple buffer]

Post by Chief Blur Buster » 29 Jan 2014, 16:47

Aha, found it!

Here's some useful info of low-latency triple buffering on AnandTech
http://www.anandtech.com/show/2794

It's essentially the same algorithm. I seem to recall that someone said it was easier to do with OpenGL than earlier versions of Direct3D which I recall reading more than 10 years ago, lobotomized a developer's ability to easily do low latency triple buffering which used to be popular on 3Dfx voodoo cards of lore...

But somewhere along the way, triple buffering became the lag-evil "render-ahead queue". That's not low latency triple buffering. There has long been confusion about this (as evidenced by developers like you who's never heard of low-latency triple buffering).
Head of Blur Busters - BlurBusters.com | TestUFO.com | Follow @BlurBusters on Twitter

Image
Forum Rules wrote:  1. Rule #1: Be Nice. This is published forum rule #1. Even To Newbies & People You Disagree With!
  2. Please report rule violations If you see a post that violates forum rules, then report the post.
  3. ALWAYS respect indie testers here. See how indies are bootstrapping Blur Busters research!

User avatar
RealNC
Site Admin
Posts: 3757
Joined: 24 Dec 2013, 18:32
Contact:

Re: Emulating GSync at fixed refresh rate [triple buffer]

Post by RealNC » 29 Jan 2014, 17:04

Thanks for the link! I always associated TB with a render-ahead queue. I'm a bit ashamed though, since I owned (and it's still around somewhere) a 3dfx Voodo 1 :oops:

It might be interesting to test modern games though. CS:GO and Tomb Raider have "V-Sync Triple Buffer" and "V-Sync Double Buffer" options. An input lag test comparing the two might be quite illuminating on how they actually implement TB.
SteamGitHubStack Overflow
The views and opinions expressed in my posts are my own and do not necessarily reflect the official policy or position of Blur Busters.

User avatar
nimbulan
Posts: 323
Joined: 29 Dec 2013, 23:32
Location: Oregon

Re: Re: Emulating GSync at fixed refresh rate? [triple buffe

Post by nimbulan » 29 Jan 2014, 20:06

I actually had no idea that triple buffering was supposed to operate this way. I don't think I ever had a machine capable of exceeding 60 fps in games back when this technique was common and probably wouldn't have known the difference anyway.

So all forcing "triple buffering" in D3D games does is add another buffer to the flip queue?

nuninho1980
Posts: 141
Joined: 26 Dec 2013, 09:49

Re: Emulating GSync at fixed refresh rate [triple buffer]

Post by nuninho1980 » 11 Feb 2014, 07:33

Chief Blur Buster wrote:Aha, found it!

Here's some useful info of low-latency triple buffering on AnandTech
http://www.anandtech.com/show/2794

It's essentially the same algorithm. I seem to recall that someone said it was easier to do with OpenGL than earlier versions of Direct3D which I recall reading more than 10 years ago, lobotomized a developer's ability to easily do low latency triple buffering which used to be popular on 3Dfx voodoo cards of lore...

But somewhere along the way, triple buffering became the lag-evil "render-ahead queue". That's not low latency triple buffering. There has long been confusion about this (as evidenced by developers like you who's never heard of low-latency triple buffering).
I have knew and liked about ~8 years. :) But...
ATTENTION: TB may damage to VRAM (videocard) because my friend have "adviced" to disable TB me after my videocards damaged (GeForce 6800Ultra and 8800GTS 640). My GeForce GTX 480 is almost 39 months old (3 years old), since TB disabled in 2009. :D
CPU: [email protected]
RAM: 2x16GB DDR4@3600MHz
MB: MSI PRO Z690-A DDR4
GPU: Zotac RTX 4090 non-OC new! <3 :D
Opt. disc: LG BD-RE writer BH16NS40
HDD: SATA 1TB
SSDs: OCZ RD400 0.5TB+Crucial MX500 2TB
PSU: AEROCOOL 1kW 80+ Gold
Disly: CRT 21" Sony E530 :D

Post Reply