[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