Synchronization
Access dependencies
|
|
|
|---|---|
|
|
CommandBuffer.Barrier with the producing and consuming stages. |
|
|
CommandBuffer.Transition with its previous and next layouts. |
|
|
TimelineValue to the consumer's Submit. |
|
|
Wait() on the relevant completion value. |
Pipeline barriers
commandBuffer.Barrier(BarrierStages.ComputeShading, BarrierStages.ComputeShading);
BarrierStages.All includes every supported stage; select a narrower set when the dependency only involves those stages.
Texture layouts
TextureLayout describes how a particular subresource, identified by a mip level and array layer, is accessed at a given point in the command sequence. When that access changes, record a transition. For example, the compute sample writes an output texture in Storage layout, then prepares it for sampling in a graphics pass:
commandBuffer.Transition(outputTexture, default, TextureLayout.Storage, TextureLayout.Sampled);
outputTexture was created with Sampled | Storage usage and the selected subresource is in Storage layout. default selects mip level 0 and array layer 0. Other mip levels and layers are unaffected by this transition.
Transition, supply the layout from the subresource's previous use. The application tracks this state as it records commands and passes textures between rendering stages.
Undefined as the previous layout when the existing contents can be discarded, such as for a new image or an attachment that will be cleared completely. To preserve the contents for loading, sampling, or accumulation, use the layout from the preceding access.
Backend behavior
Transition implementation. The Metal backend instead groups commands into render and compute encoders and inserts visibility barriers when an encoder ends. Dependent operations within one encoder, such as successive compute dispatches, use explicit Barrier calls.
Timelines and queue dependencies
Submit() returns a TimelineValue containing the timeline and the submission's value. Numeric Value fields from different timelines cannot be compared directly.
producer and consumer be recorded command buffers from two queues in the same context, with the consumer using data written by the producer. Submit them with this dependency:
TimelineValue produced = producer.Submit();
TimelineValue consumed = consumer.Submit(produced);
produced.Wait(). Keep the shared resources alive until consumed completes, and record the texture transitions required by the consumer's access.
consumed.Wait();
queue.Timeline.Signal() can likewise be waited on with Wait() or used as a dependency for another queue. Signal() places this completion point after previously submitted work; the GPU reaches it once that work has finished.
Readback completion
IsCompleted reports GPU completion. A recorded download has one further step: copying the result from internal readback storage into the application's destination memory.
CommandBuffer.Download records the GPU copy into that internal storage. After the submission finishes, the library performs the CPU copy while reclaiming the completed command buffer. Calling Wait() on the download's submission value waits for the GPU and processes that queue's completed buffers, completing both steps. Keep the destination allocated, and managed memory pinned, until the call returns.
IsCompleted alone does not perform the final CPU copy. A wait on another queue does not reclaim the download queue's completed buffers either.
Resource reuse
SwapChain.Resize or disposing resources or the context. The triangle already waits for each frame, so it can resize between callbacks.
SwapChain.Present() signals and waits on the graphics queue after presentation. The triangle therefore waits at presentation even if its explicit submission wait is removed. Work submitted independently to other queues requires its own completion tracking.