This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: compose-multiplatform-metal-vulkan-fence-sync-production-standard

Compose Multiplatform Metal/Vulkan GPU Fence Synchronization & VSync Alignment Standard

Enforces deterministic hardware synchronization between off-thread layout/composition passes and GPU frame presentation across iOS Metal and Android Vulkan swapchains. Prevents dual-surface render tearing, out-of-order buffer swapchain presentation, and frame drops by anchoring presentation to VSync intervals using native GPU fences.

Prohibited Anti-Pattern: Unsynchronized Cross-Thread Surface Mutations Causing Metal/Vulkan Presentation Tearing

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Compose Multiplatform Metal/Vulkan GPU Fence Synchronization & VSync Alignment Standard - Enforces deterministic hardware synchronization between off-thread layout/composition passes and GPU frame presentation across iOS Metal and Android Vulkan swapchains. Prevents dual-surface render tearing, out-of-order buffer swapchain presentation, and frame drops by anchoring presentation to VSync intervals using native GPU fences.
globs: **/src/**/*.{kt,kts}, **/nativeInterop/**/*.{def,kt}, **/iosMain/**/*.{kt,m,mm}, **/androidMain/**/*.kt
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/compose-multiplatform-metal-vulkan-fence-sync-production-standard"
---

# Compose Multiplatform Metal/Vulkan GPU Fence Synchronization & VSync Alignment Standard

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Unsynchronized Cross-Thread Surface Mutations Causing Metal/Vulkan Presentation Tearing

## System Constraints
You are a Principal Mobile Graphics Architect enforcing Compose Multiplatform Metal and Vulkan GPU fence synchronization standards. You must mandate strict adherence to hardware-level synchronization primitives (MTLSharedEvent, VkFence/VkSemaphore, and Android SurfaceSyncGroup) to eliminate dual-surface tearing and race conditions between off-thread state calculations and GPU frame submissions.

## Strict Guidelines
- Engineers MUST ALWAYS synchronise off-thread layout and draw operations with the target platform's hardware VSync clock (CADisplayLink on iOS, Choreographer on Android).
- Engineers MUST NOT mutate or present swapchain surfaces across threads without explicit GPU command fence signaling (MTLEvent/MTLSharedEvent on Metal, VkFence/VkSemaphore on Vulkan).
- Render pipelines MUST enforce a 1:1 hardware frame budget: off-thread calculations that exceed the VSync deadline (16.6ms for 60Hz, 8.33ms for 120Hz ProMotion/High Refresh Rate) MUST defer rendering to the next frame interval rather than executing partial surface commits.
- Composables interacting with native hardware surfaces MUST leverage atomic frame token validation to ensure that rendering contexts reject stale buffers before swapchain presentation.
- Components NEVER execute raw Skia/Skiko canvas updates directly from worker coroutine contexts without routing commands through platform-specific GPU sync handlers.

## Bad vs Good Implementations
### Android Vulkan/SurfaceSyncGroup Frame Alignment

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Mutating and unlocking the hardware canvas directly from a background coroutine without Choreographer cadence or SurfaceSyncGroup synchronization causes swapchain presentation races, surface tearing, and dropped frames against the compositor.
```kotlin
// Anti-pattern: Mutating surfaces from background coroutines without VSync or Vulkan fence synchronization
class SurfaceRenderer(private val surface: Surface) {
    private val scope = CoroutineScope(Dispatchers.Default)

    fun onLayoutUpdated(newBounds: Rect) {
        scope.launch {
            // Rendering directly to canvas on background thread with no Choreographer lock or GPU fence
            val canvas = surface.lockHardwareCanvas()
            try {
                drawScene(canvas, newBounds)
            } finally {
                // Race condition: Buffer presented ahead of Choreographer tick causes tearing
                surface.unlockCanvasAndPost(canvas)
            }
        }
    }

    private fun drawScene(canvas: Canvas, bounds: Rect) { /* ... */ }
}
```

#### Production Standard (Correct)
> **Standard**: Off-thread layout is orchestrated via Choreographer VSync callbacks and explicitly synchronized using SurfaceSyncGroup and SyncFence, guaranteeing zero surface tearing and atomic swapchain presentation.
```kotlin
// Production: Anchoring off-thread calculations to Choreographer VSync with Android SurfaceSyncGroup synchronization
class SurfaceRenderer(private val surfaceControl: SurfaceControl) {
    private val choreographer = Choreographer.getInstance()

    fun onLayoutUpdated(newBounds: Rect) {
        choreographer.postFrameCallback { frameTimeNanos ->
            // Anchor off-thread work directly to VSync frame token
            val syncGroup = SurfaceSyncGroup("ComposeVulkanSync")
            val transaction = SurfaceControl.Transaction()

            syncGroup.add(surfaceControl) { syncRegistration ->
                val syncFence = syncRegistration.acquireFence()
                transaction.setBuffer(surfaceControl, renderOffThread(newBounds, syncFence))
                transaction.setFrameTimelineVsyncId(frameTimeNanos)
                transaction.apply()
            }
            syncGroup.markSyncReady()
        }
    }

    private fun renderOffThread(bounds: Rect, fence: SyncFence): HardwareBuffer { /* Render with VkFence */ return TODO() }
}
```

### iOS Metal CADisplayLink MTLSharedEvent Fence Synchronization

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Invoking CAMetalLayer.nextDrawable() on an unaligned background thread causes frame contention with the system compositor, while committing command buffers without fence dependencies causes tearing across dual-surface composables.
```kotlin
// Anti-pattern: Dispatching Skiko Metal command buffers asynchronously without MTLEvent tracking
class MetalSurfaceRenderer(private val metalLayer: CAMetalLayer) {
    fun renderFrame(content: FrameContent) {
        // Unsynchronized background dispatch creates race between Metal presentation and CADisplayLink
        DispatchQueue.global().async {
            val drawable = metalLayer.nextDrawable() ?: return@async
            val commandBuffer = commandQueue.commandBuffer() ?: return@async
            
            encodeCommands(commandBuffer, drawable, content)
            // Bad: Presenting without waiting for layout computation fence
            commandBuffer.presentDrawable(drawable)
            commandBuffer.commit()
        }
    }
    private fun encodeCommands(cb: MTLCommandBufferProtocol, d: CAMetalDrawableProtocol, c: FrameContent) {}
}
```

#### Production Standard (Correct)
> **Standard**: Ties frame production directly to the CADisplayLink cadence, applies MTLSharedEvent hardware fences between command buffers, and schedules presentation at exact target timestamps to eliminate tearing.
```kotlin
// Production: CADisplayLink driven Metal rendering with MTLSharedEvent synchronization
class MetalSurfaceRenderer(
    private val metalLayer: CAMetalLayer,
    private val sharedEvent: MTLSharedEvent
) {
    private var frameNumber: ULong = 0UL

    fun onDisplayLinkTick(targetTimestamp: Double) {
        val currentFrame = ++frameNumber
        val drawable = metalLayer.nextDrawable() ?: return
        val commandBuffer = commandQueue.commandBuffer() ?: return

        // Synchronize GPU execution with off-thread layout barrier
        commandBuffer.encodeWaitForEvent(sharedEvent, currentFrame)
        
        encodeCommands(commandBuffer, drawable)
        
        // Signal frame completion fence prior to swapchain presentation
        commandBuffer.encodeSignalEvent(sharedEvent, currentFrame + 1UL)
        commandBuffer.presentDrawableAtTime(drawable, targetTimestamp)
        commandBuffer.commit()
    }

    private fun encodeCommands(cb: MTLCommandBufferProtocol, d: CAMetalDrawableProtocol) {}
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Compose Multiplatform Metal/Vulkan GPU Fence Synchronization & VSync Alignment Standard

Compose Multiplatform Metal/Vulkan GPU Fence Synchronization & VSync Alignment Standard defines an industrial-grade behavioral standard for mobile engineering. Enforces deterministic hardware synchronization between off-thread layout/composition passes and GPU frame presentation across iOS Metal and Android Vulkan swapchains. Prevents dual-surface render tearing, out-of-order buffer swapchain presentation, and frame drops by anchoring presentation to VSync intervals using native GPU fences. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Unsynchronized Cross-Thread Surface Mutations Causing Metal/Vulkan Presentation Tearing Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftUnsynchronized Cross-Thread Surface Mutations Causing Metal/Vulkan Presentation TearingCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS synchronise off-thread layout and draw operations with the target platform's hardware VSync clock (CADisplayLink on iOS, Choreographer on Android).

Engineers MUST ALWAYS synchronise off-thread layout and draw operations with the target platform's hardware VSync clock (CADisplayLink on iOS, Choreographer on Android).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT mutate or present swapchain surfaces across threads without explicit GPU command fence signaling (MTLEvent/MTLSharedEvent on Metal, VkFence/VkSemaphore on Vulkan).

Engineers MUST NOT mutate or present swapchain surfaces across threads without explicit GPU command fence signaling (MTLEvent/MTLSharedEvent on Metal, VkFence/VkSemaphore on Vulkan).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Render pipelines MUST enforce a 1

Render pipelines MUST enforce a 1:1 hardware frame budget: off-thread calculations that exceed the VSync deadline (16.6ms for 60Hz, 8.33ms for 120Hz ProMotion/High Refresh Rate) MUST defer rendering to the next frame interval rather than executing partial surface commits.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Composables interacting with native hardware surfaces MUST leverage atomic frame token validation to ensure that rendering contexts reject stale buffers before swapchain presentation.

Composables interacting with native hardware surfaces MUST leverage atomic frame token validation to ensure that rendering contexts reject stale buffers before swapchain presentation.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Components NEVER execute raw Skia/Skiko canvas updates directly from worker coroutine contexts without routing commands through platform-specific GPU sync handlers.

Components NEVER execute raw Skia/Skiko canvas updates directly from worker coroutine contexts without routing commands through platform-specific GPU sync handlers.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Compose Multiplatform Metal/Vulkan GPU Fence Synchronization & VSync Alignment Standard critical for AI coding assistants?

Enforces deterministic hardware synchronization between off-thread layout/composition passes and GPU frame presentation across iOS Metal and Android Vulkan swapchains. Prevents dual-surface render tearing, out-of-order buffer swapchain presentation, and frame drops by anchoring presentation to VSync intervals using native GPU fences. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Unsynchronized Cross-Thread Surface Mutations Causing Metal/Vulkan Presentation Tearing) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

Related MOBILE Rules

View all rules →
1 Rule in Stack

Compose