ALWAYS use when implementing or debugging the Metal drawable presentation contract - `CAMetalLayer` configuration, drawable lifecycle (`nextDrawable`, `waitForDrawable`, `signalDrawable`, `present`), vsync…
---
name: presenting-metal-drawables
description: ALWAYS use when implementing or debugging the Metal drawable presentation contract — `CAMetalLayer` configuration, drawable lifecycle (`nextDrawable`, `waitForDrawable`, `signalDrawable`, `present`), vsync (`displaySyncEnabled`), `CAMetalDisplayLink`, HDR/EDR layer setup, direct-to-display vs composited, or drawable-residency-set rules. Trigger for CAMetalLayer, CAMetalDrawable, nextDrawable, signalDrawable, waitForDrawable, displaySyncEnabled, presentAfterMinimumDuration, drawableSize, framebufferOnly, wantsExtendedDynamicRangeContent, EDR headroom, ProMotion, swap chain port, "blank window", "vsync not working". Do NOT trigger for render-thread / run-loop / resize / fullscreen integration on macOS — use `setting-up-macos-window`. General `MTLResidencySet` semantics — use `managing-metal4-resources`. Cross-API translation tables for non-presentation APIs — use `translating-to-metal4-api`. For dual-frame presentation via a present thread — use `using-metalfx-frame-interpolation`.
---
# Metal 4 Presentation & Frame Pacing
## Overview
Metal 4 splits the cmd-buffer-level `[cmd presentDrawable:]` into a queue-level sequence: `[queue waitForDrawable:]` before commit, `[queue signalDrawable:]` after commit, and `[drawable present]`. The conceptual flow — acquire drawable, encode, present, submit — is unchanged; only the API surface is more explicit. `MTL4CommandBuffer` does not expose `presentDrawable:`, so any code path using `MTL4CommandQueue` must use the queue-level form. Code paths still using the Metal 3 `MTLCommandQueue` keep `[cmd presentDrawable:]` and remain correct in a Metal 4 app.
## Ownership
**Owns:**
- Drawable lifecycle (`nextDrawable`, `waitForDrawable`, `signalDrawable`, `present`)
- `CAMetalLayer` configuration and properties
- Vsync semantics (`displaySyncEnabled`, `presentAfterMinimumDuration:`)
- `CAMetalDisplayLink` API basics; variable refresh rate detection
- HDR/EDR layer configuration; pixel format ↔ colorspace pairing
- Direct-to-display vs composited presentation rules
- Drawable residency set (the layer-owned read-only `residencySet`)
- Apply-after-present rule
**Doesn't own:**
- Render-thread / run-loop / fullscreen / resize integration → `setting-up-macos-window`… install to load the full skill