Commit 5388be03 authored by Alexandros Frantzis's avatar Alexandros Frantzis Committed by Chia-I Wu

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's avatarAlexandros Frantzis <alexandros.frantzis@collabora.com>
Reviewed-by: Chia-I Wu's avatarChia-I Wu <olvaffe@gmail.com>
parent 790d1a0b
......@@ -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);
......
......@@ -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++;
......
......@@ -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;
......
......@@ -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,
&copy_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(&copy_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.
......
......@@ -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,
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment