On Sat, Aug 3, 2019 at 3:19 AM Lionel Landwerlin <lionel.g.landwerlin@xxxxxxxxx> wrote:
Thanks a lot for writing this :)
I now have a canvas to add stuff on!
Just a couple of questions below.
-Lionel
On 02/08/2019 20:40, Jason Ekstrand wrote:
> This patch only brings the syncobj documentation up-to-date for the
> original form of syncobj. It does not contain any information about the
> design of timeline syncobjs.
> ---
> drivers/gpu/drm/drm_syncobj.c | 81 +++++++++++++++++++++++++++++++----
> 1 file changed, 73 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
> index 1438dcb3ebb1..03cc888744fb 100644
> --- a/drivers/gpu/drm/drm_syncobj.c
> +++ b/drivers/gpu/drm/drm_syncobj.c
> @@ -29,17 +29,82 @@
> /**
> * DOC: Overview
> *
> - * DRM synchronisation objects (syncobj, see struct &drm_syncobj) are
> - * persistent objects that contain an optional fence. The fence can be updated
> - * with a new fence, or be NULL.
> + * DRM synchronisation objects (syncobj, see struct &drm_syncobj) provide a
> + * synchronization primitive which can be used by userspace to explicitly
> + * synchronize GPU commands, can be shared between userspace processes, and
> + * can be shared between different DRM drivers.
I've been wondering whether we should call it a container for a
synchronization primitive rather than a primitive itself.
Sync files are also a container, just we fewer features (no host
operations).
It's not really important :)
That's a fun philosophical question and I think the answer entirely depends on which side of the ioctl you're on. :-)
> + * Their primary use-case is to implement Vulkan fences and semaphores.
> + * The syncobj userspace API provides ioctls for several operations:
> *
> - * syncobj's can be waited upon, where it will wait for the underlying
> - * fence.
> + * - Creation and destruction of syncobjs
> + * - Import and export of syncobjs to/from a syncobj file descriptor
> + * - Import and export a syncobj's underlying fence to/from a sync file
> + * - Reset a syncobj (set its fence to NULL)
> + * - Signal a syncobj (set a trivially signaled fence)
> + * - Wait a syncobj's fence to be signaled
> *
> - * syncobj's can be export to fd's and back, these fd's are opaque and
> - * have no other use case, except passing the syncobj between processes.
> + * At it's core, a syncobj simply a wrapper around a pointer to a struct
> + * &dma_fence which may be NULL.
> + * 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.
> *
> - * Their primary use-case is to implement Vulkan fences and semaphores.
Maybe add a line about creation (and its signaled flag)?
Sure, I'll also make a comment about reset and signal.
> + *
> + * Host-side wait on syncobjs
> + * --------------------------
> + *
> + * The userspace syncobj API provides an ioctl for waiting on a set of
> + * syncobjs.
> + * The wait ioctl takes an array of syncobj handles and a flag indicating
> + * whether it should return immediately once one syncobj has been signaled
> + * or if it should wait for all the syncobjs to be signaled.
> + * Unlike the enqueued GPU work dependencies, the host-side wait ioctl
> + * will also optionally wait for the syncobj to first receive a fence and
> + * then wait on that fence.
> + * Assuming the syncobj starts off with a NULL fence, this allows a client
> + * to do a host wait in one thread (or process) which waits on GPU work
> + * submitted in another thread (or process) without having to manually
> + * synchronize between the two.
> + * This requirement is inherited from the Vulkan fence API.
Should we list the flags & ioctl names?
I don't know. Maybe Dave or Daniel can tell me how these things are usually done?
> + *
> + *
> + * Import/export of syncobjs
> + * -------------------------
> + *
> + * The userspace syncobj API provides two mechanisms for import/export of
> + * syncobjs.
> + *
> + * The first lets the client import or export an entire syncobj to a file
> + * descriptor.
> + * These fd's are opaque and have no other use case, except passing the
> + * syncobj between processes.
> + * All syncobj handles which are created as the result of such an import
> + * operation refer to the same underlying syncobj as was used for the
> + * export and the syncobj can be used persistently across all the processes
> + * with which it is shared.
> + * Unlike dma-buf, importing a syncobj creates a new handle for every
> + * import instead of de-duplicating.
> + * The primary use-case of this persistent import/export is for shared
> + * Vulkan fences and semaphores.
> + *
> + * The second import/export mechanism lets the client export the syncobj's
> + * current fence to/from a &sync_file.
> + * When a syncobj is exported to a sync file, that sync file wraps the
> + * sycnobj's fence at the time of export and any later signal or reset
> + * operations on the syncobj will not affect the exported sync file.
> + * When a sync file is imported into a syncobj, the syncobj's fence is set
> + * to the fence wrapped by that sync file.
> + * Because sync files are immutable, resetting or signaling the syncobj
> + * will not affect any sync files whose fences have been imported into the
> + * syncobj.
> *
This 3 lines below seem to be redundant now?
Which three lines are you referring to? The thing about krefs? I agree that it feels a bit odd with the rest of the documentation because it's a very internal detail and the rest of what I've written is an overview. Maybe the bit about krefs should go in the top section and the bit about the file should stay here?
Maybe rephrase with something like :
"Sharing a syncobj increases its refcount. The syncobj is destroyed when
a client release the last reference."
I don't think we need to describe how reference counting works.
> * syncobj have a kref reference count, but also have an optional file.
> * The file is only created once the syncobj is exported.
_______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel