API in Capabilities
WebGPU API
Published Updated
WebGPU gives a page the system GPU for rendering and general-purpose compute through navigator.gpu: requestAdapter() picks a physical or software adapter, requestDevice() turns it into the GPUDevice that creates buffers, textures, pipelines, and command encoders, and shaders are written in WGSL rather than WebGL’s GLSL. The whole API is [SecureContext] and is also exposed on WorkerNavigator, so a dedicated worker can own the device.
Support is uneven by operating system rather than by browser version alone (BCD api.GPU). Chrome 113 shipped it on ChromeOS, macOS, and Windows; Chrome 144 added Linux for Intel Gen12 and newer GPUs; Chrome 121 covers Android. Firefox 141 ships on Windows only, with Apple silicon macOS following in Firefox 145 (macOS Tahoe) and 147 (older macOS), no Intel Mac (bug 2004105), no Linux (bug 2006676), and no service-worker contexts (bug 1942431); Firefox for Android has no implementation. Safari 26 ships it on macOS, iOS, iPadOS, and visionOS.
Syntax
Section titled “Syntax”navigator.gpu.requestAdapter()navigator.gpu.requestAdapter(options)
adapter.requestDevice()adapter.requestDevice(descriptor)
navigator.gpu.getPreferredCanvasFormat()canvas.getContext("webgpu")requestAdapter() returns Promise<GPUAdapter?>: it resolves with null, rather than rejecting, when the browser has no adapter that meets options. requestDevice() returns Promise<GPUDevice> and consumes the adapter; a second call on the same GPUAdapter rejects. getPreferredCanvasFormat() returns the GPUTextureFormat ("bgra8unorm" or "rgba8unorm") the canvas context should be configured with on this system.
Parameters
Section titled “Parameters”requestAdapter() takes an optional GPURequestAdapterOptions dictionary; requestDevice() takes an optional GPUDeviceDescriptor. Both have defaults for every member, so the bare calls are valid.
| Member | Type | Required | Description |
|---|---|---|---|
options.featureLevel |
DOMString |
No | "core" (default) or "compatibility". Requests an adapter that supports at least that level’s limits and features; an unsupported level resolves with null. A browser that does not implement compatibility mode treats the request as "core". |
options.powerPreference |
GPUPowerPreference |
No | "low-power" or "high-performance"; a hint only. Chrome on Windows ignores it and reuses the adapter it already allocated for the browser (crbug.com/369219127). |
options.forceFallbackAdapter |
boolean |
No | Default false. When true, only a software (fallback) adapter may be returned; null if none exists. |
options.xrCompatible |
boolean |
No | Default false. Requests an adapter that can present to a WebXR session. |
descriptor.requiredFeatures |
sequence<GPUFeatureName> |
No | Default []. Feature names the device must expose; exactly this set is enabled on the device, so an optional feature you forget to list is unavailable even when the adapter has it. |
descriptor.requiredLimits |
record<DOMString, GPUSize64 or undefined> |
No | Default {}. Limits the device must meet; each key must name a supported limit and the value may not exceed the adapter’s own. Validation on the device uses these exact limits, not the adapter’s. |
descriptor.defaultQueue |
GPUQueueDescriptor |
No | Default {}. Only carries a label for device.queue. |
descriptor.label |
USVString |
No | Inherited from GPUObjectDescriptorBase; shown in error messages and DevTools. |
Exceptions
Section titled “Exceptions”requestAdapter() has no rejection path for a missing GPU: an absent or unsuitable adapter resolves with null. requestDevice() rejects with two names, in the order the specification checks them ([GPUAdapter.requestDevice()](https://www.w3.org/TR/webgpu/#dom-gpuadapter-requestdevice) (w3.org)).
| Exception | Condition |
|---|---|
TypeError |
requiredFeatures is not a subset of adapter.features. The spec deliberately uses the same error whether the browser does not know the name or this adapter lacks it. |
OperationError |
The adapter is already consumed by an earlier requestDevice(); or a requiredLimits key is not a supported limit; or a value is better than the adapter’s limit; or an alignment limit is not a power of two below 2^32. |
Two failure modes are not rejections. If the adapter has expired or the browser cannot fulfil the request, requestDevice() still resolves, but with a device that is already lost: device.lost resolves with a GPUDeviceLostInfo whose reason is "unknown" before the requestDevice() promise itself resolves. Validation, out-of-memory, and internal errors during use arrive as GPUValidationError, GPUOutOfMemoryError, and GPUInternalError objects through device.popErrorScope() or the uncapturederror event, not as thrown exceptions.
Examples
Section titled “Examples”Every example checks for navigator.gpu first and handles the null adapter, because both happen on shipping browsers: Firefox for Android has no navigator.gpu, and Firefox on an Intel Mac has navigator.gpu but no adapter.
Detecting support and falling back to WebGL2
Section titled “Detecting support and falling back to WebGL2”The feature check has two stages: the property exists, and an adapter is returned. Treat both failures the same way and hand the canvas to a WebGL2 renderer, which Chrome 56, Firefox 51, and Safari 15 all provide.
async function createRenderer(canvas) { if (!("gpu" in navigator)) { return createWebGL2Renderer(canvas); } const adapter = await navigator.gpu.requestAdapter(); if (!adapter) { return createWebGL2Renderer(canvas); } const device = await adapter.requestDevice(); const context = canvas.getContext("webgpu"); context.configure({ device, format: navigator.gpu.getPreferredCanvasFormat() }); return createWebGPURenderer(device, context);}
function createWebGL2Renderer(canvas) { const gl = canvas.getContext("webgl2"); if (!gl) throw new Error("Neither WebGPU nor WebGL2 is available"); return { kind: "webgl2", gl };}getContext("webgpu") on a canvas that already holds a 2D or WebGL context returns null, so create the WebGPU context before any fallback touches the same element.
Requesting optional features and limits without losing the device request
Section titled “Requesting optional features and limits without losing the device request”Ask the adapter what it has, then request only what it can give. Listing a missing feature rejects with TypeError; asking for a limit above the adapter’s rejects with OperationError, so clamp against adapter.limits instead of hard-coding.
async function requestCapableDevice(adapter) { const requiredFeatures = []; for (const name of ["timestamp-query", "texture-compression-bc", "shader-f16"]) { if (adapter.features.has(name)) requiredFeatures.push(name); } const wanted = 1024 * 1024 * 1024; // 1 GiB storage buffers const requiredLimits = { maxStorageBufferBindingSize: Math.min(wanted, adapter.limits.maxStorageBufferBindingSize), }; try { return await adapter.requestDevice({ requiredFeatures, requiredLimits }); } catch (err) { if (err.name === "OperationError") { return adapter.requestDevice(); // adapter is still unconsumed after a rejection } throw err; }}A rejected requestDevice() does not consume the adapter, so the retry with defaults works on the same GPUAdapter.
Recovering from device loss
Section titled “Recovering from device loss”device.lost is a promise that settles once per device, with reason "destroyed" after your own device.destroy() call or "unknown" for everything else (driver reset, GPU process crash, tab backgrounded on a memory-constrained phone). Every GPUBuffer, GPUTexture, and pipeline created from the lost device is invalid, so recovery starts again from requestAdapter().
async function initGpu(canvas, onLost) { const adapter = await navigator.gpu.requestAdapter(); if (!adapter) return null; const device = await adapter.requestDevice();
device.lost.then((info) => { console.warn(`GPU device lost (${info.reason}): ${info.message}`); if (info.reason !== "destroyed") onLost(); // re-run initGpu and rebuild resources });
device.addEventListener("uncapturederror", (event) => { console.error(event.error.message); }); return device;}The uncapturederror listener catches validation failures that no pushErrorScope()/popErrorScope() pair wrapped; without it Chrome reports them only in the DevTools console.
See also
Section titled “See also”- WebCodecs, whose
VideoFrameobjects can be imported as WebGPU external textures - Core Web Vitals for PWAs, where GPU work on the main thread shows up as INP
- Offline strategies, for caching the WGSL and model assets a WebGPU app downloads
- WebGPU: GPU.requestAdapter() (w3.org)
- WebGPU: GPUAdapter.requestDevice() (w3.org)
- WebGPU implementation status (github.com)
- Chrome ships WebGPU (developer.chrome.com)
- News from WWDC25: web technology coming this fall in Safari 26 beta (webkit.org)
Specifications
| Specification | Status |
|---|---|
| WebGPU | W3C |
| WebGPU: GPU.requestAdapter() | W3C |
| WebGPU: GPUAdapter.requestDevice() | W3C |
| WebGPU Shading Language | W3C |
- Legend
- Yes
- Partial
- Flag
- No
- Unknown
| Browser / Platform | Support | Versions | Confidence | Source | Notes |
|---|---|---|---|---|---|
| Chrome (Desktop) | Partial | 113 → 144 | high | source | 12 |
| Chrome (Android) | Yes | 121 | high | source | — |
| Edge (Desktop) | Partial | 113 → 144 | high | source | 345 |
| Firefox (Desktop) | Partial | 141 | high | source | 67891011 |
| Firefox (Android) | No | — | high | source | 12 |
| Safari (macOS) | Yes | 26 | high | source | — |
| Safari (iOS) | Yes | 26 | high | source | 13 |
| Samsung Internet | Yes | 25.0 | high | source | 14 |
| WebView (Android) | Yes | 121 | high | source | 15 |
- Supported on ChromeOS, macOS, Windows, and Linux (Intel Gen12+ GPUs only).
- Supported on ChromeOS, macOS, and Windows.
- Supported on ChromeOS, macOS, Windows, and Linux (Intel Gen12+ GPUs only).
- Supported on ChromeOS, macOS, and Windows.
- Derived by browser-compat-data mirroring from Chrome.
- Supports all contexts except service workers. See bug 1942431 (https://bugzil.la/1942431).
- Supports Windows since Firefox 141. See bug 1972486 (https://bugzil.la/1972486).
- Supports macOS Tahoe on Apple silicon since Firefox 145. See bug 1992212 (https://bugzil.la/1992212).
- Supports older macOS versions on Apple silicon since Firefox 147. See bug 1993341 (https://bugzil.la/1993341).
- Does not support macOS on Intel CPUs. See bug 2004105 (https://bugzil.la/2004105).
- Does not support Linux. See bug 2006676 (https://bugzil.la/2006676).
- No Firefox for Android support is recorded in browser-compat-data.
- Derived by browser-compat-data mirroring from Safari.
- Derived by browser-compat-data mirroring from Chrome Android.
- Derived by browser-compat-data mirroring from Chrome Android.