From 9540139f439ad8adb906203e1deafe056602327c Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 31 Jan 2025 10:19:00 -0800 Subject: [PATCH] freedreno+tu: Add new virtgpu caps Avoid some extra round-trips at startup if the host is new enough. Signed-off-by: Rob Clark Part-of: --- src/freedreno/drm/virtio/virtio_pipe.c | 4 +++- src/freedreno/vulkan/tu_knl_drm_virtio.cc | 25 ++++++++++++++++++----- src/virtio/virtio-gpu/drm_hw.h | 17 +++++++++++++++ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/freedreno/drm/virtio/virtio_pipe.c b/src/freedreno/drm/virtio/virtio_pipe.c index cdeb9139f91..1c20499bc49 100644 --- a/src/freedreno/drm/virtio/virtio_pipe.c +++ b/src/freedreno/drm/virtio/virtio_pipe.c @@ -178,10 +178,12 @@ __open_submitqueue(struct fd_pipe *pipe, uint32_t prio, uint32_t flags) static int open_submitqueue(struct fd_pipe *pipe, uint32_t prio) { + struct virtio_device *virtio_dev = to_virtio_device(pipe->dev); const struct fd_dev_info *info = fd_dev_info_raw(&pipe->dev_id); int ret = -1; - if (info && info->chip >= A7XX) + if (info && info->chip >= A7XX && + (virtio_dev->vdrm->caps.u.msm.has_preemption != VIRTGPU_CAP_BOOL_FALSE)) ret = __open_submitqueue(pipe, prio, MSM_SUBMITQUEUE_ALLOW_PREEMPT); /* If kernel doesn't support preemption, try again without: */ diff --git a/src/freedreno/vulkan/tu_knl_drm_virtio.cc b/src/freedreno/vulkan/tu_knl_drm_virtio.cc index 3a16d0545ac..7bc7c1bf1a9 100644 --- a/src/freedreno/vulkan/tu_knl_drm_virtio.cc +++ b/src/freedreno/vulkan/tu_knl_drm_virtio.cc @@ -267,6 +267,8 @@ tu_drm_get_highest_bank_bit(struct vdrm_device *vdrm) static enum fdl_macrotile_mode tu_drm_get_macrotile_mode(struct vdrm_device *vdrm) { + if (vdrm->caps.u.msm.macrotile_mode) + return (enum fdl_macrotile_mode)vdrm->caps.u.msm.macrotile_mode; uint64_t value; int ret = tu_drm_get_param(vdrm, MSM_PARAM_MACROTILE_MODE, &value); if (ret) @@ -278,6 +280,8 @@ tu_drm_get_macrotile_mode(struct vdrm_device *vdrm) static uint32_t tu_drm_get_ubwc_swizzle(struct vdrm_device *vdrm) { + if (vdrm->caps.u.msm.ubwc_swizzle) + return (uint32_t)vdrm->caps.u.msm.ubwc_swizzle; uint64_t value; int ret = tu_drm_get_param(vdrm, MSM_PARAM_UBWC_SWIZZLE, &value); if (ret) @@ -299,10 +303,19 @@ virtio_device_get_suspend_count(struct tu_device *dev, uint64_t *suspend_count) return ret; } +static bool +opt_cap_bool(uint32_t val) +{ + if (val == VIRTGPU_CAP_BOOL_TRUE) return true; + if (val == VIRTGPU_CAP_BOOL_FALSE) return false; + unreachable("invalid val"); +} static bool tu_drm_get_raytracing(struct vdrm_device *vdrm) { + if (vdrm->caps.u.msm.has_raytracing) + return opt_cap_bool(vdrm->caps.u.msm.has_raytracing); uint64_t value; int ret = tu_drm_get_param(vdrm, MSM_PARAM_RAYTRACING, &value); if (ret) @@ -357,6 +370,8 @@ virtio_submitqueue_close(struct tu_device *dev, uint32_t queue_id) static bool virtio_has_preemption(struct vdrm_device *vdrm) { + if (vdrm->caps.u.msm.has_preemption) + return opt_cap_bool(vdrm->caps.u.msm.has_preemption); struct drm_msm_submitqueue req = { .flags = MSM_SUBMITQUEUE_ALLOW_PREEMPT, .prio = vdrm->caps.u.msm.priorities / 2, @@ -1145,9 +1160,6 @@ tu_knl_drm_virtio_load(struct tu_instance *instance, caps = vdrm->caps; - /* TODO add something to virgl_renderer_capset_drm to avoid round-trip to - * host if virglrenderer is new enough. - */ bool has_preemption = virtio_has_preemption(vdrm); /* If virglrenderer is too old, we may need another round-trip to get this. @@ -1155,11 +1167,9 @@ tu_knl_drm_virtio_load(struct tu_instance *instance, if (caps.u.msm.highest_bank_bit == 0) caps.u.msm.highest_bank_bit = tu_drm_get_highest_bank_bit(vdrm); - /* TODO add these to the caps struct */ uint32_t bank_swizzle_levels = tu_drm_get_ubwc_swizzle(vdrm); enum fdl_macrotile_mode macrotile_mode = tu_drm_get_macrotile_mode(vdrm); - /* TODO add a cap for this */ bool has_raytracing = tu_drm_get_raytracing(vdrm); vdrm_device_close(vdrm); @@ -1177,6 +1187,11 @@ tu_knl_drm_virtio_load(struct tu_instance *instance, mesa_logd("chip_id: 0x%0" PRIx64, caps.u.msm.chip_id); mesa_logd("max_freq: %u", caps.u.msm.max_freq); mesa_logd("highest_bank_bit: %u", caps.u.msm.highest_bank_bit); + mesa_logd("ubwc_swizzle: 0x%" PRIx64, caps.u.msm.ubwc_swizzle); + mesa_logd("macrotile_mode: %" PRIu64, caps.u.msm.macrotile_mode); + mesa_logd("has_raytracing: %x", caps.u.msm.has_raytracing); + mesa_logd("has_preemption: %d", caps.u.msm.has_preemption); + mesa_logd("uche_trap_base: 0x%" PRIx64, caps.u.msm.uche_trap_base); if (caps.wire_format_version != 2) { return vk_startup_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER, diff --git a/src/virtio/virtio-gpu/drm_hw.h b/src/virtio/virtio-gpu/drm_hw.h index 33a90842738..157465b8b0d 100644 --- a/src/virtio/virtio-gpu/drm_hw.h +++ b/src/virtio/virtio-gpu/drm_hw.h @@ -10,6 +10,18 @@ #include #endif +/** + * When adding new caps to the end of the capset struct, a value of + * zero should be the fallback. Ie. a newer guest on an older host + * will see a zero value. + * + * For boolean caps, use 1/~0 for true/false + */ +#define VIRTGPU_CAP_BOOL_UNSUPPORTED_BY_HOST 0 +#define VIRTGPU_CAP_BOOL_FALSE ~0 +#define VIRTGPU_CAP_BOOL_TRUE 1 + + struct virgl_renderer_capset_drm { uint32_t wire_format_version; /* Underlying drm device version: */ @@ -32,6 +44,11 @@ struct virgl_renderer_capset_drm { uint64_t chip_id; uint32_t max_freq; uint32_t highest_bank_bit; + uint64_t ubwc_swizzle; + uint64_t macrotile_mode; + uint32_t has_raytracing; /* VIRTGPU_CAP_BOOL_x */ + uint32_t has_preemption; /* VIRTGPU_CAP_BOOL_x */ + uint64_t uche_trap_base; } msm; /* context_type == VIRTGPU_DRM_CONTEXT_MSM */ struct { uint32_t address32_hi;