diff options
-rw-r--r-- | src/mesa/vbo/vbo_save.h | 14 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_save_api.c | 14 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_save_draw.c | 12 |
3 files changed, 40 insertions, 0 deletions
diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h index 9d13e0aa18d..274d667be78 100644 --- a/src/mesa/vbo/vbo_save.h +++ b/src/mesa/vbo/vbo_save.h @@ -86,6 +86,20 @@ struct vbo_save_vertex_list { struct vbo_save_primitive_store *prim_store; }; + +/** + * Is the vertex lists's buffer offset an exact multiple of the + * vertex size (in bytes)? This is used to check for a vertex array / + * drawing optimization. + */ +static inline bool +aligned_vertex_buffer_offset(const struct vbo_save_vertex_list *node) +{ + unsigned vertex_size = node->vertex_size * sizeof(GLfloat); /* in bytes */ + return vertex_size != 0 && node->buffer_offset % vertex_size == 0; +} + + /* These buffers should be a reasonable size to support upload to * hardware. Current vbo implementation will re-upload on any * changes, so don't make too big or apps which dynamically create diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index 42d883fed4d..1c575448773 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -546,6 +546,20 @@ compile_vertex_list(struct gl_context *ctx) save->prim_store = alloc_prim_store(); } + /* + * If the vertex buffer offset is a multiple of the vertex size, + * we can use the _mesa_prim::start value to indicate where the + * vertices starts, instead of the buffer offset. Also see the + * bind_vertex_list() function. + */ + if (aligned_vertex_buffer_offset(node)) { + const unsigned start_offset = + node->buffer_offset / (node->vertex_size * sizeof(GLfloat)); + for (unsigned i = 0; i < save->prim_count; i++) { + save->prims[i].start += start_offset; + } + } + /* Reset our structures for the next run of vertices: */ reset_counters(ctx); diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 1694a04a3e1..b63a9a8b869 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -146,6 +146,18 @@ bind_vertex_list(struct gl_context *ctx, memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz)); memcpy(node_attrtype, node->attrtype, sizeof(node->attrtype)); + if (aligned_vertex_buffer_offset(node)) { + /* The vertex size is an exact multiple of the buffer offset. + * This means that we can use zero-based vertex attribute pointers + * and specify the start of the primitive with the _mesa_prim::start + * field. This results in issuing several draw calls with identical + * vertex attribute information. This can result in fewer state + * changes in drivers. In particular, the Gallium CSO module will + * filter out redundant vertex buffer changes. + */ + buffer_offset = 0; + } + /* Install the default (ie Current) attributes first, then overlay * all active ones. */ |