<p dir="ltr">Hi</p>
<p dir="ltr">Out of interest will this allow tear free with PRIME?</p>
<p dir="ltr">Thanks</p>
<p dir="ltr">Mike </p>
<br><div class="gmail_quote"><div dir="ltr">On Tue, 26 Apr 2016, 12:33 a.m. Gustavo Padovan, <<a href="mailto:gustavo@padovan.org">gustavo@padovan.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Gustavo Padovan <<a href="mailto:gustavo.padovan@collabora.co.uk" target="_blank">gustavo.padovan@collabora.co.uk</a>><br>
<br>
Hi,<br>
<br>
Currently the Linux Kernel only have an implicit fencing mechanism<br>
where the fence are attached directly to buffers and userspace is unaware of<br>
what is happening. On the other hand explicit fencing which is not supported<br>
yet by Linux but it expose fences to the userspace to handle fencing between<br>
producer/consumer explicitely.<br>
<br>
For that we use the Android Sync Framework[1], a explicit fencing mechanism<br>
that help the userspace handles fences directly. It has the concept of<br>
sync_file (called sync_fence in Android) that expose the driver's fences to<br>
userspace via file descriptors. File descriptors are useful because we can pass<br>
them around between process.<br>
<br>
The Sync Framework is currently in the staging tree and on the process to<br>
be de-staged[2].<br>
<br>
With explicit fencing we have a global mechanism that optimizes the flow of<br>
buffers between consumers and producers, avoid a lot of waiting. So instead<br>
of waiting for a buffer to be processed by the GPU before sending it to DRM<br>
in an Atomic IOCTL we can get a sync_file fd from the GPU driver at the moment<br>
we submit the buffer processing. The compositor then passes these fds to DRM in<br>
a atomic commit request, that will not be displayed until the fences signal,<br>
i.e, the GPU finished processing the buffer and it is ready to display. In DRM<br>
the fences we wait on before displaying a buffer are called in-fences.<br>
<br>
Vice-versa, we have out-fences, to sychronize the return of buffers to GPU<br>
(producer) to be processed again. When DRM receives an atomic request with a<br>
special flag set it generates one fence per-crtc and attach it to a per-crtc<br>
sync_file. It then returns the array of sync_file fds to userspace as an<br>
atomic_ioctl out arg. With the fences available userspace can forward these<br>
fences to the GPU, where it will wait the fence to signal before starting to<br>
process on buffer again.<br>
<br>
Explicit fencing with Sync Framework allows buffer suballocation. Userspace<br>
get a large buffer and divides it into small ones and submit requests to<br>
process them, each subbuffer gets and sync_file fd and can be processed in<br>
parallel. This is not even possible with implicit fencing.<br>
<br>
While these are out-fences in DRM (the consumer) they become in-fences once<br>
they get to the GPU (the producer).<br>
<br>
DRM explicit fences are opt-in, as the default will still be implicit fencing.<br>
To enable explicit in-fences one just need to pass a sync_file fd in the<br>
FENCE_FD plane property. *In-fences are per-plane*, i.e., per framebuffer.<br>
<br>
For out-fences, just enabling DRM_MODE_ATOMIC_OUT_FENCE flag is enough.<br>
*Out-fences are per-crtc*.<br>
<br>
In-fences<br>
---------<br>
<br>
In the first discussions on #dri-devel on IRC we decided to hide the Sync<br>
Framework from DRM drivers to reduce complexity, so as soon we get the fd<br>
via FENCE_FD plane property we convert the sync_file fd to a struct fence.<br>
However a sync_file might contain more than one fence, so we created the<br>
fence_collection concept. struct fence_collection is a subclass of struct<br>
fence and stores a group of fences that needs to be waited together, in<br>
other words, all the fences in the sync_file.<br>
<br>
Then we just use the already in place fence support to wait on those fences.<br>
Once the producer calls fence_signal() for all fences on wait we can proceed<br>
with the atomic commit and display the framebuffers. DRM drivers only needs to<br>
be converted to struct fence to make use of this feature.<br>
<br>
Out-fences<br>
----------<br>
<br>
Passing the DRM_MODE_ATOMIC_OUT_FENCE flag to an atomic request enables<br>
out-fences. The kernel then creates a fence, attach it to a sync_file and<br>
install this file on a unused fd for each crtc. Userspace get the fence back<br>
as an array of per-crtc sync_file fds.<br>
<br>
DRM core use the already in place drm_event infrastructure to help signal<br>
fences, we've added a fence pointer to struct drm_pending_event. If the atomic<br>
update received requested an PAGE_FLIP_EVENT we just use the same<br>
drm_pending_event and set our fence there, otherwise we just create an event<br>
with a NULL file_priv to set our fence. On vblank we just call fence_signal()<br>
to signal that the buffer related to this fence is *now* on the screen.<br>
Note that this is exactly the opposite behaviour from Android, where the fences<br>
are signaled when they are not on display anymore, so free to be reused.<br>
<br>
No changes are required to DRM drivers to have out-fences support, apart from<br>
atomic support of course.<br>
<br>
Kernel tree<br>
-----------<br>
<br>
For those who want all patches on this RFC are in my tree. The tree includes<br>
all sync frameworks patches needed at the moment:<br>
<br>
<a href="https://git.kernel.org/cgit/linux/kernel/git/padovan/linux.git/log/?h=fences" rel="noreferrer" target="_blank">https://git.kernel.org/cgit/linux/kernel/git/padovan/linux.git/log/?h=fences</a><br>
<br>
I also hacked some poor some fake fences support to modetest here:<br>
<br>
<a href="https://git.collabora.com/cgit/user/padovan/libdrm.git/log/?h=atomic" rel="noreferrer" target="_blank">https://git.collabora.com/cgit/user/padovan/libdrm.git/log/?h=atomic</a><br>
<br>
<br>
v2 changes<br>
----------<br>
<br>
The changes from RFC v1 to RFC v2 are in the patches description.<br>
<br>
TODO<br>
----<br>
<br>
* upstream Android Sync ABI changes<br>
* de-stage Android Sync Framework<br>
* Upstream sync selftests (Emilio Lopez)<br>
* create tests for DRM fences<br>
<br>
Regards,<br>
<br>
Gustavo<br>
---<br>
<br>
[1] <a href="https://source.android.com/devices/graphics/implement.html#vsync" rel="noreferrer" target="_blank">https://source.android.com/devices/graphics/implement.html#vsync</a><br>
[2] <a href="https://git.kernel.org/cgit/linux/kernel/git/padovan/linux.git/log/?h=sync" rel="noreferrer" target="_blank">https://git.kernel.org/cgit/linux/kernel/git/padovan/linux.git/log/?h=sync</a><br>
<br>
Gustavo Padovan (8):<br>
dma-buf/fence: add fence_collection fences<br>
Documentation: add fence-collection to kernel DocBook<br>
dma-buf/sync_file: add sync_file_fences_get()<br>
drm/fence: allow fence waiting to be interrupted by userspace<br>
drm/fence: add in-fences support<br>
drm/fence: add fence to drm_pending_event<br>
drm/fence: add fence timeline to drm_crtc<br>
drm/fence: add out-fences support<br>
<br>
Documentation/DocBook/device-drivers.tmpl | 2 +<br>
drivers/dma-buf/Makefile | 2 +-<br>
drivers/dma-buf/fence-collection.c | 159 ++++++++++++++++++++++++<br>
drivers/dma-buf/fence.c | 2 +-<br>
drivers/dma-buf/sync_file.c | 60 +++++++++<br>
drivers/gpu/drm/Kconfig | 1 +<br>
drivers/gpu/drm/drm_atomic.c | 196 ++++++++++++++++++++++++++++--<br>
drivers/gpu/drm/drm_atomic_helper.c | 24 +++-<br>
drivers/gpu/drm/drm_crtc.c | 36 ++++++<br>
drivers/gpu/drm/drm_fops.c | 8 +-<br>
include/drm/drmP.h | 2 +<br>
include/drm/drm_atomic_helper.h | 4 +-<br>
include/drm/drm_crtc.h | 30 +++++<br>
include/linux/fence-collection.h | 73 +++++++++++<br>
include/linux/fence.h | 9 ++<br>
include/linux/sync_file.h | 3 +<br>
include/uapi/drm/drm_mode.h | 11 +-<br>
17 files changed, 600 insertions(+), 22 deletions(-)<br>
create mode 100644 drivers/dma-buf/fence-collection.c<br>
create mode 100644 include/linux/fence-collection.h<br>
<br>
--<br>
2.5.5<br>
<br>
_______________________________________________<br>
dri-devel mailing list<br>
<a href="mailto:dri-devel@lists.freedesktop.org" target="_blank">dri-devel@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/dri-devel" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/dri-devel</a><br>
</blockquote></div>