On Thu, Jan 30, 2014 at 5:33 PM, Roland Scheidegger <srol...@vmware.com> wrote: > Am 30.01.2014 02:20, schrieb Marek Olšák: >> From: Marek Olšák <marek.ol...@amd.com> >> >> --- >> src/gallium/auxiliary/util/u_upload_mgr.c | 65 >> ++++++++++++++++++++++++------- >> 1 file changed, 51 insertions(+), 14 deletions(-) >> >> diff --git a/src/gallium/auxiliary/util/u_upload_mgr.c >> b/src/gallium/auxiliary/util/u_upload_mgr.c >> index 7349d00..ccaab27 100644 >> --- a/src/gallium/auxiliary/util/u_upload_mgr.c >> +++ b/src/gallium/auxiliary/util/u_upload_mgr.c >> @@ -44,6 +44,8 @@ struct u_upload_mgr { >> 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. */ >> + unsigned map_flags; /* Bitmask of PIPE_TRANSFER_* flags. */ >> + boolean map_persistent; /* If persistent mappings are supported. */ >> >> struct pipe_resource *buffer; /* Upload buffer. */ >> struct pipe_transfer *transfer; /* Transfer object for the upload >> buffer. */ >> @@ -67,20 +69,39 @@ struct u_upload_mgr *u_upload_create( struct >> pipe_context *pipe, >> upload->default_size = default_size; >> upload->alignment = alignment; >> upload->bind = bind; >> - upload->buffer = NULL; >> + >> + upload->map_persistent = >> + pipe->screen->get_param(pipe->screen, >> + PIPE_CAP_BUFFER_TRANSFER_PERSISTENT_COHERENT); >> + >> + if (upload->map_persistent) { >> + upload->map_flags = PIPE_TRANSFER_WRITE | >> + PIPE_TRANSFER_PERSISTENT | >> + PIPE_TRANSFER_COHERENT; >> + } >> + else { >> + upload->map_flags = PIPE_TRANSFER_WRITE | >> + PIPE_TRANSFER_UNSYNCHRONIZED | >> + PIPE_TRANSFER_FLUSH_EXPLICIT; >> + } >> >> return upload; >> } >> >> -void u_upload_unmap( struct u_upload_mgr *upload ) >> + >> +static void upload_unmap_internal(struct u_upload_mgr *upload, boolean >> destroying) >> { >> + if (!destroying && upload->map_persistent) >> + return; >> + >> if (upload->transfer) { >> struct pipe_box *box = &upload->transfer->box; >> - if ((int) upload->offset > box->x) { >> >> + if (!upload->map_persistent && (int) upload->offset > box->x) { >> pipe_buffer_flush_mapped_range(upload->pipe, upload->transfer, >> box->x, upload->offset - box->x); >> } >> + >> pipe_transfer_unmap(upload->pipe, upload->transfer); >> upload->transfer = NULL; >> upload->map = NULL; >> @@ -88,10 +109,16 @@ void u_upload_unmap( struct u_upload_mgr *upload ) >> } >> >> >> +void u_upload_unmap( struct u_upload_mgr *upload ) >> +{ >> + upload_unmap_internal(upload, FALSE); >> +} >> + >> + >> static void u_upload_release_buffer(struct u_upload_mgr *upload) >> { >> /* Unmap and unreference the upload buffer. */ >> - u_upload_unmap(upload); >> + upload_unmap_internal(upload, TRUE); >> pipe_resource_reference( &upload->buffer, NULL ); >> upload->size = 0; >> } >> @@ -108,6 +135,8 @@ static enum pipe_error >> u_upload_alloc_buffer( struct u_upload_mgr *upload, >> unsigned min_size ) >> { >> + struct pipe_screen *screen = upload->pipe->screen; >> + struct pipe_resource buffer; >> unsigned size; >> >> /* Release the old buffer, if present: >> @@ -118,19 +147,29 @@ 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->bind, >> - PIPE_USAGE_STREAM, >> - size ); >> + memset(&buffer, 0, sizeof buffer); >> + buffer.target = PIPE_BUFFER; >> + buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */ >> + buffer.bind = upload->bind; >> + buffer.usage = PIPE_USAGE_STREAM; >> + buffer.width0 = size; >> + buffer.height0 = 1; >> + buffer.depth0 = 1; >> + buffer.array_size = 1; >> + >> + if (upload->map_persistent) { >> + buffer.flags = PIPE_RESOURCE_FLAG_TRANSFER_PERSISTENT | >> + PIPE_RESOURCE_FLAG_TRANSFER_COHERENT; >> + } >> + >> + upload->buffer = screen->resource_create(screen, &buffer); >> if (upload->buffer == NULL) { >> return PIPE_ERROR_OUT_OF_MEMORY; >> } >> >> /* Map the new buffer. */ >> upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer, >> - 0, size, >> - PIPE_TRANSFER_WRITE | >> - PIPE_TRANSFER_FLUSH_EXPLICIT, >> + 0, size, upload->map_flags, >> &upload->transfer); >> if (upload->map == NULL) { >> upload->transfer = NULL; >> @@ -176,9 +215,7 @@ enum pipe_error u_upload_alloc( struct u_upload_mgr >> *upload, >> if (!upload->map) { >> upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer, >> offset, upload->size - offset, >> - PIPE_TRANSFER_WRITE | >> - PIPE_TRANSFER_FLUSH_EXPLICIT | >> - PIPE_TRANSFER_UNSYNCHRONIZED, >> + upload->map_flags, >> &upload->transfer); >> if (!upload->map) { >> upload->transfer = NULL; >> > > Is this actually a win over just remapping unsynchronized buffers here? > Just curious...
Yes, it's measurable with some CPU-bound apps. I actually wanted this a couple of years ago when I was doing lots of performance measurements. Marek _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev