WebGPU
La GPU moderna en la web: gráficos 3D y cálculo general con shaders WGSL.
Sucesora de WebGL, pensada sobre Vulkan, Metal y Direct3D 12. Además de dibujar, deja usar la GPU para calcular: simulaciones, física, procesado de imagen o modelos de IA que se ejecutan en el navegador.
Está en Chrome y Edge desde 2023, en Safari desde la versión 26 (septiembre de 2025) y en Firefox para Windows desde la 141; en Mac con Apple silicon, desde Firefox 147. Todavía no es Baseline: falta Firefox en Linux y en Android.
Para qué sirve
- Simulaciones de partículas y fluidos en tiempo real
- Visualización de millones de datos
- Inferencia de modelos de IA en el dispositivo
Demo
Un campo de partículas que calcula la GPU con un compute shader en cada fotograma. Mueve el puntero (o el dedo) sobre el lienzo para atraerlas.
Compatibilidad
Disponibilidad limitada| Función | Escritorio | Móvil | |||||
|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Safari | Chrome Android | Firefox Android | Safari iOS | |
| WebGPU (navigator.gpu) | 1131Chrome: 113 | 1132Edge: 113 | 141Parcial3Firefox: 141 Parcial | 26Safari: 26 | 1214Chrome: 121 | —Firefox: No | 26Safari: 26 |
- 1Windows, macOS y ChromeOS desde 113; Linux con Intel Gen12+ desde 144 y NVIDIA con Wayland desde 147. Windows en ARM, tras una flag.
- 2Igual que Chrome en escritorio.
- 3Windows desde 141; macOS con Apple silicon desde 145 (Tahoe) y 147 (todas las versiones). Linux, Mac Intel y Android, solo en Nightly.
- 4Android 12+ con GPU Qualcomm o ARM; Imagination con Android 16+ desde 139.
Compatibilidad generada en cada publicación desde MDN browser-compat-data 8.1.3 (24 sep 2026) · web-features 3.40.0 · revisión manual: 1 oct 2026
Código mínimo
<!doctype html>
<meta charset="utf-8">
<title>WebGPU · ejemplo mínimo</title>
<!-- Cómputo en la GPU: duplica ocho números con un shader WGSL y lee el resultado. -->
<pre id="out">…</pre>
<script type="module">
const out = document.querySelector('#out');
if (!navigator.gpu) throw (out.textContent = 'WebGPU no está disponible en este navegador.');
const adapter = await navigator.gpu.requestAdapter();
if (!adapter) throw (out.textContent = 'No hay un adaptador de GPU utilizable.');
const device = await adapter.requestDevice();
device.lost.then((info) => console.warn('GPU perdida:', info.reason, info.message));
const input = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8]);
const storage = device.createBuffer({
size: input.byteLength,
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
});
device.queue.writeBuffer(storage, 0, input);
const readback = device.createBuffer({
size: input.byteLength,
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
});
const module = device.createShaderModule({ code: /* wgsl */ `
@group(0) @binding(0) var<storage, read_write> data: array<f32>;
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) id: vec3u) {
if (id.x < arrayLength(&data)) { data[id.x] = data[id.x] * 2.0; }
}` });
const pipeline = device.createComputePipeline({ layout: 'auto', compute: { module, entryPoint: 'main' } });
const bindGroup = device.createBindGroup({
layout: pipeline.getBindGroupLayout(0),
entries: [{ binding: 0, resource: { buffer: storage } }],
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginComputePass();
pass.setPipeline(pipeline);
pass.setBindGroup(0, bindGroup);
pass.dispatchWorkgroups(Math.ceil(input.length / 64));
pass.end();
encoder.copyBufferToBuffer(storage, 0, readback, 0, input.byteLength);
device.queue.submit([encoder.finish()]);
await readback.mapAsync(GPUMapMode.READ);
const result = new Float32Array(readback.getMappedRange().slice(0)); // copia antes de unmap()
readback.unmap();
out.textContent = `[${input}] → [${result}]`;
</script><!doctype html>
<meta charset="utf-8">
<title>WebGPU · ejemplo mínimo</title>
<!-- Cómputo en la GPU: duplica ocho números con un shader WGSL y lee el resultado. -->
<pre id="out">…</pre>
<script type="module">
const out = document.querySelector('#out');
if (!navigator.gpu) throw (out.textContent = 'WebGPU no está disponible en este navegador.');
const adapter = await navigator.gpu.requestAdapter();
if (!adapter) throw (out.textContent = 'No hay un adaptador de GPU utilizable.');
const device = await adapter.requestDevice();
device.lost.then((info) => console.warn('GPU perdida:', info.reason, info.message));
const input = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8]);
const storage = device.createBuffer({
size: input.byteLength,
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
});
device.queue.writeBuffer(storage, 0, input);
const readback = device.createBuffer({
size: input.byteLength,
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
});
const module = device.createShaderModule({ code: /* wgsl */ `
@group(0) @binding(0) var<storage, read_write> data: array<f32>;
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) id: vec3u) {
if (id.x < arrayLength(&data)) { data[id.x] = data[id.x] * 2.0; }
}` });
const pipeline = device.createComputePipeline({ layout: 'auto', compute: { module, entryPoint: 'main' } });
const bindGroup = device.createBindGroup({
layout: pipeline.getBindGroupLayout(0),
entries: [{ binding: 0, resource: { buffer: storage } }],
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginComputePass();
pass.setPipeline(pipeline);
pass.setBindGroup(0, bindGroup);
pass.dispatchWorkgroups(Math.ceil(input.length / 64));
pass.end();
encoder.copyBufferToBuffer(storage, 0, readback, 0, input.byteLength);
device.queue.submit([encoder.finish()]);
await readback.mapAsync(GPUMapMode.READ);
const result = new Float32Array(readback.getMappedRange().slice(0)); // copia antes de unmap()
readback.unmap();
out.textContent = `[${input}] → [${result}]`;
</script>Novedades
- Firefox 157 añade el uso de textura TRANSIENT_ATTACHMENT.
- Safari 27 admite clip_distances en WGSL.
- Chrome 147: Linux con GPU NVIDIA en Wayland.
- Chrome 146: modo de compatibilidad para GPU con OpenGL ES 3.1, empezando por Android.
- Firefox 147 la lleva a todas las versiones de macOS en Apple silicon.
- Chrome 144: Linux con GPU Intel Gen12 o posteriores.
Ten en cuenta
- navigator.gpu puede existir y requestAdapter() devolver null (GPU bloqueada o sin controlador): comprueba los dos.
- Desde Chrome 140 un adaptador solo sirve para un requestDevice(); para recuperarte de device.lost, pide otro adaptador.
- Solo en contexto seguro (HTTPS o localhost). Firefox no la expone en service workers.
Más información
Fuentes
- web.dev · WebGPU is now supported in major browsers25 nov 2025
- Chrome · What’s New in WebGPU (Chrome 153–154)15 sep 2026
- MDN · Firefox 147 for developers13 ene 2026
- WebKit · Features for Safari 26.015 sep 2025
- gpuweb · Implementation Status13 ago 2026
- W3C · GPU for the Web WG publications15 sep 2026