panfrost: Recycle fixed-size transient BOs
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Fri, 12 Jul 2019 20:05:14 +0000 (13:05 -0700)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Fri, 12 Jul 2019 22:31:48 +0000 (15:31 -0700)
The usual case. We use the bitset to mark freedom and seize it.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
src/gallium/drivers/panfrost/pan_allocate.c
src/gallium/drivers/panfrost/pan_job.c

index 4febb001033a2c397546175c416573d9b389c967..a0a96c15b946ab0ff289dd4380bef85b6b735278 100644 (file)
@@ -97,12 +97,27 @@ panfrost_allocate_transient(struct panfrost_context *ctx, size_t sz)
         bool update_offset = false;
 
         if (sz < TRANSIENT_SLAB_SIZE) {
-                /* TODO: Lookup free */
-
+                /* First, look for a free slot */
+                unsigned count = util_dynarray_num_elements(&screen->transient_bo, void *);
                 unsigned index = 0;
 
-                if (!bo)
+                unsigned free = __bitset_ffs(
+                                screen->free_transient,
+                                count / BITSET_WORDBITS);
+
+                if (likely(free)) {
+                        /* Use this one */
+                        index = free - 1;
+
+                        /* It's ours, so no longer free */
+                        BITSET_CLEAR(screen->free_transient, index);
+
+                        /* Grab the BO */
+                        bo = pan_bo_for_index(screen, index);
+                } else {
+                        /* Otherwise, create a new BO */
                         bo = panfrost_create_slab(screen, &index);
+                }
 
                 /* Remember we created this */
                 util_dynarray_append(&batch->transient_indices, unsigned, index);
index a802030769fff22fd5f8f98c847663cb7c5d29e5..0faefe2157a1ddc8f2e8d45d32de979ef6806f49 100644 (file)
@@ -61,6 +61,14 @@ panfrost_free_job(struct panfrost_context *ctx, struct panfrost_job *job)
                 panfrost_bo_unreference(ctx->base.screen, bo);
         }
 
+        /* Free up the transient BOs we're sitting on */
+        struct panfrost_screen *screen = pan_screen(ctx->base.screen);
+
+        util_dynarray_foreach(&job->transient_indices, unsigned, index) {
+                /* Mark it free */
+                BITSET_SET(screen->free_transient, *index);
+        }
+
         _mesa_hash_table_remove_key(ctx->jobs, &job->key);
 
         if (ctx->job == job)