From 659c5800e566d3fce90501c06e47c61f9623d663 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 10 May 2019 21:23:12 -0700 Subject: [PATCH] virgl: handle DONT_BLOCK and MAP_DIRECTLY Handle PIPE_TRANSFER_DONT_BLOCK and PIPE_TRANSFER_MAP_DIRECTLY. Make virgl_resource_transfer_prepare return an enum instead of a bool for extensibility (e.g., instruct the callers to map differently). Signed-off-by: Chia-I Wu Reviewed-by: Alexandros Frantzis --- src/gallium/drivers/virgl/virgl_buffer.c | 13 +++++++++++-- src/gallium/drivers/virgl/virgl_resource.c | 19 +++++++++++++++++-- src/gallium/drivers/virgl/virgl_resource.h | 7 ++++++- src/gallium/drivers/virgl/virgl_texture.c | 13 +++++++++++-- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/gallium/drivers/virgl/virgl_buffer.c b/src/gallium/drivers/virgl/virgl_buffer.c index 2b559e58468..fce1ac496e7 100644 --- a/src/gallium/drivers/virgl/virgl_buffer.c +++ b/src/gallium/drivers/virgl/virgl_buffer.c @@ -38,13 +38,22 @@ static void *virgl_buffer_transfer_map(struct pipe_context *ctx, struct virgl_screen *vs = virgl_screen(ctx->screen); struct virgl_resource *vbuf = virgl_resource(resource); struct virgl_transfer *trans; + enum virgl_transfer_map_type map_type; trans = virgl_resource_create_transfer(&vctx->transfer_pool, resource, &vbuf->metadata, level, usage, box); - virgl_resource_transfer_prepare(vctx, trans); + map_type = virgl_resource_transfer_prepare(vctx, trans); + switch (map_type) { + case VIRGL_TRANSFER_MAP_HW_RES: + trans->hw_res_map = vs->vws->resource_map(vs->vws, vbuf->hw_res); + break; + case VIRGL_TRANSFER_MAP_ERROR: + default: + trans->hw_res_map = NULL; + break; + } - trans->hw_res_map = vs->vws->resource_map(vs->vws, vbuf->hw_res); if (!trans->hw_res_map) { virgl_resource_destroy_transfer(&vctx->transfer_pool, trans); return NULL; diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c index 07ae20177bf..eaa50445d4f 100644 --- a/src/gallium/drivers/virgl/virgl_resource.c +++ b/src/gallium/drivers/virgl/virgl_resource.c @@ -103,16 +103,21 @@ static bool virgl_res_needs_readback(struct virgl_context *vctx, return true; } -void +enum virgl_transfer_map_type virgl_resource_transfer_prepare(struct virgl_context *vctx, struct virgl_transfer *xfer) { struct virgl_winsys *vws = virgl_screen(vctx->base.screen)->vws; struct virgl_resource *res = virgl_resource(xfer->base.resource); + enum virgl_transfer_map_type map_type = VIRGL_TRANSFER_MAP_HW_RES; bool flush; bool readback; bool wait; + /* there is no way to map the host storage currently */ + if (xfer->base.usage & PIPE_TRANSFER_MAP_DIRECTLY) + return VIRGL_TRANSFER_MAP_ERROR; + flush = virgl_res_needs_flush(vctx, xfer); readback = virgl_res_needs_readback(vctx, res, xfer->base.usage, xfer->base.level); @@ -138,8 +143,18 @@ virgl_resource_transfer_prepare(struct virgl_context *vctx, xfer->l_stride, xfer->offset, xfer->base.level); } - if (wait) + if (wait) { + /* fail the mapping after flush and readback so that it will succeed in + * the future + */ + if ((xfer->base.usage & PIPE_TRANSFER_DONTBLOCK) && + vws->resource_is_busy(vws, res->hw_res)) + return VIRGL_TRANSFER_MAP_ERROR; + vws->resource_wait(vws, res->hw_res); + } + + return map_type; } static struct pipe_resource *virgl_resource_create(struct pipe_screen *screen, diff --git a/src/gallium/drivers/virgl/virgl_resource.h b/src/gallium/drivers/virgl/virgl_resource.h index fda795b6b5e..c17c753a596 100644 --- a/src/gallium/drivers/virgl/virgl_resource.h +++ b/src/gallium/drivers/virgl/virgl_resource.h @@ -52,6 +52,11 @@ struct virgl_resource { struct virgl_resource_metadata metadata; }; +enum virgl_transfer_map_type { + VIRGL_TRANSFER_MAP_ERROR = -1, + VIRGL_TRANSFER_MAP_HW_RES, +}; + struct virgl_transfer { struct pipe_transfer base; uint32_t offset, l_stride; @@ -117,7 +122,7 @@ static inline unsigned pipe_to_virgl_bind(const struct virgl_screen *vs, unsigne return outbind; } -void +enum virgl_transfer_map_type virgl_resource_transfer_prepare(struct virgl_context *vctx, struct virgl_transfer *xfer); diff --git a/src/gallium/drivers/virgl/virgl_texture.c b/src/gallium/drivers/virgl/virgl_texture.c index c2bdc3ef9e2..bba5830d33c 100644 --- a/src/gallium/drivers/virgl/virgl_texture.c +++ b/src/gallium/drivers/virgl/virgl_texture.c @@ -126,6 +126,7 @@ static void *texture_transfer_map_plain(struct pipe_context *ctx, struct virgl_winsys *vws = virgl_screen(ctx->screen)->vws; struct virgl_resource *vtex = virgl_resource(resource); struct virgl_transfer *trans; + enum virgl_transfer_map_type map_type; trans = virgl_resource_create_transfer(&vctx->transfer_pool, resource, &vtex->metadata, level, usage, box); @@ -133,9 +134,17 @@ static void *texture_transfer_map_plain(struct pipe_context *ctx, assert(resource->nr_samples <= 1); - virgl_resource_transfer_prepare(vctx, trans); + map_type = virgl_resource_transfer_prepare(vctx, trans); + switch (map_type) { + case VIRGL_TRANSFER_MAP_HW_RES: + trans->hw_res_map = vws->resource_map(vws, vtex->hw_res); + break; + case VIRGL_TRANSFER_MAP_ERROR: + default: + trans->hw_res_map = NULL; + break; + } - trans->hw_res_map = vws->resource_map(vws, vtex->hw_res); if (!trans->hw_res_map) { virgl_resource_destroy_transfer(&vctx->transfer_pool, trans); return NULL; -- 2.30.2