From f23e88108d45f9f449dcee2dead7c73cfd4193fe Mon Sep 17 00:00:00 2001 From: Danylo Piliaiev Date: Fri, 13 Mar 2026 18:23:39 +0100 Subject: [PATCH] tu/kgsl: Better detection of sparse support Apparently a device can support KGSL_MEMFLAGS_VBO but not IOCTL_KGSL_GPUMEM_BIND_RANGES or IOCTL_KGSL_GPU_AUX_COMMAND. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/15006 Fixes: 71ef46717cd ("tu/kgsl: Add support for sparse binding") Signed-off-by: Danylo Piliaiev Part-of: --- src/freedreno/vulkan/tu_knl_kgsl.cc | 52 +++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/src/freedreno/vulkan/tu_knl_kgsl.cc b/src/freedreno/vulkan/tu_knl_kgsl.cc index 4af568298d9..7ba858a974b 100644 --- a/src/freedreno/vulkan/tu_knl_kgsl.cc +++ b/src/freedreno/vulkan/tu_knl_kgsl.cc @@ -572,21 +572,61 @@ kgsl_is_memory_type_supported(int fd, uint32_t flags) static bool kgsl_is_virtual_bo_supported(int fd) { - struct kgsl_gpuobj_alloc req_alloc = { - .size = 0x1000, + bool supported = false; + struct kgsl_gpuobj_alloc req_alloc_parent = { + .size = 0x2000, .flags = KGSL_MEMFLAGS_VBO, }; + struct kgsl_gpumem_alloc_id req_alloc_child = { + .size = 0x1000, + }; + struct kgsl_gpumem_bind_range req_range = {}; + struct kgsl_gpumem_bind_ranges req_ranges = {}; + struct kgsl_gpumem_free_id req_free_child = {}; + struct kgsl_gpuobj_free req_free_parent = {}; - int ret = safe_ioctl(fd, IOCTL_KGSL_GPUOBJ_ALLOC, &req_alloc); + int ret = safe_ioctl(fd, IOCTL_KGSL_GPUOBJ_ALLOC, &req_alloc_parent); if (ret) { return false; } - struct kgsl_gpuobj_free req_free = { .id = req_alloc.id }; + ret = safe_ioctl(fd, IOCTL_KGSL_GPUMEM_ALLOC_ID, &req_alloc_child); + if (ret) { + goto free_parent; + } - safe_ioctl(fd, IOCTL_KGSL_GPUOBJ_FREE, &req_free); + req_range = { + .child_offset = 0, + .target_offset = 0, + .length = 0x1000, + .child_id = req_alloc_child.id, + .op = KGSL_GPUMEM_RANGE_OP_BIND, + }; - return true; + req_ranges = { + .ranges = (uint64_t) (uintptr_t) &req_range, + .ranges_nents = 1, + .ranges_size = sizeof(req_range), + .id = req_alloc_parent.id, + .flags = 0, + }; + + ret = safe_ioctl(fd, IOCTL_KGSL_GPUMEM_BIND_RANGES, &req_ranges); + if (ret) { + goto free_child; + } + + supported = true; + +free_child: + req_free_child = { .id = req_alloc_child.id }; + safe_ioctl(fd, IOCTL_KGSL_GPUMEM_FREE_ID, &req_free_child); + +free_parent: + req_free_parent = { .id = req_alloc_parent.id }; + safe_ioctl(fd, IOCTL_KGSL_GPUOBJ_FREE, &req_free_parent); + + return supported; } enum kgsl_syncobj_state {