[Mesa-dev] [PATCH 1/3] vbo: implement uploading of current attribs

Marek Olšák maraeo at gmail.com
Sun Oct 28 20:18:22 PDT 2012


The driver chooses which attrib should be uploaded by calling
vbo_get_current_attrib_buffer.

The reason for this is we can track which current attribs are dirty and skip
uploading accordingly. Before, we had to upload the attribs every draw call,
which wasn't very effective.

Stats for a whole run of the Nexuiz demo2 benchmark:
  Without the following st/mesa patch:
  - 21099 zero-stride vertices uploaded in u_vbuf.
  With the st/mesa patch:
  - 2474 zero-stride vertices uploaded in vbo.
---
 src/mesa/vbo/vbo.h           |    6 ++++
 src/mesa/vbo/vbo_context.c   |   69 ++++++++++++++++++++++++++++++++++++++++++
 src/mesa/vbo/vbo_context.h   |   15 +++++++++
 src/mesa/vbo/vbo_exec_api.c  |    1 +
 src/mesa/vbo/vbo_save_draw.c |    1 +
 5 files changed, 92 insertions(+)

diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index e058497..214ff60 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -164,6 +164,12 @@ vbo_sw_primitive_restart(struct gl_context *ctx,
                          GLuint nr_prims,
                          const struct _mesa_index_buffer *ib);
 
+void
+vbo_get_current_attrib_buffer(struct gl_context *ctx,
+                              GLuint vert_attrib,
+                              struct gl_buffer_object **buffer,
+                              GLuint *offset);
+
 void GLAPIENTRY
 _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
 
diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c
index fd15fb6..7868f61 100644
--- a/src/mesa/vbo/vbo_context.c
+++ b/src/mesa/vbo/vbo_context.c
@@ -218,6 +218,7 @@ void _vbo_DestroyContext( struct gl_context *ctx )
 
       for (i = 0; i < VBO_ATTRIB_MAX; i++) {
          _mesa_reference_buffer_object(ctx, &vbo->currval[i].BufferObj, NULL);
+         _mesa_reference_buffer_object(ctx, &vbo->uploaded_attrib[i].buffer, NULL);
       }
 
       vbo_exec_destroy(ctx);
@@ -235,3 +236,71 @@ void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func)
    vbo->draw_prims = func;
 }
 
+
+/**
+ * Upload the current attrib and return the buffer where it's stored.
+ * The upload is skipped if it was uploaded before.
+ *
+ * \param ctx           context
+ * \param vert_attrib   one of VERT_ATTRIB_*
+ * \param buffer        returned buffer
+ * \param offset        returned offset into the buffer
+ */
+void
+vbo_get_current_attrib_buffer(struct gl_context *ctx,
+                              GLuint vert_attrib,
+                              struct gl_buffer_object **buffer,
+                              GLuint *offset)
+{
+   struct vbo_context *vbo = vbo_context(ctx);
+   struct vbo_uploaded_attrib *uploaded = &vbo->uploaded_attrib[vert_attrib];
+   GLbitfield64 vert_attrib_bit = BITFIELD64_BIT(vert_attrib);
+
+   ASSERT(vert_attrib < VERT_ATTRIB_MAX);
+   ASSERT((GLfloat*)vbo->currval[vert_attrib].Ptr ==
+          &ctx->Current.Attrib[vert_attrib][0]);
+
+   if ((vbo->current_attrib_dirty & vert_attrib_bit) ||
+       !uploaded->buffer) {
+      GLuint size = vbo->currval[vert_attrib]._ElementSize;
+      GLfloat *attrib = ctx->Current.Attrib[vert_attrib];
+      void *ptr;
+
+      ASSERT(size);
+
+      /* Get a new upload buffer if needed. */
+      if (!vbo->upload_buffer ||
+          vbo->upload_offset + size > vbo->upload_buffer->Size) {
+         _mesa_reference_buffer_object(ctx, &vbo->upload_buffer, NULL);
+         vbo->upload_buffer = ctx->Driver.NewBufferObject(ctx, 0xcafe0400,
+                                                          GL_ARRAY_BUFFER);
+
+         if (!ctx->Driver.BufferData(ctx, GL_ARRAY_BUFFER, 10 * 1024, NULL,
+                                     GL_STREAM_DRAW, vbo->upload_buffer)) {
+            _mesa_reference_buffer_object(ctx, &vbo->upload_buffer, NULL);
+            *buffer = NULL;
+            return;
+         }
+         vbo->upload_offset = 0;
+      }
+
+      /* Upload the attrib. */
+      ptr = ctx->Driver.MapBufferRange(ctx, vbo->upload_offset, size,
+                                       GL_MAP_WRITE_BIT |
+                                       GL_MAP_UNSYNCHRONIZED_BIT |
+                                       GL_MAP_INVALIDATE_RANGE_BIT,
+                                       vbo->upload_buffer);
+      memcpy(ptr, attrib, size);
+      ctx->Driver.UnmapBuffer(ctx, vbo->upload_buffer);
+
+      _mesa_reference_buffer_object(ctx, &uploaded->buffer,
+                                    vbo->upload_buffer);
+      uploaded->offset = vbo->upload_offset;
+
+      vbo->upload_offset += size;
+      vbo->current_attrib_dirty &= ~vert_attrib_bit;
+   }
+
+   *buffer = uploaded->buffer;
+   *offset = uploaded->offset;
+}
diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h
index c896f11..491b597 100644
--- a/src/mesa/vbo/vbo_context.h
+++ b/src/mesa/vbo/vbo_context.h
@@ -70,6 +70,11 @@ enum draw_method
 };
 
 
+struct vbo_uploaded_attrib {
+   struct gl_buffer_object *buffer;
+   GLuint offset;
+};
+
 struct vbo_context {
    struct gl_client_array currval[VBO_ATTRIB_MAX];
    
@@ -86,6 +91,16 @@ struct vbo_context {
    vbo_draw_func draw_prims;
 
    enum draw_method last_draw_method;
+
+   /* Uploaded current attribs. */
+   struct vbo_uploaded_attrib uploaded_attrib[VBO_ATTRIB_MAX];
+
+   /* Whether any data of currval[i].Ptr has been updated but not uploaded
+    * yet. */
+   GLbitfield64 current_attrib_dirty;
+
+   struct gl_buffer_object *upload_buffer;
+   GLuint upload_offset;
 };
 
 
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index 2ddb715..44b9475 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -181,6 +181,7 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
                ctx->NewState |= _NEW_LIGHT;
             
             ctx->NewState |= _NEW_CURRENT_ATTRIB;
+            vbo->current_attrib_dirty |= BITFIELD64_BIT(i);
          }
       }
    }
diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
index 09b8b8a..30c1d3c 100644
--- a/src/mesa/vbo/vbo_save_draw.c
+++ b/src/mesa/vbo/vbo_save_draw.c
@@ -95,6 +95,7 @@ _playback_copy_to_current(struct gl_context *ctx,
                ctx->NewState |= _NEW_LIGHT;
 
             ctx->NewState |= _NEW_CURRENT_ATTRIB;
+            vbo->current_attrib_dirty |= BITFIELD64_BIT(i);
          }
 
 	 data += node->attrsz[i];
-- 
1.7.9.5



More information about the mesa-dev mailing list