[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