From c4d1f4607abf3dfbcfcffc5c67bb89d420d3381a Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Tue, 3 Mar 2009 10:46:12 +0000 Subject: [PATCH] vbo: use MapBufferRange where available Previously would have to allocate a new VBO after firing a draw command as subsequent call to Map() on old VBO might block if the driver had submitted the commands to hardware. --- src/mesa/vbo/vbo_exec.h | 13 ++-- src/mesa/vbo/vbo_exec_api.c | 62 ++++++++++-------- src/mesa/vbo/vbo_exec_draw.c | 118 ++++++++++++++++++++++++++++++----- src/mesa/vbo/vbo_save.h | 2 +- src/mesa/vbo/vbo_save_api.c | 16 ++--- 5 files changed, 154 insertions(+), 57 deletions(-) diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h index 3ce36657bd4..100bb8a5dec 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -43,7 +43,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* Wierd implementation stuff: */ -#define VBO_VERT_BUFFER_SIZE (1024*16) /* dwords == 64k */ +#define VBO_VERT_BUFFER_SIZE (1024*64) /* bytes */ #define VBO_MAX_ATTR_CODEGEN 16 #define ERROR_ATTRIB 16 @@ -78,14 +78,15 @@ struct vbo_exec_context struct { struct gl_buffer_object *bufferobj; - GLubyte *buffer_map; - GLuint vertex_size; + GLuint vertex_size; /* in dwords */ struct _mesa_prim prim[VBO_MAX_PRIM]; GLuint prim_count; - GLfloat *vbptr; /* cursor, points into buffer */ + GLfloat *buffer_map; + GLfloat *buffer_ptr; /* cursor, points into buffer */ + GLuint buffer_used; /* in bytes */ GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current vertex */ GLuint vert_count; @@ -140,6 +141,7 @@ struct vbo_exec_context void vbo_exec_init( GLcontext *ctx ); void vbo_exec_destroy( GLcontext *ctx ); void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state ); +void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap ); void vbo_exec_BeginVertices( GLcontext *ctx ); void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ); @@ -153,7 +155,8 @@ void vbo_exec_array_destroy( struct vbo_exec_context *exec ); void vbo_exec_vtx_init( struct vbo_exec_context *exec ); void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ); -void vbo_exec_vtx_flush( struct vbo_exec_context *exec ); +void vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap ); +void vbo_exec_vtx_map( struct vbo_exec_context *exec ); void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ); void vbo_exec_eval_update( struct vbo_exec_context *exec ); diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index 093e3d21678..4c8d0c25a49 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -62,7 +62,7 @@ static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec ) if (exec->vtx.prim_count == 0) { exec->vtx.copied.nr = 0; exec->vtx.vert_count = 0; - exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; + exec->vtx.buffer_ptr = exec->vtx.buffer_map; } else { GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin; @@ -80,7 +80,7 @@ static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec ) /* Execute the buffer and save copied vertices. */ if (exec->vtx.vert_count) - vbo_exec_vtx_flush( exec ); + vbo_exec_vtx_flush( exec, GL_FALSE ); else { exec->vtx.prim_count = 0; exec->vtx.copied.nr = 0; @@ -121,9 +121,9 @@ void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ) assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { - _mesa_memcpy( exec->vtx.vbptr, data, + _mesa_memcpy( exec->vtx.buffer_ptr, data, exec->vtx.vertex_size * sizeof(GLfloat)); - exec->vtx.vbptr += exec->vtx.vertex_size; + exec->vtx.buffer_ptr += exec->vtx.vertex_size; data += exec->vtx.vertex_size; exec->vtx.vert_count++; } @@ -252,9 +252,10 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, exec->vtx.attrsz[attr] = newsz; exec->vtx.vertex_size += newsz - oldsz; - exec->vtx.max_vert = VBO_VERT_BUFFER_SIZE / exec->vtx.vertex_size; + exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / + (exec->vtx.vertex_size * sizeof(GLfloat))); exec->vtx.vert_count = 0; - exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; + exec->vtx.buffer_ptr = exec->vtx.buffer_map; /* Recalculate all the attrptr[] values @@ -280,10 +281,10 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, if (exec->vtx.copied.nr) { GLfloat *data = exec->vtx.copied.buffer; - GLfloat *dest = exec->vtx.vbptr; + GLfloat *dest = exec->vtx.buffer_ptr; GLuint j; - assert(exec->vtx.vbptr == (GLfloat *)exec->vtx.buffer_map); + assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { @@ -309,7 +310,7 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, } } - exec->vtx.vbptr = dest; + exec->vtx.buffer_ptr = dest; exec->vtx.vert_count += exec->vtx.copied.nr; exec->vtx.copied.nr = 0; } @@ -374,9 +375,9 @@ do { \ GLuint i; \ \ for (i = 0; i < exec->vtx.vertex_size; i++) \ - exec->vtx.vbptr[i] = exec->vtx.vertex[i]; \ + exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \ \ - exec->vtx.vbptr += exec->vtx.vertex_size; \ + exec->vtx.buffer_ptr += exec->vtx.vertex_size; \ exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ \ if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ @@ -533,7 +534,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) * begin/end pairs. */ if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) - vbo_exec_FlushVertices( ctx, ~0 ); + vbo_exec_FlushVertices_internal( ctx, GL_FALSE ); i = exec->vtx.prim_count++; exec->vtx.prim[i].mode = mode; @@ -567,7 +568,7 @@ static void GLAPIENTRY vbo_exec_End( void ) ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; if (exec->vtx.prim_count == VBO_MAX_PRIM) - vbo_exec_vtx_flush( exec ); + vbo_exec_vtx_flush( exec, GL_FALSE ); } else _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); @@ -673,23 +674,19 @@ void vbo_use_buffer_objects(GLcontext *ctx) */ GLuint bufName = 0xaabbccdd; GLenum target = GL_ARRAY_BUFFER_ARB; - GLenum access = GL_READ_WRITE_ARB; GLenum usage = GL_STREAM_DRAW_ARB; - GLsizei size = VBO_VERT_BUFFER_SIZE * sizeof(GLfloat); + GLsizei size = VBO_VERT_BUFFER_SIZE; /* Make sure this func is only used once */ assert(exec->vtx.bufferobj == ctx->Array.NullBufferObj); if (exec->vtx.buffer_map) { _mesa_align_free(exec->vtx.buffer_map); + exec->vtx.buffer_map = NULL; } /* Allocate a real buffer object now */ exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target); ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj); - - /* and map it */ - exec->vtx.buffer_map - = ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj); } @@ -708,7 +705,7 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec ) &exec->vtx.bufferobj, ctx->Array.NullBufferObj); - exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64); + exec->vtx.buffer_map = (GLfloat *)ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE, 64); vbo_exec_vtxfmt_init( exec ); @@ -755,21 +752,34 @@ void vbo_exec_BeginVertices( GLcontext *ctx ) // vbo_exec_vtx_map( exec ); } -void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ) +void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap ) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) - return; - - if (exec->vtx.vert_count) { - vbo_exec_vtx_flush( exec ); + if (exec->vtx.vert_count || unmap) { + vbo_exec_vtx_flush( exec, unmap ); } if (exec->vtx.vertex_size) { vbo_exec_copy_to_current( exec ); reset_attrfv( exec ); } +} + + + +void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + if (0) _mesa_printf("%s\n", __FUNCTION__); + + if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { + if (0) _mesa_printf("%s - inside begin/end\n", __FUNCTION__); + return; + } + + vbo_exec_FlushVertices_internal( ctx, GL_TRUE ); /* Need to do this to ensure BeginVertices gets called again: */ diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index ae43857c8ae..a89f1506544 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -70,7 +70,7 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec ) GLuint ovf, i; GLuint sz = exec->vtx.vertex_size; GLfloat *dst = exec->vtx.copied.buffer; - GLfloat *src = ((GLfloat *)exec->vtx.buffer_map + + GLfloat *src = (exec->vtx.buffer_map + exec->vtx.prim[exec->vtx.prim_count-1].start * exec->vtx.vertex_size); @@ -147,7 +147,7 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) struct vbo_exec_context *exec = &vbo->exec; struct gl_client_array *arrays = exec->vtx.arrays; GLuint count = exec->vtx.vert_count; - GLubyte *data = exec->vtx.buffer_map; + GLubyte *data = (GLubyte *)exec->vtx.buffer_map; const GLuint *map; GLuint attr; GLbitfield varying_inputs = 0x0; @@ -220,10 +220,78 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) } +static void vbo_exec_vtx_unmap( struct vbo_exec_context *exec ) +{ + GLenum target = GL_ARRAY_BUFFER_ARB; + + if (exec->vtx.bufferobj->Name) { + GLcontext *ctx = exec->ctx; + + exec->vtx.buffer_used += (exec->vtx.buffer_ptr - + exec->vtx.buffer_map) * sizeof(float); + + ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj); + exec->vtx.buffer_map = NULL; + exec->vtx.buffer_ptr = NULL; + exec->vtx.max_vert = 0; + } +} + +void vbo_exec_vtx_map( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + GLenum target = GL_ARRAY_BUFFER_ARB; + GLenum access = GL_READ_WRITE_ARB; + GLenum usage = GL_STREAM_DRAW_ARB; + + if (exec->vtx.bufferobj->Name == 0) + return; + + if (exec->vtx.buffer_map != NULL) { + assert(0); + exec->vtx.buffer_map = NULL; + } + + if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024 && + ctx->Driver.MapBufferRange) + { + exec->vtx.buffer_map = + (GLfloat *)ctx->Driver.MapBufferRange(ctx, + target, + exec->vtx.buffer_used, + (VBO_VERT_BUFFER_SIZE - + exec->vtx.buffer_used), + (GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_UNSYNCHRONIZED_BIT | + MESA_MAP_NOWAIT_BIT), + exec->vtx.bufferobj); + } + + if (exec->vtx.buffer_map) { + exec->vtx.buffer_map += exec->vtx.buffer_used / sizeof(float); + } + else { + exec->vtx.buffer_used = 0; + + ctx->Driver.BufferData(ctx, target, + VBO_VERT_BUFFER_SIZE, + NULL, usage, exec->vtx.bufferobj); + + exec->vtx.buffer_map = + (GLfloat *)ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj); + } + + if (0) _mesa_printf("map %d..\n", exec->vtx.buffer_used); +} + + + /** * Execute the buffer and save copied verts. */ -void vbo_exec_vtx_flush( struct vbo_exec_context *exec ) +void vbo_exec_vtx_flush( struct vbo_exec_context *exec, + GLboolean unmap ) { if (0) vbo_exec_debug_verts( exec ); @@ -236,13 +304,9 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec ) if (exec->vtx.copied.nr != exec->vtx.vert_count) { GLcontext *ctx = exec->ctx; - - GLenum target = GL_ARRAY_BUFFER_ARB; - GLenum access = GL_READ_WRITE_ARB; - GLenum usage = GL_STREAM_DRAW_ARB; - GLsizei size = VBO_VERT_BUFFER_SIZE * sizeof(GLfloat); - /* Before the unmap (why?) + /* Before the update_state() as this may raise _NEW_ARRAY + * from _mesa_set_varying_vp_inputs(). */ vbo_exec_bind_arrays( ctx ); @@ -250,8 +314,12 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec ) _mesa_update_state( ctx ); - ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj); - exec->vtx.buffer_map = NULL; + if (exec->vtx.bufferobj->Name) { + vbo_exec_vtx_unmap( exec ); + } + + if (0) _mesa_printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count, + exec->vtx.vert_count); vbo_context(ctx)->draw_prims( ctx, exec->vtx.inputs, @@ -261,15 +329,31 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec ) 0, exec->vtx.vert_count - 1); - /* Get new data: - */ - ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj); - exec->vtx.buffer_map - = ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj); + /* If using a real VBO, get new storage -- unless asked not to. + */ + if (exec->vtx.bufferobj->Name && !unmap) { + vbo_exec_vtx_map( exec ); + } } } + /* May have to unmap explicitly if we didn't draw: + */ + if (unmap && + exec->vtx.bufferobj->Name && + exec->vtx.buffer_map) { + vbo_exec_vtx_unmap( exec ); + } + + + if (unmap) + exec->vtx.max_vert = 0; + else + exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / + (exec->vtx.vertex_size * sizeof(GLfloat))); + + + exec->vtx.buffer_ptr = exec->vtx.buffer_map; exec->vtx.prim_count = 0; exec->vtx.vert_count = 0; - exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; } diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h index b7e9baabf81..de8fa193046 100644 --- a/src/mesa/vbo/vbo_save.h +++ b/src/mesa/vbo/vbo_save.h @@ -130,7 +130,7 @@ struct vbo_save_context { struct vbo_save_vertex_store *vertex_store; struct vbo_save_primitive_store *prim_store; - GLfloat *vbptr; /* cursor, points into buffer */ + GLfloat *buffer_ptr; /* cursor, points into buffer */ GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current values */ GLfloat *attrptr[VBO_ATTRIB_MAX]; GLuint vert_count; diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index f69a33d8176..9326f7e2289 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -241,7 +241,7 @@ static void _save_reset_counters( GLcontext *ctx ) save->buffer = (save->vertex_store->buffer + save->vertex_store->used); - assert(save->buffer == save->vbptr); + assert(save->buffer == save->buffer_ptr); if (save->vertex_size) save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / @@ -343,7 +343,7 @@ static void _save_compile_vertex_list( GLcontext *ctx ) /* Allocate and map new store: */ save->vertex_store = alloc_vertex_store( ctx ); - save->vbptr = map_vertex_store( ctx, save->vertex_store ); + save->buffer_ptr = map_vertex_store( ctx, save->vertex_store ); } if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) { @@ -414,9 +414,9 @@ static void _save_wrap_filled_vertex( GLcontext *ctx ) assert(save->max_vert - save->vert_count > save->copied.nr); for (i = 0 ; i < save->copied.nr ; i++) { - _mesa_memcpy( save->vbptr, data, save->vertex_size * sizeof(GLfloat)); + _mesa_memcpy( save->buffer_ptr, data, save->vertex_size * sizeof(GLfloat)); data += save->vertex_size; - save->vbptr += save->vertex_size; + save->buffer_ptr += save->vertex_size; save->vert_count++; } } @@ -550,7 +550,7 @@ static void _save_upgrade_vertex( GLcontext *ctx, } } - save->vbptr = dest; + save->buffer_ptr = dest; save->vert_count += save->copied.nr; } } @@ -622,9 +622,9 @@ do { \ GLuint i; \ \ for (i = 0; i < save->vertex_size; i++) \ - save->vbptr[i] = save->vertex[i]; \ + save->buffer_ptr[i] = save->vertex[i]; \ \ - save->vbptr += save->vertex_size; \ + save->buffer_ptr += save->vertex_size; \ \ if (++save->vert_count >= save->max_vert) \ _save_wrap_filled_vertex( ctx ); \ @@ -1035,7 +1035,7 @@ void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode ) if (!save->vertex_store) save->vertex_store = alloc_vertex_store( ctx ); - save->vbptr = map_vertex_store( ctx, save->vertex_store ); + save->buffer_ptr = map_vertex_store( ctx, save->vertex_store ); _save_reset_vertex( ctx ); _save_reset_counters( ctx ); -- 2.30.2