vbo/dlist: avoid splitting draw commands in multiple draws

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>
This commit is contained in:
Pierre-Eric Pelloux-Prayer
2020-10-20 10:57:04 +02:00
parent 83149e1c2d
commit 1c016a5ba0
+42 -7
View 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,