Looks good to me, Jose. Keith
On Thu, 2011-03-31 at 14:45 +0100, jfons...@vmware.com wrote: > From: José Fonseca <jfons...@vmware.com> > > Based on some code and ideas from Keith Whitwell. > --- > src/gallium/auxiliary/Makefile | 1 + > src/gallium/auxiliary/SConscript | 1 + > src/gallium/auxiliary/draw/draw_private.h | 8 ++ > src/gallium/auxiliary/draw/draw_pt.c | 11 +++ > src/gallium/auxiliary/draw/draw_pt_fetch.c | 2 +- > src/gallium/auxiliary/draw/draw_pt_fetch_emit.c | 2 +- > .../auxiliary/draw/draw_pt_fetch_shade_emit.c | 2 +- > src/gallium/auxiliary/draw/draw_pt_vsplit.c | 7 ++- > src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h | 12 ++- > src/gallium/auxiliary/util/u_draw.c | 94 > ++++++++++++++++++++ > src/gallium/auxiliary/util/u_draw.h | 19 ++++ > 11 files changed, 152 insertions(+), 7 deletions(-) > create mode 100644 src/gallium/auxiliary/util/u_draw.c > > diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile > index c765404..2be4509 100644 > --- a/src/gallium/auxiliary/Makefile > +++ b/src/gallium/auxiliary/Makefile > @@ -107,6 +107,7 @@ C_SOURCES = \ > util/u_caps.c \ > util/u_cpu_detect.c \ > util/u_dl.c \ > + util/u_draw.c \ > util/u_draw_quad.c \ > util/u_format.c \ > util/u_format_other.c \ > diff --git a/src/gallium/auxiliary/SConscript > b/src/gallium/auxiliary/SConscript > index 8e422b2..96ca566 100644 > --- a/src/gallium/auxiliary/SConscript > +++ b/src/gallium/auxiliary/SConscript > @@ -154,6 +154,7 @@ source = [ > 'util/u_dump_defines.c', > 'util/u_dump_state.c', > 'util/u_dl.c', > + 'util/u_draw.c', > 'util/u_draw_quad.c', > 'util/u_format.c', > 'util/u_format_other.c', > diff --git a/src/gallium/auxiliary/draw/draw_private.h > b/src/gallium/auxiliary/draw/draw_private.h > index db2e3c5..b7d693f 100644 > --- a/src/gallium/auxiliary/draw/draw_private.h > +++ b/src/gallium/auxiliary/draw/draw_private.h > @@ -146,6 +146,14 @@ struct draw_context > struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; > unsigned nr_vertex_buffers; > > + /* > + * This is the largest legal index value for the current set of > + * bound vertex buffers. Regardless of any other consideration, > + * all vertex lookups need to be clamped to 0..max_index to > + * prevent out-of-bound access. > + */ > + unsigned max_index; > + > struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; > unsigned nr_vertex_elements; > > diff --git a/src/gallium/auxiliary/draw/draw_pt.c > b/src/gallium/auxiliary/draw/draw_pt.c > index c3d7e87..e0eda67 100644 > --- a/src/gallium/auxiliary/draw/draw_pt.c > +++ b/src/gallium/auxiliary/draw/draw_pt.c > @@ -470,6 +470,17 @@ draw_vbo(struct draw_context *draw, > if (0) > draw_print_arrays(draw, info->mode, info->start, MIN2(info->count, > 20)); > > + draw->pt.max_index = util_draw_max_index(draw->pt.vertex_buffer, > + draw->pt.nr_vertex_buffers, > + draw->pt.vertex_element, > + draw->pt.nr_vertex_elements, > + info); > + > + /* > + * TODO: We could use draw->pt.max_index to further narrow > + * the min_index/max_index hints given by the state tracker. > + */ > + > for (instance = 0; instance < info->instance_count; instance++) { > draw->instance_id = instance + info->start_instance; > > diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c > b/src/gallium/auxiliary/draw/draw_pt_fetch.c > index 4fa3b26..5589a82 100644 > --- a/src/gallium/auxiliary/draw/draw_pt_fetch.c > +++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c > @@ -139,7 +139,7 @@ void draw_pt_fetch_run( struct pt_fetch *fetch, > ((char *)draw->pt.user.vbuffer[i] + > draw->pt.vertex_buffer[i].buffer_offset), > draw->pt.vertex_buffer[i].stride, > - draw->pt.user.max_index); > + draw->pt.max_index); > } > > translate->run_elts( translate, > diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c > b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c > index 5104310..0ab11d0 100644 > --- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c > +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c > @@ -186,7 +186,7 @@ static void fetch_emit_prepare( struct draw_pt_middle_end > *middle, > ((char *)draw->pt.user.vbuffer[i] + > draw->pt.vertex_buffer[i].buffer_offset), > draw->pt.vertex_buffer[i].stride, > - draw->pt.user.max_index); > + draw->pt.max_index); > } > > *max_vertices = (draw->render->max_vertex_buffer_bytes / > diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c > b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c > index 1e926fb..0dbbfe2 100644 > --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c > +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c > @@ -169,7 +169,7 @@ static void fse_prepare( struct draw_pt_middle_end > *middle, > ((const ubyte *) draw->pt.user.vbuffer[i] + > draw->pt.vertex_buffer[i].buffer_offset), > draw->pt.vertex_buffer[i].stride, > - draw->pt.user.max_index ); > + draw->pt.max_index ); > } > > *max_vertices = (draw->render->max_vertex_buffer_bytes / > diff --git a/src/gallium/auxiliary/draw/draw_pt_vsplit.c > b/src/gallium/auxiliary/draw/draw_pt_vsplit.c > index a687525..c19dcd9 100644 > --- a/src/gallium/auxiliary/draw/draw_pt_vsplit.c > +++ b/src/gallium/auxiliary/draw/draw_pt_vsplit.c > @@ -85,7 +85,12 @@ vsplit_flush_cache(struct vsplit_frontend *vsplit, > unsigned flags) > static INLINE void > vsplit_add_cache(struct vsplit_frontend *vsplit, unsigned fetch) > { > - unsigned hash = fetch % MAP_SIZE; > + struct draw_context *draw = vsplit->draw; > + unsigned hash; > + > + fetch = MIN2(fetch, draw->pt.max_index); > + > + hash = fetch % MAP_SIZE; > > if (vsplit->cache.fetches[hash] != fetch) { > /* update cache */ > diff --git a/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h > b/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h > index 10842a3..e9714c1 100644 > --- a/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h > +++ b/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h > @@ -56,7 +56,9 @@ CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend > *vsplit, > > for (i = 0; i < icount; i++) { > ELT_TYPE idx = ib[i]; > - assert(idx >= min_index && idx <= max_index); > + if (idx >= min_index && idx <= max_index) { > + debug_printf("warning: index out of range\n"); > + } > } > draw_elts = (const ushort *) ib; > } > @@ -87,7 +89,9 @@ CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend > *vsplit, > for (i = 0; i < icount; i++) { > ELT_TYPE idx = ib[i]; > > - assert(idx >= min_index && idx <= max_index); > + if (idx >= min_index && idx <= max_index) { > + debug_printf("warning: index out of range\n"); > + } > vsplit->draw_elts[i] = (ushort) idx; > } > } > @@ -95,7 +99,9 @@ CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend > *vsplit, > for (i = 0; i < icount; i++) { > ELT_TYPE idx = ib[i]; > > - assert(idx >= min_index && idx <= max_index); > + if (idx >= min_index && idx <= max_index) { > + debug_printf("warning: index out of range\n"); > + } > vsplit->draw_elts[i] = (ushort) (idx - min_index); > } > } > diff --git a/src/gallium/auxiliary/util/u_draw.c > b/src/gallium/auxiliary/util/u_draw.c > new file mode 100644 > index 0000000..8e87a3b > --- /dev/null > +++ b/src/gallium/auxiliary/util/u_draw.c > @@ -0,0 +1,94 @@ > +/************************************************************************** > + * > + * Copyright 2011 VMware, Inc. > + * All Rights Reserved. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the > + * "Software"), to deal in the Software without restriction, including > + * without limitation the rights to use, copy, modify, merge, publish, > + * distribute, sub license, and/or sell copies of the Software, and to > + * permit persons to whom the Software is furnished to do so, subject to > + * the following conditions: > + * > + * The above copyright notice and this permission notice (including the > + * next paragraph) shall be included in all copies or substantial portions > + * of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS > + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. > + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR > + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, > + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE > + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. > + * > + **************************************************************************/ > + > + > +#include "util/u_debug.h" > +#include "util/u_math.h" > +#include "util/u_format.h" > +#include "util/u_draw.h" > + > + > +/** > + * Returns the largest legal index value for the current set of bound vertex > + * buffers. Regardless of any other consideration, all vertex lookups need > to > + * be clamped to 0..max_index to prevent an out-of-bound access. > + */ > +unsigned > +util_draw_max_index( > + const struct pipe_vertex_buffer *vertex_buffers, > + unsigned nr_vertex_buffers, > + const struct pipe_vertex_element *vertex_elements, > + unsigned nr_vertex_elements, > + const struct pipe_draw_info *info) > +{ > + unsigned max_index; > + unsigned i; > + > + max_index = ~0; > + for (i = 0; i < nr_vertex_elements; i++) { > + const struct pipe_vertex_element *element = > + &vertex_elements[i]; > + const struct pipe_vertex_buffer *buffer = > + &vertex_buffers[element->vertex_buffer_index]; > + unsigned buffer_size; > + const struct util_format_description *format_desc; > + unsigned format_size; > + > + assert(buffer->buffer->height0 == 1); > + assert(buffer->buffer->depth0 == 1); > + buffer_size = buffer->buffer->width0; > + > + format_desc = util_format_description(element->src_format); > + assert(format_desc->block.width == 1); > + assert(format_desc->block.height == 1); > + assert(format_desc->block.bits % 8 == 0); > + format_size = format_desc->block.bits/8; > + > + assert(buffer->buffer_offset + format_size <= buffer_size); > + > + if (buffer->stride != 0) { > + unsigned buffer_max_index; > + > + buffer_max_index = > + (buffer_size - buffer->buffer_offset - format_size) > + / buffer->stride; > + > + if (element->instance_divisor == 0) { > + /* Per-vertex data */ > + max_index = MIN2(max_index, buffer_max_index); > + } > + else { > + /* Per-instance data. Simply make sure the state tracker didn't > + * request more instances than those that fit in the buffer */ > + assert((info->start_instance + > info->instance_count)/element->instance_divisor > + <= (buffer_max_index + 1)); > + } > + } > + } > + > + return max_index; > +} > diff --git a/src/gallium/auxiliary/util/u_draw.h > b/src/gallium/auxiliary/util/u_draw.h > index f06d09e..fdb683c 100644 > --- a/src/gallium/auxiliary/util/u_draw.h > +++ b/src/gallium/auxiliary/util/u_draw.h > @@ -34,6 +34,11 @@ > #include "pipe/p_state.h" > > > +#ifdef __cplusplus > +extern "C" { > +#endif > + > + > static INLINE void > util_draw_init_info(struct pipe_draw_info *info) > { > @@ -136,4 +141,18 @@ util_draw_range_elements(struct pipe_context *pipe, > pipe->draw_vbo(pipe, &info); > } > > + > +unsigned > +util_draw_max_index( > + const struct pipe_vertex_buffer *vertex_buffers, > + unsigned nr_vertex_buffers, > + const struct pipe_vertex_element *vertex_elements, > + unsigned nr_vertex_elements, > + const struct pipe_draw_info *info); > + > + > +#ifdef __cplusplus > +} > #endif > + > +#endif /* !U_DRAW_H */ _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev