[Mesa-dev] [Mesa-stable] [PATCH v3 3/4] mesa: move glMultiDrawArrays to vbo and fix error handling

Marek Olšák maraeo at gmail.com
Tue Apr 18 16:32:29 UTC 2017


For 1-3:

Reviewed-by: Marek Olšák <marek.olsak at amd.com>

Marek

On Apr 18, 2017 3:35 PM, "Nicolai Hähnle" <nhaehnle at gmail.com> wrote:

> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
>
> When any count[i] is negative, we must skip all draws.
>
> Moving to vbo makes the subsequent change easier.
>
> v2:
> - provide the function in all contexts, including GLES
> - adjust validation accordingly to include the xfb check
> v3:
> - fix mix-up of pre- and post-xfb prim count
>
> Cc: mesa-stable at lists.freedesktop.org
> Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>
> ---
>  src/mapi/glapi/gen/gl_API.xml |  2 +-
>  src/mesa/main/api_validate.c  | 54 ++++++++++++++++++++++++++++++
> +++++++++++++
>  src/mesa/main/api_validate.h  |  4 ++++
>  src/mesa/main/varray.c        | 18 ---------------
>  src/mesa/vbo/vbo_exec_array.c | 33 ++++++++++++++++++++++++++
>  src/mesa/vbo/vbo_save_api.c   | 35 ++++++++++++++++++++++++++++
>  6 files changed, 127 insertions(+), 19 deletions(-)
>
> diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
> index c0ee2f2..522d2e5 100644
> --- a/src/mapi/glapi/gen/gl_API.xml
> +++ b/src/mapi/glapi/gen/gl_API.xml
> @@ -10212,21 +10212,21 @@
>      </function>
>  </category>
>
>  <category name="GL_EXT_texture_perturb_normal" number="147">
>      <function name="TextureNormalEXT" exec="skip">
>          <param name="mode" type="GLenum"/>
>      </function>
>  </category>
>
>  <category name="GL_EXT_multi_draw_arrays" number="148">
> -    <function name="MultiDrawArraysEXT" es1="1.0" es2="2.0"
> alias="MultiDrawArrays">
> +    <function name="MultiDrawArraysEXT" es1="1.0" es2="2.0"
> exec="dynamic" alias="MultiDrawArrays">
>          <param name="mode" type="GLenum"/>
>          <param name="first" type="const GLint *"/>
>          <param name="count" type="const GLsizei *"/>
>          <param name="primcount" type="GLsizei"/>
>      </function>
>
>      <function name="MultiDrawElementsEXT" es1="1.0" es2="2.0"
> exec="dynamic" marshal="draw"
>                marshal_fail="_mesa_glthread_is_non_vbo_draw_elements(ctx)"
> >
>          <param name="mode" type="GLenum"/>
>          <param name="count" type="const GLsizei *"/>
> diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
> index 2e1829b..e23be60 100644
> --- a/src/mesa/main/api_validate.c
> +++ b/src/mesa/main/api_validate.c
> @@ -914,20 +914,74 @@ _mesa_validate_DrawArraysInstanced(struct
> gl_context *ctx, GLenum mode, GLint fi
>        if (numInstances < 0)
>           _mesa_error(ctx, GL_INVALID_VALUE,
>                       "glDrawArraysInstanced(numInstances=%d)",
> numInstances);
>        return GL_FALSE;
>     }
>
>     return validate_draw_arrays(ctx, "glDrawArraysInstanced", mode, count,
> 1);
>  }
>
>
> +/**
> + * Called to error check the function parameters.
> + *
> + * Note that glMultiDrawArrays is not part of GLES, so there's limited
> scope
> + * for sharing code with the validation of glDrawArrays.
> + */
> +bool
> +_mesa_validate_MultiDrawArrays(struct gl_context *ctx, GLenum mode,
> +                               const GLsizei *count, GLsizei primcount)
> +{
> +   int i;
> +
> +   FLUSH_CURRENT(ctx, 0);
> +
> +   if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawArrays"))
> +      return false;
> +
> +   if (!check_valid_to_render(ctx, "glMultiDrawArrays"))
> +      return false;
> +
> +   if (primcount < 0) {
> +      _mesa_error(ctx, GL_INVALID_VALUE, "glMultiDrawArrays(primcount=%
> d)",
> +                  primcount);
> +      return false;
> +   }
> +
> +   for (i = 0; i < primcount; ++i) {
> +      if (count[i] < 0) {
> +         _mesa_error(ctx, GL_INVALID_VALUE, "glMultiDrawArrays(count[%d]=%
> d)",
> +                     i, count[i]);
> +         return false;
> +      }
> +   }
> +
> +   if (need_xfb_remaining_prims_check(ctx)) {
> +      struct gl_transform_feedback_object *xfb_obj
> +         = ctx->TransformFeedback.CurrentObject;
> +      size_t xfb_prim_count = 0;
> +
> +      for (i = 0; i < primcount; ++i)
> +         xfb_prim_count += vbo_count_tessellated_primitives(mode,
> count[i], 1);
> +
> +      if (xfb_obj->GlesRemainingPrims < xfb_prim_count) {
> +         _mesa_error(ctx, GL_INVALID_OPERATION,
> +                     "glMultiDrawArrays(exceeds transform feedback
> size)");
> +         return false;
> +      }
> +      xfb_obj->GlesRemainingPrims -= xfb_prim_count;
> +   }
> +
> +   return true;
> +}
> +
> +
>  GLboolean
>  _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
>                                       GLenum mode, GLsizei count, GLenum
> type,
>                                       const GLvoid *indices, GLsizei
> numInstances)
>  {
>     FLUSH_CURRENT(ctx, 0);
>
>     if (numInstances < 0) {
>        _mesa_error(ctx, GL_INVALID_VALUE,
>                    "glDrawElementsInstanced(numInstances=%d)",
> numInstances);
> diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h
> index de520c9..93ec93d 100644
> --- a/src/mesa/main/api_validate.h
> +++ b/src/mesa/main/api_validate.h
> @@ -41,20 +41,24 @@ _mesa_valid_to_render(struct gl_context *ctx, const
> char *where);
>  extern bool
>  _mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode);
>
>  extern GLboolean
>  _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char
> *name);
>
>
>  extern GLboolean
>  _mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLsizei
> count);
>
> +extern bool
> +_mesa_validate_MultiDrawArrays(struct gl_context *ctx, GLenum mode,
> +                               const GLsizei *count, GLsizei primcount);
> +
>  extern GLboolean
>  _mesa_validate_DrawElements(struct gl_context *ctx,
>                             GLenum mode, GLsizei count, GLenum type,
>                             const GLvoid *indices);
>
>  extern GLboolean
>  _mesa_validate_MultiDrawElements(struct gl_context *ctx,
>                                   GLenum mode, const GLsizei *count,
>                                   GLenum type, const GLvoid * const
> *indices,
>                                   GLsizei primcount);
> diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
> index 233dc0d..2054985 100644
> --- a/src/mesa/main/varray.c
> +++ b/src/mesa/main/varray.c
> @@ -1532,38 +1532,20 @@ _mesa_UnlockArraysEXT( void )
>        _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)"
> );
>        return;
>     }
>
>     ctx->Array.LockFirst = 0;
>     ctx->Array.LockCount = 0;
>     ctx->NewState |= _NEW_ARRAY;
>  }
>
>
> -/* GL_EXT_multi_draw_arrays */
> -void GLAPIENTRY
> -_mesa_MultiDrawArrays( GLenum mode, const GLint *first,
> -                          const GLsizei *count, GLsizei primcount )
> -{
> -   GET_CURRENT_CONTEXT(ctx);
> -   GLint i;
> -
> -   FLUSH_VERTICES(ctx, 0);
> -
> -   for (i = 0; i < primcount; i++) {
> -      if (count[i] > 0) {
> -         CALL_DrawArrays(ctx->CurrentClientDispatch, (mode, first[i],
> count[i]));
> -      }
> -   }
> -}
> -
> -
>  /* GL_IBM_multimode_draw_arrays */
>  void GLAPIENTRY
>  _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
>                               const GLsizei * count,
>                               GLsizei primcount, GLint modestride )
>  {
>     GET_CURRENT_CONTEXT(ctx);
>     GLint i;
>
>     FLUSH_VERTICES(ctx, 0);
> diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
> index 30c52d5..6858eb3 100644
> --- a/src/mesa/vbo/vbo_exec_array.c
> +++ b/src/mesa/vbo/vbo_exec_array.c
> @@ -630,20 +630,52 @@ vbo_exec_DrawArraysInstancedBaseInstance(GLenum
> mode, GLint first,
>     if (0)
>        check_draw_arrays_data(ctx, first, count);
>
>     vbo_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
>
>     if (0)
>        print_draw_arrays(ctx, mode, first, count);
>  }
>
>
> +/**
> + * Called from glMultiDrawArrays when in immediate mode.
> + */
> +static void GLAPIENTRY
> +vbo_exec_MultiDrawArrays(GLenum mode, const GLint *first,
> +                         const GLsizei *count, GLsizei primcount)
> +{
> +   GET_CURRENT_CONTEXT(ctx);
> +   GLint i;
> +
> +   if (MESA_VERBOSE & VERBOSE_DRAW)
> +      _mesa_debug(ctx,
> +                  "glMultiDrawArrays(%s, %p, %p, %d)\n",
> +                  _mesa_enum_to_string(mode), first, count, primcount);
> +
> +   if (!_mesa_validate_MultiDrawArrays(ctx, mode, count, primcount))
> +      return;
> +
> +   for (i = 0; i < primcount; i++) {
> +      if (count[i] > 0) {
> +         if (0)
> +            check_draw_arrays_data(ctx, first[i], count[i]);
> +
> +         vbo_draw_arrays(ctx, mode, first[i], count[i], 1, 0);
> +
> +         if (0)
> +            print_draw_arrays(ctx, mode, first[i], count[i]);
> +      }
> +   }
> +}
> +
> +
>
>  /**
>   * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
>   * For debugging.
>   */
>  #if 0
>  static void
>  dump_element_buffer(struct gl_context *ctx, GLenum type)
>  {
>     const GLvoid *map =
> @@ -1634,20 +1666,21 @@ void
>  vbo_initialize_exec_dispatch(const struct gl_context *ctx,
>                               struct _glapi_table *exec)
>  {
>     SET_DrawArrays(exec, vbo_exec_DrawArrays);
>     SET_DrawElements(exec, vbo_exec_DrawElements);
>
>     if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
>        SET_DrawRangeElements(exec, vbo_exec_DrawRangeElements);
>     }
>
> +   SET_MultiDrawArrays(exec, vbo_exec_MultiDrawArrays);
>     SET_MultiDrawElementsEXT(exec, vbo_exec_MultiDrawElements);
>
>     if (ctx->API == API_OPENGL_COMPAT) {
>        SET_Rectf(exec, vbo_exec_Rectf);
>        SET_EvalMesh1(exec, vbo_exec_EvalMesh1);
>        SET_EvalMesh2(exec, vbo_exec_EvalMesh2);
>     }
>
>     if (ctx->API != API_OPENGLES &&
>         ctx->Extensions.ARB_draw_elements_base_vertex) {
> diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
> index f8dab0c..ad54c3b 100644
> --- a/src/mesa/vbo/vbo_save_api.c
> +++ b/src/mesa/vbo/vbo_save_api.c
> @@ -1169,20 +1169,54 @@ _save_OBE_DrawArrays(GLenum mode, GLint start,
> GLsizei count)
>                                | VBO_SAVE_PRIM_NO_CURRENT_UPDATE));
>
>     for (i = 0; i < count; i++)
>        CALL_ArrayElement(GET_DISPATCH(), (start + i));
>     CALL_End(GET_DISPATCH(), ());
>
>     _ae_unmap_vbos(ctx);
>  }
>
>
> +static void GLAPIENTRY
> +_save_OBE_MultiDrawArrays(GLenum mode, const GLint *first,
> +                          const GLsizei *count, GLsizei primcount)
> +{
> +   GET_CURRENT_CONTEXT(ctx);
> +   GLint i;
> +
> +   if (!_mesa_is_valid_prim_mode(ctx, mode)) {
> +      _mesa_compile_error(ctx, GL_INVALID_ENUM,
> "glMultiDrawArrays(mode)");
> +      return;
> +   }
> +
> +   if (primcount < 0) {
> +      _mesa_compile_error(ctx, GL_INVALID_VALUE,
> +                          "glMultiDrawArrays(primcount<0)");
> +      return;
> +   }
> +
> +   for (i = 0; i < primcount; i++) {
> +      if (count[i] < 0) {
> +         _mesa_compile_error(ctx, GL_INVALID_VALUE,
> +                             "glMultiDrawArrays(count[i]<0)");
> +         return;
> +      }
> +   }
> +
> +   for (i = 0; i < primcount; i++) {
> +      if (count[i] > 0) {
> +         _save_OBE_DrawArrays(mode, first[i], count[i]);
> +      }
> +   }
> +}
> +
> +
>  /* Could do better by copying the arrays and element list intact and
>   * then emitting an indexed prim at runtime.
>   */
>  static void GLAPIENTRY
>  _save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
>                                   const GLvoid * indices, GLint basevertex)
>  {
>     GET_CURRENT_CONTEXT(ctx);
>     struct vbo_save_context *save = &vbo_context(ctx)->save;
>     struct gl_buffer_object *indexbuf = ctx->Array.VAO->IndexBufferObj;
> @@ -1477,20 +1511,21 @@ _save_vtxfmt_init(struct gl_context *ctx)
>
>  /**
>   * Initialize the dispatch table with the VBO functions for display
>   * list compilation.
>   */
>  void
>  vbo_initialize_save_dispatch(const struct gl_context *ctx,
>                               struct _glapi_table *exec)
>  {
>     SET_DrawArrays(exec, _save_OBE_DrawArrays);
> +   SET_MultiDrawArrays(exec, _save_OBE_MultiDrawArrays);
>     SET_DrawElements(exec, _save_OBE_DrawElements);
>     SET_DrawElementsBaseVertex(exec, _save_OBE_DrawElementsBaseVertex);
>     SET_DrawRangeElements(exec, _save_OBE_DrawRangeElements);
>     SET_MultiDrawElementsEXT(exec, _save_OBE_MultiDrawElements);
>     SET_MultiDrawElementsBaseVertex(exec, _save_OBE_
> MultiDrawElementsBaseVertex);
>     SET_Rectf(exec, _save_OBE_Rectf);
>     /* Note: other glDraw functins aren't compiled into display lists */
>  }
>
>
> --
> 2.9.3
>
> _______________________________________________
> mesa-stable mailing list
> mesa-stable at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-stable
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170418/7dc7bd5e/attachment-0001.html>


More information about the mesa-dev mailing list