vbo: use MapBufferRange where available
authorKeith Whitwell <keithw@vmware.com>
Tue, 3 Mar 2009 10:46:12 +0000 (10:46 +0000)
committerKeith Whitwell <keithw@vmware.com>
Tue, 3 Mar 2009 10:46:12 +0000 (10:46 +0000)
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
src/mesa/vbo/vbo_exec_api.c
src/mesa/vbo/vbo_exec_draw.c
src/mesa/vbo/vbo_save.h
src/mesa/vbo/vbo_save_api.c

index 3ce3665..100bb8a 100644 (file)
@@ -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 );
index 093e3d2..4c8d0c2 100644 (file)
@@ -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:
     */
index ae43857..a89f150 100644 (file)
@@ -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;
 }
index b7e9baa..de8fa19 100644 (file)
@@ -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;
index f69a33d..9326f7e 100644 (file)
@@ -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 );