[Mesa-dev] [PATCH 2/2] vbo: implement primitive merging for glBegin/End sequences

Jose Fonseca jfonseca at vmware.com
Fri May 3 10:52:26 PDT 2013


Series looks alright AFAICT.
Jose

----- Original Message -----
> A surprising number of apps and benchmarks have poor code like this:
> 
> glBegin(GL_LINE_STRIP);
> glVertex(v1);
> glVertex(v2);
> glEnd();
> // Possibly some no-op state changes here
> glBegin(GL_LINE_STRIP);
> glVertex(v3);
> glVertex(v4);
> glEnd();
> // repeat many, many times.
> 
> The above sequence can be converted into:
> 
> glBegin(GL_LINES);
> glVertex(v1);
> glVertex(v2);
> glVertex(v3);
> glVertex(v4);
> glEnd();
> 
> Similarly for GL_POINTS, GL_TRIANGLES, etc.
> 
> Merging was already implemented for GL_QUADS in the display list code.
> Now other prim types are handled and it's also done for immediate mode.
> 
> In one case:
>                                  before   after
> -----------------------------------------------
> number of st_draw_vbo() calls:     141      45
> number of _mesa_prims issued:     7520     632
> ---
>  src/mesa/vbo/vbo_exec_api.c |   30 ++++++++++++++++++++++++++++++
>  src/mesa/vbo/vbo_save_api.c |   18 ++++++++----------
>  2 files changed, 38 insertions(+), 10 deletions(-)
> 
> diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
> index 88cce98..600398c 100644
> --- a/src/mesa/vbo/vbo_exec_api.c
> +++ b/src/mesa/vbo/vbo_exec_api.c
> @@ -719,6 +719,34 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
>  
>  
>  /**
> + * Try to merge / concatenate the two most recent VBO primitives.
> + */
> +static void
> +try_vbo_merge(struct vbo_exec_context *exec)
> +{
> +   struct _mesa_prim *cur =  &exec->vtx.prim[exec->vtx.prim_count - 1];
> +
> +   assert(exec->vtx.prim_count >= 1);
> +
> +   vbo_try_prim_conversion(cur);
> +
> +   if (exec->vtx.prim_count >= 2) {
> +      struct _mesa_prim *prev = &exec->vtx.prim[exec->vtx.prim_count - 2];
> +      assert(prev == cur - 1);
> +
> +      if (vbo_can_merge_prims(prev, cur)) {
> +         assert(cur->begin);
> +         assert(cur->end);
> +         assert(prev->begin);
> +         assert(prev->end);
> +         vbo_merge_prims(prev, cur);
> +         exec->vtx.prim_count--;  /* drop the last primitive */
> +      }
> +   }
> +}
> +
> +
> +/**
>   * Called via glEnd.
>   */
>  static void GLAPIENTRY vbo_exec_End( void )
> @@ -744,6 +772,8 @@ static void GLAPIENTRY vbo_exec_End( void )
>  
>        exec->vtx.prim[i].end = 1;
>        exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
> +
> +      try_vbo_merge(exec);
>     }
>  
>     ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
> diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
> index b8dd90c..9ce3c6e 100644
> --- a/src/mesa/vbo/vbo_save_api.c
> +++ b/src/mesa/vbo/vbo_save_api.c
> @@ -305,9 +305,9 @@ _save_reset_counters(struct gl_context *ctx)
>   * previous prim.
>   */
>  static void
> -vbo_merge_prims(struct gl_context *ctx,
> -                struct _mesa_prim *prim_list,
> -                GLuint *prim_count)
> +merge_prims(struct gl_context *ctx,
> +            struct _mesa_prim *prim_list,
> +            GLuint *prim_count)
>  {
>     GLuint i;
>     struct _mesa_prim *prev_prim = prim_list;
> @@ -315,10 +315,9 @@ vbo_merge_prims(struct gl_context *ctx,
>     for (i = 1; i < *prim_count; i++) {
>        struct _mesa_prim *this_prim = prim_list + i;
>  
> -      if (this_prim->mode == prev_prim->mode &&
> -          this_prim->mode == GL_QUADS &&
> -          this_prim->count % 4 == 0 &&
> -          prev_prim->count % 4 == 0 &&
> +      vbo_try_prim_conversion(this_prim);
> +
> +      if (vbo_can_merge_prims(prev_prim, this_prim) &&
>            this_prim->start == prev_prim->start + prev_prim->count &&
>            this_prim->basevertex == prev_prim->basevertex &&
>            this_prim->num_instances == prev_prim->num_instances &&
> @@ -326,8 +325,7 @@ vbo_merge_prims(struct gl_context *ctx,
>           /* We've found a prim that just extend the previous one.  Tack it
>            * onto the previous one, and let this primitive struct get
>            dropped.
>            */
> -         prev_prim->count += this_prim->count;
> -         prev_prim->end = this_prim->end;
> +         vbo_merge_prims(prev_prim, this_prim);
>           continue;
>        }
>  
> @@ -420,7 +418,7 @@ _save_compile_vertex_list(struct gl_context *ctx)
>      */
>     save->copied.nr = _save_copy_vertices(ctx, node, save->buffer);
>  
> -   vbo_merge_prims(ctx, node->prim, &node->prim_count);
> +   merge_prims(ctx, node->prim, &node->prim_count);
>  
>     /* Deal with GL_COMPILE_AND_EXECUTE:
>      */
> --
> 1.7.3.4
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
> 


More information about the mesa-dev mailing list