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 );
>>  }

Attachment: 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

Reply via email to