virgl: Use virgl_staging_mgr
authorAlexandros Frantzis <alexandros.frantzis@collabora.com>
Mon, 24 Jun 2019 13:57:46 +0000 (16:57 +0300)
committerChia-I Wu <olvaffe@gmail.com>
Fri, 28 Jun 2019 04:30:02 +0000 (04:30 +0000)
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 <alexandros.frantzis@collabora.com>
Reviewed-by: Chia-I Wu <olvaffe@gmail.com>
src/gallium/drivers/virgl/virgl_buffer.c
src/gallium/drivers/virgl/virgl_context.c
src/gallium/drivers/virgl/virgl_context.h
src/gallium/drivers/virgl/virgl_resource.c
src/gallium/drivers/virgl/virgl_resource.h
src/gallium/drivers/virgl/virgl_texture.c

index 93ccaeee99587cdaee731ffa39c2a6986f7081f1..bc12f3f887645c92de0c0a20ded5b132115d0a00 100644 (file)
@@ -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);
index 3421c71a43de12a21d2674a786f53cb4aa6db7d3..e511750dc6901f668ed07225fbe1a457d204a20e 100644 (file)
@@ -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++;
index 70807c5256cd3431987cd905a15c13dba6df7441..8ea3e1e2f6ea814153070e326e9400ea3cf95d28 100644 (file)
@@ -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;
index 24f388f86ec57a244b31b311742ebade85ded0b2..6199257a7c8515b05f8b1c1fb6c40c85b26dd6ae 100644 (file)
@@ -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.
index d390f1ce3cd2823e1732dc4e43b43f6b9e88197e..47aefb4bd38849a1ecdd3b5a133d9b41363ccbcb 100644 (file)
@@ -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,
index 1553d41a072b1ea990541e1bd873f5559705c57e..8a85a28cec4809b09760a222d7e21bdeabad043c 100644 (file)
@@ -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);