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

Author: Caio Oliveira <[email protected]>
Date:   Mon Oct  2 22:35:04 2023 -0700

util: Add a way to set the min_buffer_size in linear_alloc

The default value remains 2048, which is also used for rounding up
any user provided size.

The option is useful in cases where there's a better idea of the
amount of data that's going to be used.

Reviewed-by: Marek Olšák <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25279>

---

 src/util/ralloc.c              | 29 ++++++++++++++++++++++-------
 src/util/ralloc.h              |  6 ++++++
 src/util/tests/linear_test.cpp | 19 +++++++++++++++++++
 3 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/src/util/ralloc.c b/src/util/ralloc.c
index c85c61e3d8a..95b80a87991 100644
--- a/src/util/ralloc.c
+++ b/src/util/ralloc.c
@@ -964,7 +964,6 @@ gc_sweep_end(gc_ctx *ctx)
  * other buffers.
  */
 
-#define MIN_LINEAR_BUFSIZE 2048
 #define SUBALLOC_ALIGNMENT 8
 #define LMAGIC_CONTEXT 0x87b9c7d3
 #define LMAGIC_NODE    0x87b910d3
@@ -976,6 +975,8 @@ struct linear_ctx {
 #ifndef NDEBUG
    unsigned magic;   /* for debugging */
 #endif
+   unsigned min_buffer_size;
+
    unsigned offset;  /* points to the first unused byte in the latest buffer */
    unsigned size;    /* size of the latest buffer */
    void *latest;     /* the only buffer that has free space */
@@ -1021,9 +1022,9 @@ linear_alloc_child(linear_ctx *ctx, unsigned size)
    if (unlikely(ctx->offset + size > ctx->size)) {
       /* allocate a new node */
       unsigned node_size = size;
-      if (likely(node_size < MIN_LINEAR_BUFSIZE))
-         node_size = MIN_LINEAR_BUFSIZE;
-      
+      if (likely(node_size < ctx->min_buffer_size))
+         node_size = ctx->min_buffer_size;
+
       const unsigned canary_size = get_node_canary_size();
       const unsigned full_size = canary_size + node_size;
 
@@ -1070,21 +1071,35 @@ linear_alloc_child(linear_ctx *ctx, unsigned size)
 
 linear_ctx *
 linear_context(void *ralloc_ctx)
+{
+   const linear_opts opts = {0};
+   return linear_context_with_opts(ralloc_ctx, &opts);
+}
+
+linear_ctx *
+linear_context_with_opts(void *ralloc_ctx, const linear_opts *opts)
 {
    linear_ctx *ctx;
 
    if (unlikely(!ralloc_ctx))
       return NULL;
 
-   const unsigned size = MIN_LINEAR_BUFSIZE;
+   const unsigned default_min_buffer_size = 2048;
+   const unsigned min_buffer_size =
+      MAX2(ALIGN_POT(opts->min_buffer_size, default_min_buffer_size),
+           default_min_buffer_size);
+
+   const unsigned size = min_buffer_size;
    const unsigned canary_size = get_node_canary_size();
    const unsigned full_size =
-      sizeof(linear_ctx) + canary_size + size;                 
+      sizeof(linear_ctx) + canary_size + size;
 
    ctx = ralloc_size(ralloc_ctx, full_size);
    if (unlikely(!ctx))
       return NULL;
 
+   ctx->min_buffer_size = min_buffer_size;
+
    ctx->offset = 0;
    ctx->size = size;
    ctx->latest = (char *)&ctx[1] + canary_size;
@@ -1125,7 +1140,7 @@ ralloc_steal_linear_context(void *new_ralloc_ctx, 
linear_ctx *ctx)
 {
    if (unlikely(!ctx))
       return;
- 
+
    assert(ctx->magic == LMAGIC_CONTEXT);
 
    /* Linear context is also the ralloc parent of extra nodes. */
diff --git a/src/util/ralloc.h b/src/util/ralloc.h
index 58d851f1823..2078a88ff07 100644
--- a/src/util/ralloc.h
+++ b/src/util/ralloc.h
@@ -579,6 +579,10 @@ typedef struct linear_ctx linear_ctx;
  */
 void *linear_alloc_child(linear_ctx *ctx, unsigned size);
 
+typedef struct {
+   unsigned min_buffer_size;
+} linear_opts;
+
 /**
  * Allocate a linear context that will internally hold linear buffers.
  * Use it for all child node allocations.
@@ -587,6 +591,8 @@ void *linear_alloc_child(linear_ctx *ctx, unsigned size);
  */
 linear_ctx *linear_context(void *ralloc_ctx);
 
+linear_ctx *linear_context_with_opts(void *ralloc_ctx, const linear_opts 
*opts);
+
 /**
  * Same as linear_alloc_child, but also clears memory.
  */
diff --git a/src/util/tests/linear_test.cpp b/src/util/tests/linear_test.cpp
index 2b573184515..5b7c5525a7e 100644
--- a/src/util/tests/linear_test.cpp
+++ b/src/util/tests/linear_test.cpp
@@ -70,3 +70,22 @@ TEST(LinearAlloc, AvoidWasteAfterLargeAlloc)
 
    ralloc_free(ctx);
 }
+
+TEST(LinearAlloc, Options)
+{
+   void *ctx = ralloc_context(NULL);
+
+   linear_opts opts = {};
+   opts.min_buffer_size = 8192;
+
+   linear_ctx *lin_ctx = linear_context_with_opts(ctx, &opts);
+
+   /* Assert allocations spanning the first 8192 bytes are contiguous. */
+   char *first = (char *)linear_alloc_child(lin_ctx, 1024);
+   for (int i = 1; i < 8; i++) {
+      char *ptr = (char *)linear_alloc_child(lin_ctx, 1024);
+      EXPECT_EQ(ptr - first, 1024 * i);
+   }
+
+   ralloc_free(ctx);
+}

Reply via email to