On 22/08/2019 21:24, Jason Ekstrand wrote:
On Thu, Aug 22, 2019 at 9:55 AM Lionel Landwerlin <lionel.g.landwer...@intel.com <mailto:lionel.g.landwer...@intel.com>> wrote:

    We've added a set of new APIs to manipulate syncobjs holding timelines
    of dma_fence. This adds a bit of documentation about how this works.

    Signed-off-by: Lionel Landwerlin <lionel.g.landwer...@intel.com
    <mailto:lionel.g.landwer...@intel.com>>
    Cc: Christian Koenig <christian.koe...@amd.com
    <mailto:christian.koe...@amd.com>>
    Cc: Jason Ekstrand <ja...@jlekstrand.net
    <mailto:ja...@jlekstrand.net>>
    Cc: David(ChunMing) Zhou <david1.z...@amd.com
    <mailto:david1.z...@amd.com>>
    ---
     drivers/gpu/drm/drm_syncobj.c | 87
    +++++++++++++++++++++++++++++------
     1 file changed, 74 insertions(+), 13 deletions(-)

    diff --git a/drivers/gpu/drm/drm_syncobj.c
    b/drivers/gpu/drm/drm_syncobj.c
    index b5ad73330a48..32ffded6d2c0 100644
    --- a/drivers/gpu/drm/drm_syncobj.c
    +++ b/drivers/gpu/drm/drm_syncobj.c
    @@ -43,27 +43,66 @@
      *  - Signal a syncobj (set a trivially signaled fence)
      *  - Wait for a syncobj's fence to appear and be signaled
      *
    + * The syncobj userspace API also provides operations to
    manipulate a syncobj
    + * in terms of a timeline of struct &dma_fence rather than a
    single struct
    + * &dma_fence, through the following operations:
    + *
    + *   - Signal a given point on the timeline
    + *   - Wait for a given point to appear and/or be signaled
    + *   - Import and export from/to a given point of a timeline
    + *
      * At it's core, a syncobj is simply a wrapper around a pointer
    to a struct
      * &dma_fence which may be NULL.
      * When a syncobj is first created, its pointer is either NULL or
    a pointer
      * to an already signaled fence depending on whether the
      * &DRM_SYNCOBJ_CREATE_SIGNALED flag is passed to
      * &DRM_IOCTL_SYNCOBJ_CREATE.
    - * When GPU work which signals a syncobj is enqueued in a DRM driver,
    - * the syncobj fence is replaced with a fence which will be
    signaled by the
    - * completion of that work.
    - * When GPU work which waits on a syncobj is enqueued in a DRM
    driver, the
    - * driver retrieves syncobj's current fence at the time the work
    is enqueued
    - * waits on that fence before submitting the work to hardware.
    - * If the syncobj's fence is NULL, the enqueue operation is
    expected to fail.
    - * All manipulation of the syncobjs's fence happens in terms of
    the current
    - * fence at the time the ioctl is called by userspace regardless
    of whether
    - * that operation is an immediate host-side operation (signal or
    reset) or
    - * or an operation which is enqueued in some driver queue.
    - * &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL can be
    used to
    - * manipulate a syncobj from the host by resetting its pointer to
    NULL or
    + *
    + * If the syncobj is considered as a binary (signal/unsignaled)
    primitive,


What does "considered as a binary" mean?  Is it an inherent property of the syncobj given at create time?  Is it a state the syncobj can be in?  Or is it a property of how the submit ioctl in the DRM driver references it?  I'm really hoping it's either 1 or 3....


3: you either use it binary/legacy apis, or timeline apis. timeline apis also provide some binary compatibility with the point 0 (in particular for wait).


    + * when GPU work is enqueued in a DRM driver to signal the
    syncobj, the fence
    + * is replaced with a fence which will be signaled by the
    completion of that
    + * work.
    + * If the syncobj is considered as a timeline primitive, when GPU
    work is
    + * enqueued in a DRM driver to signal the a given point of the
    syncobj, a new
    + * struct &dma_fence_chain pointing to the DRM driver's fence and
    also
    + * pointing to the previous fence that was in the syncobj. The
    new struct
    + * &dma_fence_chain fence put into the syncobj will be signaled
    by completion
    + * of the DRM driver's work and also any work associated with the
    fence
    + * previously in the syncobj.
    + *
    + * When GPU work which waits on a syncobj is enqueued in a DRM
    driver, at the
    + * time the work is enqueued, it waits on the fence coming from
    the syncobj
    + * before submitting the work to hardware. That fence is either :
    + *
    + *    - The syncobj's current fence if the syncobj is considered
    as a binary
    + *      primitive.
    + *    - The struct &dma_fence associated with a given point if
    the syncobj is
    + *      considered as a timeline primitive.
    + *
    + * If the syncobj's fence is NULL or not present in the syncobj's
    timeline,
    + * the enqueue operation is expected to fail.
    + *
    + * With binary syncobj, all manipulation of the syncobjs's fence
    happens in
    + * terms of the current fence at the time the ioctl is called by
    userspace
    + * regardless of whether that operation is an immediate host-side
    operation
    + * (signal or reset) or or an operation which is enqueued in some
    driver
    + * queue. &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL
    can be used
    + * to manipulate a syncobj from the host by resetting its pointer
    to NULL or
      * setting its pointer to a fence which is already signaled.
      *
    + * With timeline syncobj, all manipulation of the timeline fences
    happens in
    + * terms of the fence referred to in the timeline. See
    + * dma_fence_chain_find_seqno() to see how a given point is found
    in the
    + * timeline.
    + *
    + * Note that applications should be careful to always use
    timeline set of
    + * ioctl() when dealing with syncobj considered as timeline.
    Using a binary
    + * set of ioctl() with a syncobj considered as timeline could
    result incorrect
    + * synchronization. The use of binary syncobj is supported
    through the
    + * timeline set of ioctl() by using a point value of 0, this will
    reproduce
    + * the behavior of the binary set of ioctl() (for example replace the
    + * syncobj's fence when signaling).

I know I've asked this before but I feel compelled to ask it again.  Why do we allow them to mix and match?  Why not just have a create flag and enforce meaningful behavior? I'm a bit concerned that userspace is going to start relying on the subtlties of the interaction between timeline and binary syncobjs which are neither documented nor properly tested in IGT.


For one, you might have to mix both types of syncobjs in a given wait/signal operation. So 0 ensures we can do that.


Second, drm-syncobj is a container and its payload is an interface (dma_fence) which has several implementations.

The kernel primitive is just less restrictive than the Vulkan API here.

I guess we could add a flag at creation to ensure the replacement of the fence in a timeline syncobj cannot happen.

I haven't thought of all the implications that might have though... Should we allow reset on a timeline syncobj?


-Lionel



    + *
      *
      * Host-side wait on syncobjs
      * --------------------------
    @@ -87,6 +126,16 @@
      * synchronize between the two.
      * This requirement is inherited from the Vulkan fence API.
      *
    + * Similarly, &DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT takes an array of
    syncobj
    + * handles as well as an array of u64 points and does a host-side
    wait on all
    + * of syncobj fences at the given points simultaneously.
    + *
    + * &DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT also adds the ability to wait
    for a given
    + * fence to materialize on the timeline without waiting for the
    fence to be
    + * signaled by using the &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
    flag. This
    + * requirement is inherited from the wait-before-signal behavior
    required by
    + * the Vulkan timeline semaphore API.
    + *
      *
      * Import/export of syncobjs
      * -------------------------
    @@ -120,6 +169,18 @@
      * Because sync files are immutable, resetting or signaling the
    syncobj
      * will not affect any sync files whose fences have been imported
    into the
      * syncobj.
    + *
    + *
    + * Import/export of timeline points in timeline syncobjs
    + * -----------------------------------------------------
    + *
    + * &DRM_IOCTL_SYNCOBJ_TRANSFER provides a mechanism to transfer a
    struct
    + * &dma_fence of at a given point from a timeline syncobj to
    another point
    + * into another timeline syncobj.
    + *
    + * Note that if you want to transfer a struct &dma_fence from a
    given point on
    + * a timeline syncobj from/into a binary syncobj, you can use the
    point 0 to
    + * mean take/replace the fence in the syncobj.
      */

     #include <linux/anon_inodes.h>
-- 2.23.0


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to