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 <olvaffe@gmail.com> Reviewed-by: Alexandros Frantzis <alexandros.frantzis@collabora.com>
This commit is contained in:
parent
ad1ef35dc1
commit
7e0508d9aa
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue