[Mesa-dev] [PATCH 0/2] Update on thread_submit

Axel Davy davyaxel0 at gmail.com
Sat Nov 10 16:09:34 UTC 2018

I just wanted to write a cover letter for this patch to describe
a feature not many user may know about.

On d3d9, frames are supposed to be displayed in the order
they were produced, with no frame skipped.

Thus when vsync is off, the newly produced frames replace the last frame during
refresh, thus creating screen tearing (unless your compositor composites
fullscreen apps, but that's another story).

Mesa ogl backend currently should tear as well when vsync is off.

While this is not in the spec, nine allows to enable a feature
often named 'triple buffering'.
It is named that way because intuitively the idea is to have one buffer
to render to, one buffer on screen, and one buffer more recent than the buffer
on screen that is ready to go on screen at next refresh.

When the refresh is done, we replace the buffer on screen with the more
up-to-date buffer.
When a new frame is rendered, the buffer that is not on screen,
but could go on screen are swapped.

(Ofc you have don't switch the buffer on screen if you don't have any
newer frame).

This enables to render at any framerate (even above screen refresh)
without tearing.

This feature on nine is enabled with the env var (also drirc conf option)

One issue though is that currently buffers are sent to the server while
rendering is not finished.

This behaviour, done by mesa ogl as well (both X and Wayland),
is probably done because:
. This helps reducing compositor lag.
  The compositing operation is scheduled ahead in the gpu pipeline.
. As soon as the application updates its window, it can fetch the content via
  some API, or rely on some window message communication to occur.
  You need thus to send the updated buffer when ogl swapbuffer() is called.

When fullscreen and not composited, however, we run into the following issue:
It is possible the buffer gets planned for a pageflip (replace current buffer
on screen), but it is not finished rendering when the pageflip occurs.
Thus the pageflip fails and the previous buffer stays on screen.

This can make a game fps feel smaller on screen that what it is rendering at,
and adds lag.

Fortunately for nine, we can reasonnably assume the application won't read the
window content just after presenting it with d3d (in game screenshots are
implemented by looking at the rendering buffer, not the window content,
and beside that, which app would want to access that content ?).

In order to support DRI_PRIME systems without artefacts, before the kernel
supported dma-buf synchronization, nine added support for thread_submit drirc
env var, which basically uses a thread to delay sending the last rendered
buffer to the X server until it is finished rendering.
This feature can be used without DRI_PRIME as well.

This patchset enables to use thread_submit=true with tearfree_discard=true,
thus enabling to have 'triple buffering' without the mentionned issue.

Another solution of course is to use vsync, but some games' dynamics
can work better without (because cpu time gets eaten waiting vsync).

With vsync, some users apparently have issues with
pageflip getting missed, and in that case thread_submit=true can be used
to increase smoothness.

We thus recommand the following configurations (assuming fullscreen and
not composited):

Game with vsync:
Use thread_submit=true if your graphic card rendering rate is close or
slightly above the screen refresh rate (you are more likely to have
missed pageflips).
You can also enable always, it shouldn't hurt

Game without vsync:
If you don't mind tearing, nothing particular.
If you mind tearing, thread_submit=true tearfree_discard=true

tearfree_discard=true doesn't impact vsync, and both env vars
don't affect mesa ogl, thus you can just set
export tearfree_discard=true
export thread_submit=true
 in your
~/.bashrc to have them always on.

Note: if you don't see tearing with vsync off and without
these options, it means you get composited.
Getting composited means a small perf impact
and possibly a small lag.
Either disable composition manually (alt+shift+f12 on kwin
for example) when needed, or use a wine patch like this one:

Axel Davy (2):
  st/nine: Allow 'triple buffering' with thread_submit
  st/nine: Remove thread_submit warning

 src/gallium/state_trackers/nine/swapchain9.c | 66 +++++++++++++++-----
 src/gallium/state_trackers/nine/swapchain9.h |  1 +
 src/gallium/targets/d3dadapter9/drm.c        |  3 -
 3 files changed, 50 insertions(+), 20 deletions(-)


More information about the mesa-dev mailing list