X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Futil%2Fu_upload_mgr.c;h=865dab864b39dac6bee238d848e5594d8a93c83e;hb=2a456dc123e8263de8e4666890a34f403faa9a39;hp=75d44432d9e7e9c1f23075df90bccf3e18ddac65;hpb=8f3bdeaad610d7d5a5c6e73e1e9c721219595754;p=mesa.git diff --git a/src/gallium/auxiliary/util/u_upload_mgr.c b/src/gallium/auxiliary/util/u_upload_mgr.c index 75d44432d9e..865dab864b3 100644 --- a/src/gallium/auxiliary/util/u_upload_mgr.c +++ b/src/gallium/auxiliary/util/u_upload_mgr.c @@ -41,76 +41,37 @@ struct u_upload_mgr { struct pipe_context *pipe; - unsigned default_size; - unsigned alignment; - unsigned usage; - - /* The active buffer: - */ - struct pipe_resource *buffer; - unsigned size; - unsigned offset; + unsigned default_size; /* Minimum size of the upload buffer, in bytes. */ + unsigned alignment; /* Alignment of each sub-allocation. */ + unsigned bind; /* Bitmask of PIPE_BIND_* flags. */ + + struct pipe_resource *buffer; /* Upload buffer. */ + struct pipe_transfer *transfer; /* Transfer object for the upload buffer. */ + uint8_t *map; /* Pointer to the mapped upload buffer. */ + unsigned size; /* Actual size of the upload buffer. */ + unsigned offset; /* Aligned offset to the upload buffer, pointing + * at the first unused byte. */ }; 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) + return NULL; upload->pipe = pipe; upload->default_size = default_size; upload->alignment = alignment; - upload->usage = usage; + upload->bind = bind; upload->buffer = NULL; return upload; } -/* Slightly specialized version of buffer_write designed to maximize - * chances of the driver consolidating successive writes into a single - * upload. - * - * dirty_size may be slightly greater than size to cope with - * alignment. We don't want to leave holes between succesively mapped - * regions as that may prevent the driver from consolidating uploads. - * - * Note that the 'data' pointer has probably come from the application - * and we cannot read even a byte past its end without risking - * segfaults, or at least complaints from valgrind.. - */ -static INLINE enum pipe_error -my_buffer_write(struct pipe_context *pipe, - struct pipe_resource *buf, - unsigned offset, unsigned size, unsigned dirty_size, - const void *data) -{ - struct pipe_transfer *transfer = NULL; - uint8_t *map; - - assert(offset < buf->width0); - assert(offset + size <= buf->width0); - assert(dirty_size >= size); - assert(size); - - map = pipe_buffer_map_range(pipe, buf, offset, dirty_size, - PIPE_TRANSFER_WRITE | - PIPE_TRANSFER_FLUSH_EXPLICIT | - PIPE_TRANSFER_DISCARD | - PIPE_TRANSFER_UNSYNCHRONIZED, - &transfer); - if (map == NULL) - return PIPE_ERROR_OUT_OF_MEMORY; - - memcpy(map + offset, data, size); - pipe_buffer_flush_mapped_range(pipe, transfer, offset, dirty_size); - pipe_buffer_unmap(pipe, buf, transfer); - - return PIPE_OK; -} - /* Release old buffer. * * This must usually be called prior to firing the command stream @@ -122,6 +83,12 @@ my_buffer_write(struct pipe_context *pipe, */ void u_upload_flush( struct u_upload_mgr *upload ) { + /* Unmap and unreference the upload buffer. */ + if (upload->transfer) { + pipe_transfer_unmap(upload->pipe, upload->transfer); + pipe_transfer_destroy(upload->pipe, upload->transfer); + upload->transfer = NULL; + } pipe_resource_reference( &upload->buffer, NULL ); upload->size = 0; } @@ -140,7 +107,7 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload, { unsigned size; - /* Release old buffer, if present: + /* Release the old buffer, if present: */ u_upload_flush( upload ); @@ -149,10 +116,14 @@ 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; + + /* Map the new buffer. */ + upload->map = pipe_buffer_map(upload->pipe, upload->buffer, + PIPE_TRANSFER_WRITE, &upload->transfer); upload->size = size; @@ -166,38 +137,62 @@ 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 ); + /* Make sure we have enough space in the upload buffer + * for the sub-allocation. */ + 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; } - /* Copy the data, using map_range if available: - */ - ret = my_buffer_write( upload->pipe, - upload->buffer, - upload->offset, - size, - alloc_size, - data ); + offset = MAX2(upload->offset, alloc_offset); + + assert(offset < upload->buffer->width0); + assert(offset + size <= upload->buffer->width0); + assert(size); + + /* Emit the return values: */ + *ptr = upload->map + offset; + pipe_resource_reference( outbuf, upload->buffer ); + *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; - /* Emit the return values: - */ - pipe_resource_reference( outbuf, upload->buffer ); - *out_offset = upload->offset; - upload->offset += alloc_size; + memcpy(ptr, data, size); return PIPE_OK; } @@ -208,11 +203,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; @@ -231,17 +228,16 @@ 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) - pipe_buffer_unmap( upload->pipe, inbuf, transfer ); + pipe_buffer_unmap( upload->pipe, transfer ); return ret; }