[Mesa-dev] [PATCH 1/3] vbo: implement uploading of current attribs
Brian Paul
brianp at vmware.com
Mon Oct 29 08:35:19 PDT 2012
On 10/28/2012 09:18 PM, Marek Olšák wrote:
> 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);
Just to be safe, maybe check for ptr != NULL here. I've seen buffer
maps fail in extreme circumstances.
> + 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];
For the series: Reviewed-by: Brian Paul <brianp at vmware.com>
More information about the mesa-dev
mailing list