loader/dri3: Wait on buffer at end of swap to reduce latency
Synopsis
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.
Test results
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.
Open Questions
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)