Mesa (master): virgl: add support for VIRGL_CAP_V2_UNTYPED_RESOURCE

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jan 22 21:35:26 UTC 2021


Module: Mesa
Branch: master
Commit: d37124b065c2b6c99c042fb402c6a23ce16b034e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d37124b065c2b6c99c042fb402c6a23ce16b034e

Author: Chia-I Wu <olvaffe at gmail.com>
Date:   Thu Dec 24 15:37:15 2020 -0800

virgl: add support for VIRGL_CAP_V2_UNTYPED_RESOURCE

An untyped resource is a blob resource that contains only raw bytes
without type information (e.g., width, height, format, etc.).  virgl
supports only typed resources, and when it encounters untyped resources,
it fails silently in the host.

This cap enables virgl to assign type information to untyped resources.

Signed-off-by: Chia-I Wu <olvaffe at gmail.com>
Reviewed-By: Isaac Bosompem <mrisaacb at google.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8584>

---

 src/gallium/drivers/virgl/virgl_resource.c      | 43 ++++++++++++++++++
 src/gallium/drivers/virgl/virgl_winsys.h        | 10 +++++
 src/gallium/winsys/virgl/drm/virgl_drm_winsys.c | 60 +++++++++++++++++++++++++
 src/gallium/winsys/virgl/drm/virgl_drm_winsys.h |  3 ++
 4 files changed, 116 insertions(+)

diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c
index 469ef75953f..501d69f57af 100644
--- a/src/gallium/drivers/virgl/virgl_resource.c
+++ b/src/gallium/drivers/virgl/virgl_resource.c
@@ -582,6 +582,49 @@ static struct pipe_resource *virgl_resource_from_handle(struct pipe_screen *scre
       return NULL;
    }
 
+   /* assign blob resource a type in case it was created untyped */
+   if (res->blob_mem && plane == 0 &&
+       (vs->caps.caps.v2.capability_bits_v2 & VIRGL_CAP_V2_UNTYPED_RESOURCE)) {
+      uint32_t plane_strides[VIRGL_MAX_PLANE_COUNT];
+      uint32_t plane_offsets[VIRGL_MAX_PLANE_COUNT];
+      uint32_t plane_count = 0;
+      struct pipe_resource *iter = &res->u.b;
+
+      do {
+         struct virgl_resource *plane = virgl_resource(iter);
+
+         /* must be a plain 2D texture sharing the same hw_res */
+         if (plane->u.b.target != PIPE_TEXTURE_2D ||
+             plane->u.b.depth0 != 1 ||
+             plane->u.b.array_size != 1 ||
+             plane->u.b.last_level != 0 ||
+             plane->u.b.nr_samples > 1 ||
+             plane->hw_res != res->hw_res ||
+             plane_count >= VIRGL_MAX_PLANE_COUNT) {
+            vs->vws->resource_reference(vs->vws, &res->hw_res, NULL);
+            FREE(res);
+            return NULL;
+         }
+
+         plane_strides[plane_count] = plane->metadata.stride[0];
+         plane_offsets[plane_count] = plane->metadata.plane_offset;
+         plane_count++;
+         iter = iter->next;
+      } while (iter);
+
+      vs->vws->resource_set_type(vs->vws,
+                                 res->hw_res,
+                                 pipe_to_virgl_format(res->u.b.format),
+                                 pipe_to_virgl_bind(vs, res->u.b.bind),
+                                 res->u.b.width0,
+                                 res->u.b.height0,
+                                 usage,
+                                 res->metadata.modifier,
+                                 plane_count,
+                                 plane_strides,
+                                 plane_offsets);
+   }
+
    virgl_texture_init(res);
 
    return &res->u.b;
diff --git a/src/gallium/drivers/virgl/virgl_winsys.h b/src/gallium/drivers/virgl/virgl_winsys.h
index 29f2ed8d930..0754e0d608e 100644
--- a/src/gallium/drivers/virgl/virgl_winsys.h
+++ b/src/gallium/drivers/virgl/virgl_winsys.h
@@ -33,6 +33,7 @@ struct virgl_hw_res;
 
 #define VIRGL_MAX_TBUF_DWORDS 1024
 #define VIRGL_MAX_CMDBUF_DWORDS ((64 * 1024) + VIRGL_MAX_TBUF_DWORDS)
+#define VIRGL_MAX_PLANE_COUNT 3
 
 struct virgl_drm_caps {
    union virgl_caps caps;
@@ -87,6 +88,15 @@ struct virgl_winsys {
                                                        uint32_t *plane_offset,
                                                        uint64_t *modifier,
                                                        uint32_t *blob_mem);
+   void (*resource_set_type)(struct virgl_winsys *vws,
+                             struct virgl_hw_res *res,
+                             uint32_t format, uint32_t bind,
+                             uint32_t width, uint32_t height,
+                             uint32_t usage, uint64_t modifier,
+                             uint32_t plane_count,
+                             const uint32_t *plane_strides,
+                             const uint32_t *plane_offsets);
+
    boolean (*resource_get_handle)(struct virgl_winsys *vws,
                                   struct virgl_hw_res *res,
                                   uint32_t stride,
diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c
index 2be575fb21d..bf79ba7ddf7 100644
--- a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c
+++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c
@@ -210,6 +210,7 @@ virgl_drm_winsys_resource_create_blob(struct virgl_winsys *qws,
    res->bo_handle = drm_rc_blob.bo_handle;
    res->size = size;
    res->flags = flags;
+   res->maybe_untyped = false;
    pipe_reference_init(&res->reference, 1);
    p_atomic_set(&res->external, false);
    p_atomic_set(&res->num_cs_references, 0);
@@ -267,6 +268,7 @@ virgl_drm_winsys_resource_create(struct virgl_winsys *qws,
    res->bo_handle = createcmd.bo_handle;
    res->size = size;
    res->target = target;
+   res->maybe_untyped = false;
    pipe_reference_init(&res->reference, 1);
    p_atomic_set(&res->external, false);
    p_atomic_set(&res->num_cs_references, 0);
@@ -425,6 +427,10 @@ virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws,
    struct virgl_hw_res *res = NULL;
    uint32_t handle = whandle->handle;
 
+   if (whandle->plane >= VIRGL_MAX_PLANE_COUNT) {
+      return NULL;
+   }
+
    if (whandle->offset != 0 && whandle->type == WINSYS_HANDLE_TYPE_SHARED) {
       _debug_printf("attempt to import unsupported winsys offset %u\n",
                     whandle->offset);
@@ -496,6 +502,7 @@ virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws,
    *blob_mem = info_arg.blob_mem;
 
    res->size = info_arg.size;
+   res->maybe_untyped = info_arg.blob_mem ? true : false;
    pipe_reference_init(&res->reference, 1);
    p_atomic_set(&res->external, true);
    res->num_cs_references = 0;
@@ -509,6 +516,58 @@ done:
    return res;
 }
 
+static void
+virgl_drm_winsys_resource_set_type(struct virgl_winsys *qws,
+                                   struct virgl_hw_res *res,
+                                   uint32_t format, uint32_t bind,
+                                   uint32_t width, uint32_t height,
+                                   uint32_t usage, uint64_t modifier,
+                                   uint32_t plane_count,
+                                   const uint32_t *plane_strides,
+                                   const uint32_t *plane_offsets)
+{
+   struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws);
+   uint32_t cmd[VIRGL_PIPE_RES_SET_TYPE_SIZE(VIRGL_MAX_PLANE_COUNT)];
+   struct drm_virtgpu_execbuffer eb;
+   int ret;
+
+   mtx_lock(&qdws->bo_handles_mutex);
+
+   if (!res->maybe_untyped) {
+      mtx_unlock(&qdws->bo_handles_mutex);
+      return;
+   }
+   res->maybe_untyped = false;
+
+   assert(plane_count && plane_count <= VIRGL_MAX_PLANE_COUNT);
+
+   cmd[0] = VIRGL_CMD0(VIRGL_CCMD_PIPE_RESOURCE_SET_TYPE, 0, VIRGL_PIPE_RES_SET_TYPE_SIZE(plane_count));
+   cmd[VIRGL_PIPE_RES_SET_TYPE_RES_HANDLE] = res->res_handle,
+   cmd[VIRGL_PIPE_RES_SET_TYPE_FORMAT] = format;
+   cmd[VIRGL_PIPE_RES_SET_TYPE_BIND] = bind;
+   cmd[VIRGL_PIPE_RES_SET_TYPE_WIDTH] = width;
+   cmd[VIRGL_PIPE_RES_SET_TYPE_HEIGHT] = height;
+   cmd[VIRGL_PIPE_RES_SET_TYPE_USAGE] = usage;
+   cmd[VIRGL_PIPE_RES_SET_TYPE_MODIFIER_LO] = (uint32_t)modifier;
+   cmd[VIRGL_PIPE_RES_SET_TYPE_MODIFIER_HI] = (uint32_t)(modifier >> 32);
+   for (uint32_t i = 0; i < plane_count; i++) {
+      cmd[VIRGL_PIPE_RES_SET_TYPE_PLANE_STRIDE(i)] = plane_strides[i];
+      cmd[VIRGL_PIPE_RES_SET_TYPE_PLANE_OFFSET(i)] = plane_offsets[i];
+   }
+
+   memset(&eb, 0, sizeof(eb));
+   eb.command = (uintptr_t)cmd;
+   eb.size = (1 + VIRGL_PIPE_RES_SET_TYPE_SIZE(plane_count)) * 4;
+   eb.num_bo_handles = 1;
+   eb.bo_handles = (uintptr_t)&res->bo_handle;
+
+   ret = drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &eb);
+   if (ret == -1)
+      _debug_printf("failed to set resource type: %s", errno);
+
+   mtx_unlock(&qdws->bo_handles_mutex);
+}
+
 static boolean virgl_drm_winsys_resource_get_handle(struct virgl_winsys *qws,
                                                     struct virgl_hw_res *res,
                                                     uint32_t stride,
@@ -1091,6 +1150,7 @@ virgl_drm_winsys_create(int drmFD)
    qdws->base.resource_create = virgl_drm_winsys_resource_cache_create;
    qdws->base.resource_reference = virgl_drm_resource_reference;
    qdws->base.resource_create_from_handle = virgl_drm_winsys_resource_create_handle;
+   qdws->base.resource_set_type = virgl_drm_winsys_resource_set_type;
    qdws->base.resource_get_handle = virgl_drm_winsys_resource_get_handle;
    qdws->base.resource_map = virgl_drm_resource_map;
    qdws->base.resource_wait = virgl_drm_resource_wait;
diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h
index 1d7f03de264..28fb9715aaf 100644
--- a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h
+++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h
@@ -48,6 +48,9 @@ struct virgl_hw_res {
    uint32_t flags;
    uint32_t flink_name;
 
+   /* false when the resource is known to be typed */
+   bool maybe_untyped;
+
    /* true when the resource is imported or exported */
    int external;
 



More information about the mesa-commit mailing list