virgl: fix stride + layer_stride inconsistency
authorGurchetan Singh <gurchetansingh@chromium.org>
Wed, 2 Oct 2019 01:03:11 +0000 (18:03 -0700)
committerGurchetan Singh <gurchetansingh@chromium.org>
Thu, 1 Oct 2020 23:56:37 +0000 (16:56 -0700)
With blob resources, stride doesn't necesarily have to
equal width * bpp.  The use case for this a minigbm blob
resource with blob mem BLOB_MEM_HOST3D_GUEST imported into
guest Mesa.  In addition, for BLOB_MEM_HOST we can repurpose
the transfer ioctls to also flush caches if need be, so this
seems a good time to fix this issue.

Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4821>

src/gallium/drivers/virgl/virgl_encode.c
src/gallium/winsys/virgl/drm/virgl_drm_winsys.c
src/gallium/winsys/virgl/drm/virgl_drm_winsys.h

index 2d1b91a..ee75deb 100644 (file)
@@ -1429,10 +1429,18 @@ void virgl_encode_transfer(struct virgl_screen *vs, struct virgl_cmd_buf *buf,
                            struct virgl_transfer *trans, uint32_t direction)
 {
    uint32_t command;
+   struct virgl_resource *vres = virgl_resource(trans->base.resource);
+   enum virgl_transfer3d_encode_stride stride_type =
+        virgl_transfer3d_host_inferred_stride;
+
+   if (trans->base.box.depth == 1 && trans->base.level == 0 &&
+       trans->base.resource->target == PIPE_TEXTURE_2D &&
+       vres->blob_mem == VIRGL_BLOB_MEM_HOST3D_GUEST)
+      stride_type = virgl_transfer3d_explicit_stride;
+
    command = VIRGL_CMD0(VIRGL_CCMD_TRANSFER3D, 0, VIRGL_TRANSFER3D_SIZE);
    virgl_encoder_write_dword(buf, command);
-   virgl_encoder_transfer3d_common(vs, buf, trans,
-                                   virgl_transfer3d_host_inferred_stride);
+   virgl_encoder_transfer3d_common(vs, buf, trans, stride_type);
    virgl_encoder_write_dword(buf, trans->offset);
    virgl_encoder_write_dword(buf, direction);
 }
index a5a672e..6f4b24e 100644 (file)
@@ -265,6 +265,7 @@ virgl_drm_winsys_resource_create(struct virgl_winsys *qws,
    res->res_handle = createcmd.res_handle;
    res->bo_handle = createcmd.bo_handle;
    res->size = size;
+   res->target = target;
    pipe_reference_init(&res->reference, 1);
    p_atomic_set(&res->external, false);
    p_atomic_set(&res->num_cs_references, 0);
@@ -280,6 +281,27 @@ virgl_drm_winsys_resource_create(struct virgl_winsys *qws,
    return res;
 }
 
+/*
+ * Previously, with DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, all host resources had
+ * a guest memory shadow resource with size = stride * bpp.  Virglrenderer
+ * would guess the stride implicitly when performing transfer operations, if
+ * the stride wasn't specified.  Interestingly, vtest would specify the stride.
+ *
+ * Guessing the stride breaks down with YUV images, which may be imported into
+ * Mesa as 3R8 images. It also doesn't work if an external allocator
+ * (i.e, minigbm) decides to use a stride not equal to stride * bpp. With blob
+ * resources, the size = stride * bpp restriction no longer holds, so use
+ * explicit strides passed into Mesa.
+ */
+static inline bool use_explicit_stride(struct virgl_hw_res *res, uint32_t level,
+                                      uint32_t depth)
+{
+   return (params[param_resource_blob].value &&
+           res->blob_mem == VIRTGPU_BLOB_MEM_HOST3D_GUEST &&
+           res->target == PIPE_TEXTURE_2D &&
+           level == 0 && depth == 1);
+}
+
 static int
 virgl_bo_transfer_put(struct virgl_winsys *vws,
                       struct virgl_hw_res *res,
@@ -302,8 +324,10 @@ virgl_bo_transfer_put(struct virgl_winsys *vws,
    tohostcmd.box.d = box->depth;
    tohostcmd.offset = buf_offset;
    tohostcmd.level = level;
-  // tohostcmd.stride = stride;
-  // tohostcmd.layer_stride = stride;
+
+   if (use_explicit_stride(res, level, box->depth))
+      tohostcmd.stride = stride;
+
    return drmIoctl(vdws->fd, DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST, &tohostcmd);
 }
 
@@ -323,14 +347,16 @@ virgl_bo_transfer_get(struct virgl_winsys *vws,
    fromhostcmd.bo_handle = res->bo_handle;
    fromhostcmd.level = level;
    fromhostcmd.offset = buf_offset;
-  // fromhostcmd.stride = stride;
-  // fromhostcmd.layer_stride = layer_stride;
    fromhostcmd.box.x = box->x;
    fromhostcmd.box.y = box->y;
    fromhostcmd.box.z = box->z;
    fromhostcmd.box.w = box->width;
    fromhostcmd.box.h = box->height;
    fromhostcmd.box.d = box->depth;
+
+   if (use_explicit_stride(res, level, box->depth))
+      fromhostcmd.stride = stride;
+
    return drmIoctl(vdws->fd, DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST, &fromhostcmd);
 }
 
index 0f8ecab..1d7f03d 100644 (file)
@@ -36,6 +36,7 @@ struct hash_table;
 
 struct virgl_hw_res {
    struct pipe_reference reference;
+   enum pipe_texture_target target;
    uint32_t res_handle;
    uint32_t bo_handle;
    int num_cs_references;