From: Gustavo Padovan <gustavo.pado...@collabora.co.uk>

Hi,

Currently the Linux Kernel only have an implicit fencing mechanism where the
fence are attached directly to buffers and userspace is unaware of the inner
kernel workings. However by enabling explicit fencing, where fences travels
all the way up the userspace we can provide insightful information to
compositors so smarter decisions when scheduling framebuffers.

For that we adapted the Android Sync Framework[1], a explicit fencing mechanism
that helps the userspace handles fences directly. It has the concept of
sync_file (called sync_fence in Android) that expose the driver's fences to
userspace via file descriptors, than can then be shared between process.

With explicit fencing we have a global mechanism that optimizes the flow of
buffers between consumers and producers, avoid a lot of waiting. So instead
of waiting for a buffer to be processed by the GPU before sending it to DRM/KMS
in an Atomic IOCTL we can get a sync_file fd from the GPU driver at the moment
we submit the buffer processing. The compositor then passes these fds to 
DRM/KMS 
in a Atomic Commit request, that will not be displayed until the fences signal,
i.e, the GPU finished processing the buffer and it is ready to be displayed.

In DRM/KMS the fences we wait on before displaying a buffer are called
*in-fences*.  Vice-versa, we have *out-fences*, to sychronize the return of
buffers to GPU (producer) to be processed again. When DRM/KMS receives an
atomic request with a special flag set it generates one fence per-crtc and
attach it to a per-crtc sync_file.  It then returns the array of sync_file fds
to userspace as an atomic_ioctl out arg. With the fences available userspace
can forward these fences to the GPU, where it will wait the fence to signal
before starting to process on the shared buffer again.

Explicit fencing with the Sync Framework provides better traceability and 
debuggabilty of the kernel and allows efficient buffer suballocation by
Mesa/Vulkan.

DRM/KMS explicit fences are opt-in, as the default will still be implicit
fencing.  To enable explicit in-fences one just need to pass a sync_file fd in
the FENCE_FD plane property. *In-fences are per-plane*, i.e., per framebuffer.

For out-fences, just enabling DRM_MODE_ATOMIC_OUT_FENCE flag is enough.
*Out-fences are per-crtc*.

In-fences
---------

In the first discussions on #dri-devel on IRC we decided to hide the Sync
Framework from DRM drivers to reduce complexity, so as soon we get the fd
via FENCE_FD plane property we convert the sync_file fd to a struct fence.

Then we just use the already in place fence support to wait on those fences.
Once the producer calls fence_signal() for all fences on wait we can proceed
with the atomic commit and scanout the framebuffers.

Out-fences
----------

Passing the DRM_MODE_ATOMIC_OUT_FENCE flag to an atomic request enables
out-fences. The kernel then creates a fence, attach it to a sync_file and
install this file on a unused fd. The process is repeated for each crtc.
Userspace get the fence back as an array of per-crtc sync_file fds.

DRM core use the already in place drm_event infrastructure to help signal
fences, we've added a fence pointer to struct drm_pending_event. On vblank we
just call fence_signal() to signal that the buffer related to this fence is
*now* on the screen. Note that this is exactly the opposite behaviour from
Android, where the fences are signaled when they are not on display anymore, so
free to be reused.

No changes are required to DRM drivers to have out-fences support, apart from
atomic support of course.

Kernel tree
-----------

For those who want all patches on this RFC are in my tree. The tree includes a
few other patches necessary to run it, like the interruptible wait_for_fences
patch that I sent last week to the mainling list:

https://git.kernel.org/cgit/linux/kernel/git/padovan/linux.git/log/?h=fences


Testing
-------

For testing it Rob Clark add fences support to mesa and kmscube, Rob has
patch for the Mesa core native fence work and freedeno and I have added 
support of virgl as well:

git://github.com/freedreno/libdrm.git fences

git://git.collabora.com/git/user/padovan/mesa.git fences

git://github.com/robclark/kmscube.git atomic-fence


Changes in RFC v4
-----------------

Rebased against latest drm-misc

Regards,

        Gustavo
---

[1] https://source.android.com/devices/graphics/implement.html#vsync


Gustavo Padovan (3):
  drm/fence: add in-fences support
  drm/fence: add fence timeline to drm_crtc
  drm/fence: add out-fences support

 drivers/gpu/drm/Kconfig             |   1 +
 drivers/gpu/drm/drm_atomic.c        | 233 ++++++++++++++++++++++++++++++++----
 drivers/gpu/drm/drm_atomic_helper.c |   3 +
 drivers/gpu/drm/drm_crtc.c          |  38 ++++++
 include/drm/drm_crtc.h              |  33 +++++
 include/uapi/drm/drm_mode.h         |  15 ++-
 6 files changed, 301 insertions(+), 22 deletions(-)

-- 
2.5.5

Reply via email to