For years, the performance ceiling for intensive browser tasks has been clear: the CPU. No matter how well-optimized our JavaScript is, there are operations (processing pixels, applying image filters, running ML models) that the CPU simply cannot handle fast enough to maintain 60 fps.
WebGPU changes that. It’s not a library or a framework: it’s a browser API that gives direct access to the device’s GPU. And with that, it enables a level of performance the CPU cannot match for certain types of workload.
In this first article of the series we’ll explore what WebGPU is, how it fits into the browser’s architecture, and why it matters from a performance perspective.
What is WebGPU?
WebGPU is a low-level web API for graphics and GPU computation. It was designed by the W3C as the successor to WebGL, with a programming model closer to modern graphics APIs like Vulkan, Metal, and Direct3D 12.
The key difference from WebGL is that WebGPU is not limited to graphics rendering. It includes support for compute shaders: programs that run on the GPU and can process data massively in parallel, without needing to draw anything on screen.
This opens two broad families of use:
- Rendering: 3D scenes, visual effects, browser games
- General-purpose computation (GPGPU): image processing, video, machine learning
CPU vs GPU: why it matters for performance
To understand why WebGPU has an impact on performance, we need to understand the difference between CPU and GPU.
The CPU has a few cores (4-16 in a modern laptop), but each one is very powerful and capable of running complex sequential code.
The GPU has thousands of simpler cores, designed to run the same operation over many pieces of data at the same time. A mid-range GPU has more than 1,000 cores.
When we need to apply a filter to a 4K image (8 million pixels), the CPU has to process each pixel one by one (or with very limited parallelism). The GPU can process thousands of pixels in parallel.
4K image: 3840 × 2160 = 8,294,400 pixels
CPU (8 cores): ~1M pixels/iteration
GPU (2048 cores): ~2M pixels/iteration (per shader step)
For massive, uniform data processing, the GPU wins by a wide margin.
The WebGPU model
WebGPU introduces new concepts compared to what we’re used to in JavaScript. The most important ones:
Device
Represents the GPU. It’s the entry point for creating all resources.
Command encoder
We record a sequence of GPU commands (they don’t execute until we submit them).
Render pipeline / Compute pipeline
Defines how information is processed: which shaders are used, what format the input and output data have.
Buffer
A block of memory on the GPU. Data (vertices, pixels, tensors) lives here during processing.
Shader (WGSL)
A program that runs on the GPU. WebGPU uses its own language: WGSL (WebGPU Shading Language).
// Minimal example: request GPU access
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
console.log(adapter.info);
// { vendor: 'apple', architecture: 'metal-3', device: '', description: '', subgroupMinSize: 32 }
Current support
| Platform | Browser | Version | Support |
|---|---|---|---|
| Desktop | Chrome / Edge | 113+ | ✅ Full |
| Desktop | Safari | 18+ | ✅ Full |
| Desktop | Firefox | — | 🧪 Experimental (flag) |
| Android | Chrome | 121+ | ✅ With compatible drivers |
| Android | Samsung Internet | — | ⚠️ Partial |
| iOS | Safari | iOS 18+ | ✅ Full |
| iOS | Chrome / Firefox | iOS 18+ | ✅ Use WebKit |
On iOS, Chrome and Firefox use the WebKit engine, so support depends on the iOS version, not the browser.
On Android, Chrome has support from version 121 (January 2024), but with an important caveat: support also depends on the device’s GPU drivers. An Android device with Chrome 121+ does not guarantee WebGPU availability across all models. Always check navigator.gpu at runtime.
// Feature detection
if (!navigator.gpu) {
console.warn("WebGPU is not available in this browser");
}
WebGPU on mobile: performance and battery
The support is there, but keep in mind that a mobile GPU is not a laptop GPU. There are two mobile-specific limitations that directly affect performance:
Thermal throttling: After a few seconds of sustained GPU load, the device reduces the chip frequency to avoid overheating. An operation that takes 8ms at the start may take 25ms after 30 seconds of continuous use. This is especially relevant for real-time use cases (video, camera).
Battery: The GPU consumes significantly more than the CPU. For one-off tasks it’s not a problem, but for continuous processing the impact needs to be weighed. The API doesn’t expose battery state information, so the safest strategy is to activate WebGPU only when users trigger it explicitly, not in the background.
Resources to verify support
To check whether a specific device supports WebGPU:
- webgpureport.org: open this URL on any device and it instantly shows whether WebGPU works, along with adapter details (vendor, architecture, features, limits).
- vulkan.gpuinfo.org: database with over 20,000 Android devices. Since WebGPU on Android requires Vulkan, if a device appears here with Vulkan 1.0+ support, it’s a candidate for WebGPU.
- Implementation Status (gpuweb wiki): the official W3C wiki. Lists which GPU families have support in Chrome Android (Adreno, Mali, Imagination…) and from which browser version.
- caniuse.com/webgpu: browser support table, with separate rows for Chrome Android, Samsung Internet, and Firefox Android.
For production, coverage is already sufficient to consider a progressive enhancement strategy: WebGPU when available, WebAssembly as a performance fallback, and Canvas 2D for universal coverage.
WebGPU or WebAssembly for intensive processing?
A common question: if WebAssembly also accelerates code in the browser, when should we choose WebGPU?
The performance order for operations over large amounts of uniform data (pixels, matrices) is:
WebGPU > WebAssembly (SIMD) > Canvas 2D plain JSWebAssembly with SIMD processes 4-8 values in parallel (128 bits). WebGPU processes thousands in parallel. For a 1920×1080 image, WASM sits in the ~50-80ms range; WebGPU reaches ~8ms.
WebAssembly beats WebGPU when the algorithm has a lot of conditional logic (GPUs are poor at branching), when images are small (the CPU→GPU transfer latency can outweigh the benefit), or when Firefox support is needed.
In practice: WebGPU for real-time and high volume, WebAssembly for complex algorithms or broad browser coverage.
When does WebGPU make sense?
WebGPU is not the solution for everything. The API has real complexity: verbose setup, explicit memory management, its own shader language. There’s no point using it for operations the CPU handles without issue.
It makes sense when:
- We’re processing large amounts of data with uniform operations (pixels, video frames, matrices)
- We need real-time results (< 16ms per frame for 60 fps)
- The CPU is the measured bottleneck, not an assumed one
- We’re running ML models in the browser
It doesn’t make sense when:
- The operation is one-off and there’s no time constraint
- The data is small or the logic is highly branched
- We need support in Firefox or older browsers without a fallback
What’s coming in the series
This first article establishes the foundations. The next ones explore concrete use cases with real code and benchmarks:
- Image processing with WebGPU: filters and transformations, direct comparison with Canvas 2D.
- ML in the browser with WebGPU: TensorFlow.js with the WebGPU backend, real-time inference.
- Video editing in the browser with WebGPU: real-time effects frame by frame.
If you’ve never written a shader in your life (I hadn’t either until recently), don’t worry: we start from scratch.
Conclusion
WebGPU is not hype. It’s an API with real support in the major browsers that gives access to a level of parallelism the CPU cannot match for certain tasks. For anyone working in web performance, understanding when and how to use it is one more tool in the toolkit.
In the next article we get our hands on the code: image processing, benchmarks included.