Vireo  0.0
Vireo 3D Rendering Hardware Interface
Semaphores

A semaphore is a GPU/GPU synchronization primitive. They are use between render passes : it ensures ordering between queue submissions (e.g. “don’t start color pass until depth pre pass finishes”).

There is two types of semaphores :

Using binary semaphores

Create the semaphore with vireo::Vireo::createSemaphore with the vireo::SemaphoreType::BINARY parameter :

auto semaphore = vireo->createSemaphore(vireo::SemaphoreType::BINARY);

Then use it with vireo::SubmitQueue::submit. In the following example both submissions will be started in parallel, the input assembly and vertex shaders will be executed in parallel, then the second submission will wait for the first vertex shader to end before starting the fragment shader :

...
// Record commands
...
// Submit commands and tell the GPU to signal a semaphore at the end of the vertex shader
graphicQueue->submit(vireo::WaitStage::VERTEX_SHADER, semaphore, {commandList});
...
// Record commands
...
// Submit commands and tell the GPU to wait before starting the fragment shader
graphicQueue->submit(semaphore, vireo::WaitStage::FRAGMENT_SHADER, {commandList});
Note
The shader waiting/signaling stages aren't used with DirectX 12, the semaphore will be signaled at the end of the pipeline work and waited at the start...

Using timeline semaphores

Create the semaphore with vireo::Vireo::createSemaphore with the vireo::SemaphoreType::TIMELINE parameter :

auto semaphore = vireo->createSemaphore(vireo::SemaphoreType::TIMELINE);

The reference value of the semaphore counter starts at zero at will be incremented each time it will be signaled.

You can use vireo::Semaphore::incrementValue, vireo::Semaphore::decrementValue or vireo::Semaphore::setValue to specify the reference value before waiting but be careful to set the correct value back before signaling.

Example of a submission waiting for two other render passes to signal the semaphore :

// we have two previous passes, decrement to wait for the signaling value of the first pass
frame.semaphore->decrementValue();
graphicQueue->submit(
frame.semaphore,
// wait for "currentValue - 1" and "currentValue"
{vireo::WaitStage::FRAGMENT_SHADER, vireo::WaitStage::FRAGMENT_SHADER},
frame.inFlightFence,
swapChain,
{cmdList});
swapChain->present();
swapChain->nextFrameIndex();
// roll back the semaphore value
frame.semaphore->incrementValue();

Check the "Deferred" example in the Samples repository for a complete example of a timeline semaphore use.