From: Alexandros Frantzis Date: Mon, 24 Jun 2019 13:57:46 +0000 (+0300) Subject: virgl: Use virgl_staging_mgr X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5388be039bc8dc4c0ed2875d0ca35c6f37053948;p=mesa.git virgl: Use virgl_staging_mgr Use an instance of virgl_staging_mgr instead of u_upload_mgr to handle the staging buffer. This removes the need to track the availability of the staging manager, since virgl_staging_mgr can handle concurrent active allocations. Signed-off-by: Alexandros Frantzis Reviewed-by: Chia-I Wu --- diff --git a/src/gallium/drivers/virgl/virgl_buffer.c b/src/gallium/drivers/virgl/virgl_buffer.c index 93ccaeee995..bc12f3f8876 100644 --- a/src/gallium/drivers/virgl/virgl_buffer.c +++ b/src/gallium/drivers/virgl/virgl_buffer.c @@ -62,7 +62,7 @@ static void *virgl_buffer_transfer_map(struct pipe_context *ctx, map_addr = NULL; break; case VIRGL_TRANSFER_MAP_STAGING: - map_addr = virgl_transfer_uploader_map(vctx, trans); + map_addr = virgl_staging_map(vctx, trans); /* Copy transfers don't make use of hw_res_map at the moment. */ trans->hw_res_map = NULL; break; @@ -93,12 +93,9 @@ static void virgl_buffer_transfer_unmap(struct pipe_context *ctx, struct virgl_screen *vs = virgl_screen(ctx->screen); struct pipe_resource *res = transfer->resource; - /* We don't need to transfer the contents of staging buffers, since they - * don't have any host-side storage. */ - if (pipe_to_virgl_bind(vs, res->bind, res->flags) == VIRGL_BIND_STAGING) { - virgl_resource_destroy_transfer(vctx, trans); - return; - } + /* We don't transfer the contents of staging resources, since they don't + * have any host-side storage. */ + assert(pipe_to_virgl_bind(vs, res->bind, res->flags) != VIRGL_BIND_STAGING); if (trans->base.usage & PIPE_TRANSFER_WRITE) { if (transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT) { @@ -114,8 +111,6 @@ static void virgl_buffer_transfer_unmap(struct pipe_context *ctx, if (trans->copy_src_hw_res) { virgl_encode_copy_transfer(vctx, trans); - /* It's now safe for other mappings to use the transfer_uploader. */ - vctx->transfer_uploader_in_use = false; virgl_resource_destroy_transfer(vctx, trans); } else { virgl_transfer_queue_unmap(&vctx->queue, trans); diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c index 3421c71a43d..e511750dc69 100644 --- a/src/gallium/drivers/virgl/virgl_context.c +++ b/src/gallium/drivers/virgl/virgl_context.c @@ -47,6 +47,7 @@ #include "virgl_protocol.h" #include "virgl_resource.h" #include "virgl_screen.h" +#include "virgl_staging_mgr.h" struct virgl_vertex_elements_state { uint32_t handle; @@ -1372,8 +1373,8 @@ virgl_context_destroy( struct pipe_context *ctx ) rs->vws->cmd_buf_destroy(vctx->cbuf); if (vctx->uploader) u_upload_destroy(vctx->uploader); - if (vctx->transfer_uploader) - u_upload_destroy(vctx->transfer_uploader); + if (vctx->supports_staging) + virgl_staging_destroy(&vctx->staging); util_primconvert_destroy(vctx->primconvert); virgl_transfer_queue_fini(&vctx->queue); @@ -1547,17 +1548,12 @@ struct pipe_context *virgl_context_create(struct pipe_screen *pscreen, goto fail; vctx->base.stream_uploader = vctx->uploader; vctx->base.const_uploader = vctx->uploader; - /* Use a custom/staging buffer for the transfer uploader, since we are - * using it only for copies to other resources. - */ + + /* We use a special staging buffer as the source of copy transfers. */ if ((rs->caps.caps.v2.capability_bits & VIRGL_CAP_COPY_TRANSFER) && vctx->encoded_transfers) { - vctx->transfer_uploader = u_upload_create(&vctx->base, 1024 * 1024, - PIPE_BIND_CUSTOM, - PIPE_USAGE_STAGING, - VIRGL_RESOURCE_FLAG_STAGING); - if (!vctx->transfer_uploader) - goto fail; + virgl_staging_init(&vctx->staging, &vctx->base, 1024 * 1024); + vctx->supports_staging = true; } vctx->hw_sub_ctx_id = rs->sub_ctx_id++; diff --git a/src/gallium/drivers/virgl/virgl_context.h b/src/gallium/drivers/virgl/virgl_context.h index 70807c5256c..8ea3e1e2f6e 100644 --- a/src/gallium/drivers/virgl/virgl_context.h +++ b/src/gallium/drivers/virgl/virgl_context.h @@ -28,6 +28,7 @@ #include "util/slab.h" #include "util/list.h" +#include "virgl_staging_mgr.h" #include "virgl_transfer_queue.h" struct pipe_screen; @@ -81,9 +82,9 @@ struct virgl_context { struct slab_child_pool transfer_pool; struct virgl_transfer_queue queue; struct u_upload_mgr *uploader; - struct u_upload_mgr *transfer_uploader; - bool transfer_uploader_in_use; + struct virgl_staging_mgr staging; bool encoded_transfers; + bool supports_staging; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; unsigned num_vertex_buffers; diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c index 24f388f86ec..6199257a7c8 100644 --- a/src/gallium/drivers/virgl/virgl_resource.c +++ b/src/gallium/drivers/virgl/virgl_resource.c @@ -27,6 +27,7 @@ #include "virgl_context.h" #include "virgl_resource.h" #include "virgl_screen.h" +#include "virgl_staging_mgr.h" /* A (soft) limit for the amount of memory we want to allow for queued staging * resources. This is used to decide when we should force a flush, in order to @@ -144,8 +145,7 @@ virgl_resource_transfer_prepare(struct virgl_context *vctx, if (xfer->base.usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { can_realloc = virgl_can_rebind_resource(vctx, &res->u.b); } else { - can_staging = vctx->transfer_uploader && - !vctx->transfer_uploader_in_use; + can_staging = vctx->supports_staging; } /* discard implies no readback */ @@ -564,20 +564,19 @@ static unsigned virgl_transfer_map_size(struct virgl_transfer *vtransfer, return size; } -/* Maps a region from the transfer uploader to service the transfer. */ -void *virgl_transfer_uploader_map(struct virgl_context *vctx, - struct virgl_transfer *vtransfer) +/* Maps a region from staging to service the transfer. */ +void *virgl_staging_map(struct virgl_context *vctx, + struct virgl_transfer *vtransfer) { struct virgl_resource *vres = virgl_resource(vtransfer->base.resource); - struct pipe_resource *copy_src_res = NULL; unsigned size; unsigned align_offset; unsigned stride; unsigned layer_stride; void *map_addr; + bool alloc_succeeded; - assert(vctx->transfer_uploader); - assert(!vctx->transfer_uploader_in_use); + assert(vctx->supports_staging); size = virgl_transfer_map_size(vtransfer, &stride, &layer_stride); @@ -598,18 +597,13 @@ void *virgl_transfer_uploader_map(struct virgl_context *vctx, vtransfer->base.box.x % VIRGL_MAP_BUFFER_ALIGNMENT : 0; - u_upload_alloc(vctx->transfer_uploader, 0, size + align_offset, - VIRGL_MAP_BUFFER_ALIGNMENT, - &vtransfer->copy_src_offset, - ©_src_res, &map_addr); - if (map_addr) { - struct virgl_winsys *vws = virgl_screen(vctx->base.screen)->vws; - - /* Extract and reference the hw_res backing the pipe_resource. */ - vws->resource_reference(vws, &vtransfer->copy_src_hw_res, - virgl_resource(copy_src_res)->hw_res); - pipe_resource_reference(©_src_res, NULL); - + alloc_succeeded = + virgl_staging_alloc(&vctx->staging, size + align_offset, + VIRGL_MAP_BUFFER_ALIGNMENT, + &vtransfer->copy_src_offset, + &vtransfer->copy_src_hw_res, + &map_addr); + if (alloc_succeeded) { /* Update source offset and address to point to the requested x coordinate * if we have an align_offset (see above for more information). */ vtransfer->copy_src_offset += align_offset; @@ -621,10 +615,6 @@ void *virgl_transfer_uploader_map(struct virgl_context *vctx, */ virgl_resource_dirty(vres, vtransfer->base.level); - /* The pointer returned by u_upload_alloc already has +offset - * applied. */ - vctx->transfer_uploader_in_use = true; - /* We are using the minimum required size to hold the contents, * possibly using a layout different from the layout of the resource, * so update the transfer strides accordingly. diff --git a/src/gallium/drivers/virgl/virgl_resource.h b/src/gallium/drivers/virgl/virgl_resource.h index d390f1ce3cd..47aefb4bd38 100644 --- a/src/gallium/drivers/virgl/virgl_resource.h +++ b/src/gallium/drivers/virgl/virgl_resource.h @@ -190,8 +190,8 @@ boolean virgl_resource_get_handle(struct pipe_screen *screen, void virgl_resource_dirty(struct virgl_resource *res, uint32_t level); -void *virgl_transfer_uploader_map(struct virgl_context *vctx, - struct virgl_transfer *vtransfer); +void *virgl_staging_map(struct virgl_context *vctx, + struct virgl_transfer *vtransfer); bool virgl_resource_realloc(struct virgl_context *vctx, diff --git a/src/gallium/drivers/virgl/virgl_texture.c b/src/gallium/drivers/virgl/virgl_texture.c index 1553d41a072..8a85a28cec4 100644 --- a/src/gallium/drivers/virgl/virgl_texture.c +++ b/src/gallium/drivers/virgl/virgl_texture.c @@ -149,7 +149,7 @@ static void *texture_transfer_map_plain(struct pipe_context *ctx, map_addr = NULL; break; case VIRGL_TRANSFER_MAP_STAGING: - map_addr = virgl_transfer_uploader_map(vctx, trans); + map_addr = virgl_staging_map(vctx, trans); /* Copy transfers don't make use of hw_res_map at the moment. */ trans->hw_res_map = NULL; break; @@ -317,12 +317,9 @@ static void virgl_texture_transfer_unmap(struct pipe_context *ctx, struct pipe_resource *res = transfer->resource; bool queue_unmap = false; - /* We don't need to transfer the contents of staging buffers, since they - * don't have any host-side storage. */ - if (pipe_to_virgl_bind(vs, res->bind, res->flags) == VIRGL_BIND_STAGING) { - virgl_resource_destroy_transfer(vctx, trans); - return; - } + /* We don't transfer the contents of staging resources, since they don't + * have any host-side storage. */ + assert(pipe_to_virgl_bind(vs, res->bind, res->flags) != VIRGL_BIND_STAGING); if (transfer->usage & PIPE_TRANSFER_WRITE && (transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT) == 0) { @@ -357,8 +354,6 @@ static void virgl_texture_transfer_unmap(struct pipe_context *ctx, if (queue_unmap) { if (trans->copy_src_hw_res) { virgl_encode_copy_transfer(vctx, trans); - /* It's now safe for other mappings to use the transfer_uploader. */ - vctx->transfer_uploader_in_use = false; virgl_resource_destroy_transfer(vctx, trans); } else { virgl_transfer_queue_unmap(&vctx->queue, trans);