If we decide we want more or less in the interface later, we should be able to change it easily. This patch is
Reviewed-by: Ian Romanick <ian.d.roman...@intel.com> On 01/04/2016 08:20 PM, Ilia Mirkin wrote: > 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 <imir...@alum.mit.edu> > Acked-by: Marek Olšák <marek.ol...@amd.com> > --- > > v1 -> v2: Per Ian's suggestion, add a fallback implementation so that the > main paths are nice and clean. The fallback implementation of > draw_indirect_prims just creates a separate _mesa_prim for each indirect > draw as before and calls draw_prims. > > 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 cef3b8c..0c63bf3 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 5e1a760..c29f72b 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 6293a8b..11f9b17 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 502b288..2589ff4 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); > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev