vbo/dlist: convert LINE_STRIPS to LINES
authorPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Thu, 8 Oct 2020 12:48:25 +0000 (14:48 +0200)
committerPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Tue, 8 Dec 2020 09:10:47 +0000 (10:10 +0100)
Less primitive modes allows for better primitive merging.

Lines are always used (instead of picking dynamically lines or line
strips for instance) because:
- they don't need primitive restarts to be merged
- they perform better (at least on radeonsi) - SPECviewperf13 snx subtests
  with lines (like 4 or 10) are 1.5x-2x faster.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7078>

src/mesa/vbo/vbo_save_api.c

index b76b35f..ac02674 100644 (file)
@@ -605,7 +605,7 @@ compile_vertex_list(struct gl_context *ctx)
       int end = node->prims[node->prim_count - 1].start +
                 node->prims[node->prim_count - 1].count;
       int total_vert_count = end - node->prims[0].start;
-      int max_indices_count = total_vert_count;
+      int max_indices_count = total_vert_count * 2;
       int size = max_indices_count * sizeof(uint32_t);
       uint32_t* indices = (uint32_t*) malloc(size);
       uint32_t max_index = 0, min_index = 0xFFFFFFFF;
@@ -618,8 +618,28 @@ compile_vertex_list(struct gl_context *ctx)
          int vertex_count = node->prims[i].count;
          int start = idx;
 
-         for (unsigned j = 0; j < vertex_count; j++) {
-            indices[idx++] = node->prims[i].start + j;
+         /* Convert line strips to lines if it'll allow if the previous
+          * prim mode is GL_LINES or if the next primitive mode is
+          * GL_LINES or GL_LINE_LOOP.
+          */
+         if (node->prims[i].mode == GL_LINE_STRIP &&
+             ((i > 0 && node->prims[i - 1].mode == GL_LINES) ||
+              (i < node->prim_count - 1 &&
+               (node->prims[i + 1].mode == GL_LINE_STRIP ||
+                node->prims[i + 1].mode == GL_LINES)))) {
+            for (unsigned j = 0; j < vertex_count; j++) {
+               indices[idx++] = node->prims[i].start + j;
+               /* Repeat all but the first/last indices. */
+               if (j && j != vertex_count - 1) {
+                  indices[idx++] = node->prims[i].start + j;
+                  node->prims[i].count++;
+               }
+            }
+            node->prims[i].mode = GL_LINES;
+         } else {
+            for (unsigned j = 0; j < vertex_count; j++) {
+               indices[idx++] = node->prims[i].start + j;
+            }
          }
 
          min_index = MIN2(min_index, indices[start]);