From 7e0508d9aa9575db7f608eae0c5337e2a0634197 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 15 May 2019 15:34:44 -0700 Subject: [PATCH] virgl: save virgl_hw_res in virgl_transfer When PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE is properly supported, virgl_transfer might refer to a different virgl_hw_res than virgl_resource does. We need to save the virgl_hw_res and use the saved one. Signed-off-by: Chia-I Wu Reviewed-by: Alexandros Frantzis --- src/gallium/drivers/virgl/virgl_encode.c | 8 ++++++-- src/gallium/drivers/virgl/virgl_resource.c | 7 +++++++ src/gallium/drivers/virgl/virgl_resource.h | 2 ++ src/gallium/drivers/virgl/virgl_texture.c | 2 +- .../drivers/virgl/virgl_transfer_queue.c | 17 ++++++----------- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/gallium/drivers/virgl/virgl_encode.c b/src/gallium/drivers/virgl/virgl_encode.c index d26c0670f72..95a5bf97c18 100644 --- a/src/gallium/drivers/virgl/virgl_encode.c +++ b/src/gallium/drivers/virgl/virgl_encode.c @@ -527,7 +527,6 @@ static void virgl_encoder_transfer3d_common(struct virgl_screen *vs, { struct pipe_transfer *transfer = &xfer->base; - struct virgl_resource *res = virgl_resource(transfer->resource); unsigned stride; unsigned layer_stride; @@ -541,7 +540,11 @@ static void virgl_encoder_transfer3d_common(struct virgl_screen *vs, assert(!"Invalid virgl_transfer3d_encode_stride value"); } - virgl_encoder_emit_resource(vs, buf, res); + /* We cannot use virgl_encoder_emit_resource with transfer->resource here + * because transfer->resource might have a different virgl_hw_res than what + * this transfer targets, which is saved in xfer->hw_res. + */ + vs->vws->emit_res(vs->vws, buf, xfer->hw_res, TRUE); virgl_encoder_write_dword(buf, transfer->level); virgl_encoder_write_dword(buf, transfer->usage); virgl_encoder_write_dword(buf, stride); @@ -567,6 +570,7 @@ int virgl_encoder_inline_write(struct virgl_context *ctx, struct virgl_screen *vs = virgl_screen(ctx->base.screen); transfer.base.resource = &res->u.b; + transfer.hw_res = res->hw_res; transfer.base.level = level; transfer.base.usage = usage; transfer.base.box = *box; diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c index 1c8e264e573..59afcca968e 100644 --- a/src/gallium/drivers/virgl/virgl_resource.c +++ b/src/gallium/drivers/virgl/virgl_resource.c @@ -387,6 +387,7 @@ virgl_resource_create_transfer(struct virgl_context *vctx, unsigned level, unsigned usage, const struct pipe_box *box) { + struct virgl_winsys *vws = virgl_screen(vctx->base.screen)->vws; struct virgl_transfer *trans; enum pipe_format format = pres->format; const unsigned blocksy = box->y / util_format_get_blockheight(format); @@ -418,6 +419,9 @@ virgl_resource_create_transfer(struct virgl_context *vctx, /* note that trans is not zero-initialized */ trans->base.resource = NULL; pipe_resource_reference(&trans->base.resource, pres); + trans->hw_res = NULL; + vws->resource_reference(vws, &trans->hw_res, virgl_resource(pres)->hw_res); + trans->base.level = level; trans->base.usage = usage; trans->base.box = *box; @@ -443,9 +447,12 @@ virgl_resource_create_transfer(struct virgl_context *vctx, void virgl_resource_destroy_transfer(struct virgl_context *vctx, struct virgl_transfer *trans) { + struct virgl_winsys *vws = virgl_screen(vctx->base.screen)->vws; + pipe_resource_reference(&trans->copy_src_res, NULL); util_range_destroy(&trans->range); + vws->resource_reference(vws, &trans->hw_res, NULL); pipe_resource_reference(&trans->base.resource, NULL); slab_free(&vctx->transfer_pool, trans); } diff --git a/src/gallium/drivers/virgl/virgl_resource.h b/src/gallium/drivers/virgl/virgl_resource.h index 710244d2c7f..a69b172ef2a 100644 --- a/src/gallium/drivers/virgl/virgl_resource.h +++ b/src/gallium/drivers/virgl/virgl_resource.h @@ -76,6 +76,8 @@ struct virgl_transfer { struct util_range range; struct list_head queue_link; struct pipe_transfer *resolve_transfer; + + struct virgl_hw_res *hw_res; void *hw_res_map; /* If not NULL, denotes that this is a copy transfer, i.e., * that the transfer source data should be taken from this diff --git a/src/gallium/drivers/virgl/virgl_texture.c b/src/gallium/drivers/virgl/virgl_texture.c index 6e26493cb61..1de6d4f17db 100644 --- a/src/gallium/drivers/virgl/virgl_texture.c +++ b/src/gallium/drivers/virgl/virgl_texture.c @@ -296,7 +296,7 @@ static void flush_data(struct pipe_context *ctx, const struct pipe_box *box) { struct virgl_winsys *vws = virgl_screen(ctx->screen)->vws; - vws->transfer_put(vws, virgl_resource(trans->base.resource)->hw_res, box, + vws->transfer_put(vws, trans->hw_res, box, trans->base.stride, trans->l_stride, trans->offset, trans->base.level); } diff --git a/src/gallium/drivers/virgl/virgl_transfer_queue.c b/src/gallium/drivers/virgl/virgl_transfer_queue.c index f41c0defbbe..33f8b62f4a3 100644 --- a/src/gallium/drivers/virgl/virgl_transfer_queue.c +++ b/src/gallium/drivers/virgl/virgl_transfer_queue.c @@ -57,10 +57,8 @@ static bool transfers_intersect(struct virgl_transfer *queued, struct virgl_transfer *current) { boolean tmp; - struct pipe_resource *queued_res = queued->base.resource; - struct pipe_resource *current_res = current->base.resource; - if (queued_res != current_res) + if (queued->hw_res != current->hw_res) return false; tmp = u_box_test_intersection_2d(&queued->base.box, ¤t->base.box); @@ -71,10 +69,8 @@ static bool transfers_overlap(struct virgl_transfer *queued, struct virgl_transfer *current) { boolean tmp; - struct pipe_resource *queued_res = queued->base.resource; - struct pipe_resource *current_res = current->base.resource; - if (queued_res != current_res) + if (queued->hw_res != current->hw_res) return false; if (queued->base.level != current->base.level) @@ -89,7 +85,7 @@ static bool transfers_overlap(struct virgl_transfer *queued, /* * Special case for boxes with [x: 0, width: 1] and [x: 1, width: 1]. */ - if (queued_res->target == PIPE_BUFFER) { + if (queued->base.resource->target == PIPE_BUFFER) { if (queued->base.box.x + queued->base.box.width == current->base.box.x) return false; @@ -141,9 +137,9 @@ static void transfer_put(struct virgl_transfer_queue *queue, struct list_action_args *args) { struct virgl_transfer *queued = args->queued; - struct virgl_resource *res = virgl_resource(queued->base.resource); - queue->vs->vws->transfer_put(queue->vs->vws, res->hw_res, &queued->base.box, + queue->vs->vws->transfer_put(queue->vs->vws, queued->hw_res, + &queued->base.box, queued->base.stride, queued->l_stride, queued->offset, queued->base.level); @@ -290,14 +286,13 @@ void virgl_transfer_queue_fini(struct virgl_transfer_queue *queue) int virgl_transfer_queue_unmap(struct virgl_transfer_queue *queue, struct virgl_transfer *transfer) { - struct pipe_resource *res = transfer->base.resource; struct list_iteration_args iter; /* We don't support copy transfers in the transfer queue. */ assert(!transfer->copy_src_res); /* Attempt to merge multiple intersecting transfers into a single one. */ - if (res->target == PIPE_BUFFER) { + if (transfer->base.resource->target == PIPE_BUFFER) { memset(&iter, 0, sizeof(iter)); iter.current = transfer; iter.compare = transfers_intersect; -- 2.30.2