From 60d0cfd4298d12d004e5f07ee5f94661ce0cc80f Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 30 Dec 2015 18:10:56 -0500 Subject: [PATCH] vbo: create a new draw function interface for indirect draws MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit All indirect draws are passed to the new draw function. By default there's a fallback implementation which pipes it right back to draw_prims, but eventually both the fallback and draw_prim's support for indirect drawing should be removed. This should allow a backend to properly support ARB_multi_draw_indirect and ARB_indirect_parameters. Signed-off-by: Ilia Mirkin Acked-by: Marek Olšák Reviewed-by: Ian Romanick --- src/mesa/vbo/vbo.h | 15 ++++++ src/mesa/vbo/vbo_context.c | 50 +++++++++++++++++++ src/mesa/vbo/vbo_context.h | 6 +++ src/mesa/vbo/vbo_exec_array.c | 93 +++++++---------------------------- 4 files changed, 89 insertions(+), 75 deletions(-) diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index dd9b428b104..0b8b6a9de56 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -110,6 +110,18 @@ typedef void (*vbo_draw_func)( struct gl_context *ctx, struct gl_buffer_object *indirect); +typedef void (*vbo_indirect_draw_func)( + struct gl_context *ctx, + GLuint mode, + struct gl_buffer_object *indirect_data, + GLsizeiptr indirect_offset, + unsigned draw_count, + unsigned stride, + struct gl_buffer_object *indirect_params, + GLsizeiptr indirect_params_offset, + const struct _mesa_index_buffer *ib); + + /* Utility function to cope with various constraints on tnl modules or @@ -179,6 +191,9 @@ void vbo_always_unmap_buffers(struct gl_context *ctx); void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func); +void vbo_set_indirect_draw_func(struct gl_context *ctx, + vbo_indirect_draw_func func); + void vbo_check_buffers_are_unmapped(struct gl_context *ctx); void vbo_bind_arrays(struct gl_context *ctx); diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c index 19b35a429b3..9f807a17512 100644 --- a/src/mesa/vbo/vbo_context.c +++ b/src/mesa/vbo/vbo_context.c @@ -135,6 +135,48 @@ static void init_mat_currval(struct gl_context *ctx) } } +static void +vbo_draw_indirect_prims(struct gl_context *ctx, + GLuint mode, + struct gl_buffer_object *indirect_data, + GLsizeiptr indirect_offset, + unsigned draw_count, + unsigned stride, + struct gl_buffer_object *indirect_params, + GLsizeiptr indirect_params_offset, + const struct _mesa_index_buffer *ib) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct _mesa_prim *prim; + GLsizei i; + + prim = calloc(draw_count, sizeof(*prim)); + if (prim == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDraw%sIndirect%s", + (draw_count > 1) ? "Multi" : "", + ib ? "Elements" : "Arrays", + indirect_params ? "CountARB" : ""); + return; + } + + prim[0].begin = 1; + prim[draw_count - 1].end = 1; + for (i = 0; i < draw_count; ++i, indirect_offset += stride) { + prim[i].mode = mode; + prim[i].indexed = !!ib; + prim[i].indirect_offset = indirect_offset; + prim[i].is_indirect = 1; + prim[i].draw_id = i; + } + + vbo->draw_prims(ctx, prim, draw_count, + ib, GL_TRUE, 0, ~0, + NULL, 0, + ctx->DrawIndirectBuffer); + + free(prim); +} + GLboolean _vbo_CreateContext( struct gl_context *ctx ) { @@ -152,6 +194,7 @@ GLboolean _vbo_CreateContext( struct gl_context *ctx ) init_legacy_currval( ctx ); init_generic_currval( ctx ); init_mat_currval( ctx ); + vbo_set_indirect_draw_func(ctx, vbo_draw_indirect_prims); /* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type * of vertex program active. @@ -223,3 +266,10 @@ void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func) vbo->draw_prims = func; } + +void vbo_set_indirect_draw_func(struct gl_context *ctx, + vbo_indirect_draw_func func) +{ + struct vbo_context *vbo = vbo_context(ctx); + vbo->draw_indirect_prims = func; +} diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h index 6293a8b9edc..11f9b17c7c4 100644 --- a/src/mesa/vbo/vbo_context.h +++ b/src/mesa/vbo/vbo_context.h @@ -76,6 +76,12 @@ struct vbo_context { * is responsible for initiating any fallback actions required: */ vbo_draw_func draw_prims; + + /* Optional callback for indirect draws. This allows multidraws to not be + * broken up, as well as for the actual count to be passed in as a separate + * indirect parameter. + */ + vbo_indirect_draw_func draw_indirect_prims; }; diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 502b2885892..2589ff4f9e2 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -1546,27 +1546,14 @@ vbo_validated_drawarraysindirect(struct gl_context *ctx, { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; - struct _mesa_prim prim[1]; vbo_bind_arrays(ctx); - memset(prim, 0, sizeof(prim)); - prim[0].begin = 1; - prim[0].end = 1; - prim[0].mode = mode; - prim[0].is_indirect = 1; - prim[0].indirect_offset = (GLsizeiptr)indirect; - - /* NOTE: We do NOT want to handle primitive restart here, nor perform any - * other checks that require knowledge of the values in the command buffer. - * That would defeat the whole purpose of this function. - */ - check_buffers_are_unmapped(exec->array.inputs); - vbo->draw_prims(ctx, prim, 1, - NULL, GL_TRUE, 0, ~0, - NULL, 0, - ctx->DrawIndirectBuffer); + vbo->draw_indirect_prims(ctx, mode, + ctx->DrawIndirectBuffer, (GLsizeiptr)indirect, + 1 /* draw_count */, 16 /* stride */, + NULL, 0, NULL); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) _mesa_flush(ctx); @@ -1580,36 +1567,18 @@ vbo_validated_multidrawarraysindirect(struct gl_context *ctx, { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; - struct _mesa_prim *prim; - GLsizei i; GLsizeiptr offset = (GLsizeiptr)indirect; if (primcount == 0) return; - prim = calloc(primcount, sizeof(*prim)); - if (prim == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect"); - return; - } vbo_bind_arrays(ctx); - prim[0].begin = 1; - prim[primcount - 1].end = 1; - for (i = 0; i < primcount; ++i, offset += stride) { - prim[i].mode = mode; - prim[i].indirect_offset = offset; - prim[i].is_indirect = 1; - prim[i].draw_id = i; - } - check_buffers_are_unmapped(exec->array.inputs); - vbo->draw_prims(ctx, prim, primcount, - NULL, GL_TRUE, 0, ~0, - NULL, 0, - ctx->DrawIndirectBuffer); - - free(prim); + vbo->draw_indirect_prims(ctx, mode, + ctx->DrawIndirectBuffer, offset, + primcount, stride, + NULL, 0, NULL); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) _mesa_flush(ctx); @@ -1623,7 +1592,6 @@ vbo_validated_drawelementsindirect(struct gl_context *ctx, struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct _mesa_index_buffer ib; - struct _mesa_prim prim[1]; vbo_bind_arrays(ctx); @@ -1632,19 +1600,12 @@ vbo_validated_drawelementsindirect(struct gl_context *ctx, ib.obj = ctx->Array.VAO->IndexBufferObj; ib.ptr = NULL; - memset(prim, 0, sizeof(prim)); - prim[0].begin = 1; - prim[0].end = 1; - prim[0].mode = mode; - prim[0].indexed = 1; - prim[0].indirect_offset = (GLsizeiptr)indirect; - prim[0].is_indirect = 1; - check_buffers_are_unmapped(exec->array.inputs); - vbo->draw_prims(ctx, prim, 1, - &ib, GL_TRUE, 0, ~0, - NULL, 0, - ctx->DrawIndirectBuffer); + vbo->draw_indirect_prims(ctx, mode, + ctx->DrawIndirectBuffer, (GLsizeiptr)indirect, + 1 /* draw_count */, 20 /* stride */, + NULL, 0, + &ib); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) _mesa_flush(ctx); @@ -1659,17 +1620,10 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx, struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct _mesa_index_buffer ib; - struct _mesa_prim *prim; - GLsizei i; GLsizeiptr offset = (GLsizeiptr)indirect; if (primcount == 0) return; - prim = calloc(primcount, sizeof(*prim)); - if (prim == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElementsIndirect"); - return; - } vbo_bind_arrays(ctx); @@ -1680,23 +1634,12 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx, ib.obj = ctx->Array.VAO->IndexBufferObj; ib.ptr = NULL; - prim[0].begin = 1; - prim[primcount - 1].end = 1; - for (i = 0; i < primcount; ++i, offset += stride) { - prim[i].mode = mode; - prim[i].indexed = 1; - prim[i].indirect_offset = offset; - prim[i].is_indirect = 1; - prim[i].draw_id = i; - } - check_buffers_are_unmapped(exec->array.inputs); - vbo->draw_prims(ctx, prim, primcount, - &ib, GL_TRUE, 0, ~0, - NULL, 0, - ctx->DrawIndirectBuffer); - - free(prim); + vbo->draw_indirect_prims(ctx, mode, + ctx->DrawIndirectBuffer, offset, + primcount, stride, + NULL, 0, + &ib); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) _mesa_flush(ctx); -- 2.30.2