Keith Whitwell <kei...@vmware.com> writes: > Francisco, > > It seems like this adds code to split too-long indexed primitives, but > still doesn't address the issue of splitting too-large vertex buffers > referenced by indexed primitives, right?
Yeah, that's right, IMHO vbo_split_copy is the way to go for too large indexed vertex buffers, I'll make this clear on a second resend, after more complaints have piled up. > > IE. the generated, smaller index buffers will still be applied to the > same set of unsplit vertex buffers? > > If so, it might be worth mentioning the distinction in the code & commit > log. > > Keith > > > > On Tue, 2010-02-02 at 03:07 -0800, Francisco Jerez wrote: >> The in-place splitting code wasn't dealing with index buffers at all >> (and it was being called from vbo_split_prims for too big index >> buffers, causing some occasional corruption). >> >> Additionally, it wasn't taking into account primitives arrays with >> non-contiguous indices (e.g. given prim[0].start = 0 and prim[1].start >> = max_verts, it would happily call back the driver with (max_index - >> min_index) still greater than max_verts, causing infinite recursion). >> --- >> src/mesa/vbo/vbo_split_inplace.c | 109 >> ++++++++++++++++++++----------------- >> 1 files changed, 59 insertions(+), 50 deletions(-) >> >> diff --git a/src/mesa/vbo/vbo_split_inplace.c >> b/src/mesa/vbo/vbo_split_inplace.c >> index da84eaa..c76b509 100644 >> --- a/src/mesa/vbo/vbo_split_inplace.c >> +++ b/src/mesa/vbo/vbo_split_inplace.c >> @@ -30,6 +30,7 @@ >> #include "main/mtypes.h" >> #include "main/macros.h" >> #include "main/enums.h" >> +#include "main/image.h" >> #include "vbo_split.h" >> >> >> @@ -48,6 +49,7 @@ struct split_context { >> vbo_draw_func draw; >> >> const struct split_limits *limits; >> + GLuint limit; >> >> struct _mesa_prim dstprim[MAX_PRIM]; >> GLuint dstprim_nr; >> @@ -58,38 +60,37 @@ struct split_context { >> >> static void flush_vertex( struct split_context *split ) >> { >> - GLuint min_index, max_index; >> + struct _mesa_index_buffer ib; >> GLuint i; >> >> if (!split->dstprim_nr) >> return; >> >> - min_index = split->dstprim[0].start; >> - max_index = min_index + split->dstprim[0].count - 1; >> + if (split->ib) { >> + ib = *split->ib; >> >> - for (i = 1; i < split->dstprim_nr; i++) { >> - GLuint tmp_min = split->dstprim[i].start; >> - GLuint tmp_max = tmp_min + split->dstprim[i].count - 1; >> + ib.count = split->max_index - split->min_index + 1; >> + ib.ptr += split->min_index * _mesa_sizeof_type(ib.type); >> >> - if (tmp_min < min_index) >> - min_index = tmp_min; >> - >> - if (tmp_max > max_index) >> - max_index = tmp_max; >> + /* Rebase the primitives to save index buffer entries. */ >> + for (i = 0; i < split->dstprim_nr; i++) >> + split->dstprim[i].start -= split->min_index; >> } >> >> - assert(max_index >= min_index); >> + assert(split->max_index >= split->min_index); >> >> - split->draw( split->ctx, >> - split->array, >> - split->dstprim, >> - split->dstprim_nr, >> - NULL, >> - GL_TRUE, >> - min_index, >> - max_index); >> + split->draw(split->ctx, >> + split->array, >> + split->dstprim, >> + split->dstprim_nr, >> + split->ib ? &ib : NULL, >> + !split->ib, >> + split->min_index, >> + split->max_index); >> >> split->dstprim_nr = 0; >> + split->min_index = ~0; >> + split->max_index = 0; >> } >> >> >> @@ -106,62 +107,67 @@ static struct _mesa_prim *next_outprim( struct >> split_context *split ) >> } >> } >> >> -static int align(int value, int alignment) >> +static void update_index_bounds(struct split_context *split, >> + const struct _mesa_prim *prim) >> { >> - return (value + alignment - 1) & ~(alignment - 1); >> + split->min_index = MIN2(split->min_index, prim->start); >> + split->max_index = MAX2(split->max_index, prim->start + prim->count - 1); >> } >> >> - >> +/* Return the maximum amount of vertices that can be emitted for a >> + * primitive starting at 'prim->start', depending on the previous >> + * index bounds. >> + */ >> +static GLuint get_max_vertices(struct split_context *split, >> + const struct _mesa_prim *prim) >> +{ >> + if ((prim->start > split->min_index && >> + prim->start - split->min_index >= split->limit) || >> + (prim->start < split->max_index && >> + split->max_index - prim->start >= split->limit)) >> + /* "prim" starts too far away from the old range. */ >> + return 0; >> + >> + return MIN2(split->min_index, prim->start) + split->limit - prim->start; >> +} >> >> /* Break large primitives into smaller ones. If not possible, convert >> * the primitive to indexed and pass to split_elts(). >> */ >> static void split_prims( struct split_context *split) >> { >> - GLuint csr = 0; >> GLuint i; >> >> for (i = 0; i < split->nr_prims; i++) { >> const struct _mesa_prim *prim = &split->prim[i]; >> GLuint first, incr; >> GLboolean split_inplace = split_prim_inplace(prim->mode, &first, >> &incr); >> - GLuint count; >> - >> - /* Always wrap on an even numbered vertex to avoid problems with >> - * triangle strips. >> - */ >> - GLuint available = align(split->limits->max_verts - csr - 1, 2); >> - assert(split->limits->max_verts >= csr); >> + GLuint available = get_max_vertices(split, prim); >> + GLuint count = prim->count - (prim->count - first) % incr; >> >> if (prim->count < first) >> continue; >> - >> - count = prim->count - (prim->count - first) % incr; >> >> - >> - if ((available < count && !split_inplace) || >> + if ((available < count && !split_inplace) || >> (available < first && split_inplace)) { >> flush_vertex(split); >> - csr = 0; >> - available = align(split->limits->max_verts - csr - 1, 2); >> + available = get_max_vertices(split, prim); >> } >> >> if (available >= count) { >> struct _mesa_prim *outprim = next_outprim(split); >> + >> *outprim = *prim; >> - csr += prim->count; >> - available = align(split->limits->max_verts - csr - 1, 2); >> - } >> + update_index_bounds(split, outprim); >> + } >> else if (split_inplace) { >> GLuint j, nr; >> >> - >> for (j = 0 ; j < count ; ) { >> GLuint remaining = count - j; >> struct _mesa_prim *outprim = next_outprim(split); >> >> nr = MIN2( available, remaining ); >> - >> nr -= (nr - first) % incr; >> >> outprim->mode = prim->mode; >> @@ -169,21 +175,20 @@ static void split_prims( struct split_context *split) >> outprim->end = (nr == remaining && prim->end); >> outprim->start = prim->start + j; >> outprim->count = nr; >> - >> + >> + update_index_bounds(split, outprim); >> + >> if (nr == remaining) { >> /* Finished. >> */ >> - j += nr; >> - csr += nr; >> - available = align(split->limits->max_verts - csr - 1, 2); >> + j += nr; >> } >> else { >> /* Wrapped the primitive: >> */ >> j += nr - (first - incr); >> flush_vertex(split); >> - csr = 0; >> - available = align(split->limits->max_verts - csr - 1, 2); >> + available = get_max_vertices(split, prim); >> } >> } >> } >> @@ -260,10 +265,14 @@ void vbo_split_inplace( GLcontext *ctx, >> split.prim = prim; >> split.nr_prims = nr_prims; >> split.ib = ib; >> - split.min_index = min_index; >> - split.max_index = max_index; >> + >> + /* Empty interval, makes calculations simpler. */ >> + split.min_index = ~0; >> + split.max_index = 0; >> + >> split.draw = draw; >> split.limits = limits; >> + split.limit = ib ? limits->max_indices : limits->max_verts; >> >> split_prims( &split ); >> }
pgpW6kaah2cyZ.pgp
Description: PGP signature
------------------------------------------------------------------------------ The Planet: dedicated and managed hosting, cloud storage, colocation Stay online with enterprise data centers and the best network in the business Choose flexible plans and management services without long-term contracts Personal 24x7 support from experience hosting pros just a phone call away. http://p.sf.net/sfu/theplanet-com
_______________________________________________ Mesa3d-dev mailing list Mesa3d-dev@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mesa3d-dev