Mesa (master): vbo/dlist: use a shared index buffer

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jan 5 09:23:26 UTC 2021


Module: Mesa
Branch: master
Commit: 4c751ad67aa2bbde5897030495f86e31c9e1fda7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4c751ad67aa2bbde5897030495f86e31c9e1fda7

Author: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Date:   Mon Dec  7 17:34:18 2020 +0100

vbo/dlist: use a shared index buffer

Draws can be merged by u_threaded if they share the same IB.

This improves performance in SPECviewperf13 snx-03: tests fps
are improved by a 1.2x - 2.0x factor.

v2: reworked error handling

Reviewed-by: Marek Olšák <marek.olsak at amd.com> (v2)
Reviewed-by: Zoltán Böszörményi <zboszor at gmail.com> (v2)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8111>

---

 src/mesa/vbo/vbo.h          |  2 ++
 src/mesa/vbo/vbo_save.c     |  2 ++
 src/mesa/vbo/vbo_save.h     |  1 +
 src/mesa/vbo/vbo_save_api.c | 57 ++++++++++++++++++++++++++++-----------------
 4 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index da9c5e49216..d0b0b3e26ab 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -178,6 +178,8 @@ struct vbo_save_context {
 
    struct vbo_save_vertex_store *vertex_store;
    struct vbo_save_primitive_store *prim_store;
+   struct gl_buffer_object *previous_ib;
+   unsigned ib_first_free_index;
 
    fi_type *buffer_map;            /**< Mapping of vertex_store's buffer */
    fi_type *buffer_ptr;		   /**< cursor, points into buffer_map */
diff --git a/src/mesa/vbo/vbo_save.c b/src/mesa/vbo/vbo_save.c
index 37370e7f527..d2930f505f1 100644
--- a/src/mesa/vbo/vbo_save.c
+++ b/src/mesa/vbo/vbo_save.c
@@ -70,4 +70,6 @@ void vbo_save_destroy( struct gl_context *ctx )
       free(save->vertex_store);
       save->vertex_store = NULL;
    }
+
+   _mesa_reference_buffer_object(ctx, &save->previous_ib, NULL);
 }
diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h
index 6c5ddc0b136..fba351c1f81 100644
--- a/src/mesa/vbo/vbo_save.h
+++ b/src/mesa/vbo/vbo_save.h
@@ -137,6 +137,7 @@ _vbo_save_get_vertex_count(const struct vbo_save_vertex_list *node)
 #define VBO_SAVE_BUFFER_SIZE (256*1024) /* dwords */
 #define VBO_SAVE_PRIM_SIZE   128
 #define VBO_SAVE_PRIM_MODE_MASK         0x3f
+#define VBO_SAVE_INDEX_SIZE (32 * 1024)
 
 struct vbo_save_vertex_store {
    struct gl_buffer_object *bufferobj;
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index efc80578b40..b8edee7cf5b 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -649,7 +649,7 @@ compile_vertex_list(struct gl_context *ctx)
 
    /* Create an index buffer. */
    node->min_index = node->max_index = 0;
-   if (save->vert_count) {
+   if (save->vert_count && node->prim_count) {
       /* We won't modify node->prims, so use a const alias to avoid unintended
        * writes to it. */
       const struct _mesa_prim *original_prims = node->prims;
@@ -665,6 +665,13 @@ compile_vertex_list(struct gl_context *ctx)
        * wrap_buffers may call use but the last primitive may not be complete) */
       int max_indices_count = MAX2(total_vert_count * 2 - (node->prim_count * 2) + 1,
                                    total_vert_count);
+
+      int indices_offset = 0;
+      int available = save->previous_ib ? (save->previous_ib->Size / 4 - save->ib_first_free_index) : 0;
+      if (available >= max_indices_count) {
+         indices_offset = save->ib_first_free_index;
+         node->min_index = node->max_index = indices_offset;
+      }
       int size = max_indices_count * sizeof(uint32_t);
       uint32_t* indices = (uint32_t*) malloc(size);
       uint32_t max_index = 0, min_index = 0xFFFFFFFF;
@@ -750,16 +757,13 @@ compile_vertex_list(struct gl_context *ctx)
             assert(last_valid_prim <= i);
             node->merged.prims = realloc(node->merged.prims, (1 + last_valid_prim) * sizeof(struct _mesa_prim));
             node->merged.prims[last_valid_prim] = original_prims[i];
-            node->merged.prims[last_valid_prim].start = start;
+            node->merged.prims[last_valid_prim].start = indices_offset + start;
             node->merged.prims[last_valid_prim].count = idx - start;
          }
          node->merged.prims[last_valid_prim].mode = mode;
       }
 
-      if (idx == 0)
-         goto skip_node;
-
-      assert(idx <= max_indices_count);
+      assert(idx > 0 && idx <= max_indices_count);
 
       node->merged.prim_count = last_valid_prim + 1;
       node->merged.ib.ptr = NULL;
@@ -768,25 +772,36 @@ compile_vertex_list(struct gl_context *ctx)
       node->merged.min_index = min_index;
       node->merged.max_index = max_index;
 
-      node->merged.ib.obj = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
-      bool success = ctx->Driver.BufferData(ctx,
+      if (!indices_offset) {
+         /* Allocate a new index buffer */
+         _mesa_reference_buffer_object(ctx, &save->previous_ib, NULL);
+         save->previous_ib = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1);
+         bool success = ctx->Driver.BufferData(ctx,
                                             GL_ELEMENT_ARRAY_BUFFER_ARB,
-                                            idx * sizeof(uint32_t), indices,
+                                            MAX2(VBO_SAVE_INDEX_SIZE, idx) * sizeof(uint32_t),
+                                            NULL,
                                             GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT,
-                                            node->merged.ib.obj);
-
-      if (success)
-         goto out;
-
-      ctx->Driver.DeleteBuffer(ctx, node->merged.ib.obj);
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation");
+                                            save->previous_ib);
+         if (!success) {
+            _mesa_reference_buffer_object(ctx, &save->previous_ib, NULL);
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation");
+         }
+      }
 
-   skip_node:
-      node->merged.ib.obj = NULL;
-      node->vertex_count = 0;
-      node->prim_count = 0;
+      _mesa_reference_buffer_object(ctx, &node->merged.ib.obj, save->previous_ib);
+
+      if (node->merged.ib.obj) {
+         ctx->Driver.BufferSubData(ctx,
+                                   indices_offset * sizeof(uint32_t),
+                                   idx * sizeof(uint32_t),
+                                   indices,
+                                   node->merged.ib.obj);
+         save->ib_first_free_index = indices_offset + idx;
+      } else {
+         node->vertex_count = 0;
+         node->prim_count = 0;
+      }
 
-   out:
       free(indices);
    }
 



More information about the mesa-commit mailing list