[Mesa-dev] [PATCH v2] vbo: create a new draw function interface for indirect draws

Ian Romanick idr at freedesktop.org
Thu Jan 7 14:02:22 PST 2016


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.romanick at 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 <imirkin at alum.mit.edu>
> Acked-by: Marek Olšák <marek.olsak at 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);
> 



More information about the mesa-dev mailing list