If we already have the maximum number of buffers wait on the next free one at the end of the swap. This way we stall the client's execution until a new buffer is available and the redrawing of the client starts only at this point and not before.
This change is based on a patch by @daenzer from the original ticket. Additionally we exclude surfaces from the wait if the buffer age was queried for them at any point in time (see open questions below).
Additionally a new DRI config option
block_on_depleted_buffers is introduced to enable the waits. The behavior must be explicitly enabled by user/system integrator because it could lead to missed frames if the client needs longer than one refresh cycle for producing a new frame.
The vsynced GL applications I tested this patch with behaved as usual. But I couldn't directly notice visual differences as a one-frame latency reduction is subtle. I added trace markers though and the GPUVis output for glxgears is as follows:
You can see here that with the wait the client's call to
loader_dri3_get_buffers is directly at the end of the swap and this call returns immediately. So when a client draws and then is provided a buffer for that operation the client has drawn directly for the next frame. As the first graph shows, without the patch the client has drawn but it only gets shown after
loader_dri3_get_buffers returns one frame later.
In #4859 (comment 944520) @daniels said:
If I remember right, the immediate cause of that was browsers getting framerate decimation, because they needed to know their buffer age to construct their draw calls - something that's pretty irrelevant for games.
I'm not fully understanding the problem here. When the control is returned back to the client after the additional wait on swap can't the client still query buffer age to construct its draw calls then?
Answered by @daenzer in comments.
Closes #4859 (closed)