[Intel-gfx,15/15] intel: Support passing of explicit fencing from execbuf

Submitted by Chris Wilson on Aug. 25, 2016, 9:08 a.m.

Details

Message ID 20160825090839.9952-16-chris@chris-wilson.co.uk
State New
Series "Series without cover letter"
Headers show

Commit Message

Chris Wilson Aug. 25, 2016, 9:08 a.m.
Allow the caller to pass in an fd to an array of fences to control
serialisation of the execbuf in the kernel and on the GPU, and in return
allow creation of a fence fd for signaling the completion (and flushing)
of the batch. When the returned fence is signaled, all writes to the
buffers inside the batch will be complete and coherent from the cpu, or
other consumers. The return fence is a sync_file object and can be
passed to other users (such as atomic modesetting, or other drivers).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 intel/intel_bufmgr.h     |  6 ++++++
 intel/intel_bufmgr_gem.c | 38 +++++++++++++++++++++++++++++++++-----
 2 files changed, 39 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/intel/intel_bufmgr.h b/intel/intel_bufmgr.h
index f4b9b0e..1688312 100644
--- a/intel/intel_bufmgr.h
+++ b/intel/intel_bufmgr.h
@@ -217,6 +217,12 @@  drm_intel_context *drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr);
 void drm_intel_gem_context_destroy(drm_intel_context *ctx);
 int drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
 				  int used, unsigned int flags);
+int drm_intel_gem_bo_fence_exec(drm_intel_bo *bo,
+				drm_intel_context *ctx,
+				int used,
+				int in_fence,
+				int *out_fence,
+				unsigned int flags);
 
 int drm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd);
 drm_intel_bo *drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr,
diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
index 259543f..02ec757 100644
--- a/intel/intel_bufmgr_gem.c
+++ b/intel/intel_bufmgr_gem.c
@@ -75,6 +75,12 @@ 
 
 #define EXEC_OBJECT_ASYNC	(1 << 6)
 
+#define I915_EXEC_FENCE_IN	(1 << 17)
+#define I915_EXEC_FENCE_OUT	(1 << 18)
+
+#define DRM_I915_GEM_EXECBUFFER2_WR     DRM_I915_GEM_EXECBUFFER2
+#define DRM_IOCTL_I915_GEM_EXECBUFFER2_WR       DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2_WR, struct drm_i915_gem_execbuffer2)
+
 #define memclear(s) memset(&s, 0, sizeof(s))
 
 #define DBG(...) do {					\
@@ -2359,6 +2365,7 @@  drm_intel_gem_bo_exec(drm_intel_bo *bo, int used,
 static int
 do_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
 	 drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
+	 int in_fence, int *out_fence,
 	 unsigned int flags)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
@@ -2412,13 +2419,20 @@  do_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
 		i915_execbuffer2_set_context_id(execbuf, 0);
 	else
 		i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id);
-	execbuf.rsvd2 = 0;
+	if (in_fence != -1) {
+		execbuf.rsvd2 = in_fence;
+		flags |= I915_EXEC_FENCE_IN;
+	}
+	if (out_fence != NULL) {
+		*out_fence = -1;
+		flags |= I915_EXEC_FENCE_OUT;
+	}
 
 	if (bufmgr_gem->no_exec)
 		goto skip_execution;
 
 	ret = drmIoctl(bufmgr_gem->fd,
-		       DRM_IOCTL_I915_GEM_EXECBUFFER2,
+		       DRM_IOCTL_I915_GEM_EXECBUFFER2_WR,
 		       &execbuf);
 	if (ret != 0) {
 		ret = -errno;
@@ -2434,6 +2448,9 @@  do_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
 	}
 	drm_intel_update_buffer_offsets2(bufmgr_gem);
 
+	if (out_fence != NULL)
+		*out_fence = execbuf.rsvd2 >> 32;
+
 skip_execution:
 	if (bufmgr_gem->bufmgr.debug)
 		drm_intel_gem_dump_validation_list(bufmgr_gem);
@@ -2459,7 +2476,7 @@  drm_intel_gem_bo_exec2(drm_intel_bo *bo, int used,
 		       int DR4)
 {
 	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
-			I915_EXEC_RENDER);
+			-1, NULL, I915_EXEC_RENDER);
 }
 
 static int
@@ -2468,14 +2485,25 @@  drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
 			unsigned int flags)
 {
 	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
-			flags);
+			-1, NULL, flags);
 }
 
 int
 drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
 			      int used, unsigned int flags)
 {
-	return do_exec2(bo, used, ctx, NULL, 0, 0, flags);
+	return do_exec2(bo, used, ctx, NULL, 0, 0, -1, NULL, flags);
+}
+
+int
+drm_intel_gem_bo_fence_exec(drm_intel_bo *bo,
+			    drm_intel_context *ctx,
+			    int used,
+			    int in_fence,
+			    int *out_fence,
+			    unsigned int flags)
+{
+	return do_exec2(bo, used, ctx, NULL, 0, 0, in_fence, out_fence, flags);
 }
 
 static int

Comments

Rafael Antognolli Sept. 30, 2016, 8:53 p.m.
Hi Chris,

On Thu, Aug 25, 2016 at 10:08:33AM +0100, Chris Wilson wrote:
> Allow the caller to pass in an fd to an array of fences to control
> serialisation of the execbuf in the kernel and on the GPU, and in return
> allow creation of a fence fd for signaling the completion (and flushing)
> of the batch. When the returned fence is signaled, all writes to the
> buffers inside the batch will be complete and coherent from the cpu, or
> other consumers. The return fence is a sync_file object and can be
> passed to other users (such as atomic modesetting, or other drivers).
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  intel/intel_bufmgr.h     |  6 ++++++
>  intel/intel_bufmgr_gem.c | 38 +++++++++++++++++++++++++++++++++-----
>  2 files changed, 39 insertions(+), 5 deletions(-)
> 
> diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
> index 259543f..02ec757 100644
> --- a/intel/intel_bufmgr_gem.c
> +++ b/intel/intel_bufmgr_gem.c
> @@ -2412,13 +2419,20 @@ do_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
>  		i915_execbuffer2_set_context_id(execbuf, 0);
>  	else
>  		i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id);
> -	execbuf.rsvd2 = 0;
> +	if (in_fence != -1) {
> +		execbuf.rsvd2 = in_fence;
> +		flags |= I915_EXEC_FENCE_IN;

The flags are being set here, but not really used anywhere.
Maybe you meant something like:

execbuf.flags != I915_EXEC_FENCE_IN;

?

> +	if (out_fence != NULL) {
> +		*out_fence = -1;
> +		flags |= I915_EXEC_FENCE_OUT;
> +	}

Same as above.

Regards,
Rafael
Chris Wilson Oct. 1, 2016, 8:36 a.m.
On Fri, Sep 30, 2016 at 01:53:06PM -0700, Rafael Antognolli wrote:
> Hi Chris,
> 
> On Thu, Aug 25, 2016 at 10:08:33AM +0100, Chris Wilson wrote:
> > Allow the caller to pass in an fd to an array of fences to control
> > serialisation of the execbuf in the kernel and on the GPU, and in return
> > allow creation of a fence fd for signaling the completion (and flushing)
> > of the batch. When the returned fence is signaled, all writes to the
> > buffers inside the batch will be complete and coherent from the cpu, or
> > other consumers. The return fence is a sync_file object and can be
> > passed to other users (such as atomic modesetting, or other drivers).
> > 
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > ---
> >  intel/intel_bufmgr.h     |  6 ++++++
> >  intel/intel_bufmgr_gem.c | 38 +++++++++++++++++++++++++++++++++-----
> >  2 files changed, 39 insertions(+), 5 deletions(-)
> > 
> > diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
> > index 259543f..02ec757 100644
> > --- a/intel/intel_bufmgr_gem.c
> > +++ b/intel/intel_bufmgr_gem.c
> > @@ -2412,13 +2419,20 @@ do_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
> >  		i915_execbuffer2_set_context_id(execbuf, 0);
> >  	else
> >  		i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id);
> > -	execbuf.rsvd2 = 0;
> > +	if (in_fence != -1) {
> > +		execbuf.rsvd2 = in_fence;
> > +		flags |= I915_EXEC_FENCE_IN;
> 
> The flags are being set here, but not really used anywhere.
> Maybe you meant something like:
> 
> execbuf.flags |= I915_EXEC_FENCE_IN;

Oops.
-Chris