Assuming a fixed monitor display, and a separate faster than framerate game update loop, then the ideal way to render is to sleep until you just barely have enough time and then start rending, finishing just time for the card to read out the data. But obviously that is hard, since render time is not the same for every frame. [1] But if we could pull this off, it would obviously have latency that is as low as possible given the hardware in question, with the frame actually output always containing the latest possible data without screen tearing. (If you allow for screen tearing by swapping buffers mid scan-out, then you can get even less input latency for the lower parts of the screen with the render as fast as possible techniques.)
The continuously render new frames as fast as possible approach (with triple buffering) is somewhat of a crude approximation of this. It works, and is potentially better than vsync, but is not ideal. It can give impressive framerate numbers though.
Variable refresh rate (gsync, freesync) can avoid this, and are best, at least as long as you can't render frames faster than the maximum refresh rate of the monitor. If you can render frames faster, then all these considerations apply again.
Footnotes:
[1] I seem to recall was some technology that tried to simulate this (without the sleep) by making render calls for "frames" that are too early be no-ops, and only once we are close to when the frame needs to start being actually drawn do the draw calls do anything. This obviously yielded absurd framerate numbers.
I was never suggesting that starting a render run at the last possible second to ensure the frame renders in time to be scanned out was actually a viable approach. Only that it was theoretically optimal.
But hardware changeout would not meaningfully affect people attempting such an approach, because it would obviously be based on actually timing how long a render pass took, adding a small buffer margin, and using that as the timing.
Which does mostly work, except when there is a rapid change in render time, like due to switching on a giant particle effect changing the camera from pointing at the ground to pointing out at the open world, getting close enough to an complex object to swap from a lower LOD mesh to a higher one, etc. These would likely cause meaningful lag spikes as the system tries to adapt.
Comments
Assuming a fixed monitor display, and a separate faster than framerate game update loop, then the ideal way to render is to sleep until you just barely have enough time and then start rending, finishing just time for the card to read out the data. But obviously that is hard, since render time is not the same for every frame. [1] But if we could pull this off, it would obviously have latency that is as low as possible given the hardware in question, with the frame actually output always containing the latest possible data without screen tearing. (If you allow for screen tearing by swapping buffers mid scan-out, then you can get even less input latency for the lower parts of the screen with the render as fast as possible techniques.)
The continuously render new frames as fast as possible approach (with triple buffering) is somewhat of a crude approximation of this. It works, and is potentially better than vsync, but is not ideal. It can give impressive framerate numbers though.
Variable refresh rate (gsync, freesync) can avoid this, and are best, at least as long as you can't render frames faster than the maximum refresh rate of the monitor. If you can render frames faster, then all these considerations apply again.
Footnotes: [1] I seem to recall was some technology that tried to simulate this (without the sleep) by making render calls for "frames" that are too early be no-ops, and only once we are close to when the frame needs to start being actually drawn do the draw calls do anything. This obviously yielded absurd framerate numbers.
A solution like this isn't portable and will fall over as soon as you change any piece of hardware in the system.
Separating responsibilities creates systems that are more robust.
I was never suggesting that starting a render run at the last possible second to ensure the frame renders in time to be scanned out was actually a viable approach. Only that it was theoretically optimal.
But hardware changeout would not meaningfully affect people attempting such an approach, because it would obviously be based on actually timing how long a render pass took, adding a small buffer margin, and using that as the timing.
Which does mostly work, except when there is a rapid change in render time, like due to switching on a giant particle effect changing the camera from pointing at the ground to pointing out at the open world, getting close enough to an complex object to swap from a lower LOD mesh to a higher one, etc. These would likely cause meaningful lag spikes as the system tries to adapt.