fix(graphics): align WebGPU backbuffer format with WebXR projection-layer format#8914
Merged
Conversation
…ayer format While immersive, device.backBufferFormat stayed pinned to the canvas swapchain format instead of the WebXR projection-layer format the runtime renders into. Systems keyed off it - RenderTarget#isColorBufferSrgb (forward-renderer / compose gamma correction) and scene color-grab - used the wrong format, risking gamma-incorrect XR output. Override it each frame from the projection layer's per-eye view format (which carries the runtime's sRGB reinterpretation) and revert on frame/session teardown via _clearXrState.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes WebGPU immersive WebXR rendering by keeping the engine’s GraphicsDevice#backBufferFormat aligned with the active WebXR projection-layer view format (including the runtime’s sRGB reinterpretation), so format-dependent systems (gamma/output correction and scene color-grab) behave consistently during XR and then revert back to the canvas-derived format on teardown.
Changes:
- WebGPU XR now updates
device.backBufferFormatfrom the active projection layer’s per-eyeviewFormatduringbeginFrame. WebgpuGraphicsDevicetracks the canvas-derived backbuffer format and restores it in_clearXrState.- Added a WebGPU texture-format → engine
PIXELFORMAT_*mapping used for the XR override.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/platform/graphics/webgpu/webgpu-xr-bridge.js | Sets XR color texture/view format and applies the XR-driven backbuffer format override each frame. |
| src/platform/graphics/webgpu/webgpu-graphics-device.js | Adds format mapping and canvas-format capture/restore to support correct backBufferFormat behavior during/after XR. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
While in an immersive WebGPU XR session, the engine-level backbuffer format (
device.backBufferFormat) stayed pinned to the canvas swapchain format chosen at startup, even though XR renders into the WebXR projection layer — whose format the runtime recommends independently viaXRGPUBinding.getPreferredColorFormat(). Systems that key offbackBufferFormat— notablyRenderTarget#isColorBufferSrgb, which drives output gamma correction in the forward renderer and compose pass, plus scene color-grab — therefore used the wrong format during XR. This could produce gamma-incorrect XR output (too dark/bright vs the 2D canvas) when the projection layer's sRGB-ness differed from the canvas format.Changes:
device.backBufferFormatwith the active projection layer's per-eye view format each frame, reverting to the canvas-derived format when the immersive frame/session ends (centralized in_clearXrState, which is hit on every teardown path).getPreferredColorFormat()string) because it carries the runtime's sRGB reinterpretation, which is what actually determines hardware gamma encoding on write.No public API changes — all additions are internal (
@ignore/ private).