From 1c016a5ba0818207e050a04a72ca2feb883ad6cb Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Tue, 20 Oct 2020 10:57:04 +0200 Subject: [PATCH] vbo/dlist: avoid splitting draw commands in multiple draws MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Part-of: --- src/mesa/vbo/vbo_save_api.c | 49 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index 93651f2..d8e31df 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -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, -- 2.7.4