[Mesa-dev] [PATCH 11/13] gallium/upload_mgr: don't unmap buffers if persistent mappings are supported

Marek Olšák maraeo at gmail.com
Thu Jan 30 08:58:00 PST 2014


On Thu, Jan 30, 2014 at 5:33 PM, Roland Scheidegger <sroland at vmware.com> wrote:
> Am 30.01.2014 02:20, schrieb Marek Olšák:
>> From: Marek Olšák <marek.olsak at 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


More information about the mesa-dev mailing list