[Mesa-dev] [PATCH V3 05/13] mesa: Add validation helpers for new indirect draws

Ian Romanick idr at freedesktop.org
Tue Nov 19 11:29:08 PST 2013


On 11/09/2013 01:02 AM, Chris Forbes wrote:
> Based on part of Patch 2 of Christoph Bumiller's ARB_draw_indirect series.
> 
> V3: - Disallow primcount==0 for DrawMulti*Indirect. The extension spec
>       contradicts itself on this, but the GL4.3 spec disallows it.
> 
>     - Make it clear that the caller has dealt with stride==0
> 
> Signed-off-by: Chris Forbes <chrisf at ijw.co.nz>
> Reviewed-by: Paul Berry <stereotype441 at gmail.com>
> ---
>  src/mesa/main/api_validate.c | 167 +++++++++++++++++++++++++++++++++++++++++++
>  src/mesa/main/api_validate.h |  26 +++++++
>  2 files changed, 193 insertions(+)
> 
> diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
> index f285c97..f462b68 100644
> --- a/src/mesa/main/api_validate.c
> +++ b/src/mesa/main/api_validate.c
> @@ -837,3 +837,170 @@ _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
>  
>     return GL_TRUE;
>  }
> +
> +static GLboolean
> +valid_draw_indirect(struct gl_context *ctx,
> +                    GLenum mode, const GLvoid *indirect,
> +                    GLsizei size, const char *name)
> +{
> +   const GLsizeiptr end = (GLsizeiptr)indirect + size;
> +
> +   if (!_mesa_valid_prim_mode(ctx, mode, name))
> +      return GL_FALSE;
> +
> +   if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1)) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "%s(indirect is not aligned)", name);
> +      return GL_FALSE;
> +   }
> +
> +   if (_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
> +      if (_mesa_bufferobj_mapped(ctx->DrawIndirectBuffer)) {
> +         _mesa_error(ctx, GL_INVALID_OPERATION,
> +                     "%s(DRAW_INDIRECT_BUFFER is mapped)", name);
> +         return GL_FALSE;
> +      }
> +      if (ctx->DrawIndirectBuffer->Size < end) {
> +         _mesa_error(ctx, GL_INVALID_OPERATION,
> +                     "%s(DRAW_INDIRECT_BUFFER too small)", name);
> +         return GL_FALSE;
> +      }
> +   } else {
> +      if (ctx->API != API_OPENGL_COMPAT) {
> +         _mesa_error(ctx, GL_INVALID_OPERATION,
> +                     "%s: no buffer bound to DRAW_INDIRECT_BUFFER", name);
> +         return GL_FALSE;

We can drop this check.  We'll never get ctx->API == API_OPENGL_COMPAT
because we won't even install the dispatch pointers.

> +      }
> +   }
> +
> +   if (!check_valid_to_render(ctx, name))
> +      return GL_FALSE;
> +
> +   return GL_TRUE;
> +}
> +
> +static inline GLboolean
> +valid_draw_indirect_elements(struct gl_context *ctx,
> +                             GLenum mode, GLenum type, const GLvoid *indirect,
> +                             GLsizeiptr size, const char *name)
> +{
> +   if (!valid_elements_type(ctx, type, name))
> +      return GL_FALSE;
> +
> +   /*
> +    * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
> +    * may not come from a client array and must come from an index buffer.
> +    * If no element array buffer is bound, an INVALID_OPERATION error is
> +    * generated.
> +    */
> +   if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
> +      _mesa_error(ctx, GL_INVALID_OPERATION,
> +                  "%s(no buffer bound to GL_ELEMENT_ARRAY_BUFFER)", name);
> +      return GL_FALSE;
> +   }
> +
> +   return valid_draw_indirect(ctx, mode, indirect, size, name);
> +}
> +
> +static inline GLboolean
> +valid_draw_indirect_multi(struct gl_context *ctx,
> +                          GLsizei primcount, GLsizei stride,
> +                          const char *name)
> +{
> +   if (primcount <= 0) {
> +      _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount <= 0)", name);
> +      return GL_FALSE;
> +   }
> +
> +   if (stride % 4) {
> +      _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name);
> +      return GL_FALSE;
> +   }
> +
> +   return GL_TRUE;
> +}
> +
> +GLboolean
> +_mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
> +                                  GLenum mode,
> +                                  const GLvoid *indirect)
> +{
> +   const unsigned drawArraysNumParams = 4;
> +
> +   FLUSH_CURRENT(ctx, 0);
> +
> +   return valid_draw_indirect(ctx, mode,
> +                              indirect, drawArraysNumParams * sizeof(GLuint),
> +                              "glDrawArraysIndirect");
> +}
> +
> +GLboolean
> +_mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
> +                                    GLenum mode, GLenum type,
> +                                    const GLvoid *indirect)
> +{
> +   const unsigned drawElementsNumParams = 5;
> +
> +   FLUSH_CURRENT(ctx, 0);
> +
> +   return valid_draw_indirect_elements(ctx, mode, type,
> +                                       indirect, drawElementsNumParams * sizeof(GLuint),
> +                                       "glDrawElementsIndirect");
> +}
> +
> +GLboolean
> +_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
> +                                       GLenum mode,
> +                                       const GLvoid *indirect,
> +                                       GLsizei primcount, GLsizei stride)
> +{
> +   GLsizeiptr size = 0;
> +   const unsigned drawArraysNumParams = 4;
> +
> +   FLUSH_CURRENT(ctx, 0);
> +
> +   /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
> +   assert(stride != 0);
> +
> +   if (!valid_draw_indirect_multi(ctx, primcount, stride,
> +                                  "glMultiDrawArraysIndirect"))
> +      return GL_FALSE;
> +
> +   /* number of bytes of the indirect buffer which will be read */
> +   size = (primcount - 1) * stride + drawArraysNumParams * sizeof(GLuint);
> +
> +   if (!valid_draw_indirect(ctx, mode, indirect, size,
> +                            "glMultiDrawArraysIndirect"))
> +      return GL_FALSE;
> +
> +   return GL_TRUE;
> +}
> +
> +GLboolean
> +_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
> +                                         GLenum mode, GLenum type,
> +                                         const GLvoid *indirect,
> +                                         GLsizei primcount, GLsizei stride)
> +{
> +   GLsizeiptr size = 0;
> +   const unsigned drawElementsNumParams = 5;
> +
> +   FLUSH_CURRENT(ctx, 0);
> +
> +   /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
> +   assert(stride != 0);
> +
> +   if (!valid_draw_indirect_multi(ctx, primcount, stride,
> +                                  "glMultiDrawElementsIndirect"))
> +      return GL_FALSE;
> +
> +   /* number of bytes of the indirect buffer which will be read */
> +   size = (primcount - 1) * stride + drawElementsNumParams * sizeof(GLuint);
> +
> +   if (!valid_draw_indirect_elements(ctx, mode, type,
> +                                     indirect, size,
> +                                     "glMultiDrawElementsIndirect"))
> +      return GL_FALSE;
> +
> +   return GL_TRUE;
> +}
> diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h
> index f2b753c..8238df1 100644
> --- a/src/mesa/main/api_validate.h
> +++ b/src/mesa/main/api_validate.h
> @@ -87,5 +87,31 @@ _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
>                                       GLuint stream,
>                                       GLsizei numInstances);
>  
> +extern GLboolean
> +_mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
> +                                  GLenum mode,
> +                                  const GLvoid *indirect);
> +
> +extern GLboolean
> +_mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
> +                                    GLenum mode,
> +                                    GLenum type,
> +                                    const GLvoid *indirect);
> +
> +extern GLboolean
> +_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
> +                                       GLenum mode,
> +                                       const GLvoid *indirect,
> +                                       GLsizei primcount,
> +                                       GLsizei stride);
> +
> +extern GLboolean
> +_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
> +                                         GLenum mode,
> +                                         GLenum type,
> +                                         const GLvoid *indirect,
> +                                         GLsizei primcount,
> +                                         GLsizei stride);
> +
>  
>  #endif
> 



More information about the mesa-dev mailing list