WebXR/WebGPU Binding Module - Level 1

Editor’s Draft , 30 July

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 XRCompositionLayer s, 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 XRCompositionLayer s 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 . XRSession s created with this feature are referred to as WebGPU-compatible session s.

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 .

2.3. 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 GPUTexture s 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 GPUTextureDescriptor s 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 format s for XRGPUBinding layer creation are:

The supported depth/stencil format s 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 XRCompositionLayer s and obtaining XRGPUSubImage s 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 = {});
   = "none");
  );

  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.

2.3.1.

Constructor 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);

2.3.2. Attributes

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 .

2.3.3. Recommended WebGPU Texture Resolution

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 . This resolution is Unless the same as space-warp feature descriptor is enabled, this resolution MUST be equal to the recommended WebGPU texture resolution unless otherwise specified. .

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.

2.3.4. getPreferredColorFormat

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 2.3.5. GPUDevice createProjectionLayer 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 invoked, 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 the session has ended , throw an InvalidStateError DOMException .

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

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

  6. If init ’s depthStencilFormat is present and is not a supported depth-stencil format , throw an a InvalidStateError 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 ( recommendedSize colorWidth , colorHeight ) be the result of scaling an XR GPU texture size of the recommended WebGPU texture resolution by scaleFactor for the session’s XR device . .

  11. Let Initialize textureSize depthWidth be to recommendedSize colorWidth scaled by and scaleFactor depthHeight to colorHeight .

  12. If useSpaceWarp is true :

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

    2. Set depthWidth to spaceWarpWidth and depthHeight to spaceWarpHeight .

  13. Let maxDimension arrayLayerCount be the device 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 maxTextureDimension2D limit. null .

  16. If either dimension of textureSize init exceeds ’s depthStencilFormat is present, set maxDimension depthStencilDescriptor to the result of creating an XR GPU texture descriptor with binding , scale textureSize depthWidth , depthHeight , arrayLayerCount , 1 , init proportionally so the largest dimension equals ’s depthStencilFormat , and maxDimension . init ’s textureUsage .

  17. If either dimension of Initialize depthStencilSize motionVectorDescriptor exceeds to null .

  18. If maxDimension , scale useSpaceWarp is true :

    1. Set depthStencilSize motionVectorDescriptor proportionally so to the largest dimension equals result of creating an XR GPU texture descriptor with maxDimension . binding , depthWidth , depthHeight , arrayLayerCount , 1 , "rgba16float" , and init ’s textureUsage .

  19. Create Let layer be a new XRProjectionLayer with color textures in the relevant realm of size textureSize binding .

  20. Run initialize a composition layer on layer and format with colorFormat session .

  21. If Set init layer ’s WebGPU device to device .

  22. Set layer ’s depthStencilFormat layout is present, let to "default" .

  23. Set depthStencilFormat layer be ’s isStatic to false .

  24. Set init layer ’s depthStencilFormat needsRedraw and allocate depth/stencil textures of size to true .

  25. Set depthStencilSize layer and format ’s mipLevels to 1 .

  26. Set depthStencilFormat layer ’s textureWidth to colorWidth .

  27. If the session Set layer ’s textureHeight was created with the space-warp to colorHeight .

  28. Set layer ’s textureArrayLength feature descriptor , allocate motion vector textures of size to depthStencilSize arrayLayerCount .

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

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

  31. Return the Otherwise, set layer ’s XRProjectionLayer ignoreDepthValues to true .

  32. If fixed foveation is supported, set layer ’s NOTE: The textures allocated for projection layers are typically fixedFoveation to 0 . Otherwise, set it to null .

  33. Set layer ’s deltaPose to null .

  34. Set layer ’s color texture arrays, with one descriptor to colorDescriptor .

  35. Set layer per view (e.g., 2 layers for stereoscopic VR). The number ’s depth-stencil texture descriptor to depthStencilDescriptor .

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

  37. Set layer ’s list of layers is determined by texture sets to the session’s view count. 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] });

2.3.6. createQuadLayer / createCylinderLayer / createEquirectLayer / createCubeLayer NOTE: Non-projection layer types are still in development and are not yet supported by any user agent. The interfaces described in this section and the associated layer init dictionaries are subject to change.

The createQuadLayer( init ) , createCylinderLayer( init ) , createEquirectLayer( init ) , and createCubeLayer( init ) methods each create a new layer of the corresponding type backed by To validate WebGPU textures. These methods MUST only succeed if the "layers" feature descriptor was requested and enabled for the session. If "layers" is not enabled, the user agent MUST throw a layer creation with an NotSupportedError XRGPUBinding DOMException . When any of these methods are invoked, binding , the user agent MUST run the following steps:

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

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

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

If init ’s color format is not To determine a supported color format , throw WebGPU layer texture layout from an InvalidStateError XRGPULayerInit init , the user agent MUST run the following steps:

  1. Let width be init ’s DOMException viewPixelWidth .

  2. If Let height be init ’s depth/stencil format is present and is not a supported depth-stencil format , throw an InvalidStateError DOMException viewPixelHeight .

  3. Create and return a new layer of the appropriate type using the remaining fields of Let init . arrayLayerCount be 1 .

  4. Switch on init ’s 2.3.7. layout getSubImage :

    "mono" The
    Do nothing.
    getSubImage( layer , frame , "stereo"
    Set eye arrayLayerCount ) to 2 .
    method returns an XRGPUSubImage "stereo-left-right" for non-projection layers. This method MUST only succeed if the
    Set width to width multiplied by "layers" feature descriptor 2 .
    "stereo-top-bottom" was requested and enabled for the session. If "layers" is not enabled, the user agent MUST throw a
    Set height to height multiplied by 2 .
    NotSupportedError "default"
    Throw a DOMException TypeError .
  5. Return ( width , height , arrayLayerCount ).

When invoked, 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 the width or height is "layers" feature descriptor 0 , throw a TypeError .

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

  4. If layer init was not created by this ’s XRGPUBinding depthStencilFormat , is present and is not a supported depth-stencil format , throw an a InvalidStateError NotSupportedError DOMException .

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

  6. Let maximumMipLevelCount be floor(log 2 (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 frame init ’s depthStencilFormat is not present, set depthStencilDescriptor to the result of creating an active XR animation frame , throw an GPU texture descriptor with binding , width , height , arrayLayerCount , mipLevelCount , init ’s InvalidStateError depthStencilFormat , and init ’s DOMException textureUsage .

  11. Let Run initialize a composition layer on subImage layer be with session .

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

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

  14. Set layer ’s colorTexture layout to the layer’s current color texture . init ’s layout .

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

  16. Set layer ’s mipLevels to the layer’s current depth-stencil texture , or null if no depth/stencil format was specified during layer creation. mipLevelCount .

  17. Set subImage layer ’s motionVectorTexture needsRedraw to null true .

  18. Set subImage layer ’s viewport based on the color texture descriptor to eye parameter and the layer’s layout. colorDescriptor .

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

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

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

2.3.8. getViewSubImage

The getViewSubImage( layer , createQuadLayer( view init ) method returns an creates a new XRGPUSubImage XRQuadLayer for a specific view of a projection layer. backed by WebGPU textures.

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

  1. If 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 was not created by this be a new XRGPUBinding XRQuadLayer , throw an 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 InvalidStateError space to init ’s DOMException space .

  6. If view init ’s session transform is not the session , throw an present, set layer ’s InvalidStateError transform to a new DOMException XRRigidTransform . Let in subImage layer be ’s relevant realm , initialized with the position and orientation of init ’s transform . Otherwise, set it to a new identity XRGPUSubImage XRRigidTransform . in layer ’s relevant realm .

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

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

  9. Set Return subImage layer .

The createCylinderLayer( init ’s ) method creates a new motionVectorTexture XRCylinderLayer to the layer’s current motion vector texture , or null backed by WebGPU textures.

When this method is invoked on an XRGPUBinding if binding , the space-warp feature descriptor was not enabled when user agent MUST run the session was created. following steps:

  1. Set subImage ’s array Run validate WebGPU layer index to the view’s index. creation with binding .

  2. Set Let ( subImage width , height , arrayLayerCount ’s viewport to ) be the region result of the determining a WebGPU layer texture layout from init .

  3. Let layer be a new colorTexture XRCylinderLayer corresponding to view , adjusted by in the current viewport scale. relevant realm of binding .

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

  5. Set layer ’s space Rendering a projection layer during an animation frame: session to init ’s space .

  6. If init ’s colorAttachments view loadOp storeOp clearValue depthStencilAttachment view depthLoadOp depthClearValue depthStoreOp transform passEncoder is present, set layer ’s transform passEncoder to a new device XRRigidTransform 3. in layer ’s relevant realm , initialized with the position and orientation of init ’s Rendering transform . Otherwise, set it to a new identity XRRigidTransform 3.1. in layer ’s relevant realm .

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

  8. An Set layer ’s XRGPUSubImage centralAngle represents a view into a WebGPU-backed composition layer’s textures. It provides the to init ’s GPUTexture centralAngle s to render into and a .

  9. Set layer ’s GPUTextureViewDescriptor aspectRatio that describes which portion of the texture corresponds to the requested view. init ’s aspectRatio .

  10. Return layer .

NOTE: The WebXR Layers space requirements allow viewport XRQuadLayer describes the region of the and colorTexture XRCylinderLayer that corresponds to the requested view. It does not describe the region of the use any depthStencilTexture XRSpace , including "viewer" or for head-locked content. motionVectorTexture XREquirectLayer . Each and XRCompositionLayer XRCubeLayer created with an are restricted to XRGPUBinding XRReferenceSpace has an associated current color texture and an optional current depth-stencil texture . Each values other than XRProjectionLayer "viewer" created with an so that environment content, such as 360-degree media and skyboxes, preserves rotational reprojection.

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

When this method is invoked on an optional current motion vector texture . These are GPUTexture XRGPUBinding objects allocated and managed by the user agent’s swap chain for the layer. At the beginning of each XR animation frame , binding , the user agent provides new textures for rendering. The color and motion vector textures MUST be cleared to zero before being provided to the application. The depth component of depth/stencil textures MUST be cleared to 1.0 , and the stencil component MUST be cleared to 0 . The textures from the previous frame are submitted to run the compositor and are no longer available for rendering. following steps:

  1. Before the XR Compositor Run validate WebGPU layer creation consumes a layer’s current color texture , current depth-stencil texture , or current motion vector texture with binding .

  2. If init ’s space for is not an XRFrame XRReferenceSpace , the user agent MUST ensure that all WebGPU work submitted during the processing of that throw a XRFrame TypeError that writes to those textures has completed, or MUST synchronize the XR Compositor with that work using an equivalent GPU-side dependency. .

  3. If multiple init ’s submit() space calls write to the same current texture for a layer during has a single type of XRFrame "viewer" , this synchronization MUST include throw a TypeError .

  4. Let ( width , height , arrayLayerCount ) be the last such submit before that result of determining a WebGPU layer texture is consumed by the XR Compositor . layout from init .

    ] { [; [; [;
  5. Let layer be a new (); }; XREquirectLayer 3.1.1. 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 Attributes space to init ’s space .

  8. The If init ’s colorTexture transform attribute returns the is present, set layer ’s GPUTexture transform to be used as the color attachment when rendering this sub image. This texture is allocated by the user agent and its lifetime is managed by the layer’s swap chain. The same a new GPUTexture XRRigidTransform object is returned for all sub images of the same in layer within a single frame — use ’s relevant realm , initialized with the result position and orientation of init ’s getViewDescriptor() transform . Otherwise, set it to determine which array a new identity XRRigidTransform in layer of the texture to render to. The returned texture has the following properties: ’s relevant realm .

  9. Set layer ’s radius dimension : "2d" to init ’s radius .

  10. format : The Set layer ’s colorFormat centralHorizontalAngle specified during layer creation. to init ’s centralHorizontalAngle .

  11. size : The width and height are determined by the recommended WebGPU texture resolution , scaled by the Set layer ’s scaleFactor upperVerticalAngle . The depthOrArrayLayers is equal to the number of views in the session (typically 2 for stereoscopic rendering). init ’s upperVerticalAngle .

  12. usage : The Set layer ’s textureUsage lowerVerticalAngle flags specified during layer creation. The default value includes GPUTextureUsage.RENDER_ATTACHMENT ; if overriding, developers must explicitly include RENDER_ATTACHMENT if it is needed. to init ’s lowerVerticalAngle .

  13. Return layer .

mipLevelCount : 1

The depthStencilTexture createCubeLayer( init ) attribute returns the method creates a new GPUTexture XRCubeLayer to be used as the depth/stencil attachment when rendering backed by WebGPU textures.

When this sub image, or null method is invoked on an XRGPUBinding if no depth/stencil format was specified when creating the layer. When provided, binding , the user agent MAY use MUST run the depth information to improve composition quality (for example, for reprojection). following steps:

  1. When present, the returned texture has the following properties: Run validate WebGPU layer creation with binding .

  2. If init ’s space dimension : "2d" is not an XRReferenceSpace format : The , throw a depthStencilFormat TypeError specified during layer creation. .

  3. size : For projection layers, the width and height are determined by the recommended WebGPU depth-stencil texture resolution , scaled by the If init ’s scaleFactor space . The depthOrArrayLayers is equal to the number has a type of views in the session. For non-projection layers, the size is determined by the layer’s initialization dictionary. usage : The "viewer" , throw a textureUsage TypeError flags specified during layer creation. The default value includes GPUTextureUsage.RENDER_ATTACHMENT ; if overriding, developers must explicitly include RENDER_ATTACHMENT if it is needed. .

  4. mipLevelCount : 1 NOTE: If a init ’s depthStencilFormat layout 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 "mono" to be used as the motion vector attachment when rendering this sub image, or null if the space-warp feature descriptor "stereo" was not enabled when the session was created or the layer is not an , throw a XRProjectionLayer TypeError .

    When present, the returned texture has the following properties:
  5. If init ’s viewPixelWidth dimension : "2d" is not equal to init ’s viewPixelHeight , throw a TypeError .

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

  7. size : The width and height are determined by the recommended WebGPU motion vector texture resolution , scaled by the Let layer be a new scaleFactor XRCubeLayer . The depthOrArrayLayers is equal to the number of views in the session. relevant realm of binding .

  8. Run initialize a WebGPU-backed layer with layer , binding , init , init ’s usage : The viewPixelWidth , init ’s textureUsage viewPixelHeight flags specified during , and arrayLayerCount .

  9. Set layer creation. The default value includes GPUTextureUsage.RENDER_ATTACHMENT ; if overriding, developers must explicitly include RENDER_ATTACHMENT ’s space if it is needed. to init ’s space .

  10. If init ’s mipLevelCount : 1 orientation 3.1.2. is present, set layer ’s getViewDescriptor orientation to the result of running fromPoint() The getViewDescriptor() with init ’s method returns a orientation . Otherwise, set it to the result of running GPUTextureViewDescriptor fromPoint() configured with { x: 0, y: 0, z: 0, w: 1 } .

  11. Return layer .

Cube layer textures use six consecutive array layers for creating each eye, in the order +X , -X , +Y , -Y , +Z , -Z . For a texture view of this sub image’s portion of stereo cube layer, the layer’s textures. The returned descriptor can be passed to left eye’s faces begin at array layer GPUTexture.createView() 0 on and the right eye’s faces begin at array layer 6 .

To validate WebGPU subimage creation with an colorTexture XRGPUBinding , binding , an depthStencilTexture XRCompositionLayer , layer , and an motionVectorTexture XRFrame . When invoked, frame , the user agent MUST run the following steps:

  1. Let If descriptor layer be is not a new WebGPU-backed layer , throw an GPUTextureViewDescriptor InvalidStateError DOMException .

  2. Set Let descriptor session be binding ’s dimension to "2d" . session .

  3. Set If descriptor layer ’s mipLevelCount session is not session , throw an InvalidStateError to 1. DOMException .

  4. Set If descriptor layer ’s arrayLayerCount WebGPU device is not binding ’s device , throw an InvalidStateError to 1. DOMException .

  5. Set If descriptor binding ’s baseArrayLayer device has been destroyed , throw an InvalidStateError to the array layer index corresponding to this sub image’s view (e.g., 0 for the left eye, 1 for the right eye). DOMException .

  6. Return If descriptor . NOTE: The returned descriptor selects a single 2D slice from the texture array via baseArrayLayer paired with frame ’s session is not session , throw an arrayLayerCount InvalidStateError of 1 DOMException . The viewport still needs to be applied via setViewport() on the render pass encoder.

  7. If frame is not an active XR animation frame , throw an InvalidStateError Using the view descriptor to create render pass attachments: 4. Layer Creation DOMException .

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

  9. If layer is not contained in session ’s renderState . layers The supported color format s for , throw a XRGPUBinding TypeError layer creation are: .

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

"rgba16float"

The supported depth/stencil format getSubImage( layer , frame , eye ) s for method returns an XRGPUBinding XRGPUSubImage layer creation are: for non-projection layers.

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

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

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

  3. If layer is an "depth24plus-stencil8" XRProjectionLayer , throw a TypeError .

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

    NOTE: The formats listed above are the only formats that MUST be accepted for
  5. If layer creation. User agents MUST NOT accept formats outside of these lists. 4.2. XRGPUProjectionLayerInit ’s layout The is not XRGPUProjectionLayerInit "mono" dictionary and eye is used to configure projection layers created with createProjectionLayer() "none" , throw a TypeError .

    { ; ; = 0x10; // GPUTextureUsage.RENDER_ATTACHMENT = 1.0; };
  6. Run acquire WebGPU textures Creating a projection for layer with the preferred color format: colorFormat depthStencilFormat and frame .

  7. The Let subImage be a new colorFormat XRGPUSubImage member specifies the .

  8. Set subImage ’s GPUTextureFormat colorTexture for to the layer’s current color textures. This MUST be a supported color format texture .

  9. The depthStencilFormat member, when present, specifies the Set subImage ’s GPUTextureFormat depthStencilTexture for to the layer’s depth/stencil textures. This MUST be a supported current depth-stencil format . When not present, texture , or null if no depth/stencil texture is allocated. format was specified during layer creation.

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

  11. The Set subImage ’s scaleFactor viewport 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( full width and height of subImage ’s nativeProjectionScaleFactor colorTexture , 1.0)]. with an x and y offset of 0 .

    4.3.
  12. If layer ’s XRGPULayerInit layout is "stereo-left-right" The , divide subImage ’s XRGPULayerInit viewport dictionary is the base dictionary for configuring non-projection composition layers. Non-projection layers require the width by "layers" 2 feature descriptor and set its x offset to be enabled for the session. that width multiplied by eyeIndex .

    { ; ; = 0x10; // GPUTextureUsage.RENDER_ATTACHMENT ; = 1; ; ; = "mono"; ; };
  13. The colorFormat member specifies the If layer ’s GPUTextureFormat layout for the layer’s color textures. The is depthStencilFormat "stereo-top-bottom" member, when present, specifies the , divide subImage ’s GPUTextureFormat viewport for the layer’s depth/stencil textures. height by 2 and set its y offset to that height multiplied by eyeIndex .

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

    If layer is an textureUsage XRCubeLayer member specifies additional and its GPUTextureUsageFlags layout for the allocated textures. The is space "stereo" member specifies the
    Set it to eyeIndex multiplied by 6 .
    If layer ’s XRSpace layout in which the layer is positioned. The mipLevels "stereo" member specifies the number of mip levels
    Set it to eyeIndex .
    Otherwise
    Set it to allocate for the layer’s textures. The viewPixelWidth member specifies the width, in pixels, of each view’s texture. 0 .
  15. Return subImage .

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

The layout getViewSubImage( layer , view ) member specifies the method returns an XRLayerLayout XRGPUSubImage for a specific view of the a projection layer.

The isStatic member, when set to true , indicates that the layer’s content will rarely change. This allows When invoked, the user agent to optimize for this scenario. MUST run the following steps:

4.4. XRGPUQuadLayerInit
  1. If view ’s session is not the session , throw an { ; = 1.0; = 1.0; }; The InvalidStateError transform member specifies the initial position and orientation of the quad layer relative to the space DOMException .

  2. The width member specifies the width of the quad in meters. Let frame be view ’s frame .

  3. The Run validate WebGPU subimage creation with this height XRGPUBinding member specifies the height of the quad in meters. , layer , and frame .

    4.5.
  4. If view ’s active flag is false , throw an XRGPUCylinderLayerInit InvalidStateError DOMException { ; = 2.0; = 0.78539; = 2.0; }; .

  5. The transform member specifies the initial position Run acquire WebGPU textures for layer and orientation of the cylinder layer. frame .

  6. The Let subImage be a new radius XRGPUSubImage member specifies the radius of the cylinder in meters. .

  7. The Set subImage ’s centralAngle colorTexture 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. layer’s current color texture .

    4.6. XRGPUEquirectLayerInit
  8. Set subImage ’s depthStencilTexture { ; = 0; = 6.28318; = 1.570795; = -1.570795; }; The transform member specifies the initial position and orientation of to the equirect layer. layer’s current depth-stencil texture , or null if no depth/stencil format was specified during layer creation.

  9. The Set subImage ’s radius motionVectorTexture member specifies the radius of to the sphere in meters. A value of layer’s current motion vector texture , or 0 null indicates an infinite sphere (the equirect if the layer’s motion vector texture descriptor is rendered as a skybox). null .

  10. The centralHorizontalAngle member specifies the horizontal angular extent of the sphere in radians. The default value of 6.28318 corresponds Set subImage ’s array layer index to a full 360 degrees. the view’s index.

  11. The upperVerticalAngle member specifies Set subImage ’s viewport to the upper vertical angle region of the visible portion in radians, measured from colorTexture corresponding to view , adjusted by the horizon. current viewport scale.

  12. The lowerVerticalAngle Return subImage .

member specifies Rendering a projection layer during an animation frame when the lower vertical angle of space-warp feature descriptor is not enabled. In this case, the visible portion in radians, measured from color and depth/stencil textures have the horizon. same dimensions and use the same viewport:
function onXRFrame(time, frame) {
  session.requestAnimationFrame(onXRFrame);

4.7.

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

  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',
      },    });
 {
  ;
};
The

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

orientation

    // Render scene from the viewpoint of view...
member
specifies
the
initial
orientation
of
the
cube
layer
as
a
quaternion.

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

5. 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, values and ignoreDepthValues MUST be set to false , and .

An usesDepthValues XRProjectionLayer MUST be set to participates in space warp only when its motion vector texture descriptor is not true null . When Such a descriptor is allocated only when the space-warp feature descriptor is enabled, 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 SHOULD render representative depth values into the depthStencilTexture for each . When the XRProjectionLayer motionVectorTexture it submits. The is not null , the depthStencilTexture MUST also not be null , and motionVectorTexture will the two textures MUST have the same dimensions, which may MAY be different from the dimensions of the colorTexture . Authors should 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 SHOULD render depth/stencil and motion vector information separately at their attachment dimensions.

The When the motionVectorTexture is not null , it MUST be in "rgba16float" format. The For such a texture, the author SHOULD fill in the RG components of this texture 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.

6. 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.

7. 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]
 {
  );
  ;
  ;
   = {});
   = {});
   = {});
   = {});
   = {});
   = "none");
  );
  ();
};
[]

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();
};