Skip to content

fix(webgpu): WebGPU XR rendering on Apple Vision Pro#8756

Merged
mvaligursky merged 1 commit into
mainfrom
mv-webgpu-xr-avp-scissor-fix
May 21, 2026
Merged

fix(webgpu): WebGPU XR rendering on Apple Vision Pro#8756
mvaligursky merged 1 commit into
mainfrom
mv-webgpu-xr-avp-scissor-fix

Conversation

@mvaligursky
Copy link
Copy Markdown
Contributor

@mvaligursky mvaligursky commented May 21, 2026

Summary

Related to #8755.

WebGPU+WebXR was rendering only into a sub-rectangle of each eye on Apple Vision Pro. Root cause is a visionOS Safari quirk where any explicit passEncoder.setScissorRect(...) call (even one equal to the WebGPU pass-start default = full attachment) is interpreted as a positional hint for the eye-display sub-region, clipping the content. Upstream WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=315274.

Changes

  • WebgpuGraphicsDevice#setViewport / #setScissor — early-return without calling the underlying passEncoder methods when this.xrColorTexture is set. The default viewport/scissor (= attachment extent) is what AVP needs to map the projection-layer texture across the full eye. Shadow state is deliberately not updated either, so non-XR cache checks aren't poisoned.
  • frameStart — track the backbuffer's intrinsic _width / _height to whatever texture we're rendering into this frame (canvas swapchain or XR projection layer), instead of falling back to device.width via the getter.
  • WebgpuRenderTarget#assignColorTexture — pass the WebXR runtime's per-eye view descriptor through to createView as-is, preserving its format (e.g. sRGB view over a linear texture) instead of clobbering with a separate format override.
  • WebgpuXrBridge#beginFrame — prefer viewDescriptor.format for the per-view viewFormat so the render pipeline format matches what the view will see.

Fixes #8755.

- WebgpuGraphicsDevice#setViewport / setScissor skip the underlying
  passEncoder calls when the backbuffer is bound to an XR projection-layer
  texture. visionOS Safari treats an explicit scissor call as a positional
  hint for the eye-display sub-region (even at the attachment extent),
  clipping the rendered content to a sub-rectangle of the eye. The default
  scissor (= attachment) works correctly, so we leave it untouched. See
  https://bugs.webkit.org/show_bug.cgi?id=315274.
- frameStart tracks the backbuffer's intrinsic width/height to the actual
  output texture (canvas swapchain or XR projection layer) so downstream
  viewport / Y-flip math uses the right extent.
- WebXR runtime view descriptors are passed through to createView as-is,
  preserving the runtime's per-eye format (e.g. sRGB view over a linear
  texture) instead of clobbering it with a format override.
- xr-bridge prefers the view descriptor's format for the per-view
  viewFormat so the render pipeline matches what the view sees.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@mvaligursky mvaligursky self-assigned this May 21, 2026
@mvaligursky mvaligursky added area: graphics Graphics related issue area: xr XR related issue labels May 21, 2026
@mvaligursky mvaligursky merged commit cf1176f into main May 21, 2026
8 checks passed
@mvaligursky mvaligursky deleted the mv-webgpu-xr-avp-scissor-fix branch May 21, 2026 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: graphics Graphics related issue area: xr XR related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant