r600g: use u_upload_mgr for allocating staging transfer buffers
authorMarek Olšák <maraeo@gmail.com>
Sun, 9 Dec 2012 15:43:16 +0000 (16:43 +0100)
committerMarek Olšák <maraeo@gmail.com>
Wed, 12 Dec 2012 12:11:52 +0000 (13:11 +0100)
u_upload_mgr suballocates memory from a large buffer and maps the allocated
range (unsychronized), which is perfect for short-lived staging buffers.

This reduces the number of relocations sent to the kernel.

Tested-by: Aaron Watry <awatry@gmail.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
src/gallium/drivers/r600/r600_buffer.c

index 9e2cf6650ad6f4e360e7d6176078a9906c88db5c..e674e13a1443a29d720639f923a78287f0b313b7 100644 (file)
@@ -66,7 +66,8 @@ static void *r600_buffer_get_transfer(struct pipe_context *ctx,
                                       unsigned usage,
                                       const struct pipe_box *box,
                                      struct pipe_transfer **ptransfer,
-                                     void *data, struct r600_resource *staging)
+                                     void *data, struct r600_resource *staging,
+                                     unsigned offset)
 {
        struct r600_context *rctx = (struct r600_context*)ctx;
        struct r600_transfer *transfer = util_slab_alloc(&rctx->pool_transfers);
@@ -77,8 +78,7 @@ static void *r600_buffer_get_transfer(struct pipe_context *ctx,
        transfer->transfer.box = *box;
        transfer->transfer.stride = 0;
        transfer->transfer.layer_stride = 0;
-       transfer->staging = NULL;
-       transfer->offset = 0;
+       transfer->offset = offset;
        transfer->staging = staging;
        *ptransfer = &transfer->transfer;
        return data;
@@ -147,18 +147,17 @@ static void *r600_buffer_transfer_map(struct pipe_context *ctx,
                if (rctx->ws->cs_is_buffer_referenced(rctx->cs, rbuffer->cs_buf, RADEON_USAGE_READWRITE) ||
                    rctx->ws->buffer_is_busy(rbuffer->buf, RADEON_USAGE_READWRITE)) {
                        /* Do a wait-free write-only transfer using a temporary buffer. */
-                       struct r600_resource *staging = (struct r600_resource*)
-                               pipe_buffer_create(ctx->screen, PIPE_BIND_VERTEX_BUFFER,
-                                                  PIPE_USAGE_STAGING,
-                                                  box->width + (box->x % R600_MAP_BUFFER_ALIGNMENT));
-                       data = rctx->ws->buffer_map(staging->cs_buf, rctx->cs, PIPE_TRANSFER_WRITE);
+                       unsigned offset;
+                       struct r600_resource *staging = NULL;
 
-                       if (!data)
-                               return NULL;
+                       u_upload_alloc(rctx->uploader, 0, box->width + (box->x % R600_MAP_BUFFER_ALIGNMENT),
+                                      &offset, (struct pipe_resource**)&staging, (void**)&data);
 
-                       data += box->x % R600_MAP_BUFFER_ALIGNMENT;
-                       return r600_buffer_get_transfer(ctx, resource, level, usage, box,
-                                                       ptransfer, data, staging);
+                       if (staging) {
+                               data += box->x % R600_MAP_BUFFER_ALIGNMENT;
+                               return r600_buffer_get_transfer(ctx, resource, level, usage, box,
+                                                               ptransfer, data, staging, offset);
+                       }
                }
        }
 
@@ -169,7 +168,7 @@ static void *r600_buffer_transfer_map(struct pipe_context *ctx,
        data += box->x;
 
        return r600_buffer_get_transfer(ctx, resource, level, usage, box,
-                                       ptransfer, data, NULL);
+                                       ptransfer, data, NULL, 0);
 }
 
 static void r600_buffer_transfer_unmap(struct pipe_context *pipe,
@@ -180,7 +179,8 @@ static void r600_buffer_transfer_unmap(struct pipe_context *pipe,
 
        if (rtransfer->staging) {
                struct pipe_box box;
-               u_box_1d(transfer->box.x % R600_MAP_BUFFER_ALIGNMENT, transfer->box.width, &box);
+               u_box_1d(rtransfer->offset + transfer->box.x % R600_MAP_BUFFER_ALIGNMENT,
+                        transfer->box.width, &box);
 
                /* Copy the staging buffer into the original one. */
                r600_copy_buffer(pipe, transfer->resource, transfer->box.x,