KhronosGroup / Vulkan-Docs

The Vulkan API Specification and related tools
Other
2.79k stars 466 forks source link

What happens if waiting for a keyed mutex times out? #1554

Open DadSchoorse opened 3 years ago

DadSchoorse commented 3 years ago

While working on resource sharing in Wine I've hit the issue that it's not specified how vkQueueSubmit waits for the keyed mutexes.

VkWin32KeyedMutexAcquireReleaseInfoKHR and VkWin32KeyedMutexAcquireReleaseInfoNV allow specifying a timeout per mutex that is going to be acquire. But VK_TIMEOUT is not listed as a possible return value, so what exactly happens on timeout? Also the possibility of timeouts means that vkQueueSubmit has to wait on until it acquires the mutexes or times out, so why is Acquire not a separate operation in the first place? (e.g. vkAcquireKeyedMutexKHR(VkDevice, VkDeviceMemory, key, timeout)

stonesthrow commented 3 years ago

Scheduled for triage discussion 6/23

Guy1524 commented 3 years ago

I decided to test the current behavior of this on the windows NVIDIA driver version 461.33. When specifying a timeout and acquiring a keyed mutex released to a different key, vkQueueSubmitKHR simply returns VK_TIMEOUT (without waiting for any noticeable amount of time), unless the timeout is ~0ul, in which case the function blocks forever.

cubanismo commented 3 years ago

It took us a while to discuss this within NVIDIA. From our point of view:

But VK_TIMEOUT is not listed as a possible return value, so what exactly happens on timeout?

We consider this a spec bug. Unfortunately, VK_TIMEOUT should be a valid return value for vkQueueSubmit() when using a keyed mutex.

Also the possibility of timeouts means that vkQueueSubmit has to wait on until it acquires the mutexes or times out, so why is Acquire not a separate operation in the first place? (e.g. vkAcquireKeyedMutexKHR(VkDevice, VkDeviceMemory, key, timeout)

Because keyed mutex is an odd primitive. It internally appears to consist of both a CPU side wait and some queue-side synchronization work. Separating the two would have complicated the API quite a bit (E.g., as written, your proposed acquire function would need to operate on a VkQueue object as well), but I agree that in retrospect there may have been cleaner API design options.

DadSchoorse commented 3 years ago

An additional questions that came up: Is a timeout of UINT32_MAX supported to be infinity? Currently the spec doesn't mention this at all, but all the DirectX functionality works that way, and all tested current implementations of the extension behave like that.

Guy1524 commented 2 years ago

I recently finished implementing this extension in Wine's Vulkan implementation, along with tests, and it seem the behavior I described in my previous comment is still present on NVidia's 512.59 Windows driver, but works as expected on AMD.

Here's the source: https://gist.github.com/Guy1524/4c8d4ab5a4f9b0e69d3323f2b488513d#file-vulkan-c-L913

To recap, only with a ~0ul timeout value will vkQueueSubmit block, other timeout values are functionally equivalent to 0. AMD's Windows driver on the other hand loops through all acquire mutexes, and waits with the specified timeout. All these waits are consecutive, not concurrent.