virgl: fix stride + layer_stride inconsistency

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>
This commit is contained in:
Gurchetan Singh 2019-10-01 18:03:11 -07:00
parent 87383e3163
commit 5c2129d434
3 changed files with 41 additions and 6 deletions

View 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);
}

View 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);
}

View 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;