From dec68e32ea09e3163c39ee270782682621301370 Mon Sep 17 00:00:00 2001 From: David Riley Date: Wed, 24 Apr 2019 16:12:48 -0700 Subject: [PATCH] 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 Reviewed-by: Gurchetan Singh --- src/gallium/drivers/virgl/virgl_resource.c | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c index 5f0040c..ef81f21 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 -- 2.7.4