From 5645ca1be47a24475c59c1aea2c6523751a487da Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Wed, 4 Dec 2024 14:51:20 +0100 Subject: [PATCH] vkd3d: Add workaround to explicitly clear memory on 6.10+ amdgpu. It seems like there is a bug with the new zerovram code in kernel. Manifests as test failures in specific circumstances. Signed-off-by: Hans-Kristian Arntzen --- libs/vkd3d/device.c | 28 ++++++++++++++++++++++++++++ libs/vkd3d/memory.c | 1 + libs/vkd3d/vkd3d_private.h | 5 +++++ 3 files changed, 34 insertions(+) diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 8c8ab3dec6..9a6ee1fb98 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -2998,6 +2998,32 @@ static HRESULT vkd3d_select_queues(const struct d3d12_device *device, return S_OK; } +static void d3d12_device_init_workarounds(struct d3d12_device *device) +{ + uint32_t major, minor, patch; + + if (vkd3d_config_flags & VKD3D_CONFIG_FLAG_SKIP_DRIVER_WORKAROUNDS) + return; + + if (device->device_info.properties2.properties.vendorID != 0x1002) + return; + + if (vkd3d_get_linux_kernel_version(&major, &minor, &patch)) + { + /* 6.10 amdgpu kernel changes the clear vram code to do background clears instead + * of on-demand clearing. This seems to have bugs, and we have been able to observe + * non-zeroed VRAM coming from the affected kernels. + * This workaround needs to be in place until we have confirmed a fix in upstream kernel. */ + INFO("Detected Linux kernel version %u.%u.%u\n", major, minor, patch); + + if (major > 6 || (major == 6 && minor >= 10)) + { + INFO("AMDGPU broken kernel detected. Enabling manual memory clearing path.\n"); + device->workarounds.amdgpu_broken_clearvram = true; + } + } +} + static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, const struct vkd3d_device_create_info *create_info) { @@ -3136,6 +3162,8 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, device->vk_info.extension_count = device_info.enabledExtensionCount; device->vk_info.extension_names = extensions; + d3d12_device_init_workarounds(device); + TRACE("Created Vulkan device %p.\n", vk_device); return hr; diff --git a/libs/vkd3d/memory.c b/libs/vkd3d/memory.c index 1d62fc2fac..c1766495fb 100644 --- a/libs/vkd3d/memory.c +++ b/libs/vkd3d/memory.c @@ -1892,6 +1892,7 @@ HRESULT vkd3d_allocate_memory(struct d3d12_device *device, struct vkd3d_memory_a * RADV definitely does this, and it seems like NV also does it. * TODO: an extension for this would be nice. */ implementation_implicitly_clears = + !device->workarounds.amdgpu_broken_clearvram && vkd3d_driver_implicitly_clears(device->device_info.vulkan_1_2_properties.driverID) && !suballocate; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 63abb30c19..bde9536037 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -4980,6 +4980,11 @@ struct d3d12_device struct vkd3d_device_swapchain_info swapchain_info; struct vkd3d_device_frame_markers frame_markers; + + struct + { + bool amdgpu_broken_clearvram; + } workarounds; }; HRESULT d3d12_device_create(struct vkd3d_instance *instance,