virgl: add virgl_resource_transfer_prepare
authorChia-I Wu <olvaffe@gmail.com>
Thu, 9 May 2019 20:27:34 +0000 (13:27 -0700)
committerChia-I Wu <olvaffe@gmail.com>
Wed, 15 May 2019 20:51:28 +0000 (20:51 +0000)
virgl_resource_transfer_prepare should be called before mapping to
prepare the resource.  It does flush, readback, and wait as needed.
virgl_res_needs_flush and virgl_res_needs_readback become internal
helpers to the new function.

There should be no externally visible change.

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Reviewed-by: Alexandros Frantzis <alexandros.frantzis@collabora.com>
src/gallium/drivers/virgl/virgl_buffer.c
src/gallium/drivers/virgl/virgl_resource.c
src/gallium/drivers/virgl/virgl_resource.h
src/gallium/drivers/virgl/virgl_texture.c

index f955b7c624b57a0842c5702a3066b91910d377f8..2b559e584687589353e643e3c3532e216d0f5487 100644 (file)
@@ -38,33 +38,11 @@ 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;
-   bool readback;
-   bool flush = false;
 
    trans = virgl_resource_create_transfer(&vctx->transfer_pool, resource,
                                           &vbuf->metadata, level, usage, box);
 
-   flush = virgl_res_needs_flush(vctx, trans);
-   if (flush)
-      ctx->flush(ctx, NULL, 0);
-
-   readback = virgl_res_needs_readback(vctx, vbuf, usage, 0);
-   if (readback)
-      vs->vws->transfer_get(vs->vws, vbuf->hw_res, box, trans->base.stride,
-                            trans->l_stride, trans->offset, level);
-
-   /* XXX Consider
-    *
-    *   glBufferSubData(GL_ARRAY_BUFFER, 0, 12, data1);
-    *   glDrawArrays(..);
-    *   glFlush();
-    *   glBufferSubData(GL_ARRAY_BUFFER, 0, 12, data2)
-    *
-    * readback and flush are both false in the second glBufferSubData call.
-    * The draw call might end up seeing data2.
-    */
-   if (readback || flush)
-      vs->vws->resource_wait(vs->vws, vbuf->hw_res);
+   virgl_resource_transfer_prepare(vctx, trans);
 
    trans->hw_res_map = vs->vws->resource_map(vs->vws, vbuf->hw_res);
    if (!trans->hw_res_map) {
index 5d1ee234ea28d55b2f4aebabeeeb1552ef05cfbd..07ae20177bf3f4094bf2614ebfc3b54820c5f1c6 100644 (file)
@@ -38,8 +38,8 @@
  *    cmdbuf has no command that accesses the region (XXX we cannot just check
  *    for overlapping transfers)
  */
-bool virgl_res_needs_flush(struct virgl_context *vctx,
-                           struct virgl_transfer *trans)
+static bool virgl_res_needs_flush(struct virgl_context *vctx,
+                                  struct virgl_transfer *trans)
 {
    struct virgl_winsys *vws = virgl_screen(vctx->base.screen)->vws;
    struct virgl_resource *res = virgl_resource(trans->base.resource);
@@ -89,9 +89,9 @@ bool virgl_res_needs_flush(struct virgl_context *vctx,
  * PIPE_TRANSFER_READ becomes irrelevant.  PIPE_TRANSFER_UNSYNCHRONIZED and
  * PIPE_TRANSFER_FLUSH_EXPLICIT are also irrelevant.
  */
-bool virgl_res_needs_readback(struct virgl_context *vctx,
-                              struct virgl_resource *res,
-                              unsigned usage, unsigned level)
+static bool virgl_res_needs_readback(struct virgl_context *vctx,
+                                     struct virgl_resource *res,
+                                     unsigned usage, unsigned level)
 {
    if (usage & (PIPE_TRANSFER_DISCARD_RANGE |
                 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE))
@@ -103,6 +103,45 @@ bool virgl_res_needs_readback(struct virgl_context *vctx,
    return true;
 }
 
+void
+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);
+   bool flush;
+   bool readback;
+   bool wait;
+
+   flush = virgl_res_needs_flush(vctx, xfer);
+   readback = virgl_res_needs_readback(vctx, res, xfer->base.usage,
+                                       xfer->base.level);
+
+   /* XXX This is incorrect.  Consider
+    *
+    *   glTexImage2D(..., data1);
+    *   glDrawArrays();
+    *   glFlush();
+    *   glTexImage2D(..., data2);
+    *
+    * readback and flush are both false in the second glTexImage2D call.  The
+    * draw call might end up seeing data2.  Same applies to buffers with
+    * glBufferSubData.
+    */
+   wait = flush || readback;
+
+   if (flush)
+      vctx->base.flush(&vctx->base, NULL, 0);
+
+   if (readback) {
+      vws->transfer_get(vws, res->hw_res, &xfer->base.box, xfer->base.stride,
+                        xfer->l_stride, xfer->offset, xfer->base.level);
+   }
+
+   if (wait)
+      vws->resource_wait(vws, res->hw_res);
+}
+
 static struct pipe_resource *virgl_resource_create(struct pipe_screen *screen,
                                                    const struct pipe_resource *templ)
 {
index 380e145564a6466d25b373c31d102280d428f0f4..fda795b6b5e018d8e58afa06a9e6fe31fff5cce3 100644 (file)
@@ -117,11 +117,9 @@ static inline unsigned pipe_to_virgl_bind(const struct virgl_screen *vs, unsigne
    return outbind;
 }
 
-bool virgl_res_needs_flush(struct virgl_context *vctx,
-                           struct virgl_transfer *transfer);
-bool virgl_res_needs_readback(struct virgl_context *vctx,
-                              struct virgl_resource *res,
-                              unsigned usage, unsigned level);
+void
+virgl_resource_transfer_prepare(struct virgl_context *vctx,
+                                struct virgl_transfer *xfer);
 
 void virgl_resource_layout(struct pipe_resource *pt,
                            struct virgl_resource_metadata *metadata);
index 53cd038e500d09db06cd7cb59296ba8372084ed7..c2bdc3ef9e239f3b33bb0b0e97554662b9d286cd 100644 (file)
@@ -126,7 +126,6 @@ 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;
-   bool flush, readback;
 
    trans = virgl_resource_create_transfer(&vctx->transfer_pool, resource,
                                           &vtex->metadata, level, usage, box);
@@ -134,27 +133,7 @@ static void *texture_transfer_map_plain(struct pipe_context *ctx,
 
    assert(resource->nr_samples <= 1);
 
-   flush = virgl_res_needs_flush(vctx, trans);
-   if (flush)
-      ctx->flush(ctx, NULL, 0);
-
-   readback = virgl_res_needs_readback(vctx, vtex, usage, level);
-   if (readback)
-      vws->transfer_get(vws, vtex->hw_res, box, trans->base.stride,
-                        trans->l_stride, trans->offset, level);
-
-   /* XXX Consider
-    *
-    *   glTexImage2D(..., data1);
-    *   glDrawArrays();
-    *   glFlush();
-    *   glTexImage2D(..., data2);
-    *
-    * readback and flush are both false in the second glTexImage2D call.  The
-    * draw call might end up seeing data2.
-    */
-   if (readback || flush)
-      vws->resource_wait(vws, vtex->hw_res);
+   virgl_resource_transfer_prepare(vctx, trans);
 
    trans->hw_res_map = vws->resource_map(vws, vtex->hw_res);
    if (!trans->hw_res_map) {