Quest Browser: immersive WebXR hangs with MSAA + per-frame shadows + 3D Gaussian Splatting
We isolated a reproducible browser/driver-level hang on Meta Quest Browser and want to share it with other WebXR developers (also filed via the developer Feedback Center).
Symptom: entering an immersive WebXR session permanently hangs (rAF stops within ~2 seconds, no webglcontextlost event, no GPU process recovery; the headset OS stays responsive) when a WebGL2 page combines ALL THREE of:
- antialias: true on the WebGL2 context (MSAA)
- 2. A per-frame shadow map pass (rendering into a depth texture every frame, e.g. three.js shadowMap)
- 3. The Spark 3D Gaussian Splatting renderer (sparkjs.dev), which performs out-of-band GPU work between frames and fence-based async readbacks (fenceSync + getBufferSubData) for splat sorting
Removing any ONE of the three avoids the hang. Baking the shadow map once (three.js: shadowMap.autoUpdate = false) instead of rendering it every frame also avoids it - that is the workaround we shipped.
Environment: Quest 3, Meta Quest Browser (latest as of July 2026), three.js 0.185.1 / @sparkjsdev/spark 2.1.0. NOT reproducible on desktop Chrome, PICO 4, or Apple Vision Pro - Quest Browser only.
Minimal single-file repro (all variables toggleable via URL params):
https://github.com/sawa-zen/xrift-world-3dgs-musium/tree/7fab1f8/tools/quest-msaa-repro
- /?aa=1&shadow=0 -> OK
- - /?aa=0&shadow=1 -> OK
- - /?aa=1&shadow=1&splat=0 -> OK
- - /?aa=1&shadow=1 -> hangs within seconds
- - /?aa=1&shadow=1&shadowstatic=1 -> OK (shadow baked once)
Related analysis on the Spark side: https://github.com/sparkjsdev/spark/issues/400
Whatever GL command pattern a page issues, the browser should recover via context loss rather than permanently hanging the XR session, so we believe this is a browser/driver robustness bug. Hope this saves someone the debugging time - and if anyone from the Browser team wants more traces, happy to help.
