diff --git a/src/freedreno/vulkan/tu_device.h b/src/freedreno/vulkan/tu_device.h index afdf1f3576f..6f57e42cb13 100644 --- a/src/freedreno/vulkan/tu_device.h +++ b/src/freedreno/vulkan/tu_device.h @@ -124,6 +124,8 @@ struct tu_physical_device bool has_cached_non_coherent_memory; uintptr_t level1_dcache_size; + bool has_preemption; + struct { uint32_t type_count; VkMemoryPropertyFlags types[VK_MAX_MEMORY_TYPES]; diff --git a/src/freedreno/vulkan/tu_knl_drm_msm.cc b/src/freedreno/vulkan/tu_knl_drm_msm.cc index d8aac72d08d..9e5cf65d591 100644 --- a/src/freedreno/vulkan/tu_knl_drm_msm.cc +++ b/src/freedreno/vulkan/tu_knl_drm_msm.cc @@ -121,6 +121,24 @@ tu_drm_get_va_prop(const struct tu_physical_device *dev, return 0; } +static bool +tu_drm_has_preemption(const struct tu_physical_device *dev) +{ + struct drm_msm_submitqueue req = { + .flags = MSM_SUBMITQUEUE_ALLOW_PREEMPT, + .prio = dev->submitqueue_priority_count / 2, + }; + + int ret = drmCommandWriteRead(dev->local_fd, + DRM_MSM_SUBMITQUEUE_NEW, &req, sizeof(req)); + if (ret) + return false; + + drmCommandWrite(dev->local_fd, DRM_MSM_SUBMITQUEUE_CLOSE, &req.id, + sizeof(req.id)); + return true; +} + static uint32_t tu_drm_get_priorities(const struct tu_physical_device *dev) { @@ -214,7 +232,9 @@ msm_submitqueue_new(struct tu_device *dev, assert(priority >= 0 && priority < dev->physical_device->submitqueue_priority_count); struct drm_msm_submitqueue req = { - .flags = 0, + .flags = dev->physical_device->info->chip >= 7 && + dev->physical_device->has_preemption ? + MSM_SUBMITQUEUE_ALLOW_PREEMPT : 0, .prio = priority, }; @@ -1245,6 +1265,8 @@ tu_knl_drm_msm_load(struct tu_instance *instance, device->has_set_iova = !tu_drm_get_va_prop(device, &device->va_start, &device->va_size); + device->has_preemption = tu_drm_has_preemption(device); + /* Even if kernel is new enough, the GPU itself may not support it. */ device->has_cached_coherent_memory = (device->msm_minor_version >= 8) && diff --git a/src/freedreno/vulkan/tu_knl_drm_virtio.cc b/src/freedreno/vulkan/tu_knl_drm_virtio.cc index 01af4450b00..8a8ea6c0074 100644 --- a/src/freedreno/vulkan/tu_knl_drm_virtio.cc +++ b/src/freedreno/vulkan/tu_knl_drm_virtio.cc @@ -310,11 +310,13 @@ virtio_submitqueue_new(struct tu_device *dev, priority < dev->physical_device->submitqueue_priority_count); struct drm_msm_submitqueue req = { - .flags = 0, + .flags = dev->physical_device->info->chip >= 7 && + dev->physical_device->has_preemption ? + MSM_SUBMITQUEUE_ALLOW_PREEMPT : 0, .prio = priority, }; - int ret = virtio_simple_ioctl(dev, DRM_IOCTL_MSM_SUBMITQUEUE_NEW, &req); + int ret = virtio_simple_ioctl(dev->vdev->vdrm, DRM_IOCTL_MSM_SUBMITQUEUE_NEW, &req); if (ret) return ret; @@ -328,6 +330,22 @@ virtio_submitqueue_close(struct tu_device *dev, uint32_t queue_id) virtio_simple_ioctl(dev->vdev->vdrm, DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE, &queue_id); } +static bool +virtio_has_preemption(struct vdrm_device *vdrm) +{ + struct drm_msm_submitqueue req = { + .flags = MSM_SUBMITQUEUE_ALLOW_PREEMPT, + .prio = vdrm->caps.u.msm.priorities / 2, + }; + + int ret = virtio_simple_ioctl(vdrm, DRM_IOCTL_MSM_SUBMITQUEUE_NEW, &req); + if (ret) + return false; + + virtio_simple_ioctl(vdrm, DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE, &req.id); + return true; +} + static VkResult tu_wait_fence(struct tu_device *dev, uint32_t queue_id, @@ -1312,6 +1330,11 @@ 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); + vdrm_device_close(vdrm); mesa_logd("wire_format_version: %u", caps.wire_format_version); @@ -1367,6 +1390,7 @@ tu_knl_drm_virtio_load(struct tu_instance *instance, device->va_start = caps.u.msm.va_start; device->va_size = caps.u.msm.va_size; device->has_set_iova = true; + device->has_preemption = has_preemption; device->gmem_size = debug_get_num_option("TU_GMEM", device->gmem_size); diff --git a/src/freedreno/vulkan/tu_knl_kgsl.cc b/src/freedreno/vulkan/tu_knl_kgsl.cc index b822fed0866..13b592e9a9b 100644 --- a/src/freedreno/vulkan/tu_knl_kgsl.cc +++ b/src/freedreno/vulkan/tu_knl_kgsl.cc @@ -1596,6 +1596,9 @@ tu_knl_kgsl_load(struct tu_instance *instance, int fd) fd, KGSL_MEMFLAGS_IOCOHERENT | (KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT)); + /* preemption is always supported on kgsl */ + device->has_preemption = true; + instance->knl = &kgsl_knl_funcs; result = tu_physical_device_init(device, instance);