DEV Community

Oleg Sidorkin
Oleg Sidorkin

Posted on

Detecting WebGPU support, the right way

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?
}
Enter fullscreen mode Exit fullscreen mode

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 }
}
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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'
}
Enter fullscreen mode Exit fullscreen mode

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:

WebGL & WebGPU Checker

Handy for triaging "works on my machine" bug reports: have the reporter open it and paste what they see.

Recap

  1. navigator.gpu only means the API exists, not that you can render.
  2. Detect by awaiting requestAdapter() and checking for a non-null result.
  3. Read adapter.features and adapter.limits before relying on anything specific.
  4. Fall back to WebGL 2 when WebGPU isn't available.

Top comments (0)