Eric Anholt wrote:
> This saves mapping the index buffer to get a bounds on the indices that
> drivers just drop on the floor in the VBO case (cache win), saves a bonus
> walk of the indices in the CheckArrayBounds case, and other miscellaneous
> validation. On intel it's a particularly a large win (50-100% in my app)
> because even though we let the indices stay in both CPU and GPU caches, we
> still end up waiting for the GPU to be done with the buffer before reading
> from it.
>
> Drivers supporting draw_prims must now handle min_index == ~0 indicating that
> min/max_index are not computed, if they want to use these fields.
This looks pretty good.
I guess the only thing I'd question is using min_index==~0 as the
indicator that indices have not been validated. Another approach
would be for drivers to call a new
vbo_enable_index_validation(GLboolean) function to tell the VBO module
whether or not it should validate indices. Would that be any better?
One other comment below...
-Brian
> ---
> src/mesa/drivers/dri/i965/brw_draw.c | 52 +++-------
> src/mesa/drivers/dri/i965/brw_draw_upload.c | 1 +
> src/mesa/drivers/dri/r300/r300_draw.c | 6 +
> src/mesa/tnl/t_draw.c | 3 +
> src/mesa/vbo/vbo.h | 5 +-
> src/mesa/vbo/vbo_exec_array.c | 151
> ++++++++++++++-------------
> 6 files changed, 107 insertions(+), 111 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_draw.c
> b/src/mesa/drivers/dri/i965/brw_draw.c
> index 5152c3f..01e5f36 100644
> --- a/src/mesa/drivers/dri/i965/brw_draw.c
> +++ b/src/mesa/drivers/dri/i965/brw_draw.c
> @@ -422,34 +422,6 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
> return retval;
> }
>
> -static GLboolean brw_need_rebase( GLcontext *ctx,
> - const struct gl_client_array *arrays[],
> - const struct _mesa_index_buffer *ib,
> - GLuint min_index )
> -{
> - if (min_index == 0)
> - return GL_FALSE;
> -
> - if (ib) {
> - if (!vbo_all_varyings_in_vbos(arrays))
> - return GL_TRUE;
> - else
> - return GL_FALSE;
> - }
> - else {
> - /* Hmm. This isn't quite what I wanted. BRW can actually
> - * handle the mixed case well enough that we shouldn't need to
> - * rebase. However, it's probably not very common, nor hugely
> - * expensive to do it this way:
> - */
> - if (!vbo_all_varyings_in_vbos(arrays))
> - return GL_TRUE;
> - else
> - return GL_FALSE;
> - }
> -}
> -
> -
> void brw_draw_prims( GLcontext *ctx,
> const struct gl_client_array *arrays[],
> const struct _mesa_prim *prim,
> @@ -460,16 +432,20 @@ void brw_draw_prims( GLcontext *ctx,
> {
> GLboolean retval;
>
> - /* Decide if we want to rebase. If so we end up recursing once
> - * only into this function.
> - */
> - if (brw_need_rebase( ctx, arrays, ib, min_index )) {
> - vbo_rebase_prims( ctx, arrays,
> - prim, nr_prims,
> - ib, min_index, max_index,
> - brw_draw_prims );
> -
> - return;
> + if (!vbo_all_varyings_in_vbos(arrays)) {
> + if (min_index == ~0)
> + vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
> +
> + /* Decide if we want to rebase. If so we end up recursing once
> + * only into this function.
> + */
> + if (min_index != 0) {
> + vbo_rebase_prims(ctx, arrays,
> + prim, nr_prims,
> + ib, min_index, max_index,
> + brw_draw_prims );
> + return;
> + }
> }
>
> /* Make a first attempt at drawing:
> diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c
> b/src/mesa/drivers/dri/i965/brw_draw_upload.c
> index 4bdb373..a4457b8 100644
> --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
> +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
> @@ -411,6 +411,7 @@ static void brw_prepare_vertices(struct brw_context *brw)
> */
> assert(input->offset < input->bo->size);
> } else {
> + assert(min_index != ~0);
> input->count = input->glarray->StrideB ? max_index + 1 - min_index :
> 1;
> if (input->bo != NULL) {
> /* Already-uploaded vertex data is present from a previous
> diff --git a/src/mesa/drivers/dri/r300/r300_draw.c
> b/src/mesa/drivers/dri/r300/r300_draw.c
> index fcfd309..bc5a234 100644
> --- a/src/mesa/drivers/dri/r300/r300_draw.c
> +++ b/src/mesa/drivers/dri/r300/r300_draw.c
> @@ -476,6 +476,12 @@ static void r300DrawPrims(GLcontext *ctx,
> limits.max_indices = 65535;
> limits.max_vb_size = 1024*1024;
>
> + /* This check should get folded into just the places that
> + * min/max index are really needed.
> + */
> + if (min_index == ~0)
> + vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
> +
> if (min_index) {
> vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, min_index,
> max_index, r300DrawPrims );
> return;
> diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c
> index 2ec65d5..d093293 100644
> --- a/src/mesa/tnl/t_draw.c
> +++ b/src/mesa/tnl/t_draw.c
> @@ -388,6 +388,9 @@ void _tnl_draw_prims( GLcontext *ctx,
> prim[i].count);
> }
>
> + if (min_index == ~0)
> + vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
> +
> if (min_index) {
> /* We always translate away calls with min_index != 0.
> */
> diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
> index 5362226..9052ce3 100644
> --- a/src/mesa/vbo/vbo.h
> +++ b/src/mesa/vbo/vbo.h
> @@ -112,7 +112,10 @@ void vbo_rebase_prims( GLcontext *ctx,
> GLuint min_index,
> GLuint max_index,
> vbo_draw_func draw );
> -
> +void
> +vbo_get_minmax_index(GLcontext *ctx, const struct _mesa_prim *prim,
> + const struct _mesa_index_buffer *ib,
> + GLuint *min_index, GLuint *max_index);
>
> void vbo_use_buffer_objects(GLcontext *ctx);
>
> diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
> index f4b9b2f..9ea3e4a 100644
> --- a/src/mesa/vbo/vbo_exec_array.c
> +++ b/src/mesa/vbo/vbo_exec_array.c
> @@ -41,15 +41,29 @@
> /**
> * Compute min and max elements for glDraw[Range]Elements() calls.
> */
> -static void
> -get_minmax_index(GLuint count, GLuint type, const GLvoid *indices,
> - GLuint *min_index, GLuint *max_index)
> +void
> +vbo_get_minmax_index(GLcontext *ctx,
> + const struct _mesa_prim *prim,
> + const struct _mesa_index_buffer *ib,
> + GLuint *min_index, GLuint *max_index)
> {
> GLuint i;
> + GLsizei count = prim->count;
> + const void *indices;
> +
> + if (ib->obj->Name) {
> + const GLvoid *map = ctx->Driver.MapBuffer(ctx,
> + GL_ELEMENT_ARRAY_BUFFER_ARB,
> + GL_READ_ONLY,
> + ib->obj);
> + indices = ADD_POINTERS(map, ib->ptr);
> + } else {
> + indices = ib->ptr;
> + }
>
> - switch(type) {
> + switch (ib->type) {
> case GL_UNSIGNED_INT: {
> - const GLuint *ui_indices = (const GLuint *)indices;
> + const GLuint *ui_indices = (const GLuint *)ib->ptr;
Are you sure the above change is correct? Don't you want the indices
ptr? I presume the ushort and ubyte cases still use 'indices'.
> GLuint max_ui = ui_indices[count-1];
> GLuint min_ui = ui_indices[0];
> for (i = 0; i < count; i++) {
> @@ -88,6 +102,12 @@ get_minmax_index(GLuint count, GLuint type, const GLvoid
> *indices,
> assert(0);
> break;
> }
> +
> + if (ib->obj->Name != 0) {
> + ctx->Driver.UnmapBuffer(ctx,
> + GL_ELEMENT_ARRAY_BUFFER_ARB,
> + ib->obj);
> + }
> }
>
>
> @@ -566,53 +586,18 @@ dump_element_buffer(GLcontext *ctx, GLenum type)
> ctx->Array.ElementArrayBufferObj);
> }
>
> -
> -static void GLAPIENTRY
> -vbo_exec_DrawRangeElements(GLenum mode,
> - GLuint start, GLuint end,
> - GLsizei count, GLenum type, const GLvoid *indices)
> +/* Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements */
> +static void
> +vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode,
> + GLuint start, GLuint end,
> + GLsizei count, GLenum type,
> + const GLvoid *indices)
> {
> - GET_CURRENT_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];
>
> - if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
> - type, indices ))
> - return;
> -
> - if (end >= ctx->Array.ArrayObj->_MaxElement) {
> - /* the max element is out of bounds of one or more enabled arrays */
> - _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
> - "type 0x%x, indices=%p)\n"
> - "\tindex=%u is out of bounds (max=%u) "
> - "Element Buffer %u (size %d)",
> - start, end, count, type, indices, end,
> - ctx->Array.ArrayObj->_MaxElement - 1,
> - ctx->Array.ElementArrayBufferObj->Name,
> - ctx->Array.ElementArrayBufferObj->Size);
> -
> - if (0)
> - dump_element_buffer(ctx, type);
> -
> - if (0)
> - _mesa_print_arrays(ctx);
> - return;
> - }
> - else if (0) {
> - _mesa_printf("glDraw[Range]Elements"
> - "(start %u, end %u, type 0x%x, count %d) ElemBuf %u\n",
> - start, end, type, count,
> - ctx->Array.ElementArrayBufferObj->Name);
> - }
> -
> -#if 0
> - check_draw_elements_data(ctx, count, type, indices);
> -#else
> - (void) check_draw_elements_data;
> -#endif
> -
> FLUSH_CURRENT( ctx, 0 );
>
> if (ctx->NewState)
> @@ -623,13 +608,13 @@ vbo_exec_DrawRangeElements(GLenum mode,
> return;
> }
>
> - bind_arrays( ctx );
> -
> if (ctx->NewState)
> _mesa_update_state( ctx );
>
> + bind_arrays( ctx );
> +
> ib.count = count;
> - ib.type = type;
> + ib.type = type;
> ib.obj = ctx->Array.ElementArrayBufferObj;
> ib.ptr = indices;
>
> @@ -676,41 +661,63 @@ vbo_exec_DrawRangeElements(GLenum mode,
> vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end );
> }
>
> -
> static void GLAPIENTRY
> -vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
> - const GLvoid *indices)
> +vbo_exec_DrawRangeElements(GLenum mode,
> + GLuint start, GLuint end,
> + GLsizei count, GLenum type, const GLvoid *indices)
> {
> GET_CURRENT_CONTEXT(ctx);
> - GLuint min_index = 0;
> - GLuint max_index = 0;
>
> - if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
> + if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
> + type, indices ))
> return;
>
> - if (!vbo_validate_shaders(ctx)) {
> - _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawElements(bad shader)");
> + if (end >= ctx->Array.ArrayObj->_MaxElement) {
> + /* the max element is out of bounds of one or more enabled arrays */
> + _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
> + "type 0x%x, indices=%p)\n"
> + "\tindex=%u is out of bounds (max=%u) "
> + "Element Buffer %u (size %d)",
> + start, end, count, type, indices, end,
> + ctx->Array.ArrayObj->_MaxElement - 1,
> + ctx->Array.ElementArrayBufferObj->Name,
> + ctx->Array.ElementArrayBufferObj->Size);
> +
> + if (0)
> + dump_element_buffer(ctx, type);
> +
> + if (0)
> + _mesa_print_arrays(ctx);
> return;
> }
> + else if (0) {
> + _mesa_printf("glDraw[Range]Elements"
> + "(start %u, end %u, type 0x%x, count %d) ElemBuf %u\n",
> + start, end, type, count,
> + ctx->Array.ElementArrayBufferObj->Name);
> + }
>
> - if (ctx->Array.ElementArrayBufferObj->Name) {
> - const GLvoid *map = ctx->Driver.MapBuffer(ctx,
> - GL_ELEMENT_ARRAY_BUFFER_ARB,
> - GL_READ_ONLY,
> -
> ctx->Array.ElementArrayBufferObj);
> +#if 0
> + check_draw_elements_data(ctx, count, type, indices);
> +#else
> + (void) check_draw_elements_data;
> +#endif
> +
> + vbo_validated_drawrangeelements(ctx, mode, start, end,
> + count, type, indices);
> +}
>
> - get_minmax_index(count, type, ADD_POINTERS(map, indices),
> - &min_index, &max_index);
>
> - ctx->Driver.UnmapBuffer(ctx,
> - GL_ELEMENT_ARRAY_BUFFER_ARB,
> - ctx->Array.ElementArrayBufferObj);
> - }
> - else {
> - get_minmax_index(count, type, indices, &min_index, &max_index);
> - }
> +static void GLAPIENTRY
> +vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
> + const GLvoid *indices)
> +{
> + GET_CURRENT_CONTEXT(ctx);
> +
> + if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
> + return;
>
> - vbo_exec_DrawRangeElements(mode, min_index, max_index, count, type,
> indices);
> + vbo_validated_drawrangeelements(ctx, mode, ~0, ~0, count, type, indices);
> }
>
>
> --
> 1.6.3.3
>
>
> ------------------------------------------------------------------------------
> Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
> trial. Simplify your report design, integration and deployment - and focus on
> what you do best, core application coding. Discover what's new with
> Crystal Reports now. http://p.sf.net/sfu/bobj-july
> _______________________________________________
> Mesa3d-dev mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/mesa3d-dev
> .
>
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now. http://p.sf.net/sfu/bobj-july
_______________________________________________
Mesa3d-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev