Contents

Synchronizing passes with producer barriers

Block GPU stages in subsequent passes from running until stages in a pass, and earlier passes, finish.

Overview

Producer queue barriers are coarse synchronization primitives that resolve access conflicts between commands in different passes that you submit to the same command queue, including passes from other command buffers. Producer barriers are convenient for synchronizing passes that modify common resources that multiple, subsequent passes in the same queue load later on.

When your app encodes commands that access a resource from different passes — or different stages within a single pass — it creates an access conflict when at least one command modifies that resource. This conflict happens because the GPU can run multiple commands at the same time, including those from:

  • Multiple passes

  • Different stages of a pass, such as the blit and dispatch stages of a compute pass

  • Multiple instances of a stage, such as two or more dispatch commands within a compute pass

For more information about resource access conflicts and GPU stages, see Resource synchronization and MTLStages, respectively.

Start by identifying which memory operations from subsequent passes in the same queue introduce a conflict and resolve them with an intraqueue barrier in the producing pass.

Identify access conflicts with subsequent passes

The following code example encodes three compute passes. The first pass runs a single copy command:

The second pass runs a copy command and a dispatch command:

The third pass runs a single dispatch command:

The example has at least one access conflict because passes 2 and 3 both access a common resource, bufferD:

  • The copy command from the second pass stores to bufferD.

  • The dispatch command from the third pass loads from bufferD.

[Image]

Without synchronization, the GPU can run all three passes and their stages in parallel, which can yield inconsistent results in resources with access conflicts.

[Image]

Resolve access conflicts with a producer barrier

To resolve access conflicts between passes from the same command queue, use a producer barrier by calling the encoder’s barrier(afterStages:beforeQueueStages:visibilityOptions:) method.

Each producer queue barrier temporarily blocks the GPU from running the specific stage types, which you pass to the beforeQueueStages parameter, in all subsequent passes in the same queue. The barrier unblocks those stages when all the stage types you pass to the afterStages parameter finish running in the pass and all previous passes.

The following example modifies the code that encodes the second pass by adding a producer queue barrier just before the dispatch command stage in the second pass.

In this example, the barrier prevents the GPU from running the dispatch stage in the third pass until the blit stages in both the first and second pass finish storing their modifications.

[Image]

The barrier unblocks the dispatch stage of the third pass when the blit stage from the first pass finishes running because it’s the last blit stage to finish of all the passes that apply to the afterStages parameter.

For more information about other synchronization mechanisms, see these articles in the series:

See Also

Synchronizing with barriers and fences