summaryrefslogtreecommitdiff
path: root/src/mesa/vbo
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2013-05-03 19:00:07 -0600
committerBrian Paul <brianp@vmware.com>2013-05-03 19:00:07 -0600
commit4ea05bcba66cb0d49cbad20158b41864a20a73b9 (patch)
treede6816913b5064297fbd591253f61aa2da4cf8c7 /src/mesa/vbo
parent3702d2508249bb264ab502c0093dbbc10b0b02fa (diff)
vbo: implement primitive merging for glBegin/End sequences
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 Reviewed-by: Eric Anholt <eric@anholt.net> Reviewed-by: José Fonseca <jfonseca@vmware.com>
Diffstat (limited to 'src/mesa/vbo')
-rw-r--r--src/mesa/vbo/vbo_exec_api.c30
-rw-r--r--src/mesa/vbo/vbo_save_api.c22
2 files changed, 38 insertions, 14 deletions
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index 88cce984f8d..600398c5891 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 b8dd90c67f1..04904e11969 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,19 +315,13 @@ 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 &&
- this_prim->start == prev_prim->start + prev_prim->count &&
- this_prim->basevertex == prev_prim->basevertex &&
- this_prim->num_instances == prev_prim->num_instances &&
- this_prim->base_instance == prev_prim->base_instance) {
+ vbo_try_prim_conversion(this_prim);
+
+ if (vbo_can_merge_prims(prev_prim, this_prim)) {
/* 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 +414,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:
*/