---
title: Resource synchronization
framework: metal
role: collectionGroup
role_heading: API Collection
path: metal/resource-synchronization
---

# Resource synchronization

Prevent multiple commands that can access the same resources simultaneously by coordinating those reads and writes with barriers, fences, or events.

## Overview

Overview By design, GPUs can run multiple commands in parallel. Many of those commands access underlying memory of resources, including buffers and textures, with read and write operations. Commands can have an access conflict when one or more of them has a memory write, or store, operation and at least one other command has a memory read, or load, operation. Synchronize commands submitted to an MTL4CommandQueue instance when they have an access conflict with a resource. Access conflicts can cause problems in your app, such as nondeterministic behavior. For example, without synchronization, a draw command that reads from a texture to get the results of an earlier draw command might start loading from the texture’s memory before the other command finishes writing its output to that texture. important: The value of an MTLResource instance’s hazardTrackingMode property has no effect on the work you submit to an MTL4CommandQueue. Look for resources with access conflicts Start by identifying the commands that access the same resource, such as an MTLBuffer or an MTLTexture instance. Consider any resource that multiple passes can access concurrently by any means, including: Resource bindings, which you configure directly with the MTLCommandEncoder or MTL4ArgumentTable protocols Argument buffers, which you create and configure (see Managing groups of resources with argument buffers) Attachments for a render pass, which are textures that store rendering information, such as color, depth, or stencil data It’s okay for multiple commands to load data from the same resource memory at the same time because they all read from memory without modifying it. For example, multiple commands can load segments of a buffer at the same time, even if those segments overlap, because none of them are writing to that memory.

However, an app can introduce an access conflict when it encodes commands that both read and write to the same memory of a resource.

Locate potential access conflicts by checking which resources apply to multiple commands, where at least one of those commands modifies the resource with a store operation. Commands with an access conflict that run concurrently create a race condition that can yield inconsistent results. This is because any overlapping memory load and store operations don’t always run in the same order relative to each other. Each time a GPU runs a batch of commands without synchronization, a load operation from one command can run before, during, or after a store operation. note: Even though race conditions typically arise from an implementation mistake, some apps intentionally introduce them as an optimization technique, such as two commands that don’t need synchronization because they store the same modifications to a resource. Check render pass commands that access its attachments A render pass that writes to an attachment may introduce an access conflict because a render pass can have implicit load and store operations for that attachment. For render passes, look for potential conflicts with its attachment textures by: Noting the attachments the pass loads and stores at the beginning and end of the pass, respectively Finding any commands that read or modify those attachment textures Render command encoders add a load operation, a store operation, or both for each applicable texture attachment of the render pass it encodes. You configure which attachments, if any, the GPU loads at the beginning of the pass when you configure the loadAction property of the MTLRenderPassAttachmentDescriptor instance that applies to each attachment. Similarly, you configure which attachments, if any, the GPU stores at the end of the pass by setting the storeAction property of the MTLRenderPassAttachmentDescriptor instance that applies to each attachment. Note which attachment textures that have a load action that’s equal to MTLLoadAction.load, or a store action that’s equal to MTLStoreAction.store, then look for commands that also load and store those attachments. note: You can use any combination of load and store actions for each attachment. Check compute pass commands that can run concurrently An MTL4ComputeCommandEncoder instance creates a compute pass that runs commands concurrently on the GPU, which can introduce access conflicts. By default, an MTLComputeCommandEncoder encodes a compute pass that runs its commands serially, However, you can create one that encodes a concurrent compute pass by configuring an MTLComputePassDescriptor instance’s dispatchType property to MTLDispatchType.concurrent. Ignore memory operations the system already guarantees Metal provides several built-in resource ordering guarantees within compute and render passes, which your app doesn’t need to synchronize. For example, you don’t need to synchronize compute or render passes when they access an instance of an atomic type because they serially access those instances. See section 2.6 Atomic Data Types in the Metal Shading Language Specification (PDF) for more information. Render passes also order memory operations for specific cases, including: A render-pass attachment’s load and store operations run in primitive order for each fragment, which is the order of your app’s draw commands and the order of each primitive within a draw call. A fragment shader’s load and store operations for a raster-order group run in primitive order for each fragment. A tile shader’s load and store operations run in the same order as your app’s tile dispatch calls and on a per-tile basis. Resolve access conflicts with synchronization You can address access conflicts with one or more synchronization mechanisms. Each synchronization mechanism forces the GPU to pause before it runs a stage that accesses a resource, until another stage finishes. This means the memory operations from one stage completely finish before another stage can run its memory operations. You can choose one of the following synchronization mechanisms, which are in order of increasing scope: tip: Select the synchronizing mechanism with smallest scope that can resolve the access conflict because larger scopes pause the GPU from doing more work than smaller scopes. Track hazards with the framework prior to Metal 4 The Metal framework automatically synchronizes resource access conflicts for the commands you submit to an MTLCommandQueue instance, and only for the resources that: You configure its hazardTrackingMode property to MTLHazardTrackingMode.tracked You directly bind that resource to an encoder type that adopts the MTLCommandEncoder protocol Resources you create from an MTLDevice instance default to MTLHazardTrackingMode.tracked, and the resources you create from an MTLHeap instance default to MTLHazardTrackingMode.untracked. For more information, see Resource fundamentals and Memory heaps.

## Topics

### Synchronizing with barriers and fences

- [Synchronizing stages within a pass](metal/synchronizing-stages-within-a-pass.md)
- [Synchronizing passes with a fence](metal/synchronizing-passes-with-a-fence.md)
- [Synchronizing passes with consumer barriers](metal/synchronizing-passes-with-consumer-barriers.md)
- [Synchronizing passes with producer barriers](metal/synchronizing-passes-with-producer-barriers.md)
- [Synchronizing CPU and GPU work](metal/synchronizing-cpu-and-gpu-work.md)
- [Implementing a multistage image filter using heaps and fences](metal/implementing-a-multistage-image-filter-using-heaps-and-fences.md)
- [MTLStages](metal/mtlstages.md)
- [MTLFence](metal/mtlfence.md)
- [MTLRenderStages](metal/mtlrenderstages.md)
- [MTLBarrierScope](metal/mtlbarrierscope.md)
- [MTL4VisibilityOptions](metal/mtl4visibilityoptions.md)

### Synchronizing with events

- [Implementing a multistage image filter using heaps and events](metal/implementing-a-multistage-image-filter-using-heaps-and-events.md)
- [About synchronization events](metal/about-synchronization-events.md)
- [Synchronizing events within a single device](metal/synchronizing-events-within-a-single-device.md)
- [Synchronizing events across multiple devices or processes](metal/synchronizing-events-across-multiple-devices-or-processes.md)
- [Synchronizing events between a GPU and the CPU](metal/synchronizing-events-between-a-gpu-and-the-cpu.md)
- [MTLEvent](metal/mtlevent.md)
- [MTLSharedEvent](metal/mtlsharedevent.md)
- [MTLSharedEventHandle](metal/mtlsharedeventhandle.md)
- [MTLSharedEventListener](metal/mtlsharedeventlistener.md)
- [MTLSharedEventNotificationBlock](metal/mtlsharedeventnotificationblock.md)

## See Also

### Resources

- [Resource fundamentals](metal/resource-fundamentals.md)
- [Buffers](metal/buffers.md)
- [Textures](metal/textures.md)
- [Memory heaps](metal/memory-heaps.md)
- [Resource loading](metal/resource-loading.md)
