FrameSync
Updated: May 13, 2026
FrameSync is the default frame timing algorithm on Meta Horizon OS. It coordinates when your app starts rendering each frame so the compositor always has something fresh to display at the next vertical sync. FrameSync is on by default for every app on every supported Quest device — there is nothing to enable, and no integration steps are required.
FrameSync replaces PhaseSync, the previous frame timing algorithm. The two are not configurable side by side; on devices that ship FrameSync, your app uses it automatically.
FrameSync is on by default. You do not enable it, opt in, or change your render loop. If your app previously called PhaseSync APIs, those calls are no-ops on devices that ship FrameSync.
Every immersive frame is the product of a coordinated handoff between your app and the compositor. The Horizon OS runtime sits in the middle of that handoff, deciding when your app should begin rendering each frame so the result lands in time for the next vertical sync.
The runtime balances two competing goals:
- Don’t be late. A frame delivered after its target vertical sync forces the compositor to reproject an older frame. This produces a stale frame, and a run of consecutive stale frames creates judder and discomfort.
- Don’t be early. A frame produced too soon sits in the queue, widening the gap between the user’s head motion and what they see. This is motion-to-photon latency, and conservative scheduling avoids stale frames at the cost of feeling sluggish.
The hard part is hitting the moving target. Per-frame cost shifts constantly because of scene transitions, thermal throttling, and changing workload. The algorithm has to react fast enough to absorb those shifts without overreacting to a single hitch.
FrameSync is a redesign of the timing algorithm, with three changes that matter for app developers:
- Sliding-window statistics — FrameSync treats each recent frame as an equally weighted sample. PhaseSync used exponential decay, which weighted recent frames more heavily and could over-correct after a single spike.
- Symmetric handling of early and late frames — FrameSync adapts at the same speed whether frame times go up or down. PhaseSync was biased toward over-estimating after spikes, which traded latency for stability.
- Outlier-resistant averaging — FrameSync excludes the highest and lowest samples in the window before averaging. A single hiccup no longer poisons predictions for the frames that follow it.
The combined result is a single algorithm that adjusts continuously to what the device is actually doing. PhaseSync needed three hand-tuned modes (adaptive, fixed latency, and Application SpaceWarp) to cover the same range of workloads, and the runtime had to pick which mode to use.
What this means for your app
- No integration work. FrameSync runs in the runtime. You do not need to enable it, opt in, or change your render loop.
- Smoother frames under variable load. Apps that previously saw stale frames during scene transitions, asset streaming, or thermal throttling typically see fewer of them under FrameSync.
- Lower motion-to-photon latency. The symmetric early-and-late adaptation reduces the average gap between head motion and rendered output.
- No PhaseSync configuration carries over. If your app previously called PhaseSync APIs to switch modes or tune behavior, those calls are no-ops on devices that ship FrameSync. Remove them at your convenience.
When variable load is a factor
FrameSync responds best when the runtime can predict your app’s frame cost. A few common patterns make prediction harder:
- Thermal throttling. When the device throttles, frame cost can shift by milliseconds within a few frames. FrameSync’s sliding-window statistics and outlier rejection are designed for this case, but minimizing sustained heavy workload still helps.
- Large scene transitions. Loading a new environment or streaming in large assets can spike per-frame work. Stagger heavy work across frames where possible.
- Burst per-frame work. Single-frame spikes from infrequent events (for example, a one-shot physics simulation) are absorbed by the outlier-rejection logic, but predictable per-frame patterns still produce the smoothest output.
If you previously enabled PhaseSync explicitly through Unity, see the legacy
PhaseSync documentation for the calls that are now superseded. No replacement calls are required — the runtime takes over the entire decision.