Mesa (main): panfrost: Stop using sparse_array for batch BOs

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jun 15 00:09:29 UTC 2022


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

Author: Icecream95 <ixn at disroot.org>
Date:   Fri Jun 10 23:41:48 2022 +1200

panfrost: Stop using sparse_array for batch BOs

Iterating over a util_sparse_array is very expensive; replace this
with a standard dynarray.

Using the sparse 'nodearray' datastructure instead was tested, but
found to be slower in some cases.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16988>

---

 src/gallium/drivers/panfrost/pan_job.c | 44 ++++++++++++++++++++++------------
 src/gallium/drivers/panfrost/pan_job.h |  3 +--
 src/panfrost/lib/pan_bo.h              |  2 ++
 3 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c
index 7c8df123a01..ba07c6cfc65 100644
--- a/src/gallium/drivers/panfrost/pan_job.c
+++ b/src/gallium/drivers/panfrost/pan_job.c
@@ -72,9 +72,7 @@ panfrost_batch_init(struct panfrost_context *ctx,
 
         batch->seqnum = ++ctx->batches.seqnum;
 
-        batch->first_bo = INT32_MAX;
-        batch->last_bo = INT32_MIN;
-        util_sparse_array_init(&batch->bos, sizeof(uint32_t), 64);
+        util_dynarray_init(&batch->bos, NULL);
 
         batch->minx = batch->miny = ~0;
         batch->maxx = batch->maxy = 0;
@@ -113,10 +111,11 @@ panfrost_batch_cleanup(struct panfrost_context *ctx, struct panfrost_batch *batc
 
         unsigned batch_idx = panfrost_batch_idx(batch);
 
-        for (int i = batch->first_bo; i <= batch->last_bo; i++) {
-                uint32_t *flags = util_sparse_array_get(&batch->bos, i);
+        pan_bo_access *flags = util_dynarray_begin(&batch->bos);
+        unsigned end_bo = util_dynarray_num_elements(&batch->bos, pan_bo_access);
 
-                if (!*flags)
+        for (int i = 0; i < end_bo; ++i) {
+                if (!flags[i])
                         continue;
 
                 struct panfrost_bo *bo = pan_lookup_bo(dev, i);
@@ -142,7 +141,7 @@ panfrost_batch_cleanup(struct panfrost_context *ctx, struct panfrost_batch *batc
 
         util_unreference_framebuffer_state(&batch->key);
 
-        util_sparse_array_finish(&batch->bos);
+        util_dynarray_fini(&batch->bos);
 
         memset(batch, 0, sizeof(*batch));
         BITSET_CLEAR(ctx->batches.active, batch_idx);
@@ -275,6 +274,21 @@ panfrost_batch_update_access(struct panfrost_batch *batch,
         }
 }
 
+static pan_bo_access *
+panfrost_batch_get_bo_access(struct panfrost_batch *batch, unsigned handle)
+{
+        unsigned size = util_dynarray_num_elements(&batch->bos, pan_bo_access);
+
+        if (handle >= size) {
+                unsigned grow = handle + 1 - size;
+
+                memset(util_dynarray_grow(&batch->bos, pan_bo_access, grow),
+                       0, grow * sizeof(pan_bo_access));
+        }
+
+        return util_dynarray_element(&batch->bos, pan_bo_access, handle);
+}
+
 static void
 panfrost_batch_add_bo_old(struct panfrost_batch *batch,
                 struct panfrost_bo *bo, uint32_t flags)
@@ -282,13 +296,12 @@ panfrost_batch_add_bo_old(struct panfrost_batch *batch,
         if (!bo)
                 return;
 
-        uint32_t *entry = util_sparse_array_get(&batch->bos, bo->gem_handle);
-        uint32_t old_flags = *entry;
+        pan_bo_access *entry =
+                panfrost_batch_get_bo_access(batch, bo->gem_handle);
+        pan_bo_access old_flags = *entry;
 
         if (!old_flags) {
                 batch->num_bos++;
-                batch->first_bo = MIN2(batch->first_bo, bo->gem_handle);
-                batch->last_bo = MAX2(batch->last_bo, bo->gem_handle);
                 panfrost_bo_reference(bo);
         }
 
@@ -590,10 +603,11 @@ panfrost_batch_submit_ioctl(struct panfrost_batch *batch,
                             sizeof(*bo_handles));
         assert(bo_handles);
 
-        for (int i = batch->first_bo; i <= batch->last_bo; i++) {
-                uint32_t *flags = util_sparse_array_get(&batch->bos, i);
+        pan_bo_access *flags = util_dynarray_begin(&batch->bos);
+        unsigned end_bo = util_dynarray_num_elements(&batch->bos, pan_bo_access);
 
-                if (!*flags)
+        for (int i = 0; i < end_bo; ++i) {
+                if (!flags[i])
                         continue;
 
                 assert(submit.bo_handle_count < batch->num_bos);
@@ -608,7 +622,7 @@ panfrost_batch_submit_ioctl(struct panfrost_batch *batch,
                  */
                 struct panfrost_bo *bo = pan_lookup_bo(dev, i);
 
-                bo->gpu_access |= *flags & (PAN_BO_ACCESS_RW);
+                bo->gpu_access |= flags[i] & (PAN_BO_ACCESS_RW);
         }
 
         panfrost_pool_get_bo_handles(&batch->pool, bo_handles + submit.bo_handle_count);
diff --git a/src/gallium/drivers/panfrost/pan_job.h b/src/gallium/drivers/panfrost/pan_job.h
index 94635b3cc90..49dedf84d8b 100644
--- a/src/gallium/drivers/panfrost/pan_job.h
+++ b/src/gallium/drivers/panfrost/pan_job.h
@@ -126,9 +126,8 @@ struct panfrost_batch {
         bool scissor_culls_everything;
 
         /* BOs referenced not in the pool */
-        int first_bo, last_bo;
         unsigned num_bos;
-        struct util_sparse_array bos;
+        struct util_dynarray bos;
 
         /* Pool owned by this batch (released when the batch is released) used for temporary descriptors */
         struct panfrost_pool pool;
diff --git a/src/panfrost/lib/pan_bo.h b/src/panfrost/lib/pan_bo.h
index e267cb4d919..7d19fba9dfc 100644
--- a/src/panfrost/lib/pan_bo.h
+++ b/src/panfrost/lib/pan_bo.h
@@ -68,6 +68,8 @@
 /* BO is accessed by the fragment job. */
 #define PAN_BO_ACCESS_FRAGMENT        (1 << 4)
 
+typedef uint8_t pan_bo_access;
+
 struct panfrost_device;
 
 struct panfrost_ptr {



More information about the mesa-commit mailing list