virgl: use transfer queue
authorGurchetan Singh <gurchetansingh@chromium.org>
Thu, 3 Jan 2019 18:31:06 +0000 (10:31 -0800)
committerGert Wollny <gert.wollny@collabora.com>
Fri, 15 Feb 2019 10:19:05 +0000 (11:19 +0100)
This improves Unigine Valley benchmark by 3 to 10 fps (depending
on the scene).

It also improves the Team Fortress 2 benchmark from 6 fps to 13
fps (host: 20 fps).

Reviewed-by: Gert Wollny <gert.wollny@collabora.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_texture.c

index 269a451ac18c91e71fb5e0d093dac2fac2ca3372..c500b1c297a92a47f1509ed7cbb11d55d807b533 100644 (file)
@@ -83,8 +83,10 @@ static void virgl_buffer_transfer_unmap(struct pipe_context *ctx,
    if (trans->base.usage & PIPE_TRANSFER_WRITE) {
       struct virgl_screen *vs = virgl_screen(ctx->screen);
       if (transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT) {
-         if (trans->range.end <= trans->range.start)
-            goto out;
+         if (trans->range.end <= trans->range.start) {
+            virgl_resource_destroy_transfer(&vctx->transfer_pool, trans);
+            return;
+         }
 
          transfer->box.x += trans->range.start;
          transfer->box.width = trans->range.end - trans->range.start;
@@ -92,21 +94,15 @@ static void virgl_buffer_transfer_unmap(struct pipe_context *ctx,
       }
 
       vctx->num_transfers++;
-      vs->vws->transfer_put(vs->vws, vbuf->hw_res,
-                            &transfer->box, trans->base.stride,
-                            trans->l_stride, trans->offset,
-                            transfer->level);
-
+      virgl_transfer_queue_unmap(&vctx->queue, trans);
    }
-
-out:
-   virgl_resource_destroy_transfer(&vctx->transfer_pool, trans);
 }
 
 static void virgl_buffer_transfer_flush_region(struct pipe_context *ctx,
                                                struct pipe_transfer *transfer,
                                                const struct pipe_box *box)
 {
+   struct virgl_context *vctx = virgl_context(ctx);
    struct virgl_resource *vbuf = virgl_resource(transfer->resource);
    struct virgl_transfer *trans = virgl_transfer(transfer);
 
index afc9fe883f7725f9c605a1e8a654d60741cfd705..4c74b16d01db330e58200c4f4358f854e81b183e 100644 (file)
@@ -762,12 +762,17 @@ static void virgl_flush_eq(struct virgl_context *ctx, void *closure,
    /* send the buffer to the remote side for decoding */
    ctx->num_transfers = ctx->num_draws = ctx->num_compute = 0;
 
+   virgl_transfer_queue_clear(&ctx->queue, ctx->cbuf);
    rs->vws->submit_cmd(rs->vws, ctx->cbuf, ctx->cbuf->in_fence_fd,
                        ctx->cbuf->needs_out_fence_fd ? &out_fence_fd : NULL);
 
    if (fence)
       *fence = rs->vws->cs_create_fence(rs->vws, out_fence_fd);
 
+   /* Reserve some space for transfers. */
+   if (ctx->encoded_transfers)
+      ctx->cbuf->cdw = VIRGL_MAX_TBUF_DWORDS;
+
    virgl_encoder_set_sub_ctx(ctx, ctx->hw_sub_ctx_id);
 
    /* add back current framebuffer resources to reference list? */
@@ -1190,6 +1195,7 @@ virgl_context_destroy( struct pipe_context *ctx )
    if (vctx->uploader)
       u_upload_destroy(vctx->uploader);
    util_primconvert_destroy(vctx->primconvert);
+   virgl_transfer_queue_fini(&vctx->queue);
 
    slab_destroy_child(&vctx->transfer_pool);
    FREE(vctx);
@@ -1333,6 +1339,13 @@ struct pipe_context *virgl_context_create(struct pipe_screen *pscreen,
    virgl_init_so_functions(vctx);
 
    slab_create_child(&vctx->transfer_pool, &rs->transfer_pool);
+   virgl_transfer_queue_init(&vctx->queue, rs, &vctx->transfer_pool);
+   vctx->encoded_transfers = (rs->vws->supports_encoded_transfers &&
+                       (rs->caps.caps.v2.capability_bits & VIRGL_CAP_TRANSFER));
+
+   /* Reserve some space for transfers. */
+   if (vctx->encoded_transfers)
+      vctx->cbuf->cdw = VIRGL_MAX_TBUF_DWORDS;
 
    vctx->primconvert = util_primconvert_create(&vctx->base, rs->caps.caps.v1.prim_mask);
    vctx->uploader = u_upload_create(&vctx->base, 1024 * 1024,
index 65485475d9d18be317e9f8498f292af0452f6b67..f42a719966db46d7ee552ae4cedacf24643f49f9 100644 (file)
@@ -28,6 +28,8 @@
 #include "util/slab.h"
 #include "util/list.h"
 
+#include "virgl_transfer_queue.h"
+
 struct pipe_screen;
 struct tgsi_token;
 struct u_upload_mgr;
@@ -64,8 +66,9 @@ struct virgl_context {
    struct pipe_framebuffer_state framebuffer;
 
    struct slab_child_pool transfer_pool;
-
+   struct virgl_transfer_queue queue;
    struct u_upload_mgr *uploader;
+   bool encoded_transfers;
 
    struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
    unsigned num_vertex_buffers;
index ddb6b77b7691d470dfff4469605e21d417db8cb8..a21e9111769e6d1d636f6edca0d3485cca83d815 100644 (file)
@@ -40,6 +40,8 @@ bool virgl_res_needs_flush_wait(struct virgl_context *vctx,
    if (res->clean[trans->base.level]) {
       if (vctx->num_draws == 0 && vctx->num_compute == 0)
          return false;
+      if (!virgl_transfer_queue_is_queued(&vctx->queue, trans))
+         return false;
    }
 
    return true;
index 3bffee9b7a54955938622108623612e2228d5e60..c661ca91752bae44dd2e2a610b846c393d56c924 100644 (file)
@@ -166,18 +166,22 @@ static void virgl_texture_transfer_unmap(struct pipe_context *ctx,
       if (!(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) {
          struct virgl_screen *vs = virgl_screen(ctx->screen);
          vctx->num_transfers++;
-         vs->vws->transfer_put(vs->vws, vtex->hw_res,
-                               &transfer->box, trans->base.stride,
-                               trans->l_stride, trans->offset,
-                               transfer->level);
 
+         if (trans->resolve_tmp) {
+            vs->vws->transfer_put(vs->vws, vtex->hw_res,
+                                  &transfer->box, trans->base.stride,
+                                  trans->l_stride, trans->offset,
+                                  transfer->level);
+         } else {
+            virgl_transfer_queue_unmap(&vctx->queue, trans);
+         }
       }
    }
 
-   if (trans->resolve_tmp)
+   if (trans->resolve_tmp) {
       pipe_resource_reference((struct pipe_resource **)&trans->resolve_tmp, NULL);
-
-   virgl_resource_destroy_transfer(&vctx->transfer_pool, trans);
+      virgl_resource_destroy_transfer(&vctx->transfer_pool, trans);
+   }
 }
 
 static const struct u_resource_vtbl virgl_texture_vtbl =