Mesa (main): iris: Handle multiple BOs backed by the same GEM object in execbuf code

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Oct 1 05:13:34 UTC 2021


Module: Mesa
Branch: main
Commit: 8a1fd43d61cd68118254ec2b301b0c148d15003b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=8a1fd43d61cd68118254ec2b301b0c148d15003b

Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Wed Aug  4 11:22:45 2021 -0700

iris: Handle multiple BOs backed by the same GEM object in execbuf code

With suballocation, our batch BO list may have multiple BOs that are
suballocated from the same GEM object.  We still need to track each of
those buffers for cross-batch write tracking, cache tracking, and busy
tracking.  However, we only want to include underlying GEM objects in
the actual validation list building.  The validation list entry should
have EXEC_OBJECT_WRITE if any of the BOs are marked as writable.

We use a temporary array to map GEM handles to validation list entries
so we can quickly see if we've already emitted one and update the
EXEC_OBJECT_WRITE flag as needed.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12623>

---

 src/gallium/drivers/iris/iris_batch.c | 39 +++++++++++++++++++++++------------
 src/gallium/drivers/iris/iris_batch.h |  1 +
 2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/src/gallium/drivers/iris/iris_batch.c b/src/gallium/drivers/iris/iris_batch.c
index 4ffeb3988af..bd129fd0527 100644
--- a/src/gallium/drivers/iris/iris_batch.c
+++ b/src/gallium/drivers/iris/iris_batch.c
@@ -196,6 +196,7 @@ iris_init_batch(struct iris_context *ice,
    util_dynarray_init(&batch->syncobjs, ralloc_context(NULL));
 
    batch->exec_count = 0;
+   batch->max_gem_handle = 0;
    batch->exec_array_size = 128;
    batch->exec_bos =
       malloc(batch->exec_array_size * sizeof(batch->exec_bos[0]));
@@ -281,6 +282,8 @@ add_bo_to_batch(struct iris_batch *batch, struct iris_bo *bo, bool writable)
    bo->index = batch->exec_count;
    batch->exec_count++;
    batch->aperture_space += bo->size;
+
+   batch->max_gem_handle = MAX2(batch->max_gem_handle, bo->gem_handle);
 }
 
 /**
@@ -748,23 +751,32 @@ submit_batch(struct iris_batch *batch)
    struct drm_i915_gem_exec_object2 *validation_list =
       malloc(batch->exec_count * sizeof(*validation_list));
 
+   unsigned *index_for_handle =
+      calloc(batch->max_gem_handle + 1, sizeof(unsigned));
+
+   unsigned validation_count = 0;
    for (int i = 0; i < batch->exec_count; i++) {
       struct iris_bo *bo = batch->exec_bos[i];
       bool written = BITSET_TEST(batch->bos_written, i);
-      unsigned extra_flags = 0;
-
-      if (written)
-         extra_flags |= EXEC_OBJECT_WRITE;
-      if (!iris_bo_is_external(bo))
-         extra_flags |= EXEC_OBJECT_ASYNC;
-
-      validation_list[i] = (struct drm_i915_gem_exec_object2) {
-         .handle = bo->gem_handle,
-         .offset = bo->address,
-         .flags  = bo->real.kflags | extra_flags,
-      };
+      unsigned prev_index = index_for_handle[bo->gem_handle];
+      if (prev_index > 0) {
+         if (written)
+            validation_list[prev_index].flags |= EXEC_OBJECT_WRITE;
+      } else {
+         index_for_handle[bo->gem_handle] = validation_count;
+         validation_list[validation_count] =
+            (struct drm_i915_gem_exec_object2) {
+               .handle = bo->gem_handle,
+               .offset = bo->address,
+               .flags  = bo->real.kflags | (written ? EXEC_OBJECT_WRITE : 0) |
+                         (iris_bo_is_external(bo) ? 0 : EXEC_OBJECT_ASYNC),
+            };
+         ++validation_count;
+      }
    }
 
+   free(index_for_handle);
+
    if (INTEL_DEBUG & (DEBUG_BATCH | DEBUG_SUBMIT)) {
       dump_fence_list(batch);
       dump_validation_list(batch, validation_list);
@@ -788,7 +800,7 @@ submit_batch(struct iris_batch *batch)
     */
    struct drm_i915_gem_execbuffer2 execbuf = {
       .buffers_ptr = (uintptr_t) validation_list,
-      .buffer_count = batch->exec_count,
+      .buffer_count = validation_count,
       .batch_start_offset = 0,
       /* This must be QWord aligned. */
       .batch_len = ALIGN(batch->primary_batch_size, 8),
@@ -887,6 +899,7 @@ _iris_batch_flush(struct iris_batch *batch, const char *file, int line)
       iris_syncobj_signal(screen->bufmgr, iris_batch_get_signal_syncobj(batch));
 
    batch->exec_count = 0;
+   batch->max_gem_handle = 0;
    batch->aperture_space = 0;
 
    util_dynarray_foreach(&batch->syncobjs, struct iris_syncobj *, s)
diff --git a/src/gallium/drivers/iris/iris_batch.h b/src/gallium/drivers/iris/iris_batch.h
index 2803ae18a84..0d3d597839c 100644
--- a/src/gallium/drivers/iris/iris_batch.h
+++ b/src/gallium/drivers/iris/iris_batch.h
@@ -87,6 +87,7 @@ struct iris_batch {
    int exec_array_size;
    /** Bitset of whether this batch writes to BO `i'. */
    BITSET_WORD *bos_written;
+   uint32_t max_gem_handle;
 
    /** Whether INTEL_BLACKHOLE_RENDER is enabled in the batch (aka first
     * instruction is a MI_BATCH_BUFFER_END).



More information about the mesa-commit mailing list