diff options
author | Marek Olšák <[email protected]> | 2010-12-24 13:47:32 +0100 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2011-01-06 16:16:29 +0100 |
commit | 8b7bd3ce8875f5028bbf234d107f56d595a0d0b7 (patch) | |
tree | 2ceea56ae34dc79da49ad0b631d1bd5175cc81de /src | |
parent | 8fd8de3995343f5cee8536c235e2a4fc5c768490 (diff) |
u_upload_mgr: keep the upload buffer mapped until it is flushed
The map/unmap overhead can be significant even though there is no waiting on busy
buffers. There is simply a huge number of uploads.
This is a performance optimization for Torcs, a car racing game.
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/auxiliary/util/u_upload_mgr.c | 66 |
1 files changed, 14 insertions, 52 deletions
diff --git a/src/gallium/auxiliary/util/u_upload_mgr.c b/src/gallium/auxiliary/util/u_upload_mgr.c index 4daa55d6638..4d97bf0377f 100644 --- a/src/gallium/auxiliary/util/u_upload_mgr.c +++ b/src/gallium/auxiliary/util/u_upload_mgr.c @@ -48,6 +48,8 @@ struct u_upload_mgr { /* The active buffer: */ struct pipe_resource *buffer; + struct pipe_transfer *transfer; + uint8_t *map; unsigned size; unsigned offset; }; @@ -71,48 +73,6 @@ struct u_upload_mgr *u_upload_create( struct pipe_context *pipe, 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, transfer); - - return PIPE_OK; -} - /* Release old buffer. * * This must usually be called prior to firing the command stream @@ -124,6 +84,10 @@ my_buffer_write(struct pipe_context *pipe, */ void u_upload_flush( struct u_upload_mgr *upload ) { + if (upload->transfer) { + pipe_transfer_unmap(upload->pipe, upload->transfer); + upload->transfer = NULL; + } pipe_resource_reference( &upload->buffer, NULL ); upload->size = 0; } @@ -155,6 +119,9 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload, size ); if (upload->buffer == NULL) goto fail; + + upload->map = pipe_buffer_map(upload->pipe, upload->buffer, + PIPE_TRANSFER_WRITE, &upload->transfer); upload->size = size; @@ -184,16 +151,11 @@ enum pipe_error u_upload_data( struct u_upload_mgr *upload, return ret; } - /* Copy the data, using map_range if available: - */ - ret = my_buffer_write( upload->pipe, - upload->buffer, - upload->offset, - size, - alloc_size, - data ); - if (ret) - return ret; + assert(upload->offset < upload->buffer->width0); + assert(upload->offset + size <= upload->buffer->width0); + assert(size); + + memcpy(upload->map + upload->offset, data, size); /* Emit the return values: */ |