etnaviv: add texture descriptor suballocator
authorLucas Stach <l.stach@pengutronix.de>
Sun, 10 Jul 2022 14:03:45 +0000 (16:03 +0200)
committerMarge Bot <emma+marge@anholt.net>
Wed, 13 Jul 2022 15:00:33 +0000 (15:00 +0000)
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@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17448>

src/gallium/drivers/etnaviv/etnaviv_context.c
src/gallium/drivers/etnaviv/etnaviv_context.h
src/gallium/drivers/etnaviv/etnaviv_texture.c
src/gallium/drivers/etnaviv/etnaviv_texture.h
src/gallium/drivers/etnaviv/etnaviv_texture_desc.c

index 9eeff1c..f665877 100644 (file)
@@ -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)
index 02523c6..8ab37ba 100644 (file)
@@ -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 */
index fb8152f..78ec27f 100644 (file)
@@ -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);
 }
index f0d3230..1874d0f 100644 (file)
@@ -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 *
index fa63c1a..9891dfe 100644 (file)
@@ -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);
 }