radv: Move VMID reservation to vkCreateDevice

DXVK's DXGI implementation can create extra instances used for
enumerating physical devices besides the games' instance. When reserving
VMIDs for SPM, the DXGI instances may snatch the VMID reservation early,
making VMID reservation for the instance that actually needs it fail.
This starts being a problem on kernels 6.18+ where only one user may
reserve a VMID at a time.

Move reserving VMIDs to SQTT initialization inside vkCreateDevice so
that only the instances that actually create logical devices try
reserving VMIDs.

Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38746>
(cherry picked from commit a7a4abc8d8)
This commit is contained in:
Natalie Vock 2025-12-01 15:41:32 +01:00 committed by Eric Engestrom
parent a72e8eefa1
commit 1846c7cc9b
7 changed files with 32 additions and 21 deletions

View file

@ -674,7 +674,7 @@
"description": "radv: Move VMID reservation to vkCreateDevice",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View file

@ -2211,10 +2211,7 @@ radv_physical_device_try_create(struct radv_instance *instance, drmDevicePtr drm
result = VK_ERROR_OUT_OF_HOST_MEMORY;
#else
if (drm_device) {
bool reserve_vmid = instance->vk.trace_mode & RADV_TRACE_MODE_RGP;
result = radv_amdgpu_winsys_create(fd, instance->debug_flags, instance->perftest_flags, reserve_vmid, is_virtio,
&pdev->ws);
result = radv_amdgpu_winsys_create(fd, instance->debug_flags, instance->perftest_flags, is_virtio, &pdev->ws);
} else {
pdev->ws = radv_null_winsys_create();
if (!pdev->ws)

View file

@ -319,6 +319,9 @@ struct radeon_winsys {
const struct vk_sync_type *const *(*get_sync_types)(struct radeon_winsys *ws);
struct util_sync_provider *(*get_sync_provider)(struct radeon_winsys *ws);
int (*reserve_vmid)(struct radeon_winsys *ws);
void (*unreserve_vmid)(struct radeon_winsys *ws);
};
static inline uint64_t

View file

@ -455,6 +455,11 @@ radv_sqtt_init(struct radv_device *device)
device->sqtt.buffer_size = (uint32_t)debug_get_num_option("RADV_THREAD_TRACE_BUFFER_SIZE", 32 * 1024 * 1024);
device->sqtt.instruction_timing_enabled = radv_is_instruction_timing_enabled();
if (device->ws->reserve_vmid && device->ws->reserve_vmid(device->ws) < 0) {
fprintf(stderr, "radv: Failed to reserve VMID for SQTT tracing.\n");
return false;
}
if (!radv_sqtt_init_bo(device))
return false;
@ -490,6 +495,9 @@ radv_sqtt_finish(struct radv_device *device)
radv_unregister_queues(device, sqtt);
ac_sqtt_finish(sqtt);
if (device->ws && device->ws->unreserve_vmid)
device->ws->unreserve_vmid(device->ws);
}
static bool

View file

@ -148,9 +148,6 @@ radv_amdgpu_winsys_destroy(struct radeon_winsys *rws)
u_rwlock_destroy(&ws->global_bo_list.lock);
free(ws->global_bo_list.bos);
if (ws->reserve_vmid)
ac_drm_vm_unreserve_vmid(ws->dev, 0);
u_rwlock_destroy(&ws->log_bo_list_lock);
ac_drm_device_deinitialize(ws->dev);
FREE(rws);
@ -179,6 +176,20 @@ radv_amdgpu_winsys_get_sync_provider(struct radeon_winsys *rws)
return p->clone(p);
}
static int
radv_amdgpu_winsys_reserve_vmid(struct radeon_winsys *rws)
{
struct radv_amdgpu_winsys *ws = (struct radv_amdgpu_winsys *)rws;
return ac_drm_vm_reserve_vmid(ws->dev, 0);
}
static void
radv_amdgpu_winsys_unreserve_vmid(struct radeon_winsys *rws)
{
struct radv_amdgpu_winsys *ws = (struct radv_amdgpu_winsys *)rws;
ac_drm_vm_unreserve_vmid(ws->dev, 0);
}
static uint64_t
radv_amdgpu_winsys_filter_perftest_flags(uint64_t perftest_flags)
{
@ -187,7 +198,7 @@ radv_amdgpu_winsys_filter_perftest_flags(uint64_t perftest_flags)
}
VkResult
radv_amdgpu_winsys_create(int fd, uint64_t debug_flags, uint64_t perftest_flags, bool reserve_vmid, bool is_virtio,
radv_amdgpu_winsys_create(int fd, uint64_t debug_flags, uint64_t perftest_flags, bool is_virtio,
struct radeon_winsys **winsys)
{
VkResult result = VK_SUCCESS;
@ -287,15 +298,6 @@ radv_amdgpu_winsys_create(int fd, uint64_t debug_flags, uint64_t perftest_flags,
if (debug_flags & RADV_DEBUG_NO_IBS)
ws->use_ib_bos = false;
ws->reserve_vmid = reserve_vmid;
if (ws->reserve_vmid) {
r = ac_drm_vm_reserve_vmid(ws->dev, 0);
if (r) {
fprintf(stderr, "radv/amdgpu: failed to reserve vmid.\n");
result = VK_ERROR_INITIALIZATION_FAILED;
goto winsys_fail;
}
}
int num_sync_types = 0;
ws->syncobj_sync_type = vk_drm_syncobj_get_type_from_provider(ac_drm_device_get_sync_provider(dev));
@ -334,6 +336,8 @@ radv_amdgpu_winsys_create(int fd, uint64_t debug_flags, uint64_t perftest_flags,
ws->base.get_fd = radv_amdgpu_winsys_get_fd;
ws->base.get_sync_types = radv_amdgpu_winsys_get_sync_types;
ws->base.get_sync_provider = radv_amdgpu_winsys_get_sync_provider;
ws->base.reserve_vmid = radv_amdgpu_winsys_reserve_vmid;
ws->base.unreserve_vmid = radv_amdgpu_winsys_unreserve_vmid;
radv_amdgpu_bo_init_functions(ws);
radv_amdgpu_cs_init_functions(ws);

View file

@ -33,7 +33,6 @@ struct radv_amdgpu_winsys {
bool debug_log_bos;
bool use_ib_bos;
bool zero_all_vram_allocs;
bool reserve_vmid;
uint64_t perftest;
alignas(8) uint64_t allocated_vram;

View file

@ -12,8 +12,8 @@
#ifndef RADV_AMDGPU_WINSYS_PUBLIC_H
#define RADV_AMDGPU_WINSYS_PUBLIC_H
VkResult radv_amdgpu_winsys_create(int fd, uint64_t debug_flags, uint64_t perftest_flags, bool reserve_vmid,
bool is_virtio, struct radeon_winsys **winsys);
VkResult radv_amdgpu_winsys_create(int fd, uint64_t debug_flags, uint64_t perftest_flags, bool is_virtio,
struct radeon_winsys **winsys);
struct radeon_winsys *radv_dummy_winsys_create(void);