Oskar Sundbom | 3764eb8 | 2023-02-24 17:15:25 +0100 | [diff] [blame] | 1 | # Vulkan Timeline Semaphores |
| 2 | |
| 3 | [Vulkan Timeline |
| 4 | Semaphores](https://www.khronos.org/blog/vulkan-timeline-semaphores) are a |
| 5 | synchronization primitive accessible both from the device and the host. A |
| 6 | timeline semaphore represents a monotonically increasing 64-bit unsigned |
| 7 | value. Whereas binary Vulkan semaphores are waited on just to become signaled, |
| 8 | timeline semaphores are waited on to reach a specific value. Once a timeline |
| 9 | semaphore reaches a certain value, it is considered signaled for every value |
| 10 | less than or equal to that |
| 11 | value. [`vkWaitSemaphores`](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkWaitSemaphores.html) |
| 12 | is used to wait for semaphores on the host. It can operate in one of two modes: |
| 13 | "wait for all" and "wait for any". |
| 14 | |
| 15 | In SwiftShader, Vulkan Timeline Semaphores are implemented as an unsigned 64-bit |
| 16 | integer protected by a mutex with changes signaled by a condition |
| 17 | variable. Waiting for all timeline semaphores in a set is implemented by simply |
| 18 | waiting for each of the semaphores in turn. Waiting for any semaphore in a set |
| 19 | is a bit more complex. |
| 20 | |
| 21 | ## Wait for any semaphore |
| 22 | |
| 23 | A "wait for any" of a set of semaphores is represented by a |
| 24 | `TimelineSemaphore::WaitForAny` object. Additionally, `TimelineSemaphore` |
| 25 | contains an internal list of all `WaitForAny` objects that wait for it, as well |
| 26 | as for which values they wait. When signaled, the timeline semaphore looks |
| 27 | through this list and, in turn, signals any `WaitForAny` objects that are |
| 28 | waiting for a value less than or equal to the timeline semaphore's new value. |
| 29 | |
| 30 | A `WaitForAny` object is created from a `VkSemaphoreWaitInfo`. During |
| 31 | construction, it checks the value of each timeline semaphore provided against |
| 32 | the value for which it is waiting. If it has not yet been reached, the wait |
| 33 | object registers itself with the timeline semaphore. If it _has_ been reached, |
| 34 | the wait object is immediately signaled and no further timeline semaphores are |
| 35 | checked. |
| 36 | |
| 37 | Once a `WaitForAny` object is signaled, it remains signaled. There is no way to |
| 38 | change what semaphores or values to wait for after construction. Any subsequent |
| 39 | calls to `wait()` will return `VK_SUCCESS` immediately. |
| 40 | |
| 41 | When a `WaitForAny` object is destroyed, it unregisters itself from every |
| 42 | `TimelineSemaphore` it was waiting for. It is expected that the number of |
| 43 | concurrent waits are few, and that the wait objects are short-lived, so there |
| 44 | should not be a build-up of wait objects in any timeline semaphore. |