Mesa (main): etnaviv: add texture descriptor suballocator

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jul 13 15:08:41 UTC 2022


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

Author: Lucas Stach <l.stach at pengutronix.de>
Date:   Sun Jul 10 16:03:45 2022 +0200

etnaviv: add texture descriptor suballocator

Texture descriptors currently waste a massive ammount of memory, as every
one is allocated via a separate BO. As the allocation granularity of the
kernel is 4KB and the descriptor is only 256B, 93.75% of the allocated
memory is wasted.

Add a simple suballocator for the texture descriptors, to allocate multiple
ones out of a single kernel BO. This isn't perfect, as freed slots in the
suballocated resource are not reused, but worst-case we end up with the
same waste as we had before. This also potentially improves efficiency at
the kernel side, as this reduces the number of BOs needed for the sampler
views in each submit.

As the BO is now used by multiple descriptors, avoid syncing with the GPU
via the cpu_prep/fini calls, as to not introduce stalls between pending
rendering and new descriptors being filled. This is safe, as each
suballocation slot is only used once, so newly filled slots are certainly
not in use by the GPU.

Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel at pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17448>

---

 src/gallium/drivers/etnaviv/etnaviv_context.c      |  2 ++
 src/gallium/drivers/etnaviv/etnaviv_context.h      |  2 ++
 src/gallium/drivers/etnaviv/etnaviv_texture.c      | 17 +++++++++++++++--
 src/gallium/drivers/etnaviv/etnaviv_texture.h      |  3 +++
 src/gallium/drivers/etnaviv/etnaviv_texture_desc.c | 21 ++++++++++-----------
 5 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c
index 9eeff1cef42..f66587711bc 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
@@ -119,6 +119,8 @@ etna_context_destroy(struct pipe_context *pctx)
    if (ctx->stream)
       etna_cmd_stream_del(ctx->stream);
 
+   etna_texture_fini(pctx);
+
    slab_destroy_child(&ctx->transfer_pool);
 
    if (ctx->in_fence_fd != -1)
diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.h b/src/gallium/drivers/etnaviv/etnaviv_context.h
index 02523c6aa0d..8ab37ba33f0 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.h
@@ -38,6 +38,7 @@
 #include "pipe/p_shader_tokens.h"
 #include "pipe/p_state.h"
 #include "util/slab.h"
+#include <util/u_suballoc.h>
 
 struct pipe_screen;
 struct etna_shader_variant;
@@ -143,6 +144,7 @@ struct etna_context {
    } dirty;
 
    struct slab_child_pool transfer_pool;
+   struct u_suballocator tex_desc_allocator;
    struct blitter_context *blitter;
 
    /* compiled bindable state */
diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.c b/src/gallium/drivers/etnaviv/etnaviv_texture.c
index fb8152fbd8e..78ec27f4142 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_texture.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_texture.c
@@ -345,8 +345,21 @@ etna_texture_init(struct pipe_context *pctx)
    pctx->set_sampler_views = etna_set_sampler_views;
    pctx->texture_barrier = etna_texture_barrier;
 
-   if (screen->specs.halti >= 5)
+   if (screen->specs.halti >= 5) {
+      u_suballocator_init(&ctx->tex_desc_allocator, pctx, 4096, 0,
+                          PIPE_USAGE_IMMUTABLE, 0, true);
       etna_texture_desc_init(pctx);
-   else
+   } else {
       etna_texture_state_init(pctx);
+   }
+}
+
+void
+etna_texture_fini(struct pipe_context *pctx)
+{
+   struct etna_context *ctx = etna_context(pctx);
+   struct etna_screen *screen = ctx->screen;
+
+   if (screen->specs.halti >= 5)
+      u_suballocator_destroy(&ctx->tex_desc_allocator);
 }
diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.h b/src/gallium/drivers/etnaviv/etnaviv_texture.h
index f0d32307cb6..1874d0f7b4e 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_texture.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_texture.h
@@ -48,6 +48,9 @@ struct etna_sampler_ts {
 void
 etna_texture_init(struct pipe_context *pctx);
 
+void
+etna_texture_fini(struct pipe_context *pctx);
+
 /* If the original resource is not compatible with the sampler.  Allocate
  * an appropriately tiled texture. */
 struct etna_resource *
diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture_desc.c b/src/gallium/drivers/etnaviv/etnaviv_texture_desc.c
index fa63c1a2f65..9891dfe69ce 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_texture_desc.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_texture_desc.c
@@ -62,7 +62,7 @@ struct etna_sampler_view_desc {
    uint32_t SAMP_CTRL0;
    uint32_t SAMP_CTRL1;
 
-   struct etna_bo *bo;
+   struct pipe_resource *res;
    struct etna_reloc DESC_ADDR;
    struct etna_sampler_ts ts;
 };
@@ -135,6 +135,7 @@ etna_create_sampler_view_desc(struct pipe_context *pctx, struct pipe_resource *p
    const uint32_t swiz = get_texture_swiz(so->format, so->swizzle_r,
                                           so->swizzle_g, so->swizzle_b,
                                           so->swizzle_a);
+   unsigned suballoc_offset;
 
    if (!sv)
       return NULL;
@@ -164,13 +165,12 @@ etna_create_sampler_view_desc(struct pipe_context *pctx, struct pipe_resource *p
       sv->SAMP_CTRL1 |= VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_SRGB;
 
    /* Create texture descriptor */
-   sv->bo = etna_bo_new(ctx->screen->dev, 0x100, DRM_ETNA_GEM_CACHE_WC);
-   if (!sv->bo)
+   u_suballocator_alloc(&ctx->tex_desc_allocator, 256, 64,
+                        &suballoc_offset, &sv->res);
+   if (!sv->res)
       goto error;
 
-   uint32_t *buf = etna_bo_map(sv->bo);
-   etna_bo_cpu_prep(sv->bo, DRM_ETNA_PREP_WRITE);
-   memset(buf, 0, 0x100);
+   uint32_t *buf = etna_bo_map(etna_resource(sv->res)->bo) + suballoc_offset;
 
    /** GC7000 needs the size of the BASELOD level */
    uint32_t base_width = u_minify(res->base.width0, sv->base.u.tex.first_level);
@@ -217,10 +217,8 @@ etna_create_sampler_view_desc(struct pipe_context *pctx, struct pipe_resource *p
       DESC_SET(LOD_ADDR(lod), etna_bo_gpu_va(res->bo) + res->levels[lod].offset);
 #undef DESC_SET
 
-   etna_bo_cpu_fini(sv->bo);
-
-   sv->DESC_ADDR.bo = sv->bo;
-   sv->DESC_ADDR.offset = 0;
+   sv->DESC_ADDR.bo = etna_resource(sv->res)->bo;
+   sv->DESC_ADDR.offset = suballoc_offset;
    sv->DESC_ADDR.flags = ETNA_RELOC_READ;
 
    return &sv->base;
@@ -251,8 +249,9 @@ etna_sampler_view_desc_destroy(struct pipe_context *pctx,
                           struct pipe_sampler_view *so)
 {
    struct etna_sampler_view_desc *sv = etna_sampler_view_desc(so);
+
    pipe_resource_reference(&sv->base.texture, NULL);
-   etna_bo_del(sv->bo);
+   pipe_resource_reference(&sv->res, NULL);
    FREE(sv);
 }
 



More information about the mesa-commit mailing list