summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2010-12-24 13:47:32 +0100
committerMarek Olšák <[email protected]>2011-01-06 16:16:29 +0100
commit8b7bd3ce8875f5028bbf234d107f56d595a0d0b7 (patch)
tree2ceea56ae34dc79da49ad0b631d1bd5175cc81de /src
parent8fd8de3995343f5cee8536c235e2a4fc5c768490 (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.c66
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:
*/