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?

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



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