<!--
{
  "documentType" : "article",
  "framework" : "Metal",
  "identifier" : "/documentation/Metal/synchronizing-events-within-a-single-device",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "Synchronizing events within a single device"
}
-->

# Synchronizing events within a single device

Use nonshareable events to synchronize your app’s work within a single device.

## Discussion

The following figure and code show a nonshareable event that synchronizes graphics rendering on one command queue with compute processing on another.

![Timeline diagram that shows a nonshareable synchronization event encoded into two command queues. Command queue A shows graphics-rendering commands, and command queue B shows compute-processing commands.](images/com.apple.metal/synchronizing-events-within-a-single-device-1@2x.png)

```swift
func setupSingleDeviceEvent() {
    // Nonshareable event
    event = device.makeEvent()
    
    // Command queues
    commandQueueA = device.makeCommandQueue()
    commandQueueB = device.makeCommandQueue()
}

func renderFrame() {
    guard
        let event = event,
        let commandBufferA = commandQueueA?.makeCommandBuffer(),
        let commandBufferB = commandQueueB?.makeCommandBuffer()
        else { return }
    
    // Command Queue A (Graphics Rendering)
    /* Encode first render pass */
    commandBufferA.encodeSignalEvent(event, value: 1)
    /* Encode second render pass */
    commandBufferA.encodeWaitForEvent(event, value: 2)
    /* Encode third render pass */
    commandBufferA.commit()
    
    // Command Queue B (Compute Processing)
    /* Encode first compute pass */
    commandBufferB.encodeWaitForEvent(event, value: 1)
    /* Encode second compute pass */
    commandBufferB.encodeSignalEvent(event, value: 2)
    /* Encode third compute pass */
    commandBufferB.commit()
}
```

During setup, the code creates a nonshareable event and two command queues. Then, to render a frame, the code encodes render commands onto the first queue and compute commands on the second queue. While the code shows these commands being encoded sequentially, in a real app, you should determine whether you can encode the commands for each command queue on a different thread.

The first render pass and first compute pass are assumed to not depend on each other’s results and modify the same data. By encoding them on different queues, the device object can schedule these commands concurrently.

When two sets of commands have dependencies on each other, the code expresses these dependencies by signaling or waiting on the event. When each queue reaches a command that waits for an event, that queue blocks further execution until the event is signaled.

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)