Mesa (staging/21.0): tnl: Try not to botch index buffer munging when start > 0.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jan 20 19:19:49 UTC 2021


Module: Mesa
Branch: staging/21.0
Commit: f2fdb35f393b426d876773df2effe19e30349b8f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f2fdb35f393b426d876773df2effe19e30349b8f

Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Thu Jan 14 15:45:20 2021 -0800

tnl: Try not to botch index buffer munging when start > 0.

Commit 4c751ad67aa2bbde5897030495f86e31c9e1fda7 (vbo/dlist: use a shared
index buffer) caused multiple draws to use the same index buffer, and
began setting the primitive's `start` field to the offset needed to
access the right portion of the index buffer.

Unfortunately, t_rebase_prims completely botches handling this case.
Say for example we had start = 40, min_index = 6, max_index = 11.
The actual indexes in the buffer are ib[40..45].  t_rebase_prims,
however, would allocate an index buffer containing only 6 elements,
and populate them with <ib[0..5] - min_index>.  For one, this reads
the wrong source data, leading to garbage index values.  For another,
it stores the new index buffer in the wrong spot, so drawing will try
and read elements [40..45] of an array of length 6, and crash.

This patch makes t_rebase_prims allocate a larger index buffer, with
the blank space at the beginning, and try to copy the correct section
of index buffer data over.  This only works if `start` is the same for
all primitives, however, so if we detect different ones, we recurse
to rebase and call draw() separately for each different start value.

Fixes: 4c751ad67aa ("vbo/dlist: use a shared index buffer")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4082
Acked-by: Marek Olšák <marek.olsak at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8522>
(cherry picked from commit bd6120f562d57e150aa2071f9108f538858311a6)

---

 .pick_status.json       |  2 +-
 src/mesa/tnl/t_rebase.c | 28 +++++++++++++++++++++++-----
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/.pick_status.json b/.pick_status.json
index 878c46c14a0..bf83d7bbca9 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -265,7 +265,7 @@
         "description": "tnl: Try not to botch index buffer munging when start > 0.",
         "nominated": true,
         "nomination_type": 1,
-        "resolution": 0,
+        "resolution": 1,
         "master_sha": null,
         "because_sha": "4c751ad67aa2bbde5897030495f86e31c9e1fda7"
     },
diff --git a/src/mesa/tnl/t_rebase.c b/src/mesa/tnl/t_rebase.c
index 6f600e39068..0471895641e 100644
--- a/src/mesa/tnl/t_rebase.c
+++ b/src/mesa/tnl/t_rebase.c
@@ -59,11 +59,12 @@
 
 #define REBASE(TYPE) 						\
 static void *rebase_##TYPE(const void *ptr,			\
+                           unsigned start, 			\
                            unsigned count, 			\
                            TYPE min_index)			\
 {								\
    const TYPE *in = (TYPE *)ptr;				\
-   TYPE *tmp_indices = malloc(count * sizeof(TYPE));		\
+   TYPE *tmp_indices = malloc((start + count) * sizeof(TYPE));	\
                                                                 \
    if (tmp_indices == NULL) {                                   \
       _mesa_error_no_memory(__func__);                          \
@@ -71,7 +72,7 @@ static void *rebase_##TYPE(const void *ptr,			\
    }                                                            \
                                                                 \
    for (unsigned i = 0; i < count; i++)                         \
-      tmp_indices[i] = in[i] - min_index;			\
+      tmp_indices[start + i] = in[start + i] - min_index;	\
                                                                 \
    return (void *)tmp_indices;					\
 }
@@ -145,6 +146,23 @@ void t_rebase_prims(struct gl_context *ctx,
 
       prim = tmp_prims;
    } else if (ib) {
+      unsigned start = prim[0].start;
+      for (i = 1; i < nr_prims; i++) {
+         if (prim[i].start != start) {
+            if (0) {
+               printf("%s recursing due to mismatched start "
+                      "(prim[0].start = %u vs. prim[%u].start = %u)\n",
+                      __func__, start, i, prim[i].start);
+            }
+
+            t_rebase_prims(ctx, arrays, &prim[0], i, ib, min_index,
+                           max_index, num_instances, base_instance, draw);
+            t_rebase_prims(ctx, arrays, &prim[i], nr_prims - i, ib, min_index,
+                           max_index, num_instances, base_instance, draw);
+            return;
+         }
+      }
+
       /* Unfortunately need to adjust each index individually.
        */
       bool map_ib = false;
@@ -166,13 +184,13 @@ void t_rebase_prims(struct gl_context *ctx,
        */
       switch (ib->index_size_shift) {
       case 2:
-         tmp_indices = rebase_GLuint( ptr, ib->count, min_index );
+         tmp_indices = rebase_GLuint(ptr, start, ib->count, min_index);
          break;
       case 1:
-         tmp_indices = rebase_GLushort( ptr, ib->count, min_index );
+         tmp_indices = rebase_GLushort(ptr, start, ib->count, min_index);
          break;
       case 0:
-         tmp_indices = rebase_GLubyte( ptr, ib->count, min_index );
+         tmp_indices = rebase_GLubyte(ptr, start, ib->count, min_index);
          break;
       }
 



More information about the mesa-commit mailing list