panfrost: Pre-allocate memory for pool
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Fri, 14 Aug 2020 23:08:57 +0000 (19:08 -0400)
committerTomeu Vizoso <tomeu.vizoso@collabora.com>
Thu, 20 Aug 2020 16:15:00 +0000 (18:15 +0200)
Seeing random BO creates in the middle of command stream generation is
annoying, let's preallocate memory so CPU profiling is less random.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6373>

src/gallium/drivers/panfrost/pan_job.c
src/panfrost/lib/pan_pool.c
src/panfrost/lib/pan_pool.h

index b0665da6b6ea44e3a06c06d1ca4a150a0339576d..50616eb90172c75115f55e06e34c474d9d0cc481 100644 (file)
@@ -112,7 +112,7 @@ panfrost_create_batch(struct panfrost_context *ctx,
         batch->out_sync = panfrost_create_batch_fence(batch);
         util_copy_framebuffer_state(&batch->key, key);
 
-        batch->pool = panfrost_create_pool(batch, pan_device(ctx->base.screen));
+        batch->pool = panfrost_create_pool(batch, pan_device(ctx->base.screen), 0, true);
 
         panfrost_batch_add_fbo_bos(batch);
 
index 1a08be2aacfc072b2772780150d7b3a52c1c5357..94847565f6b745bc4ec3886c3117b964ef0e7de7 100644 (file)
  * into whereever we left off. If there isn't space, we allocate a new entry
  * into the pool and copy there */
 
+static struct panfrost_bo *
+panfrost_pool_alloc_backing(struct pan_pool *pool, size_t bo_sz)
+{
+        /* We don't know what the BO will be used for, so let's flag it
+         * RW and attach it to both the fragment and vertex/tiler jobs.
+         * TODO: if we want fine grained BO assignment we should pass
+         * flags to this function and keep the read/write,
+         * fragment/vertex+tiler pools separate.
+         */
+        struct panfrost_bo *bo = panfrost_bo_create(pool->dev, bo_sz,
+                        pool->create_flags);
+
+        uintptr_t flags = PAN_BO_ACCESS_PRIVATE |
+                PAN_BO_ACCESS_RW |
+                PAN_BO_ACCESS_VERTEX_TILER |
+                PAN_BO_ACCESS_FRAGMENT;
+
+        _mesa_hash_table_insert(pool->bos, bo, (void *) flags);
+
+        pool->transient_bo = bo;
+        pool->transient_offset = 0;
+
+        return bo;
+}
+
 struct pan_pool
-panfrost_create_pool(void *memctx, struct panfrost_device *dev)
+panfrost_create_pool(void *memctx, struct panfrost_device *dev,
+                unsigned create_flags, bool prealloc)
 {
         struct pan_pool pool = {
                 .dev = dev,
+                .create_flags = create_flags,
                 .transient_offset = 0,
                 .transient_bo = NULL
         };
@@ -46,6 +73,8 @@ panfrost_create_pool(void *memctx, struct panfrost_device *dev)
         pool.bos = _mesa_hash_table_create(memctx, _mesa_hash_pointer,
                         _mesa_key_pointer_equal);
 
+        if (prealloc)
+                panfrost_pool_alloc_backing(&pool, TRANSIENT_SLAB_SIZE);
 
         return pool;
 }
@@ -57,45 +86,18 @@ panfrost_pool_alloc(struct pan_pool *pool, size_t sz)
         sz = ALIGN_POT(sz, ALIGNMENT);
 
         /* Find or create a suitable BO */
-        struct panfrost_bo *bo = NULL;
-
-        unsigned offset = 0;
-
-        bool fits_in_current = (pool->transient_offset + sz) < TRANSIENT_SLAB_SIZE;
-
-        if (likely(pool->transient_bo && fits_in_current)) {
-                /* We can reuse the current BO, so get it */
-                bo = pool->transient_bo;
-
-                /* Use the specified offset */
-                offset = pool->transient_offset;
-                pool->transient_offset = offset + sz;
-        } else {
-                size_t bo_sz = sz < TRANSIENT_SLAB_SIZE ?
-                               TRANSIENT_SLAB_SIZE : ALIGN_POT(sz, 4096);
-
-                /* We can't reuse the current BO, but we can create a new one.
-                 * We don't know what the BO will be used for, so let's flag it
-                 * RW and attach it to both the fragment and vertex/tiler jobs.
-                 * TODO: if we want fine grained BO assignment we should pass
-                 * flags to this function and keep the read/write,
-                 * fragment/vertex+tiler pools separate.
-                 */
-                bo = panfrost_bo_create(pool->dev, bo_sz, 0);
-
-                uintptr_t flags = PAN_BO_ACCESS_PRIVATE |
-                                  PAN_BO_ACCESS_RW |
-                                  PAN_BO_ACCESS_VERTEX_TILER |
-                                  PAN_BO_ACCESS_FRAGMENT;
-
-                _mesa_hash_table_insert(pool->bos, bo, (void *) flags);
-
-                if (sz < TRANSIENT_SLAB_SIZE) {
-                        pool->transient_bo = bo;
-                        pool->transient_offset = offset + sz;
-                }
+        struct panfrost_bo *bo = pool->transient_bo;
+        unsigned offset = pool->transient_offset;
+
+        /* If we don't fit, allocate a new backing */
+        if (unlikely(bo == NULL || (offset + sz) >= TRANSIENT_SLAB_SIZE)) {
+                bo = panfrost_pool_alloc_backing(pool,
+                                ALIGN_POT(MAX2(TRANSIENT_SLAB_SIZE, sz), 4096));
+                offset = 0;
         }
 
+        pool->transient_offset += sz;
+
         struct panfrost_transfer ret = {
                 .cpu = bo->cpu + offset,
                 .gpu = bo->gpu + offset,
index c4668af57feec72d75312c4d73aaafeb20e0b44d..22fddb8870c6c2914dc24a1d91b232cc23a579d0 100644 (file)
@@ -45,10 +45,13 @@ struct pan_pool {
 
         /* Within the topmost transient BO, how much has been used? */
         unsigned transient_offset;
+
+        /* BO flags to use in the pool */
+        unsigned create_flags;
 };
 
 struct pan_pool
-panfrost_create_pool(void *memctx, struct panfrost_device *dev);
+panfrost_create_pool(void *memctx, struct panfrost_device *dev, unsigned create_flags, bool prealloc);
 
 /* Represents a fat pointer for GPU-mapped memory, returned from the transient
  * allocator and not used for much else */