[Mesa-dev] [PATCH 1/7] u_upload_mgr: new features

Brian Paul brianp at vmware.com
Mon Jan 3 07:43:35 PST 2011


Could you also add comments to all the u_upload_mgr.c functions?  In 
particular, what are the possible values for the usage/bind 
parameters?  A follow-on patch is fine.  I know that comments have 
been missing all along.

-Brian


On 12/29/2010 12:00 PM, Marek Olšák wrote:
> - Added a parameter to specify a minimum offset that should be returned.
>    r300g needs this to better implement user buffer uploads. This weird
>    requirement comes from the fact that the Radeon DRM doesn't support negative
>    offsets.
>
> - Added a parameter to notify a driver that the upload flush occured.
>    A driver may skip buffer validation if there was no flush, resulting
>    in a better performance.
>
> - Added a new upload function that returns a pointer to the upload buffer
>    directly, so that the buffer can be filled e.g. by the translate module.
> ---
>   src/gallium/auxiliary/util/u_upload_mgr.c     |   75 +++++++++++++++++--------
>   src/gallium/auxiliary/util/u_upload_mgr.h     |   43 +++++++++++++-
>   src/gallium/drivers/i965/brw_draw_upload.c    |   12 +++-
>   src/gallium/drivers/r300/r300_screen_buffer.c |   10 ++-
>   src/gallium/drivers/svga/svga_draw_elements.c |    5 +-
>   src/gallium/drivers/svga/svga_state_vdecl.c   |    6 +-
>   6 files changed, 115 insertions(+), 36 deletions(-)
>
> diff --git a/src/gallium/auxiliary/util/u_upload_mgr.c b/src/gallium/auxiliary/util/u_upload_mgr.c
> index 4d97bf0..80c9b63 100644
> --- a/src/gallium/auxiliary/util/u_upload_mgr.c
> +++ b/src/gallium/auxiliary/util/u_upload_mgr.c
> @@ -43,7 +43,7 @@ struct u_upload_mgr {
>
>      unsigned default_size;
>      unsigned alignment;
> -   unsigned usage;
> +   unsigned bind;
>
>      /* The active buffer:
>       */
> @@ -58,7 +58,7 @@ struct u_upload_mgr {
>   struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
>                                         unsigned default_size,
>                                         unsigned alignment,
> -                                      unsigned usage )
> +                                      unsigned bind )
>   {
>      struct u_upload_mgr *upload = CALLOC_STRUCT( u_upload_mgr );
>      if (!upload)
> @@ -67,7 +67,7 @@ struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
>      upload->pipe = pipe;
>      upload->default_size = default_size;
>      upload->alignment = alignment;
> -   upload->usage = usage;
> +   upload->bind = bind;
>      upload->buffer = NULL;
>
>      return upload;
> @@ -115,7 +115,7 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload,
>      size = align(MAX2(upload->default_size, min_size), 4096);
>
>      upload->buffer = pipe_buffer_create( upload->pipe->screen,
> -                                        upload->usage,
> +                                        upload->bind,
>                                           size );
>      if (upload->buffer == NULL)
>         goto fail;
> @@ -135,33 +135,61 @@ fail:
>      return PIPE_ERROR_OUT_OF_MEMORY;
>   }
>
> -
> -enum pipe_error u_upload_data( struct u_upload_mgr *upload,
> -                               unsigned size,
> -                               const void *data,
> -                               unsigned *out_offset,
> -                               struct pipe_resource **outbuf )
> +enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
> +                                unsigned min_out_offset,
> +                                unsigned size,
> +                                unsigned *out_offset,
> +                                struct pipe_resource **outbuf,
> +                                boolean *flushed,
> +                                void **ptr )
>   {
>      unsigned alloc_size = align( size, upload->alignment );
> -   enum pipe_error ret = PIPE_OK;
> +   unsigned alloc_offset = align(min_out_offset, upload->alignment);
> +   unsigned offset;
>
> -   if (upload->offset + alloc_size>  upload->size) {
> -      ret = u_upload_alloc_buffer( upload, alloc_size );
> +   if (MAX2(upload->offset, alloc_offset) + alloc_size>  upload->size) {
> +      enum pipe_error ret = u_upload_alloc_buffer(upload,
> +                                                  alloc_offset + alloc_size);
>         if (ret)
>            return ret;
> +
> +      *flushed = TRUE;
> +   } else {
> +      *flushed = FALSE;
>      }
>
> -   assert(upload->offset<  upload->buffer->width0);
> -   assert(upload->offset + size<= upload->buffer->width0);
> +   offset = MAX2(upload->offset, alloc_offset);
> +
> +   assert(offset<  upload->buffer->width0);
> +   assert(offset + size<= upload->buffer->width0);
>      assert(size);
>
> -   memcpy(upload->map + upload->offset, data, size);
> +   *ptr = upload->map + offset;
>
>      /* Emit the return values:
>       */
>      pipe_resource_reference( outbuf, upload->buffer );
> -   *out_offset = upload->offset;
> -   upload->offset += alloc_size;
> +   *out_offset = offset;
> +   upload->offset = offset + alloc_size;
> +   return PIPE_OK;
> +}
> +
> +enum pipe_error u_upload_data( struct u_upload_mgr *upload,
> +                               unsigned min_out_offset,
> +                               unsigned size,
> +                               const void *data,
> +                               unsigned *out_offset,
> +                               struct pipe_resource **outbuf,
> +                               boolean *flushed )
> +{
> +   uint8_t *ptr;
> +   enum pipe_error ret = u_upload_alloc(upload, min_out_offset, size,
> +                                        out_offset, outbuf, flushed,
> +                                        (void**)&ptr);
> +   if (ret)
> +      return ret;
> +
> +   memcpy(ptr, data, size);
>      return PIPE_OK;
>   }
>
> @@ -172,11 +200,13 @@ enum pipe_error u_upload_data( struct u_upload_mgr *upload,
>    * renders or DrawElements calls.
>    */
>   enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
> +                                 unsigned min_out_offset,
>                                    unsigned offset,
>                                    unsigned size,
>                                    struct pipe_resource *inbuf,
>                                    unsigned *out_offset,
> -                                 struct pipe_resource **outbuf )
> +                                 struct pipe_resource **outbuf,
> +                                 boolean *flushed )
>   {
>      enum pipe_error ret = PIPE_OK;
>      struct pipe_transfer *transfer = NULL;
> @@ -195,13 +225,12 @@ enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
>      if (0)
>         debug_printf("upload ptr %p ofs %d sz %d\n", map, offset, size);
>
> -   ret = u_upload_data( upload,
> +   ret = u_upload_data( upload,
> +                        min_out_offset,
>                           size,
>                           map + offset,
>                           out_offset,
> -                        outbuf );
> -   if (ret)
> -      goto done;
> +                        outbuf, flushed );
>
>   done:
>      if (map)
> diff --git a/src/gallium/auxiliary/util/u_upload_mgr.h b/src/gallium/auxiliary/util/u_upload_mgr.h
> index de016df..fc8f4d3 100644
> --- a/src/gallium/auxiliary/util/u_upload_mgr.h
> +++ b/src/gallium/auxiliary/util/u_upload_mgr.h
> @@ -32,6 +32,8 @@
>   #ifndef U_UPLOAD_MGR_H
>   #define U_UPLOAD_MGR_H
>
> +#include "pipe/p_compiler.h"
> +
>   struct pipe_context;
>   struct pipe_resource;
>
> @@ -39,7 +41,7 @@ struct pipe_resource;
>   struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
>                                         unsigned default_size,
>                                         unsigned alignment,
> -                                      unsigned usage );
> +                                      unsigned bind );
>
>   void u_upload_destroy( struct u_upload_mgr *upload );
>
> @@ -53,20 +55,55 @@ void u_upload_destroy( struct u_upload_mgr *upload );
>    */
>   void u_upload_flush( struct u_upload_mgr *upload );
>
> +/**
> + * Sub-allocate new memory from the upload buffer.
> + *
> + * \param upload           Upload manager
> + * \param min_out_offset   Minimum offset that should be returned in out_offset.
> + * \param size             Size of the allocation.
> + * \param out_offset       Pointer to where the new buffer offset will be returned.
> + * \param outbuf           Pointer to where the upload buffer will be returned.
> + * \param flushed          Whether the upload buffer was flushed.
> + * \param ptr              Pointer to the allocated memory that is returned.
> + */
> +enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
> +                                unsigned min_out_offset,
> +                                unsigned size,
> +                                unsigned *out_offset,
> +                                struct pipe_resource **outbuf,
> +                                boolean *flushed,
> +                                void **ptr );
> +
>
> +/**
> + * Allocate and write data to the upload buffer.
> + *
> + * Same as u_upload_alloc, but in addition to that, it copies "data"
> + * to the pointer returned from u_upload_alloc.
> + */
>   enum pipe_error u_upload_data( struct u_upload_mgr *upload,
> +                               unsigned min_out_offset,
>                                  unsigned size,
>                                  const void *data,
>                                  unsigned *out_offset,
> -                               struct pipe_resource **outbuf );
> +                               struct pipe_resource **outbuf,
> +                               boolean *flushed );
>
>
> +/**
> + * Allocate and copy an input buffer to the upload buffer.
> + *
> + * Same as u_upload_data, except that the input data comes from a buffer
> + * instead of a user pointer.
> + */
>   enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
> +                                 unsigned min_out_offset,
>                                    unsigned offset,
>                                    unsigned size,
>                                    struct pipe_resource *inbuf,
>                                    unsigned *out_offset,
> -                                 struct pipe_resource **outbuf );
> +                                 struct pipe_resource **outbuf,
> +                                 boolean *flushed );
>
>
>
> diff --git a/src/gallium/drivers/i965/brw_draw_upload.c b/src/gallium/drivers/i965/brw_draw_upload.c
> index ebeb1e1..cf94054 100644
> --- a/src/gallium/drivers/i965/brw_draw_upload.c
> +++ b/src/gallium/drivers/i965/brw_draw_upload.c
> @@ -89,13 +89,16 @@ static int brw_prepare_vertices(struct brw_context *brw)
>                            vb->buffer->width0 - vb->buffer_offset :
>                            MAX2(vb->buffer->width0 - vb->buffer_offset,
>                                 vb->stride * (max_index + 1 - min_index)));
> +        boolean flushed;
>
> -        ret = u_upload_buffer( brw->vb.upload_vertex,
> +        ret = u_upload_buffer( brw->vb.upload_vertex,
> +                               0,
>                                  vb->buffer_offset + min_index * vb->stride,
>                                  size,
>                                  vb->buffer,
>                                  &offset,
> -&upload_buf );
> +&upload_buf,
> +&flushed );
>           if (ret)
>              return ret;
>
> @@ -251,13 +254,16 @@ static int brw_prepare_indices(struct brw_context *brw)
>      /* Turn userbuffer into a proper hardware buffer?
>       */
>      if (brw_buffer_is_user_buffer(index_buffer)) {
> +      boolean flushed;
>
>         ret = u_upload_buffer( brw->vb.upload_index,
> +                             0,
>                               index_offset,
>                               ib_size,
>                               index_buffer,
>                               &offset,
> -&upload_buf );
> +&upload_buf,
> +&flushed );
>         if (ret)
>           return ret;
>
> diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c
> index f969981..11ad87e 100644
> --- a/src/gallium/drivers/r300/r300_screen_buffer.c
> +++ b/src/gallium/drivers/r300/r300_screen_buffer.c
> @@ -62,15 +62,16 @@ void r300_upload_index_buffer(struct r300_context *r300,
>                                unsigned count)
>   {
>       unsigned index_offset;
> +    boolean flushed;
>       uint8_t *ptr = r300_buffer(*index_buffer)->user_buffer;
>
>       *index_buffer = NULL;
>
>       u_upload_data(r300->upload_ib,
> -                  count * index_size,
> +                  0, count * index_size,
>                     ptr + (*start * index_size),
>                     &index_offset,
> -                  index_buffer);
> +                  index_buffer,&flushed);
>
>       *start = index_offset / index_size;
>   }
> @@ -78,6 +79,7 @@ void r300_upload_index_buffer(struct r300_context *r300,
>   void r300_upload_user_buffers(struct r300_context *r300)
>   {
>       int i, nr = r300->velems->count;
> +    boolean flushed;
>
>       for (i = 0; i<  nr; i++) {
>           struct pipe_vertex_buffer *vb =
> @@ -85,9 +87,9 @@ void r300_upload_user_buffers(struct r300_context *r300)
>
>           if (r300_buffer_is_user_buffer(vb->buffer)) {
>               u_upload_data(r300->upload_vb,
> -                          vb->buffer->width0,
> +                          0, vb->buffer->width0,
>                             r300_buffer(vb->buffer)->user_buffer,
> -&vb->buffer_offset,&vb->buffer);
> +&vb->buffer_offset,&vb->buffer,&flushed);
>
>               r300->validate_buffers = TRUE;
>               r300->vertex_arrays_dirty = TRUE;
> diff --git a/src/gallium/drivers/svga/svga_draw_elements.c b/src/gallium/drivers/svga/svga_draw_elements.c
> index c7ea014..83527c6 100644
> --- a/src/gallium/drivers/svga/svga_draw_elements.c
> +++ b/src/gallium/drivers/svga/svga_draw_elements.c
> @@ -120,14 +120,17 @@ svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
>      if (index_buffer&&
>          svga_buffer_is_user_buffer(index_buffer))
>      {
> +      boolean flushed;
>         assert( index_buffer->width0>= index_offset + count * index_size );
>
>         ret = u_upload_buffer( hwtnl->upload_ib,
> +                             0,
>                                index_offset,
>                                count * index_size,
>                                index_buffer,
>                                &index_offset,
> -&upload_buffer );
> +&upload_buffer,
> +&flushed );
>         if (ret)
>            goto done;
>
> diff --git a/src/gallium/drivers/svga/svga_state_vdecl.c b/src/gallium/drivers/svga/svga_state_vdecl.c
> index 3af7bf2..958d003 100644
> --- a/src/gallium/drivers/svga/svga_state_vdecl.c
> +++ b/src/gallium/drivers/svga/svga_state_vdecl.c
> @@ -57,12 +57,14 @@ upload_user_buffers( struct svga_context *svga )
>            struct svga_buffer *buffer = svga_buffer(svga->curr.vb[i].buffer);
>
>            if (!buffer->uploaded.buffer) {
> +            boolean flushed;
>               ret = u_upload_buffer( svga->upload_vb,
> -                                   0,
> +                                   0, 0,
>                                      buffer->b.b.width0,
>                                      &buffer->b.b,
>                                      &buffer->uploaded.offset,
> -&buffer->uploaded.buffer );
> +&buffer->uploaded.buffer,
> +&flushed);
>               if (ret)
>                  return ret;
>
> --
> 1.7.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
> .
>



More information about the mesa-dev mailing list