WebXR/WebGPU Binding

The spec is finally moving. The WebXR/WebGPU Binding is now an official Immersive Web Editor’s Draft (dated 15 June 2026). It defines XRGPUBinding where you request an xrCompatible GPUDevice and create WebGPU-backed projection/composition layers instead of XRWebGLLayer. After ~3 years of the proposal sitting dead, it’s active again, largely because Quest Browser shipping WebGPU made it worth doing. As a result, can we expect Babylon to enable a WebGPU backend for immersive mode sometime in the near future? :partying_face:

https://immersive-web.github.io/WebXR-WebGPU-Binding/

5 Likes

Things are happening. I will keep you updated about the WebGPU support.

4 Likes

Oh, the link of the proposal has been updated to below I think:

1 Like

Yup, we are actively connected with the spec ppl there :slight_smile:

1 Like

If anyone wants to track the work - [Epic] WebGPU support for WebXR · Issue #18635 · BabylonJS/Babylon.js · GitHub

Experimental on the quest browser is more than enough to start playing around with it :slight_smile:

3 Likes

Will this help unlock WebXR support for Babylon Lite?

Of course. WebXR for lite is already partly implemented, but will stay experimental for a long time because of the lack of WebGPU support in most browsers. It is not yet commited and there are still things to be fixed. But know that I am working on it.

2 Likes

What all has to be done to check and set up WebGPU with WebXR if it is fully supported (and fall back to WebGL?)

I’ve attempted to create a Playground, but haven’t figured out how even to get ordinary WebGPU running in the Playground — my latest attempt is

export const createEngine = async function () {
    const cvs = (typeof canvas !== "undefined" && canvas) || document.querySelector("canvas");
    let supported = false;
    try {
        supported = !!(BABYLON.WebGPUEngine && (await BABYLON.WebGPUEngine.IsSupportedAsync));
    } catch (e) {
        console.error(e);
    }

    if (supported) {
        try {
            const wgpu = new BABYLON.WebGPUEngine(cvs, { xrCompatible: true, antialias: true });
            await wgpu.initAsync();
            return wgpu;
        } catch (e) {
            console.error(e);
        }
    }
    const gl = new BABYLON.Engine(cvs, true, { preserveDrawingBuffer: true, stencil: true, xrCompatible: true });
    return gl;
};

based on https://playground.babylonjs.com/#55MXDY#0

Based on Babylon.js docs the code in my app checks both WebGPUEngine.IsSupportedAsync and `const isXRLayersSupported = WebXRFeaturesManager.GetAvailableFeatures().includes(WebXRFeatureName.LAYERS);`

async function createEngineForImmersiveXR(canvas: HTMLCanvasElement, isXRLayersSupported: boolean, willUseXR: boolean) : Promise<WebGPUEngine | Engine> {
    const webGPUSupported = await WebGPUEngine.IsSupportedAsync;
    // Includes XRGPUBinding projection APIs and XRGPUSubImage.getViewDescriptor.
    // @ts-ignore
    const webGPUXRSupported = WebXRSessionManager.IsWebGPUXRSupported;

    console.log(`isXRLayersSupported`, isXRLayersSupported, `willUseXR`, willUseXR, `webGPUSupported`, webGPUSupported, `webGPUXRSupported`, webGPUXRSupported);
    dialog.show(`isXRLayersSupported ${isXRLayersSupported}\nwillUseXR ${willUseXR}\nwebGPUSupported ${webGPUSupported}\nwebGPUXRSupported ${webGPUXRSupported}`);

    if (webGPUSupported && (willUseXR ? webGPUXRSupported && isXRLayersSupported : true)) {
        let engine: WebGPUEngine;
        try {
            console.log(`new WebGPU options:`, { xrCompatible: willUseXR && webGPUXRSupported && isXRLayersSupported });
            engine = new WebGPUEngine(canvas, { xrCompatible: willUseXR && webGPUXRSupported && isXRLayersSupported });
            await engine.initAsync();
            return engine;
        } catch (error) {
            // @ts-ignore
            engine?.dispose();
            console.warn("failed to initialize an XR-compatible WebGPU engine; using WebGL instead:", error);
            const msgs = errToMessages(error as ErrorLike, new Set(["failed to initialize an XR-compatible WebGPU engine"]));
            for (let msg of msgs) {
                dialog.show(msg);
            }
        }
    }

    return new Engine(canvas, true, {xrCompatible: willUseXR});
}

When the system supports WebGPU but not WebGL, this creates a WebGPU engine that works fine.

With this, I can create a default WebXRExperience, which runs in flat mode (and in immersive modes when a WebGL engine is selected), but when webGPUSupported, `webGPUXRSupportedandisXRLayersSupported` are all true, I click the button to go into immersive-ar or immersive-vr mode, it fails and this is logged to the console:

BJS - [15:46:07]: Error: One or more required features are not supported by the device.
logger.js:52 BJS - [15:46:07]: One or more required features are not supported by the device.

1 Like

thanks, I will look into that!

1 Like

FWIW, it’s pretty tricky and it took me a few days in my BabylonNative wgpu branch to get my Factotum WebXR app launching and working in WebXR-on-WebGPU across Pico, Quest, HTC, and Apple Vision Pro. Pro tip: for lower-end Qualcomm XR2 gen 1 devices, and for AR on iPhone XR, the WebGPU feature multi-draw indirect is an absolute necessity. Even on Qualcomm XR Elite, it helps keep CPU clocks lower which helps with thermals and battery life while maintaining 72-90fps.

1 Like

Is it possible to enable that in a webapp? I can set enableIndirectDraw in the WebGPUEngine constructor arguments, but I’m not seeing that multi-draw indirect is available.

the underlying WebGPU implementation has to have the feature enabled on the given adapter. my wgpu branch of BabylonNative is building against a PR branch of wgpu itself: use Metal's Indirect Command Buffers for true GPU-side multi draw indirect by matthargett · Pull Request #9640 · gfx-rs/wgpu · GitHub . the nice thing with BabylonNative is that we can build beyond the edge of the current desktop browser uptake of recent standards work :slight_smile:

I notice with the browser flag for GPU bindings on, XR is working well on the latest Blink distros.
Appreciate @RaananW et al. for that. That was my main hesitancy from Lite.

1 Like