From 972ce74ac620cde763abd54160c8de7c9927e422 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Mon, 14 Feb 2022 15:28:05 +0100 Subject: [PATCH] vkd3d: When using breadcrumbs, consider that WaitSemaphore can be buggy. Spec says that in device lost, driver must return DEVICE_LOST in finite time, but this does not happen on NV drivers. Use a long timeout instead in this scenario. Signed-off-by: Hans-Kristian Arntzen --- libs/vkd3d/command.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 26581c57..e61b2357 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -331,6 +331,7 @@ static void vkd3d_wait_for_gpu_timeline_semaphore(struct vkd3d_fence_worker *wor struct d3d12_device *device = worker->device; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; VkSemaphoreWaitInfoKHR wait_info; + uint64_t timeout = UINT64_MAX; HRESULT hr; int vr; @@ -341,14 +342,22 @@ static void vkd3d_wait_for_gpu_timeline_semaphore(struct vkd3d_fence_worker *wor wait_info.pSemaphores = &fence->fence->timeline_semaphore; wait_info.pValues = &fence->value; - if ((vr = VK_CALL(vkWaitSemaphoresKHR(device->vk_device, &wait_info, ~(uint64_t)0)))) + /* Some drivers hang indefinitely in face of device lost. + * If a wait here takes more than 5 seconds, this is pretty much + * a guaranteed timeout (TDR) scenario. + * Usually, we'd observe DEVICE_LOST in subsequent submissions, + * but if application submits something and expects to wait on that submission + * immediately, this can happen. */ + if (vkd3d_config_flags & VKD3D_CONFIG_FLAG_BREADCRUMBS) + timeout = 5000000000ull; + + if ((vr = VK_CALL(vkWaitSemaphoresKHR(device->vk_device, &wait_info, timeout)))) { ERR("Failed to wait for Vulkan timeline semaphore, vr %d.\n", vr); + VKD3D_DEVICE_REPORT_BREADCRUMB_IF(device, vr == VK_ERROR_DEVICE_LOST || vr == VK_TIMEOUT); return; } - VKD3D_DEVICE_REPORT_BREADCRUMB_IF(device, vr == VK_ERROR_DEVICE_LOST); - /* This is a good time to kick the debug threads into action. */ if (device->debug_ring.active) pthread_cond_signal(&device->debug_ring.ring_cond);