Keith Whitwell <[email protected]> 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 [email protected] https://lists.sourceforge.net/lists/listinfo/mesa3d-dev
