WebXR/WebGPU Binding Module - Level 1

Editor’s Draft,

More details about this document
This version:
https://immersive-web.github.io/webxr-webgpu-binding/
Latest published version:
https://www.w3.org/TR/webxr-webgpu-binding-1/
Previous Versions:
Feedback:
GitHub
Editor:
(Google)
Not Ready For Implementation

This spec is not yet ready for implementation. It exists in this repository to record the ideas and promote discussion.

Before attempting to implement this spec, please contact the editors.


Abstract

This specification describes support for rendering content for a WebXR session with WebGPU.

Status of this document

This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document was published by the Immersive Web Working Group as an Editors' Draft. This document is intended to become a W3C Recommendation. Feedback and comments on this specification are welcome. Please use Github issues. Discussions may also be found in the public-immersive-web-wg@w3.org archives.

Publication as an Editors' Draft does not imply endorsement by W3C and its Members. This is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to cite this document as other than a work in progress.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent that the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 18 August 2025 W3C Process Document.

1. Introduction

This specification describes a mechanism for rendering WebXR content using WebGPU, instead of WebGL.

It adds support for creation of XRCompositionLayers, as described in the WebXR Layers API, which are rendered using the WebGPU API.

WebGPU is an API for utilizing the graphics and compute capabilities of a device’s GPU more efficiently than WebGL allows, with an API that better matches both GPU hardware architecture and the modern native APIs that interface with them, such as Vulkan, Direct3D 12, and Metal.

1.1. Terminology

This specification uses the terms XR device, XR Compositor, XRSession, XRFrame, XRView, and feature descriptor as defined in the WebXR Device API specification.

It uses the terms XRCompositionLayer, XRProjectionLayer, XRQuadLayer, XRCylinderLayer, XREquirectLayer, XRCubeLayer, XRSubImage, and XRWebGLBinding as defined in the WebXR Layers API specification.

It uses the terms GPUDevice, GPUAdapter, GPUQueue, GPUTexture, GPUTextureViewDescriptor, GPUTextureFormat, and GPUTextureUsageFlags as defined in the WebGPU specification.

1.2. Application flow

If an author wants to use WebGPU to render content for a WebXR Session, they must perform the following steps:

In no particular order

  1. Create a GPUDevice from an GPUAdapter which was requested with the xrCompatible option set to true.

  2. Create an XRSession with the webgpu feature.

Then

  1. Create an XRGPUBinding with both the XR-compatible GPUDevice and WebGPU-compatible session.

  2. Create one or more XRCompositionLayers with the XRGPUBinding

  3. Add the layers to XRRenderStateInit and call updateRenderState().

  4. During requestAnimationFrame() for each WebGPU layer:

    1. For each XRGPUSubImage exposed by the layer:

      1. Draw the contents of the subimage using the GPUDevice the XRGPUBinding was created with.

2. Initialization

2.1. Feature Descriptor

The string "webgpu" is introduced by this module as a new valid feature descriptor for the WebXR/WebGPU Binding feature.

If a user agent wants to use WebGPU for rendering during a session, the session MUST be requested with the webgpu feature descriptor. XRSessions created with this feature are referred to as WebGPU-compatible sessions.

A WebGPU-compatible session MUST have the following behavioral differences from a WebGL-compatible session:

The following code creates a WebGPU-compatible session.
const session = await navigator.xr.requestSession('immersive-vr', {
  requiredFeatures: ['webgpu']
});

NOTE: The webgpu feature may be passed to either requiredFeatures or optionalFeatures. If passed to optionalFeatures, the author MUST check enabledFeatures after the session is created and use either WebGPU or WebGL to render the session’s content depending on whether webgpu is present.

2.2. GPUAdapter Integration

To create a GPUDevice that is compatible with an XR device, the GPUAdapter used to create it must have been requested with the xrCompatible option set to true.

partial dictionary GPURequestAdapterOptions {
    boolean xrCompatible = false;
};

The xrCompatible option, when set to true, indicates that the returned GPUAdapter MUST be compatible with the XR device selected by the user agent. If no GPUAdapter can satisfy this constraint, the request MUST return null.

NOTE: There is no WebGPU equivalent to the WebGLRenderingContextBase.makeXRCompatible() method. If a user agent needs to ensure XR compatibility, the GPUAdapter MUST be requested with xrCompatible set to true from the start.

An XR-compatible adapter is a GPUAdapter that was successfully returned from a requestAdapter() call with xrCompatible set to true.

An XR-compatible device is a GPUDevice that was created from an XR-compatible adapter.

3. Layer Types

XRCompositionLayer, XRProjectionLayer, XRQuadLayer, XRCylinderLayer, XREquirectLayer, and XRCubeLayer are defined by the WebXR Layers API.

An XRCompositionLayer created by an XRGPUBinding is a WebGPU-backed layer. Each WebGPU-backed layer has an associated WebGPU device, which is the device of the XRGPUBinding that created it.

4. Rendering

4.1. XRGPUSubImage

An XRGPUSubImage represents a view into a WebGPU-backed composition layer’s textures. It provides the GPUTextures to render into and a GPUTextureViewDescriptor that describes which portion of the texture corresponds to the requested view. The viewport describes the region of the colorTexture that corresponds to the requested view. When present, the depthStencilTexture has the same corresponding region, except when the motionVectorTexture is not null. In that case, the viewport does not describe the region of the depth/stencil or motion vector texture.

Each XRGPUSubImage has an associated non-negative integer array layer index, which identifies the first array layer belonging to the subimage.

Each WebGPU-backed layer has an associated current color texture, an optional current depth-stencil texture, a current texture set, and a current texture frame, all initially null. Each WebGPU-backed XRProjectionLayer also has an optional current motion vector texture, initially null. The current textures are GPUTexture objects that expose the backing resources of the layer’s current texture set during its current texture frame.

The user agent MUST return the same current GPUTexture objects for every subimage of a layer within an XR animation frame. After that frame’s animation frame callbacks have completed, the user agent MUST release the WebGPU textures for the layer. A retained XRGPUSubImage will therefore return destroyed textures after the frame in which it was obtained.

Calling destroy() on a current color texture, current depth-stencil texture, or current motion vector texture MUST terminate write access through that GPUTexture, but MUST NOT destroy or alter the WebGPU layer texture resource that backs it. The layer continues to reference the same destroyed GPUTexture until its current textures are expired. Consequently, subsequent subimage requests for the same layer in the same frame return the same destroyed texture.

[Exposed=(Window), SecureContext]
interface XRGPUSubImage : XRSubImage {
  [SameObject] readonly attribute GPUTexture colorTexture;
  [SameObject] readonly attribute GPUTexture? depthStencilTexture;
  [SameObject] readonly attribute GPUTexture? motionVectorTexture;

  GPUTextureViewDescriptor getViewDescriptor();
};

4.1.1. Attributes

The colorTexture attribute returns the GPUTexture to be used as the color attachment when rendering this sub image. Its backing resource is allocated and managed by the user agent. The same GPUTexture object is returned for all subimages of the same layer within a single frame. Use the result of getViewDescriptor() to determine which array layer of the texture to render to.

The returned texture has the following properties:

The depthStencilTexture attribute returns the GPUTexture containing the depth/stencil data for this sub image, or null if no depth/stencil format was specified when creating the layer. When this texture is present and the motionVectorTexture is null, it has the same dimensions as the colorTexture and can be used as the depth/stencil attachment in the render pass that renders to the color texture. When the motion vector texture is not null, the depth/stencil texture is also present, has the same dimensions as the motion vector texture, may have different dimensions than the color texture, and is rendered separately as described in § 6 Space Warp. When provided, the user agent MAY use the depth information to improve composition quality (for example, for reprojection).

When present, the returned texture has the following properties:

NOTE: If a depthStencilFormat other than "stencil8" was provided during layer creation, it is implied that the author will populate it with an accurate representation of the scene’s depth. If the depth information is not representative of the rendered scene, the user agent SHOULD allocate its own depth/stencil textures rather than use the layer-provided one.

The motionVectorTexture attribute returns the GPUTexture to be used as the motion vector attachment when rendering this sub image. It returns null unless the layer is an XRProjectionLayer, the space-warp feature descriptor was enabled when the session was created, and the layer was created with an depthStencilFormat that is present and is not "stencil8".

When present, the returned texture has the following properties:

4.1.2. getViewDescriptor

The getViewDescriptor() method returns a GPUTextureViewDescriptor configured for creating a texture view of this sub image’s portion of the layer’s textures. The returned descriptor can be passed to GPUTexture.createView() on the colorTexture, depthStencilTexture, and motionVectorTexture.

When invoked, the user agent MUST run the following steps:

  1. Let descriptor be a new GPUTextureViewDescriptor.

  2. Set descriptor’s dimension to "2d".

  3. Set descriptor’s mipLevelCount to 1.

  4. Set descriptor’s arrayLayerCount to 1.

  5. Set descriptor’s baseArrayLayer to this XRGPUSubImage’s array layer index.

  6. Return descriptor.

NOTE: The returned descriptor selects a single 2D slice from the texture array via baseArrayLayer paired with an arrayLayerCount of 1. The viewport still needs to be applied via setViewport() when rendering to the color texture and, when the motionVectorTexture is null, when rendering to the depth/stencil texture. Depth/stencil and motion vector textures used for space warp are rendered to their full extent as described in § 6 Space Warp.

NOTE: For an XRCubeLayer, the returned descriptor selects the first face for the requested eye. Authors can render the remaining faces by creating descriptors with baseArrayLayer increased by 1 through 5, following the face order defined for createCubeLayer().

Using the view descriptor to create render pass attachments:
const subImage = binding.getViewSubImage(layer, view);
const viewDesc = subImage.getViewDescriptor();

const colorView = subImage.colorTexture.createView(viewDesc);
const depthView = subImage.depthStencilTexture.createView(viewDesc);

5. GPU Layer and View Creation

This section defines the binding, initialization dictionaries, and algorithms used to create WebGPU-backed layers and access their per-frame texture views.

5.1. Texture allocation

Each WebGPU-backed layer has an internal color texture descriptor and an optional depth-stencil texture descriptor. Each WebGPU-backed XRProjectionLayer also has an optional motion vector texture descriptor. These GPUTextureDescriptors describe the textures used to render the layer.

A WebGPU layer texture resource is GPU texture storage allocated by the user agent for a WebGPU-backed layer using the layer’s WebGPU device. It is not itself a Web-exposed GPUTexture, but it can be exposed through a GPUTexture whose underlying storage points to the resource. Its allocation MUST be attributed to the GPUDevice and subject to the same resource limits as a texture created with createTexture().

A WebGPU layer texture set is an internal tuple containing one color WebGPU layer texture resource, an optional depth-stencil resource, and an optional motion vector resource. Each set has an available boolean. Each WebGPU-backed layer has an internal list of texture sets. Until destroy() is invoked, the list’s length is implementation-defined but MUST be greater than zero. The resources in every set MUST have the properties specified by their corresponding texture descriptors.

If a WebGPU-backed layer has two or more mipLevels, the author SHOULD populate every mip level. The user agent MUST NOT generate the mip levels on the author’s behalf.

To create an XR GPU texture descriptor with an XRGPUBinding binding, positive integers width, height, arrayLayerCount, and mipLevelCount, a GPUTextureFormat format, and GPUTextureUsageFlags usage, the user agent MUST run the following steps:

  1. Let descriptor be a new GPUTextureDescriptor with the following members:

  2. If descriptor would not satisfy the validation requirements for createTexture() when invoked on binding’s device, throw a NotSupportedError DOMException.

  3. Return descriptor.

To allocate WebGPU layer texture sets with an XRGPUBinding binding, a GPUTextureDescriptor colorDescriptor, a nullable GPUTextureDescriptor depthStencilDescriptor, and a nullable GPUTextureDescriptor motionVectorDescriptor, the user agent MUST run the following steps:

  1. Let textureSets be a new empty list.

  2. Let textureSetCount be an implementation-defined positive integer sufficient to allow the application and the XR Compositor to use different texture sets concurrently.

  3. Repeat textureSetCount times:

    1. Let textureSet be a new WebGPU layer texture set.

    2. Allocate textureSet’s color resource using binding’s device with the storage properties described by colorDescriptor.

    3. If depthStencilDescriptor is not null, allocate textureSet’s depth-stencil resource using binding’s device with the storage properties described by depthStencilDescriptor. Otherwise, set its depth-stencil resource to null.

    4. If motionVectorDescriptor is not null, allocate textureSet’s motion vector resource using binding’s device with the storage properties described by motionVectorDescriptor. Otherwise, set its motion vector resource to null.

    5. If the user agent was unable to allocate any resource for textureSet, release every resource allocated by these steps and throw an OperationError DOMException.

    6. Set textureSet’s available boolean to true.

    7. Append textureSet to textureSets.

  4. Return textureSets.

To acquire WebGPU textures for a WebGPU-backed layer layer and an XRFrame frame, the user agent MUST run the following steps:

  1. Let device be layer’s WebGPU device.

  2. If device has been destroyed, throw an InvalidStateError DOMException.

  3. If layer’s list of texture sets is empty, throw an InvalidStateError DOMException.

  4. If layer’s current texture set is not null:

    1. Assert that layer’s current texture frame is frame.

    2. Return.

  5. Let textureSet be an entry in layer’s list of texture sets whose available boolean is true.

  6. Assert that textureSet exists. The user agent MUST ensure that a texture set is available before invoking the animation frame callbacks for frame.

  7. Set textureSet’s available boolean to false.

  8. Set layer’s current texture set to textureSet and its current texture frame to frame.

  9. Set layer’s current color texture to the result of calling device.createTexture() with layer’s color texture descriptor, except with the GPUTexture’s underlying storage pointing to textureSet’s color resource.

  10. If layer’s depth-stencil texture descriptor is not null, set layer’s current depth-stencil texture to the result of calling device.createTexture() with that descriptor, except with the GPUTexture’s underlying storage pointing to textureSet’s depth-stencil resource.

  11. If layer is an XRProjectionLayer and its motion vector texture descriptor is not null, set layer’s current motion vector texture to the result of calling device.createTexture() with that descriptor, except with the GPUTexture’s underlying storage pointing to textureSet’s motion vector resource.

  12. Clear every color and motion vector resource in textureSet to zero. Clear every depth component in its depth-stencil resource to 1.0 and every stencil component to 0.

To expire the WebGPU textures for a WebGPU-backed layer layer, the user agent MUST run the following steps:

  1. If layer’s current color texture is not null, call destroy() on it (without destroying the underlying storage) to terminate write access to the image.

  2. If layer’s current depth-stencil texture is not null, call destroy() on it (without destroying the underlying storage) to terminate write access to the image.

  3. If layer is an XRProjectionLayer and its current motion vector texture is not null, call destroy() on it (without destroying the underlying storage) to terminate write access to the image.

  4. Set layer’s current color texture and current depth-stencil texture to null.

  5. If layer is an XRProjectionLayer, set its current motion vector texture to null.

  6. Set layer’s current texture set and current texture frame to null.

To release the WebGPU textures for a WebGPU-backed layer layer and an XRFrame frame, the user agent MUST run the following steps:

  1. If layer’s current texture frame is not frame, return.

  2. Let textureSet be layer’s current texture set.

  3. Before the XR Compositor consumes textureSet, ensure that all WebGPU work submitted during the processing of frame that writes to the current textures has completed, or synchronize the compositor with that work using an equivalent GPU-side dependency. If multiple submit() calls write to a current texture during frame, this synchronization MUST include the last such submission.

  4. Make textureSet’s backing resources available to the XR Compositor for frame.

  5. Run expire the WebGPU textures for layer.

  6. Set layer’s needsRedraw to false.

  7. Once the XR Compositor no longer accesses textureSet’s backing resources, set textureSet’s available boolean to true.

When destroy() is invoked on a WebGPU-backed layer layer, the user agent MUST run the following steps instead of the WebXR Layers API’s steps for calling destroy() on a layer:

  1. Let textureSets be layer’s list of texture sets.

  2. Run expire the WebGPU textures for layer.

  3. Set layer’s list of texture sets to an empty list.

  4. For each textureSet of textureSets, once neither previously submitted WebGPU work nor the XR Compositor accesses its backing resources, release each non-null backing resource in textureSet.

The XR animation frame algorithm is extended as follows: immediately before setting its active boolean to false, the user agent MUST release the WebGPU textures for every WebGPU-backed layer whose current texture frame is that XRFrame.

5.2. Supported Texture Formats

The supported color formats for XRGPUBinding layer creation are:

The supported depth/stencil formats for XRGPUBinding layer creation are:

The formats listed above are the only formats that can be used for layer creation. User agents MUST NOT accept formats outside of these lists. A listed format can still be rejected when it does not satisfy the WebGPU feature or usage requirements of the device.

5.3. XRGPUProjectionLayerInit

The XRGPUProjectionLayerInit dictionary is used to configure projection layers created with createProjectionLayer().

dictionary XRGPUProjectionLayerInit {
  required GPUTextureFormat colorFormat;
  GPUTextureFormat? depthStencilFormat;
  GPUTextureUsageFlags textureUsage = 0x10; // GPUTextureUsage.RENDER_ATTACHMENT
  double scaleFactor = 1.0;
};
Creating a projection layer with the preferred color format:
const layer = binding.createProjectionLayer({
  colorFormat: binding.getPreferredColorFormat(),
  depthStencilFormat: 'depth24plus-stencil8',
});

The colorFormat member specifies the GPUTextureFormat for the layer’s color textures. This MUST be a supported color format.

The depthStencilFormat member, when present, specifies the GPUTextureFormat for the layer’s depth/stencil textures. This MUST be a supported depth-stencil format. When not present, no depth/stencil texture is allocated. A motion vector texture is allocated only when the space-warp feature descriptor is enabled and this member is present and is not "stencil8".

The textureUsage member specifies the GPUTextureUsageFlags to be set on the allocated textures. The default value is GPUTextureUsage.RENDER_ATTACHMENT. If overriding this value, developers MUST explicitly include RENDER_ATTACHMENT if they intend to use the textures as render attachments.

The scaleFactor member specifies a scale factor to apply to the recommended WebGPU texture resolution. A value of 1.0 uses the recommended resolution; values less than 1.0 reduce quality for improved performance; values greater than 1.0 increase quality at the cost of performance. The value is clamped to the range [0.2, max(nativeProjectionScaleFactor, 1.0)].

5.4. XRGPULayerInit

The XRGPULayerInit dictionary is the base dictionary for configuring non-projection composition layers. Non-projection layers require the "layers" feature descriptor to be enabled for the session.

dictionary XRGPULayerInit {
  required GPUTextureFormat colorFormat;
  GPUTextureFormat? depthStencilFormat;
  GPUTextureUsageFlags textureUsage = 0x10; // GPUTextureUsage.RENDER_ATTACHMENT
  required XRSpace space;
  unsigned long mipLevels = 1;
  required unsigned long viewPixelWidth;
  required unsigned long viewPixelHeight;
  XRLayerLayout layout = "mono";
  boolean isStatic = false;
};

The colorFormat member specifies the GPUTextureFormat for the layer’s color textures. This MUST be a supported color format.

The depthStencilFormat member, when present, specifies the GPUTextureFormat for the layer’s depth/stencil textures. This MUST be a supported depth-stencil format. When not present, no depth/stencil texture is allocated.

The textureUsage member specifies the GPUTextureUsageFlags for the allocated textures. The default value is GPUTextureUsage.RENDER_ATTACHMENT.

The space member specifies the XRSpace in which the layer is positioned.

The mipLevels member specifies the desired number of mip levels for the layer’s textures. The actual number is returned by mipLevels and can be lower than the requested value.

The viewPixelWidth member specifies the width, in pixels, of each view’s texture.

The viewPixelHeight member specifies the height, in pixels, of each view’s texture.

The layout member specifies the XRLayerLayout of the layer. "default" is not valid for non-projection layers created by an XRGPUBinding.

The isStatic member, when set to true, indicates that the author will only draw to the layer when needsRedraw is true. This allows the user agent to optimize for this scenario.

5.5. XRGPUQuadLayerInit

dictionary XRGPUQuadLayerInit : XRGPULayerInit {
  XRRigidTransform? transform;
  float width = 1.0;
  float height = 1.0;
};

The transform member specifies the initial position and orientation of the quad layer relative to the space.

The width member specifies the width of the quad in meters.

The height member specifies the height of the quad in meters.

5.6. XRGPUCylinderLayerInit

dictionary XRGPUCylinderLayerInit : XRGPULayerInit {
  XRRigidTransform? transform;
  float radius = 2.0;
  float centralAngle = 0.78539;
  float aspectRatio = 2.0;
};

The transform member specifies the initial position and orientation of the cylinder layer.

The radius member specifies the radius of the cylinder in meters.

The centralAngle member specifies the central angle of the cylinder in radians. The default value of 0.78539 corresponds to approximately 45 degrees.

The aspectRatio member specifies the aspect ratio (width / height) of the visible portion of the cylinder.

5.7. XRGPUEquirectLayerInit

dictionary XRGPUEquirectLayerInit : XRGPULayerInit {
  XRRigidTransform? transform;
  float radius = 0;
  float centralHorizontalAngle = 6.28318;
  float upperVerticalAngle = 1.570795;
  float lowerVerticalAngle = -1.570795;
};

The transform member specifies the initial position and orientation of the equirect layer.

The radius member specifies the radius of the sphere in meters. A value of 0 indicates an infinite sphere (the equirect is rendered as a skybox).

The centralHorizontalAngle member specifies the horizontal angular extent of the sphere in radians. The default value of 6.28318 corresponds to a full 360 degrees.

The upperVerticalAngle member specifies the upper vertical angle of the visible portion in radians, measured from the horizon.

The lowerVerticalAngle member specifies the lower vertical angle of the visible portion in radians, measured from the horizon.

5.8. XRGPUCubeLayerInit

dictionary XRGPUCubeLayerInit : XRGPULayerInit {
  DOMPointReadOnly? orientation;
};

The orientation member specifies the initial orientation of the cube layer as a quaternion.

For cube layers, viewPixelWidth and viewPixelHeight specify the dimensions of each cube face and MUST be equal.

5.9. XRGPUBinding

The XRGPUBinding interface is the entry point for using WebGPU with a WebGPU-compatible session. It provides methods for creating WebGPU-backed XRCompositionLayers and obtaining XRGPUSubImages for rendering.

[Exposed=(Window), SecureContext]
interface XRGPUBinding {
  constructor(XRSession session, GPUDevice device);

  readonly attribute double nativeProjectionScaleFactor;
  readonly attribute boolean usesDepthValues;

  XRProjectionLayer createProjectionLayer(optional XRGPUProjectionLayerInit init = {});
  XRQuadLayer createQuadLayer(optional XRGPUQuadLayerInit init = {});
  XRCylinderLayer createCylinderLayer(optional XRGPUCylinderLayerInit init = {});
  XREquirectLayer createEquirectLayer(optional XRGPUEquirectLayerInit init = {});
  XRCubeLayer createCubeLayer(optional XRGPUCubeLayerInit init = {});

  XRGPUSubImage getSubImage(XRCompositionLayer layer, XRFrame frame, optional XREye eye = "none");
  XRGPUSubImage getViewSubImage(XRProjectionLayer layer, XRView view);

  GPUTextureFormat getPreferredColorFormat();
};

Each XRGPUBinding has an associated session which is the XRSession it was created with, and an associated device which is the GPUDevice it was created with.

NOTE: A WebGPU-backed layer can be used with any XRGPUBinding that has the same session and device as the binding that created the layer.

The XRGPUBinding(session, device) constructor MUST perform the following steps when invoked:

  1. If session’s ended value is true, throw an InvalidStateError DOMException.

  2. If session is NOT a WebGPU-compatible session, throw an InvalidStateError DOMException.

  3. If device has been destroyed, throw an InvalidStateError DOMException.

  4. If device was NOT created from an XR-compatible adapter, throw an InvalidStateError DOMException.

  5. Let binding be a new XRGPUBinding.

  6. Set binding’s session to session.

  7. Set binding’s device to device.

  8. Return binding.

Creating an XRGPUBinding:
const adapter = await navigator.gpu.requestAdapter({ xrCompatible: true });
const device = await adapter.requestDevice();
const binding = new XRGPUBinding(session, device);

The nativeProjectionScaleFactor attribute returns the scale factor that, when applied to the recommended WebGPU texture resolution, would result in a 1:1 texel-to-pixel ratio at the center of the user’s view. This value MAY change over the lifetime of the session.

The usesDepthValues attribute, if false, indicates that the XR Compositor MUST NOT make use of values in a depth/stencil texture. When the attribute is true, it indicates that the contents of the depth/stencil texture will be used by the XR Compositor and are expected to be representative of the scene rendered into the layer. If the space-warp feature descriptor is enabled, this attribute MUST return true.

Each XR device has a recommended WebGPU texture resolution, which represents the per-view dimensions that the user agent considers a good balance between rendering quality and performance for that device. The recommended resolution is determined by taking the maximum width and height across all of the session’s views, scaled by a user agent-defined default scale factor.

NOTE: Unlike the recommended WebGL framebuffer resolution defined in the WebXR spec, which concatenates views side-by-side into a single framebuffer, the recommended WebGPU texture resolution describes the size of a single view. When creating projection layers, the user agent allocates a texture array where each layer corresponds to one view, with each layer having the recommended resolution.

Each XR device has a recommended WebGPU depth-stencil texture resolution, which represents the per-view dimensions that the user agent considers sufficient for depth/stencil textures used by the XR Compositor. Unless the space-warp feature descriptor is enabled, this resolution MUST be equal to the recommended WebGPU texture resolution.

If the space-warp feature descriptor is enabled, each XR device MUST have a recommended WebGPU motion vector texture resolution, which represents the per-view dimensions that the user agent considers sufficient for motion vector textures used by space warp. When the space-warp feature descriptor is enabled, the recommended WebGPU depth-stencil texture resolution MUST be equal to the recommended WebGPU motion vector texture resolution.

The nativeProjectionScaleFactor attribute can be used to determine the scale factor needed to achieve the native 1:1 resolution. A scaleFactor of 1.0 in createProjectionLayer() uses the recommended resolution directly.

The getPreferredColorFormat() method returns the GPUTextureFormat that the user agent recommends for the color attachments of layers created with this binding.

When invoked, the user agent MUST return the preferred GPUTextureFormat for the session’s XR device.

NOTE: The preferred color format is typically "rgba8unorm" or "bgra8unorm" depending on the platform. The preferred format for WebXR may differ from the format reported by navigator.gpu.getPreferredCanvasFormat(). Authors SHOULD use this method rather than getPreferredCanvasFormat() to determine the format for their XR projection layers.

To scale an XR GPU texture size recommendedSize by a double scaleFactor for a GPUDevice device, the user agent MUST run the following steps:

  1. Let width be max(1, floor(recommendedSize’s width multiplied by scaleFactor)).

  2. Let height be max(1, floor(recommendedSize’s height multiplied by scaleFactor)).

  3. Let maxDimension be device’s limits.maxTextureDimension2D.

  4. If width or height is greater than maxDimension:

    1. Let limitScale be min(maxDimension divided by width, maxDimension divided by height).

    2. Set width to max(1, floor(width multiplied by limitScale)).

    3. Set height to max(1, floor(height multiplied by limitScale)).

  5. Return (width, height).

The createProjectionLayer(init) method creates a new XRProjectionLayer backed by WebGPU textures.

When this method is invoked on an XRGPUBinding binding, the user agent MUST run the following steps:

  1. Let session be binding’s session.

  2. Let device be binding’s device.

  3. If session has ended, throw an InvalidStateError DOMException.

  4. If device has been destroyed, throw an InvalidStateError DOMException.

  5. If init’s colorFormat is not a supported color format, throw a NotSupportedError DOMException.

  6. If init’s depthStencilFormat is present and is not a supported depth-stencil format, throw a NotSupportedError DOMException.

  7. Let hasDepthAspect be true if init’s depthStencilFormat is present and is not "stencil8"; otherwise false.

  8. Let useSpaceWarp be true if hasDepthAspect is true and session was created with the space-warp feature descriptor; otherwise false.

  9. Let scaleFactor be init’s scaleFactor, clamped to the range [0.2, max(binding’s nativeProjectionScaleFactor, 1.0)].

  10. Let (colorWidth, colorHeight) be the result of scaling an XR GPU texture size of the recommended WebGPU texture resolution by scaleFactor for device.

  11. Initialize depthWidth to colorWidth and depthHeight to colorHeight.

  12. If useSpaceWarp is true:

    1. Let (spaceWarpWidth, spaceWarpHeight) be the result of scaling an XR GPU texture size of the recommended WebGPU depth-stencil texture resolution by scaleFactor for device.

    2. Set depthWidth to spaceWarpWidth and depthHeight to spaceWarpHeight.

  13. Let arrayLayerCount be the number of entries in session’s list of views.

  14. Let colorDescriptor be the result of creating an XR GPU texture descriptor with binding, colorWidth, colorHeight, arrayLayerCount, 1, init’s colorFormat, and init’s textureUsage.

  15. Initialize depthStencilDescriptor to null.

  16. If init’s depthStencilFormat is present, set depthStencilDescriptor to the result of creating an XR GPU texture descriptor with binding, depthWidth, depthHeight, arrayLayerCount, 1, init’s depthStencilFormat, and init’s textureUsage.

  17. Initialize motionVectorDescriptor to null.

  18. If useSpaceWarp is true:

    1. Set motionVectorDescriptor to the result of creating an XR GPU texture descriptor with binding, depthWidth, depthHeight, arrayLayerCount, 1, "rgba16float", and init’s textureUsage.

  19. Let layer be a new XRProjectionLayer in the relevant realm of binding.

  20. Run initialize a composition layer on layer with session.

  21. Set layer’s WebGPU device to device.

  22. Set layer’s layout to "default".

  23. Set layer’s isStatic to false.

  24. Set layer’s needsRedraw to true.

  25. Set layer’s mipLevels to 1.

  26. Set layer’s textureWidth to colorWidth.

  27. Set layer’s textureHeight to colorHeight.

  28. Set layer’s textureArrayLength to arrayLayerCount.

  29. If motionVectorDescriptor is not null, set layer’s ignoreDepthValues to false.

  30. Otherwise, if hasDepthAspect is true and binding’s usesDepthValues is true, set layer’s ignoreDepthValues to false.

  31. Otherwise, set layer’s ignoreDepthValues to true.

  32. If fixed foveation is supported, set layer’s fixedFoveation to 0. Otherwise, set it to null.

  33. Set layer’s deltaPose to null.

  34. Set layer’s color texture descriptor to colorDescriptor.

  35. Set layer’s depth-stencil texture descriptor to depthStencilDescriptor.

  36. Set layer’s motion vector texture descriptor to motionVectorDescriptor.

  37. Set layer’s list of texture sets to the result of allocating WebGPU layer texture sets with binding, colorDescriptor, depthStencilDescriptor, and motionVectorDescriptor.

  38. Set layer’s current color texture, current depth-stencil texture, current motion vector texture, current texture set, and current texture frame to null.

  39. Return layer.

Creating a projection layer with color and depth and making it the active layer for the session:
const layer = binding.createProjectionLayer({
  colorFormat: binding.getPreferredColorFormat(),
  depthStencilFormat: 'depth24plus',
});
session.updateRenderState({ layers: [layer] });

To validate WebGPU layer creation with an XRGPUBinding binding, the user agent MUST run the following steps:

  1. If binding’s session has ended, throw an InvalidStateError DOMException.

  2. If binding’s device has been destroyed, throw an InvalidStateError DOMException.

  3. If the layers feature descriptor is not enabled for binding’s session, throw a NotSupportedError DOMException.

To determine a WebGPU layer texture layout from an XRGPULayerInit init, the user agent MUST run the following steps:

  1. Let width be init’s viewPixelWidth.

  2. Let height be init’s viewPixelHeight.

  3. Let arrayLayerCount be 1.

  4. Switch on init’s layout:

    "mono"
    Do nothing.
    "stereo"
    Set arrayLayerCount to 2.
    "stereo-left-right"
    Set width to width multiplied by 2.
    "stereo-top-bottom"
    Set height to height multiplied by 2.
    "default"
    Throw a TypeError.
  5. Return (width, height, arrayLayerCount).

To initialize a WebGPU-backed layer layer with an XRGPUBinding binding, an XRGPULayerInit init, non-negative integers width and height, and a positive integer arrayLayerCount, the user agent MUST run the following steps:

  1. Let session be binding’s session.

  2. If width or height is 0, throw a TypeError.

  3. If init’s colorFormat is not a supported color format, throw a NotSupportedError DOMException.

  4. If init’s depthStencilFormat is present and is not a supported depth-stencil format, throw a NotSupportedError DOMException.

  5. If init’s mipLevels is less than 1, throw an InvalidStateError DOMException.

  6. Let maximumMipLevelCount be floor(log2(max(width, height))) + 1.

  7. Let mipLevelCount be min(init’s mipLevels, maximumMipLevelCount). The user agent MAY reduce mipLevelCount further if it cannot support the requested number of mip levels, but it MUST NOT reduce it below 1.

  8. Let colorDescriptor be the result of creating an XR GPU texture descriptor with binding, width, height, arrayLayerCount, mipLevelCount, init’s colorFormat, and init’s textureUsage.

  9. Initialize depthStencilDescriptor to null.

  10. If init’s depthStencilFormat is present, set depthStencilDescriptor to the result of creating an XR GPU texture descriptor with binding, width, height, arrayLayerCount, mipLevelCount, init’s depthStencilFormat, and init’s textureUsage.

  11. Run initialize a composition layer on layer with session.

  12. Run setting the space on a layer with init’s space and layer.

  13. Set layer’s WebGPU device to binding’s device.

  14. Set layer’s layout to init’s layout.

  15. Set layer’s isStatic to init’s isStatic.

  16. Set layer’s mipLevels to mipLevelCount.

  17. Set layer’s needsRedraw to true.

  18. Set layer’s color texture descriptor to colorDescriptor.

  19. Set layer’s depth-stencil texture descriptor to depthStencilDescriptor.

  20. Set layer’s list of texture sets to the result of allocating WebGPU layer texture sets with binding, colorDescriptor, depthStencilDescriptor, and null.

  21. Set layer’s current color texture, current depth-stencil texture, current texture set, and current texture frame to null.

The createQuadLayer(init) method creates a new XRQuadLayer backed by WebGPU textures.

When this method is invoked on an XRGPUBinding binding, the user agent MUST run the following steps:

  1. Run validate WebGPU layer creation with binding.

  2. Let (width, height, arrayLayerCount) be the result of determining a WebGPU layer texture layout from init.

  3. Let layer be a new XRQuadLayer in the relevant realm of binding.

  4. Run initialize a WebGPU-backed layer with layer, binding, init, width, height, and arrayLayerCount.

  5. Set layer’s space to init’s space.

  6. If init’s transform is present, set layer’s transform to a new XRRigidTransform in layer’s relevant realm, initialized with the position and orientation of init’s transform. Otherwise, set it to a new identity XRRigidTransform in layer’s relevant realm.

  7. Set layer’s width to init’s width.

  8. Set layer’s height to init’s height.

  9. Return layer.

The createCylinderLayer(init) method creates a new XRCylinderLayer backed by WebGPU textures.

When this method is invoked on an XRGPUBinding binding, the user agent MUST run the following steps:

  1. Run validate WebGPU layer creation with binding.

  2. Let (width, height, arrayLayerCount) be the result of determining a WebGPU layer texture layout from init.

  3. Let layer be a new XRCylinderLayer in the relevant realm of binding.

  4. Run initialize a WebGPU-backed layer with layer, binding, init, width, height, and arrayLayerCount.

  5. Set layer’s space to init’s space.

  6. If init’s transform is present, set layer’s transform to a new XRRigidTransform in layer’s relevant realm, initialized with the position and orientation of init’s transform. Otherwise, set it to a new identity XRRigidTransform in layer’s relevant realm.

  7. Set layer’s radius to init’s radius.

  8. Set layer’s centralAngle to init’s centralAngle.

  9. Set layer’s aspectRatio to init’s aspectRatio.

  10. Return layer.

NOTE: The WebXR Layers space requirements allow XRQuadLayer and XRCylinderLayer to use any XRSpace, including "viewer" for head-locked content. XREquirectLayer and XRCubeLayer are restricted to XRReferenceSpace values other than "viewer" so that environment content, such as 360-degree media and skyboxes, preserves rotational reprojection.

The createEquirectLayer(init) method creates a new XREquirectLayer backed by WebGPU textures.

When this method is invoked on an XRGPUBinding binding, the user agent MUST run the following steps:

  1. Run validate WebGPU layer creation with binding.

  2. If init’s space is not an XRReferenceSpace, throw a TypeError.

  3. If init’s space has a type of "viewer", throw a TypeError.

  4. Let (width, height, arrayLayerCount) be the result of determining a WebGPU layer texture layout from init.

  5. Let layer be a new XREquirectLayer in the relevant realm of binding.

  6. Run initialize a WebGPU-backed layer with layer, binding, init, width, height, and arrayLayerCount.

  7. Set layer’s space to init’s space.

  8. If init’s transform is present, set layer’s transform to a new XRRigidTransform in layer’s relevant realm, initialized with the position and orientation of init’s transform. Otherwise, set it to a new identity XRRigidTransform in layer’s relevant realm.

  9. Set layer’s radius to init’s radius.

  10. Set layer’s centralHorizontalAngle to init’s centralHorizontalAngle.

  11. Set layer’s upperVerticalAngle to init’s upperVerticalAngle.

  12. Set layer’s lowerVerticalAngle to init’s lowerVerticalAngle.

  13. Return layer.

The createCubeLayer(init) method creates a new XRCubeLayer backed by WebGPU textures.

When this method is invoked on an XRGPUBinding binding, the user agent MUST run the following steps:

  1. Run validate WebGPU layer creation with binding.

  2. If init’s space is not an XRReferenceSpace, throw a TypeError.

  3. If init’s space has a type of "viewer", throw a TypeError.

  4. If init’s layout is not "mono" or "stereo", throw a TypeError.

  5. If init’s viewPixelWidth is not equal to init’s viewPixelHeight, throw a TypeError.

  6. Let arrayLayerCount be 6 if init’s layout is "mono", and 12 otherwise.

  7. Let layer be a new XRCubeLayer in the relevant realm of binding.

  8. Run initialize a WebGPU-backed layer with layer, binding, init, init’s viewPixelWidth, init’s viewPixelHeight, and arrayLayerCount.

  9. Set layer’s space to init’s space.

  10. If init’s orientation is present, set layer’s orientation to the result of running fromPoint() with init’s orientation. Otherwise, set it to the result of running fromPoint() with { x: 0, y: 0, z: 0, w: 1 }.

  11. Return layer.

Cube layer textures use six consecutive array layers for each eye, in the order +X, -X, +Y, -Y, +Z, -Z. For a stereo cube layer, the left eye’s faces begin at array layer 0 and the right eye’s faces begin at array layer 6.

To validate WebGPU subimage creation with an XRGPUBinding binding, an XRCompositionLayer layer, and an XRFrame frame, the user agent MUST run the following steps:

  1. If layer is not a WebGPU-backed layer, throw an InvalidStateError DOMException.

  2. Let session be binding’s session.

  3. If layer’s session is not session, throw an InvalidStateError DOMException.

  4. If layer’s WebGPU device is not binding’s device, throw an InvalidStateError DOMException.

  5. If binding’s device has been destroyed, throw an InvalidStateError DOMException.

  6. If frame’s session is not session, throw an InvalidStateError DOMException.

  7. If frame is not an active XR animation frame, throw an InvalidStateError DOMException.

  8. If layer’s list of texture sets is empty, throw an InvalidStateError DOMException.

  9. If layer is not contained in session’s renderState.layers, throw a TypeError.

  10. If layer’s isStatic is true and its needsRedraw is false, throw an InvalidStateError DOMException.

The getSubImage(layer, frame, eye) method returns an XRGPUSubImage for non-projection layers.

When invoked, the user agent MUST run the following steps:

  1. If the "layers" feature descriptor is not enabled for the session, throw a NotSupportedError DOMException.

  2. Run validate WebGPU subimage creation with this XRGPUBinding, layer, and frame.

  3. If layer is an XRProjectionLayer, throw a TypeError.

  4. Let eyeIndex be 1 if eye is "right", and 0 otherwise.

  5. If layer’s layout is not "mono" and eye is "none", throw a TypeError.

  6. Run acquire WebGPU textures for layer and frame.

  7. Let subImage be a new XRGPUSubImage.

  8. Set subImage’s colorTexture to the layer’s current color texture.

  9. Set subImage’s depthStencilTexture to the layer’s current depth-stencil texture, or null if no depth/stencil format was specified during layer creation.

  10. Set subImage’s motionVectorTexture to null.

  11. Set subImage’s viewport to the full width and height of subImage’s colorTexture, with an x and y offset of 0.

  12. If layer’s layout is "stereo-left-right", divide subImage’s viewport width by 2 and set its x offset to that width multiplied by eyeIndex.

  13. If layer’s layout is "stereo-top-bottom", divide subImage’s viewport height by 2 and set its y offset to that height multiplied by eyeIndex.

  14. Set subImage’s array layer index as follows:

    If layer is an XRCubeLayer and its layout is "stereo"
    Set it to eyeIndex multiplied by 6.
    If layer’s layout is "stereo"
    Set it to eyeIndex.
    Otherwise
    Set it to 0.
  15. Return subImage.

The getViewSubImage(layer, view) method returns an XRGPUSubImage for a specific view of a projection layer.

When invoked, the user agent MUST run the following steps:

  1. If view’s session is not the session, throw an InvalidStateError DOMException.

  2. Let frame be view’s frame.

  3. Run validate WebGPU subimage creation with this XRGPUBinding, layer, and frame.

  4. If view’s active flag is false, throw an InvalidStateError DOMException.

  5. Run acquire WebGPU textures for layer and frame.

  6. Let subImage be a new XRGPUSubImage.

  7. Set subImage’s colorTexture to the layer’s current color texture.

  8. Set subImage’s depthStencilTexture to the layer’s current depth-stencil texture, or null if no depth/stencil format was specified during layer creation.

  9. Set subImage’s motionVectorTexture to the layer’s current motion vector texture, or null if the layer’s motion vector texture descriptor is null.

  10. Set subImage’s array layer index to the view’s index.

  11. Set subImage’s viewport to the region of the colorTexture corresponding to view, adjusted by the current viewport scale.

  12. Return subImage.

Rendering a projection layer during an animation frame when the space-warp feature descriptor is not enabled. In this case, the color and depth/stencil textures have the same dimensions and use the same viewport:
function onXRFrame(time, frame) {
  session.requestAnimationFrame(onXRFrame);

  const pose = frame.getViewerPose(refSpace);
  if (!pose) return;

  const commandEncoder = device.createCommandEncoder();

  for (const view of pose.views) {
    const subImage = binding.getViewSubImage(layer, view);
    const viewDesc = subImage.getViewDescriptor();

    const passEncoder = commandEncoder.beginRenderPass({
      colorAttachments: [{
        view: subImage.colorTexture.createView(viewDesc),
        loadOp: 'clear',
        storeOp: 'store',
        clearValue: { r: 0, g: 0, b: 0, a: 1 },
      }],
      depthStencilAttachment: {
        view: subImage.depthStencilTexture.createView(viewDesc),
        depthLoadOp: 'clear',
        depthClearValue: 1.0,
        depthStoreOp: 'store',
      },
    });

    const vp = subImage.viewport;
    passEncoder.setViewport(vp.x, vp.y, vp.width, vp.height, 0.0, 1.0);

    // Render scene from the viewpoint of view...

    passEncoder.end();
  }

  device.queue.submit([commandEncoder.finish()]);
}

6. Space Warp

Space warp is a technology that improves the XR Compositor’s reprojection. By submitting a motionVectorTexture along with a depthStencilTexture, the XR Compositor can do high quality frame extrapolation and reprojection which allows the user agent to run at a reduced framerate but still provide a smooth experience to users. The rate at which requestAnimationFrame() callbacks are delivered may be lower than the display’s native refresh rate. The XR Compositor will synthesize the missing frames using the motion vectors and depth information provided by the experience.

To enable space warp, the XRSession MUST be created with the space-warp feature descriptor. If the space-warp feature descriptor is enabled, usesDepthValues MUST be set to true. For an XRProjectionLayer whose motion vector texture descriptor is not null, the XR Compositor MUST make use of depth values and ignoreDepthValues MUST be set to false.

An XRProjectionLayer participates in space warp only when its motion vector texture descriptor is not null. Such a descriptor is allocated only when the space-warp feature descriptor is enabled and the layer was created with an depthStencilFormat that is present and is not "stencil8". For each XRGPUSubImage obtained from such a layer, the experience SHOULD render representative depth values into the depthStencilTexture. When the motionVectorTexture is not null, the depthStencilTexture MUST also not be null, and the two textures MUST have the same dimensions, which MAY be different from the dimensions of the colorTexture. For such a subimage, authors SHOULD render depth/stencil and motion vector information to the full extent of the texture view selected by getViewDescriptor(), rather than to the viewport.

NOTE: Since the depth/stencil and motion vector attachments can have different dimensions than the color attachment, they are not intended to be attached to the render pass used to render into the colorTexture. Authors SHOULD render depth/stencil and motion vector information separately at their attachment dimensions.

When the motionVectorTexture is not null, it MUST be in "rgba16float" format. For such a texture, the author SHOULD fill in the RG components with the 2D screen-space motion vector for that area, expressed as a delta in Normalized Device Coordinates between the current frame and the previous frame. The motion vector is computed as (currentClipPos / currentW) - (prevClipPos / prevW), where currentClipPos and prevClipPos are the clip space positions of the fragment in the current and previous frames, respectively. The red channel corresponds to the delta in X, and the green channel corresponds to the delta in Y. The blue channel MAY contain the delta in Z depth, and the alpha channel is unused.

If the motionVectorTexture or depthStencilTexture were not submitted during the processing of the XRFrame, the XR Compositor MUST process the XRFrame as if space warp was not enabled.

7. Security and Privacy Considerations

This specification does not introduce any new security or privacy considerations beyond those described in the WebXR Device API, WebXR Layers API, and WebGPU specifications.

The textures provided by XRGPUSubImage are allocated by the user agent and do not expose any additional information about the user’s environment beyond what the underlying XR session already provides. The user agent MUST ensure that textures returned by the binding do not contain data from previous frames or other origins.

The xrCompatible flag does not expose any new fingerprinting surface beyond what is already available through the requestAdapter() API, as the returned adapter capabilities are the same regardless of whether XR compatibility is requested.

8. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 when, and only when, they appear in all capitals, as shown here.

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Conformant Algorithms

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[GEOMETRY-1]
Sebastian Zartner; Yehonatan Daniv. Geometry Interfaces Module Level 1. URL: https://drafts.csswg.org/geometry/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBGPU]
Kai Ninomiya; Brandon Jones; Jim Blandy. WebGPU. URL: https://gpuweb.github.io/gpuweb/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/
[WEBXR]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR Device API. URL: https://immersive-web.github.io/webxr/
[WEBXRLAYERS-1]
Rik Cabanier. WebXR Layers API Level 1. URL: https://immersive-web.github.io/layers/

IDL Index

partial dictionary GPURequestAdapterOptions {
    boolean xrCompatible = false;
};

[Exposed=(Window), SecureContext]
interface XRGPUSubImage : XRSubImage {
  [SameObject] readonly attribute GPUTexture colorTexture;
  [SameObject] readonly attribute GPUTexture? depthStencilTexture;
  [SameObject] readonly attribute GPUTexture? motionVectorTexture;

  GPUTextureViewDescriptor getViewDescriptor();
};

dictionary XRGPUProjectionLayerInit {
  required GPUTextureFormat colorFormat;
  GPUTextureFormat? depthStencilFormat;
  GPUTextureUsageFlags textureUsage = 0x10; // GPUTextureUsage.RENDER_ATTACHMENT
  double scaleFactor = 1.0;
};

dictionary XRGPULayerInit {
  required GPUTextureFormat colorFormat;
  GPUTextureFormat? depthStencilFormat;
  GPUTextureUsageFlags textureUsage = 0x10; // GPUTextureUsage.RENDER_ATTACHMENT
  required XRSpace space;
  unsigned long mipLevels = 1;
  required unsigned long viewPixelWidth;
  required unsigned long viewPixelHeight;
  XRLayerLayout layout = "mono";
  boolean isStatic = false;
};

dictionary XRGPUQuadLayerInit : XRGPULayerInit {
  XRRigidTransform? transform;
  float width = 1.0;
  float height = 1.0;
};

dictionary XRGPUCylinderLayerInit : XRGPULayerInit {
  XRRigidTransform? transform;
  float radius = 2.0;
  float centralAngle = 0.78539;
  float aspectRatio = 2.0;
};

dictionary XRGPUEquirectLayerInit : XRGPULayerInit {
  XRRigidTransform? transform;
  float radius = 0;
  float centralHorizontalAngle = 6.28318;
  float upperVerticalAngle = 1.570795;
  float lowerVerticalAngle = -1.570795;
};

dictionary XRGPUCubeLayerInit : XRGPULayerInit {
  DOMPointReadOnly? orientation;
};

[Exposed=(Window), SecureContext]
interface XRGPUBinding {
  constructor(XRSession session, GPUDevice device);

  readonly attribute double nativeProjectionScaleFactor;
  readonly attribute boolean usesDepthValues;

  XRProjectionLayer createProjectionLayer(optional XRGPUProjectionLayerInit init = {});
  XRQuadLayer createQuadLayer(optional XRGPUQuadLayerInit init = {});
  XRCylinderLayer createCylinderLayer(optional XRGPUCylinderLayerInit init = {});
  XREquirectLayer createEquirectLayer(optional XRGPUEquirectLayerInit init = {});
  XRCubeLayer createCubeLayer(optional XRGPUCubeLayerInit init = {});

  XRGPUSubImage getSubImage(XRCompositionLayer layer, XRFrame frame, optional XREye eye = "none");
  XRGPUSubImage getViewSubImage(XRProjectionLayer layer, XRView view);

  GPUTextureFormat getPreferredColorFormat();
};