[Mesa-dev] [PATCH V3 06/13] vbo: Flesh out implementation of indirect draws

Ian Romanick idr at freedesktop.org
Tue Nov 19 12:15:52 PST 2013


With the issues below fixed,

Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>

On 11/09/2013 01:02 AM, Chris Forbes wrote:
> Based on part of Patch 2 of Christoph Bumiller's ARB_draw_indirect series.
> 
> Signed-off-by: Chris Forbes <chrisf at ijw.co.nz>
> ---
>  src/mesa/vbo/vbo_exec_array.c | 216 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 216 insertions(+)
> 
> diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
> index 4ea10ee..1c6b8b3 100644
> --- a/src/mesa/vbo/vbo_exec_array.c
> +++ b/src/mesa/vbo/vbo_exec_array.c
> @@ -1564,6 +1564,164 @@ vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
>     vbo_draw_transform_feedback(ctx, mode, obj, stream, primcount);
>  }
>  
> +static void
> +vbo_validated_drawarraysindirect(struct gl_context *ctx,
> +                                 GLenum mode, const GLvoid *indirect)
> +{
> +   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].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 deafeat 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,
> +                   ctx->DrawIndirectBuffer);
> +
> +   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
> +      _mesa_flush(ctx);
> +}
> +
> +static void
> +vbo_validated_multidrawarraysindirect(struct gl_context *ctx,
> +                                      GLenum mode,
> +                                      const GLvoid *indirect,
> +                                      GLsizei primcount, GLsizei stride)
> +{
> +   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(1, primcount * sizeof(*prim));

      prim = calloc(primcount, sizeof(*prim));

because primcount could be 0x7fffffff, and that would overflow on 32-bit
leading to sadness.  calloc will do the right thing.

> +   if (prim == NULL) {
> +      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect");
> +      return;
> +   }
> +
> +   vbo_bind_arrays(ctx);
> +
> +   memset(prim, 0, primcount * sizeof(*prim));

But you used calloc. :(

> +   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;
> +   }
> +
> +   check_buffers_are_unmapped(exec->array.inputs);
> +   vbo->draw_prims(ctx, prim, primcount,
> +                   NULL, GL_TRUE, 0, ~0,
> +                   NULL,
> +                   ctx->DrawIndirectBuffer);
> +
> +   free(prim);
> +
> +   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
> +      _mesa_flush(ctx);
> +}
> +
> +static void
> +vbo_validated_drawelementsindirect(struct gl_context *ctx,
> +                                   GLenum mode, GLenum type,
> +                                   const GLvoid *indirect)
> +{
> +   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);
> +
> +   ib.count = 0; /* unknown */
> +   ib.type = type;
> +   ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
> +   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;
> +
> +   check_buffers_are_unmapped(exec->array.inputs);
> +   vbo->draw_prims(ctx, prim, 1,
> +                   &ib, GL_TRUE, 0, ~0,
> +                   NULL,
> +                   ctx->DrawIndirectBuffer);
> +
> +   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
> +      _mesa_flush(ctx);
> +}
> +
> +static void
> +vbo_validated_multidrawelementsindirect(struct gl_context *ctx,
> +                                        GLenum mode, GLenum type,
> +                                        const GLvoid *indirect,
> +                                        GLsizei primcount, GLsizei stride)
> +{
> +   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(1, primcount * sizeof(*prim));

Same here.

> +   if (prim == NULL) {
> +      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElementsIndirect");
> +      return;
> +   }
> +
> +   vbo_bind_arrays(ctx);
> +
> +   /* NOTE: ElementArrayBufferObj is guaranteed to be a VBO. */
> +
> +   ib.count = 0; /* unknown */
> +   ib.type = type;
> +   ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
> +   ib.ptr = NULL;
> +
> +   memset(prim, 0, primcount * sizeof(*prim));

Same here.

> +   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;
> +   }
> +
> +   check_buffers_are_unmapped(exec->array.inputs);
> +   vbo->draw_prims(ctx, prim, primcount,
> +                   &ib, GL_TRUE, 0, ~0,
> +                   NULL,
> +                   ctx->DrawIndirectBuffer);
> +
> +   free(prim);
> +
> +   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
> +      _mesa_flush(ctx);
> +}
> +
>  /**
>   * Like [Multi]DrawArrays/Elements, but they take most arguments from
>   * a buffer object.
> @@ -1571,12 +1729,33 @@ vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
>  static void GLAPIENTRY
>  vbo_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
>  {
> +   GET_CURRENT_CONTEXT(ctx);
> +
> +   if (MESA_VERBOSE & VERBOSE_DRAW)
> +      _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n",
> +                  _mesa_lookup_enum_by_nr(mode), indirect);
> +
> +   if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect))
> +      return;
> +
> +   vbo_validated_drawarraysindirect(ctx, mode, indirect);
>  }
>  
>  static void GLAPIENTRY
>  vbo_exec_DrawElementsIndirect(GLenum mode, GLenum type,
>                                const GLvoid *indirect)
>  {
> +   GET_CURRENT_CONTEXT(ctx);
> +
> +   if (MESA_VERBOSE & VERBOSE_DRAW)
> +      _mesa_debug(ctx, "glDrawElementsIndirect(%s, %s, %p)\n",
> +                  _mesa_lookup_enum_by_nr(mode),
> +                  _mesa_lookup_enum_by_nr(type), indirect);
> +
> +   if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect))
> +      return;
> +
> +   vbo_validated_drawelementsindirect(ctx, mode, type, indirect);
>  }
>  
>  static void GLAPIENTRY
> @@ -1584,6 +1763,24 @@ vbo_exec_MultiDrawArraysIndirect(GLenum mode,
>                                   const GLvoid *indirect,
>                                   GLsizei primcount, GLsizei stride)
>  {
> +   GET_CURRENT_CONTEXT(ctx);
> +
> +   if (MESA_VERBOSE & VERBOSE_DRAW)
> +      _mesa_debug(ctx, "glMultiDrawArraysIndirect(%s, %p, %i, %i)\n",
> +                  _mesa_lookup_enum_by_nr(mode), indirect, primcount, stride);
> +
> +   /* If <stride> is zero, the array elements are treated as tightly packed. */
> +   if (stride == 0)
> +      stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
> +
> +   if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode,
> +                                               indirect,
> +                                               primcount, stride))
> +      return;
> +
> +   vbo_validated_multidrawarraysindirect(ctx, mode,
> +                                         indirect,
> +                                         primcount, stride);
>  }
>  
>  static void GLAPIENTRY
> @@ -1591,6 +1788,25 @@ vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type,
>                                     const GLvoid *indirect,
>                                     GLsizei primcount, GLsizei stride)
>  {
> +   GET_CURRENT_CONTEXT(ctx);
> +
> +   if (MESA_VERBOSE & VERBOSE_DRAW)
> +      _mesa_debug(ctx, "glMultiDrawElementsIndirect(%s, %s, %p, %i, %i)\n",
> +                  _mesa_lookup_enum_by_nr(mode),
> +                  _mesa_lookup_enum_by_nr(type), indirect, primcount, stride);
> +
> +   /* If <stride> is zero, the array elements are treated as tightly packed. */
> +   if (stride == 0)
> +      stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */
> +
> +   if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type,
> +                                                 indirect,
> +                                                 primcount, stride))
> +      return;
> +
> +   vbo_validated_multidrawelementsindirect(ctx, mode, type,
> +                                           indirect,
> +                                           primcount, stride);
>  }
>  
>  /**
> 



More information about the mesa-dev mailing list