# 5. Quest 2 Performance and Rendering Part of [[Meta Quest 2]]. Requires Unity 6.3 LTS (6000.3.27f2) and newer. Previous: [[4.Quest 2 Testing and Deployment]]. Next: [[6.Quest 2 Input Hands and Passthrough]]. > [!important] Version requirement > Unity 6.3 LTS (6000.3.27f2) and newer. Quest 2 is a mobile (Snapdragon XR2 Gen 1) headset. You are tile-based and fill-rate bound. A VR app that misses its refresh rate causes discomfort and fails Store review (VRC.Quest.Performance.1). ## 5.1 Budgets | Budget | Value | Source | |---|---|---| | Refresh rate (Store minimum) | **72 Hz** = 13.9 ms per frame | [VRC list](https://developers.meta.com/horizon/resources/publish-quest-req/) | | Optional higher rates | 90 / 120 Hz; query/set with `OVRPlugin.systemDisplayFrequency` (Meta SDK) or the Unity display subsystem | [Meta: display refresh rate](https://developers.meta.com/horizon/documentation/unity/unity-set-disp-freq/) | | Draw calls | Meta's Unity guidance for Quest 2: ~80-200 for a busy scene, 200-300 medium, 400-600 light | [Meta perf guidance](https://developers.meta.com/horizon/documentation/unity/unity-perf/) | | Draw calls (conservative) | Meta's device comparison recommends fewer than 100 draw calls | [Meta device optimization comparison](https://developers.meta.com/horizon/documentation/unity/device-optimization-comparison/) | | Triangles | 750K - 1M visible per frame (same pages recommend under 750K) | same | | Eye buffer | Panel is 1832x1920 per eye; render scale 1.0 = 1440x1584; ~1.24 matches the panel | Meta [render scale](https://developers.meta.com/horizon/documentation/unity/os-render-scale/) | | Render scale floor | 0.85 recommended (VRC.Quest.Performance.4) | VRC list | > [!tip] Design to the lower bound > Pick the conservative numbers (under 100 draw calls, under 750K triangles) for a Quest 2 scene with real-time lights, and relax them only after you measure on the device. ## 5.2 Rendering settings that matter - **URP, Vulkan, Render Graph**, Instancing stereo path (the build profile default). - **MSAA 4x** (tile memory makes it cheap), no post-processing, no HDR. - **SRP Batcher** friendly shaders only: use URP Lit/Unlit or Shader Graph. Do not call `Shader.Find` at runtime (shaders get stripped; see [[9.Quest 2 Pitfalls]]). - **Baked lighting** wherever possible; one real-time light at most. - **ASTC** textures ([[3.Quest 2 Project and Build Setup]]). - Avoid `Camera` stacking, grab pass, and full-screen effects. ## 5.3 Application SpaceWarp (ASW) ASW lets you render at half the rate (for example 36 fps) while the runtime synthesizes in-between frames from motion vectors and depth. Requirements for Unity's implementation ([URP Spacewarp](https://docs.unity3d.com/6000.2/Documentation/Manual/xr-graphics-spacewarp.html), [OpenXR Spacewarp feature](https://docs.unity3d.com/Packages/[email protected]/manual/features/spacewarp.html)): | Requirement | Value | |---|---| | Unity | 6.1+ | | OpenXR Plugin | 1.11+ | | URP | 17.0.3+ | | Graphics API | Vulkan | | URP render path | Render Graph (not compatibility mode) | Enable it: **Project Settings > XR Plug-in Management > OpenXR > Android > Application SpaceWarp**. At runtime it is controlled through `SpaceWarpFeature` (calls: `SetSpaceWarp(true)`, and `SetAppSpacePosition` / `SetAppSpaceRotation` for the tracking-space offset when you move the rig). > [!warning] ASW can hurt more than help > ASW needs correct motion vectors on every moving object, including your hands and UI. Artifacts appear around fast-moving transparent objects. Try it only when you are GPU-bound at 72 Hz. ## 5.4 Foveated rendering Foveation renders the periphery at lower resolution. On Quest 2 only **fixed** foveated rendering (FFR, centered) is available; eye-tracked foveation needs eye-tracking hardware, which Quest 2 does not have (general knowledge, not taken from a fetched page). - Enable **Foveated Rendering** under the OpenXR Meta Quest feature options, and set the level at runtime through `XRDisplaySubsystem.foveatedRenderingLevel` (0..1) per the [SRP foveated rendering docs](https://docs.unity3d.com/6000.3/Documentation/Manual/xr-foveated-rendering.html). - Higher levels gain more fill rate but show visible edge shimmer on text. UI panels at the periphery will blur ([[8.UI Toolkit for VR]]). ## 5.5 A runtime quality profile (inline script) This script applies Quest 2-safe defaults at startup. It assumes Quest 2 unless it can positively identify a newer device, so a failed detection is safe. `SystemInfo.deviceModel` values for Quest headsets are **(unverified)**: check the log line on your device and adjust the string match. ```csharp using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.XR; /// <summary> /// Applies conservative Quest 2 defaults at startup. /// Not compiled in an editor: verify API names against your installed package versions. /// </summary> public class QuestPerformanceProfile : MonoBehaviour { public enum Tier { Quest2, Newer } [Header("Quest 2 tier")] [SerializeField] float renderScale = 1.0f; // keep >= 0.85 (VRC.Quest.Performance.4) [SerializeField, Range(0f, 1f)] float foveationLevel = 0.5f; [SerializeField] float requestedRefreshRate = 72f; // Store minimum [Header("Newer headsets")] [SerializeField] float newerRefreshRate = 90f; public static Tier DetectedTier { get; private set; } = Tier.Quest2; public static float CurrentRefreshRate { get; private set; } void Awake() { string model = SystemInfo.deviceModel ?? string.Empty; Debug.Log(quot;[QuestPerformanceProfile] deviceModel = '{model}'"); // Default to Quest 2 (the performance floor). Only upgrade on a positive match. DetectedTier = (model.Contains("Quest 3") || model.Contains("Quest 3S") || model.Contains("Pro")) ? Tier.Newer : Tier.Quest2; ApplyRenderScale(); ApplyDisplaySettings(); } void ApplyRenderScale() { // Do not write the asset in the editor: renderScale is saved in the URP asset. if (Application.isEditor) return; if (GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset urp) { urp.renderScale = Mathf.Clamp(renderScale, 0.85f, 1.5f); } } void ApplyDisplaySettings() { var displays = new List<XRDisplaySubsystem>(); SubsystemManager.GetSubsystems(displays); foreach (var display in displays) { if (!display.running) continue; display.foveatedRenderingLevel = foveationLevel; float target = DetectedTier == Tier.Quest2 ? requestedRefreshRate : newerRefreshRate; if (display.TrySetDisplayRefreshRate(target)) { Debug.Log(quot;[QuestPerformanceProfile] requested {target} Hz"); } if (display.TryGetDisplayRefreshRate(out float hz)) { CurrentRefreshRate = hz; Debug.Log(quot;[QuestPerformanceProfile] runtime refresh rate = {hz} Hz"); } } } } ``` Attach it to a GameObject in your first scene. The panel in [[7.Quest 2 Worked Example Room]] reads `CurrentRefreshRate`. ## 5.6 Measure on the device 1. Run the standalone build from [[4.Quest 2 Testing and Deployment]]. 2. Open the performance overlay in MQDH, or use the Unity Profiler over USB (Development Build + Autoconnect Profiler). 3. Keep CPU frame time and GPU frame time each under 13.9 ms at 72 Hz. 4. If GPU-bound: lower foveation (raise level), reduce MSAA, reduce lights, then consider ASW. If CPU-bound: reduce draw calls and per-frame allocations. ## Official references - [Meta: Unity performance](https://developers.meta.com/horizon/documentation/unity/unity-perf/) - [Meta: Device optimization comparison](https://developers.meta.com/horizon/documentation/unity/device-optimization-comparison/) - [Unity: Spacewarp in URP](https://docs.unity3d.com/6000.2/Documentation/Manual/xr-graphics-spacewarp.html) (this is the 6000.2 copy of the page; the 6000.3 URL returned an error when I checked) - [Unity: Foveated rendering](https://docs.unity3d.com/6000.3/Documentation/Manual/xr-foveated-rendering.html) Next: [[6.Quest 2 Input Hands and Passthrough]] > [!note] Unity 6000.4 and 6000.5 are not recommended > This series targets Unity 6.3 LTS. 6000.4.x and 6000.5.x are end of life, have no patch for the October 2026 advisories, and have reported Meta SDK build breakage. See [[0.Choosing a Unity Version]].