[Mesa-dev] [PATCH 09/13] i965: Always create the batch with the batch object in the first execobject slot

Chris Wilson chris at chris-wilson.co.uk
Thu Jul 20 15:37:45 UTC 2017


Quoting Kenneth Graunke (2017-07-19 23:43:04)
> On Wednesday, July 19, 2017 3:09:17 AM PDT Chris Wilson wrote:
> > Even if we are using older kernels that do not accept the batch in the
> > first slot, we can simplify our code by creating the batch with itself
> > in the first slot and moving it to the end on execbuf submission.
> > ---
> >  src/mesa/drivers/dri/i965/intel_batchbuffer.c | 70 ++++++++++++---------------
> >  1 file changed, 31 insertions(+), 39 deletions(-)
> 
> Alternatively, instead of swapping them out, we could simply add_exec_bo the
> batch at the end, and in execbuffer() do:
> 
> if (!use_batch_first) {
>    execbuf.buffers_ptr++;
>    execbuf.buffers_count--;
> }
> 
> to skip over the batchbuffer entry at the beginning.  That seems easier...

To do that neatly I thought I would need to break apart execbuffer().
Something like,

diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
index f88e000b71..729f411be2 100644
--- a/src/mesa/drivers/dri/i965/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
@@ -645,8 +645,14 @@ do_flush_locked(struct brw_context *brw, int in_fence_fd, int *out_fence_fd)
       }
    }
 
-   if (!brw->screen->no_hw) {
-      unsigned int flags;
+   if (ret == 0 && !brw->screen->no_hw) {
+      struct drm_i915_gem_execbuffer2 execbuf = {
+         .buffers_ptr = (uintptr_t) batch->exec_objects,
+         .buffer_count = batch->exec_count,
+         .batch_len = used,
+         /* rsvd1 is actually the context ID */
+         .rsvd1 = batch->ring == RENDER_RING ? brw->hw_ctx : 0;
+      };
 
       /* The requirement for using I915_EXEC_NO_RELOC are:
        *
@@ -660,37 +666,63 @@ do_flush_locked(struct brw_context *brw, int in_fence_fd, int *out_fence_fd)
        *   To avoid stalling, execobject.offset should match the current
        *   address of that object within the active context.
        */
-      flags = I915_EXEC_NO_RELOC;
+      execbuf.flags = I915_EXEC_NO_RELOC;
       if (brw->gen >= 6 && batch->ring == BLT_RING) {
-         flags |= I915_EXEC_BLT;
+         execbuf.flags |= I915_EXEC_BLT;
       } else {
-         flags |= I915_EXEC_RENDER;
+         execbuf.flags |= I915_EXEC_RENDER;
       }
 
       if (batch->needs_sol_reset)
-        flags |= I915_EXEC_GEN7_SOL_RESET;
+        execbuf.flags |= I915_EXEC_GEN7_SOL_RESET;
 
-      struct drm_i915_gem_exec_object2 *exec_object = &batch->exec_objects[0];
+      unsigned int index;
+      if (batch->use_exec_lut) {
+         execbuf.flags |= I915_EXEC_BATCH_FIRST | I915_EXEC_HANDLE_LUT;
+         index = 0;
+      } else {
+         index = add_exec_bo(batch, target);
+         execbuf.buffers_ptr = (uintptr_t) (batch->exec_objects + 1);
+      }
+      struct drm_i915_gem_exec_object2 *exec_object =
+         &batch->exec_objects[index];
       assert(exec_object->handle == batch->bo->gem_handle);
       exec_object->relocation_count = batch->reloc_count;
       exec_object->relocs_ptr = (uintptr_t) batch->relocs;
-      if (batch->use_exec_lut) {
-         flags |= I915_EXEC_BATCH_FIRST | I915_EXEC_HANDLE_LUT;
-      } else {
-         struct drm_i915_gem_exec_object2 tmp = *exec_object;
-         unsigned int index = batch->exec_count - 1;
-         *exec_object = batch->exec_objects[index];
-         batch->exec_objects[index] = tmp;
+
+      unsigned long cmd = DRM_IOCTL_I915_GEM_EXECBUFFER2;
+
+      if (in_fence_fd != -1) {
+         execbuf.rsvd2 = in_fence;
+         execbuf.flags |= I915_EXEC_FENCE_IN;
       }
 
-      if (ret == 0) {
-         uint32_t hw_ctx = batch->ring == RENDER_RING ? brw->hw_ctx : 0;
+      if (out_fence_fd != NULL) {
+         cmd = DRM_IOCTL_I915_GEM_EXECBUFFER2_WR;
+         *out_fence_fd = -1;
+         execbuf.flags |= I915_EXEC_FENCE_OUT;
+      }
+
+      if (drmIoctl(fd, cmd, &execbuf))
+         ret = -errno;
+
+      for (int i = 0; i < batch->exec_count; i++) {
+         struct brw_bo *bo = batch->exec_bos[i];
 
-         ret = execbuffer(dri_screen->fd, batch, hw_ctx,
-                          4 * USED_BATCH(*batch),
-                          in_fence_fd, out_fence_fd, flags);
+         bo->idle = false;
+         bo->index = -1;
+
+         /* Update brw_bo::offset64 */
+         if (batch->exec_objects[i].offset != bo->offset64) {
+            DBG("BO %d migrated: 0x%" PRIx64 " -> 0x%llx\n",
+                bo->gem_handle, bo->offset64, batch->exec_objects[i].offset);
+            bo->offset64 = batch->exec_objects[i].offset;
+         }
       }
 
+      if (ret == 0 && out_fence != NULL)
+         *out_fence = execbuf.rsvd2 >> 32;
+
       throttle(brw);
    }
 


More information about the mesa-dev mailing list