fix(xr): visionOS MSAA resolve into XR framebuffer#8730
Conversation
On Apple Vision Pro, gl.blitFramebuffer directly into the XRWebGLLayer opaque framebuffer produces a small zoomed-in sub-region instead of correct stereo content. On visionOS only, MSAA color is now resolved into an engine-owned scratch texture first, then copied 1:1 into the XR framebuffer via a single fullscreen quad draw — the rasterization path that AVP renders correctly. - Add pc.platform.visionos detection (Macintosh UA + maxTouchPoints > 0 + no iPhone/iPad/iPod, since visionOS Safari spoofs a macOS UA) - Add WebglXrMsaaCopy helper: scratch Texture/RenderTarget + fullscreen quad shader built via engine infrastructure (ShaderDefinitionUtils, device.scope, QuadRender-style draw) - Gate the new path on platform.visionos in WebglRenderTarget.resolve — other XR platforms keep the direct-blit path with zero overhead Fixes #7410
There was a problem hiding this comment.
Pull request overview
This PR adds a visionOS-specific workaround for WebXR MSAA resolves by avoiding direct gl.blitFramebuffer into the XR opaque framebuffer (which visionOS WebKit renders incorrectly) and instead resolving into an intermediate texture and copying via a fullscreen quad. It also exposes a new pc.platform.visionos flag for platform detection.
Changes:
- Added
pc.platform.visionosboolean detection for Apple Vision Pro / visionOS. - Introduced
WebglXrMsaaCopyhelper to resolve MSAA into a scratch texture and then draw a fullscreen quad into the XR framebuffer. - Updated
WebglRenderTarget.resolveto route XR MSAA color resolves through the helper on visionOS only, preserving the existing direct-blit path elsewhere.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/platform/graphics/webgl/webgl-xr-msaa-copy.js | New helper implementing MSAA resolve to scratch texture + fullscreen quad copy into XR framebuffer. |
| src/platform/graphics/webgl/webgl-render-target.js | Routes XR MSAA color resolves through the new helper on platform.visionos. |
| src/platform/graphics/webgl/webgl-graphics-device.js | Lazily instantiates/destroys the helper and exposes an internal resolve entry point. |
| src/core/platform.js | Adds platform.visionos detection and exposes it on the platform namespace. |
Comments suppressed due to low confidence (1)
src/platform/graphics/webgl/webgl-graphics-device.js:1120
- The docstring mentions resolving MSAA color into the XR framebuffer “via two quad draws”, but the helper performs one fullscreen quad draw (plus a blit into a scratch texture). Please adjust the wording so it reflects the real steps (blit + single quad) and matches the helper’s implementation.
/**
* Resolve multisampled color into the WebXR session framebuffer via two textured quad draws
* (horizontal SBS). Used on visionOS / Apple Vision Pro where direct `blitFramebuffer` into
* the XR opaque framebuffer does not produce correct results.
*
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * | ||
| * @type {boolean} | ||
| */ | ||
| visionos: visionos, |
There was a problem hiding this comment.
Gotta say - I'm not a fan of explanding the platform object further. This user agent sniffing technique is really scary (should the browser change it someday) - people's published app behavior can suddenly change/break.
There was a problem hiding this comment.
yeah those are dirty.
but I need it internally .. I'll make it @ignore.
Fixed #7410
Working WebXR with MSAA on Apple Vision Pro. Previously the only way to get a usable image on AVP was to disable anti-aliasing, because the engine's MSAA resolve uses
gl.blitFramebufferdirectly into theXRWebGLLayer's opaque framebuffer — a path that visionOS WebKit handles incorrectly, producing a small zoomed-in sub-region instead of full stereo content.Fix: on visionOS only, MSAA color is resolved into an internal scratch texture via
blitFramebuffer, then copied 1:1 into the XR framebuffer with a single fullscreen textured quad. The rasterization path is what AVP renders correctly.Changes:
pc.platform.visionosboolean — detects Apple Vision Pro. visionOS Safari spoofs a macOS UA (no"visionOS"string), so detection combinesMacintoshUA +maxTouchPoints > 0+ no iPhone/iPad/iPod token.WebglXrMsaaCopyhelper — owns a scratchTexture/RenderTargetand a fullscreen-quad copy shader, built viaShader,ShaderDefinitionUtils, anddevice.scope. Lazily created onWebglGraphicsDevice, only on visionOS.WebglRenderTarget.resolveroutes XR color resolves through the helper whenplatform.visionosis true; all other XR platforms (Quest, Chrome, etc.) keep the existing direct-blit path with zero overhead.API Changes:
pc.platform.visionos(boolean).Performance:
blitFramebuffer(MSAA → scratch texture) plus one fullscreen quad draw per frame. Required because direct blits into the AVP XR FBO are broken;WEBGL_multisampled_render_to_textureis not available on AVP.platform.visionos.