vbo/dlist: avoid splitting draw commands in multiple draws
authorPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Tue, 20 Oct 2020 08:57:04 +0000 (10:57 +0200)
committerPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Tue, 8 Dec 2020 09:10:47 +0000 (10:10 +0100)
For (Multi)DrawArrays and (Multi)DrawElements commands, the storage size
needed are known early so we can make sure that the prim_store/vertex_store
will be big enough to store the whole command.

This reduces the amount of drawcalls in snx03 tests. For instance in test10:

      | Num draw calls |     GPU-load    |
------|----------------|-----------------|
      | Before | After |  Before | After |
------|--------|-------|---------|-------|
test10|  35k   |   8k  |   58%   |  80%  |

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 93651f2..d8e31df 100644 (file)
@@ -253,12 +253,7 @@ alloc_prim_store(int prim_count)
    struct vbo_save_primitive_store *store =
       CALLOC_STRUCT(vbo_save_primitive_store);
    store->size = MAX2(prim_count, VBO_SAVE_PRIM_SIZE);
-   if (store->prims) {
-      assert(store->refcount == 0);
-   }
-   store->prims = realloc(store->prims,
-                          store->size * sizeof(struct _mesa_prim));
-   memset(store->prims, 0, store->size * sizeof(struct _mesa_prim));
+   store->prims = calloc(store->size, sizeof(struct _mesa_prim));
    store->used = 0;
    store->refcount = 1;
    return store;
@@ -504,7 +499,10 @@ realloc_storage(struct gl_context *ctx, int prim_count, int vertex_count)
    }
 
    if (prim_count >= 0) {
-      save->prim_store->refcount--;
+      if (--save->prim_store->refcount == 0) {
+         free(save->prim_store->prims);
+         free(save->prim_store);
+      }
       save->prim_store = alloc_prim_store(prim_count);
    }
 }
@@ -1462,6 +1460,23 @@ _save_OBE_Rectsv(const GLshort *v1, const GLshort *v2)
    _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
 }
 
+static void
+_ensure_draws_fits_in_storage(struct gl_context *ctx, int primcount, int vertcount)
+{
+   struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+   bool realloc_prim = save->prim_count + primcount > save->prim_max;
+   bool realloc_vert = save->vertex_size && (save->vert_count + vertcount >= save->max_vert);
+
+   if (realloc_prim || realloc_vert) {
+      if (save->vert_count || save->prim_count)
+         compile_vertex_list(ctx);
+      realloc_storage(ctx, realloc_prim ? primcount : -1, realloc_vert ? vertcount : -1);
+      reset_counters(ctx);
+      assert(save->prim_max);
+   }
+}
+
 
 static void GLAPIENTRY
 _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
@@ -1483,6 +1498,8 @@ _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
    if (save->out_of_memory)
       return;
 
+   _ensure_draws_fits_in_storage(ctx, 1, count);
+
    /* Make sure to process any VBO binding changes */
    _mesa_update_state(ctx);
 
@@ -1516,14 +1533,18 @@ _save_OBE_MultiDrawArrays(GLenum mode, const GLint *first,
       return;
    }
 
+   unsigned vertcount = 0;
    for (i = 0; i < primcount; i++) {
       if (count[i] < 0) {
          _mesa_compile_error(ctx, GL_INVALID_VALUE,
                              "glMultiDrawArrays(count[i]<0)");
          return;
       }
+      vertcount += count[i];
    }
 
+   _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
+
    for (i = 0; i < primcount; i++) {
       if (count[i] > 0) {
          _save_OBE_DrawArrays(mode, first[i], count[i]);
@@ -1586,6 +1607,8 @@ _save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
    if (save->out_of_memory)
       return;
 
+   _ensure_draws_fits_in_storage(ctx, 1, count);
+
    /* Make sure to process any VBO binding changes */
    _mesa_update_state(ctx);
 
@@ -1672,6 +1695,12 @@ _save_OBE_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
    struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
    GLsizei i;
 
+   int vertcount = 0;
+   for (i = 0; i < primcount; i++) {
+      vertcount += count[i];
+   }
+   _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
+
    for (i = 0; i < primcount; i++) {
       if (count[i] > 0) {
         CALL_DrawElements(dispatch, (mode, count[i], type, indices[i]));
@@ -1691,6 +1720,12 @@ _save_OBE_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
    struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
    GLsizei i;
 
+   int vertcount = 0;
+   for (i = 0; i < primcount; i++) {
+      vertcount += count[i];
+   }
+   _ensure_draws_fits_in_storage(ctx, primcount, vertcount);
+
    for (i = 0; i < primcount; i++) {
       if (count[i] > 0) {
         CALL_DrawElementsBaseVertex(dispatch, (mode, count[i], type,