WebGPU is shipping in more browsers every release, but "is it supported here?" is trickier than a one-liner. Here's how to detect it correctly, why the obvious check is wrong, and how to fall back cleanly.
The check most people write (and why it's not enough)
if (navigator.gpu) {
// WebGPU supported... right?
}
navigator.gpu existing only tells you the API surface is present. It does not mean you can actually render. The browser can expose navigator.gpu and still hand you no usable GPU because the device has no compatible adapter, WebGPU is disabled in settings, or the driver is blocklisted. You only know once you ask for an adapter.
The correct detection
async function getWebGPU() {
if (!('gpu' in navigator)) return { supported: false, reason: 'no-api' }
let adapter
try {
adapter = await navigator.gpu.requestAdapter()
} catch (e) {
return { supported: false, reason: 'request-failed' }
}
if (!adapter) return { supported: false, reason: 'no-adapter' }
const device = await adapter.requestDevice()
return { supported: true, adapter, device }
}
requestAdapter() is the real gate. It returns null when there's no usable GPU, which is the case the navigator.gpu check silently misses. Both requestAdapter() and requestDevice() are async, so detection has to be async too.
Support isn't all-or-nothing
Two devices that both "support WebGPU" can differ a lot. The adapter tells you what this one can actually do:
const adapter = await navigator.gpu.requestAdapter()
console.log([...adapter.features]) // e.g. 'texture-compression-bc', 'float32-filterable'
console.log(adapter.limits.maxTextureDimension2D)
console.log(adapter.limits.maxComputeWorkgroupSizeX)
If your app needs a specific feature (a compression format, timestamp queries, a higher limit), check adapter.features.has('...') and the relevant adapter.limits before you rely on it. Requesting a feature on a device that lacks it throws.
Falling back to WebGL 2
Most real apps want WebGPU when available and WebGL 2 otherwise:
async function pickRenderer() {
if ('gpu' in navigator && (await navigator.gpu.requestAdapter())) return 'webgpu'
const gl = document.createElement('canvas').getContext('webgl2')
return gl ? 'webgl2' : 'none'
}
Engines like three.js and Babylon.js do this internally with a WebGPU backend and a WebGL 2 fallback, so if you're on one of those you mostly get it for free. If you're writing to the API directly, do the check yourself.
See a browser's real WebGPU profile without writing code
To eyeball what a given browser actually reports, its adapter, every standard feature with green/red status, the limits as a table, plus a live render test that confirms it really works, I put together a free tool:
Handy for triaging "works on my machine" bug reports: have the reporter open it and paste what they see.
Recap
-
navigator.gpuonly means the API exists, not that you can render. - Detect by awaiting
requestAdapter()and checking for a non-null result. - Read
adapter.featuresandadapter.limitsbefore relying on anything specific. - Fall back to WebGL 2 when WebGPU isn't available.

Top comments (0)