diff options
author | David Riley <[email protected]> | 2019-04-24 16:12:48 -0700 |
---|---|---|
committer | Gurchetan Singh <[email protected]> | 2019-05-01 15:48:51 -0700 |
commit | dec68e32ea09e3163c39ee270782682621301370 (patch) | |
tree | 31089d486661a2a326480a3859359a472d4d724d | |
parent | a54c231b56005f172cbd744fb7c592922b077526 (diff) |
virgl: Re-use and extend queue transfers for intersecting buffer subdatas.
Small buffer subdatas which are essentially doing a memcpy were getting
bogged down by all the overhead of creating new transfers.
Signed-off-by: David Riley <[email protected]>
Reviewed-by: Gurchetan Singh <[email protected]>
-rw-r--r-- | src/gallium/drivers/virgl/virgl_resource.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c index 5f0040c1db1..ef81f213f40 100644 --- a/src/gallium/drivers/virgl/virgl_resource.c +++ b/src/gallium/drivers/virgl/virgl_resource.c @@ -132,6 +132,43 @@ void virgl_init_screen_resource_functions(struct pipe_screen *screen) screen->resource_destroy = u_resource_destroy_vtbl; } +static bool virgl_buffer_transfer_extend(struct pipe_context *ctx, + struct pipe_resource *resource, + unsigned usage, + const struct pipe_box *box, + const void *data) +{ + struct virgl_context *vctx = virgl_context(ctx); + struct virgl_resource *vbuf = virgl_resource(resource); + struct virgl_transfer dummy_trans = { 0 }; + bool flush; + struct virgl_transfer *queued; + + /* + * Attempts to short circuit the entire process of mapping and unmapping + * a resource if there is an existing transfer that can be extended. + * Pessimestically falls back if a flush is required. + */ + dummy_trans.base.resource = resource; + dummy_trans.base.usage = usage; + dummy_trans.base.box = *box; + dummy_trans.base.stride = vbuf->metadata.stride[0]; + dummy_trans.base.layer_stride = vbuf->metadata.layer_stride[0]; + dummy_trans.offset = box->x; + + flush = virgl_res_needs_flush(vctx, &dummy_trans); + if (flush) + return false; + + queued = virgl_transfer_queue_extend(&vctx->queue, &dummy_trans); + if (!queued || !queued->hw_res_map) + return false; + + memcpy(queued->hw_res_map + dummy_trans.offset, data, box->width); + + return true; +} + static void virgl_buffer_subdata(struct pipe_context *pipe, struct pipe_resource *resource, unsigned usage, unsigned offset, @@ -139,6 +176,11 @@ static void virgl_buffer_subdata(struct pipe_context *pipe, { struct pipe_box box; + assert(!(usage & PIPE_TRANSFER_READ)); + + /* the write flag is implicit by the nature of buffer_subdata */ + usage |= PIPE_TRANSFER_WRITE; + if (offset == 0 && size == resource->width0) usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; else @@ -146,6 +188,10 @@ static void virgl_buffer_subdata(struct pipe_context *pipe, u_box_1d(offset, size, &box); + if (usage & PIPE_TRANSFER_DISCARD_RANGE && + virgl_buffer_transfer_extend(pipe, resource, usage, &box, data)) + return; + if (resource->width0 >= getpagesize()) u_default_buffer_subdata(pipe, resource, usage, offset, size, data); else |