"gpu" in navigator 只说明页面看见一个 API 入口,不说明当前机器能拿到 adapter,不说明所需 feature 与 limit 存在,更不说明这条实现比 WebGL 快。驱动黑名单、硬件加速设置、操作系统、浏览器渠道、远程桌面、隐私策略和资源压力都可能改变结果。把 WebGPU 当作布尔开关,最终会让一部分用户得到黑屏,而不是更先进的动画。
本文面向准备为作品集实验或数据可视化加入 WebGPU 的前端开发者。前置知识是 Promise、GPU pipeline 与 WebGL 基础。截至 2026-07-16,MDN 仍将 WebGPU 标记为 Limited availability、非 Baseline,并要求安全上下文;W3C 文档是 2026-05-21 Candidate Recommendation Draft。浏览器支持处于变化中,本文固定这个核验时间点,不把任何实现状态写成永久结论。
视觉资产记录:封面(1600 × 900)与文中能力决策图(1200 × 680)均为 WEB/SUN 于 2026-07-16 创作的程序化 SVG;来源/许可为本项目原创自有资产,未使用第三方图片。
兼容性不是一张“支持/不支持”表
MDN WebGPU API明确标注其可用性有限,并说明 API 暴露在 Navigator 与 WorkerNavigator、只在 secure context 可用。Chrome 官方概览记录了 Chrome 113 的首批发布,以及后续 Firefox 141 在 Windows、Safari 26 等实现进展;这些信息只能描述对应版本与平台,不能推导所有 Firefox、所有 Safari 或嵌入式 WebView 都已具备同等能力。
生产文档应写“2026-07-16 在目标浏览器矩阵实测”,并列出 OS、浏览器版本和硬件,而不是写“现代浏览器都支持”。本地 localhost 通常被视为可信来源,部署却需要合法 HTTPS;测试环境能看到 navigator.gpu 不代表 HTTP 线上也能看到。
规范状态也要区分。W3C WebGPU 文档与发布历史显示它仍在候选推荐草案阶段。浏览器可以在规范完成前实现,API 也可能继续演进。固定 lockfile、编译器和 shader 测试比凭记忆追新更可靠。
能力是逐层协商
完整初始化至少经过五道门:
- 页面处于安全上下文,且产品确实需要增强层。
navigator.gpu存在。requestAdapter()返回非空 adapter。- adapter 的
features和limits满足这个效果的最小合同。 requestDevice()成功,配置 canvas、创建 shader module 与 pipeline 也成功。
MDN requestAdapter()说明 Promise 可能得到 null:没有合适 adapter、实现不可用或请求条件无法满足都可能发生。请求 high-performance 也只是偏好,不是保证;不要因未获得独显就拒绝一个本可运行的轻量效果。
图 1(1200 × 680):从 HTTPS 到 device 逐级协商,任何拒绝、初始化错误或设备丢失都进入相同语义的 WebGL、Canvas 2D 或 DOM 实现。原创程序化 SVG,WEB/SUN,2026-07-16。
返回结果,不要把失败变成未捕获异常
初始化函数适合返回带后端和 cleanup 的判别联合,让调用者只关心“最终能展示什么”:
type RendererResult =
{ backend: 'webgpu'; dispose(): void } | { backend: 'webgl' | 'canvas' | 'dom'; dispose(): void };
async function createRenderer(host: HTMLElement): Promise<RendererResult> {
if (!window.isSecureContext || !('gpu' in navigator)) {
return createFallback(host);
}
try {
const adapter = await navigator.gpu.requestAdapter({
powerPreference: 'high-performance',
});
if (!adapter) return createFallback(host);
const required = 'timestamp-query' as GPUFeatureName;
if (!adapter.features.has(required)) return createFallback(host);
const device = await adapter.requestDevice({
requiredFeatures: [required],
});
return await createWebGpuRenderer(host, adapter, device);
} catch (error) {
reportInitializationFailure(error);
return createFallback(host);
}
}
示例中的 timestamp-query 只是演示 feature 协商,普通动效不应无理由要求它。每增加一个 required feature 或更高 limit,兼容集合都会缩小。先写最小需求,再让高能力设备开启额外效果;不要把“可能用到”全部塞进 requestDevice()。
limits 也不能只看是否大于某数。WebGPU 的可移植模型要求应用在 adapter 报告范围内申请设备限制;纹理维度、绑定组、buffer 大小与 workgroup 限制都可能影响算法。设计时准备数据分块、降低粒子数量或使用较小纹理,而不是遇到较低 limit 就整页失败。
Pipeline 失败也必须回退
拿到 device 之后仍可能在 WGSL 编译、bind group layout、canvas format、pipeline 创建或资源分配处失败。Chrome 从 WebGL 到 WebGPU 的指南强调 WebGPU 使用更显式的 pipeline、command encoder 与资源绑定模型;把 WebGL 初始化代码逐行翻译,并不会自动得到正确或更快的实现。
在开发环境读取 shader compilation info,给异步 pipeline 创建加错误边界;用 device.pushErrorScope() / popErrorScope() 捕获预期的 validation 或 out-of-memory 错误,并监听 uncapturederror 记录漏出的错误。错误信息可以进入本地诊断,但不要在公开页面暴露硬件细节。
device.lost 是整个生命周期的一部分。它可能由资源压力、驱动重置、设备销毁或其他原因触发。处理器要停止调度、释放 DOM 引用、撤下 GPU ready 状态;只在明确可恢复且有次数上限时重新初始化,否则落到备用后端,避免无限重试。
const generation = ++rendererGeneration;
let disposed = false;
device.lost.then((info) => {
if (disposed || generation !== rendererGeneration) return;
stopFrameLoop();
host.removeAttribute('data-gpu-ready');
recordDeviceLoss(info.reason);
mountFallback(host);
});
return () => {
disposed = true;
if (generation === rendererGeneration) rendererGeneration += 1;
stopFrameLoop();
disposeGpuResources();
};
Canvas 配置同样属于可失败边界。先取得 webgpu context,再用 navigator.gpu.getPreferredCanvasFormat() 选择当前平台推荐格式,按实际 CSS 尺寸与受控 DPR 配置画布。尺寸为零、宿主已从 DOM 移除或页面已经 cleanup 时,不应继续创建纹理和 command buffer。ResizeObserver 只更新待处理尺寸,下一帧再重配资源,避免同一回调读写布局。
若把渲染移到 Worker,WebGPU 在支持环境可以通过 WorkerNavigator 使用,但 OffscreenCanvas、消息传输和页面生命周期又形成一层独立能力门禁。主线程仍拥有语义 DOM与路由 scope;切页时向 Worker 发送停止协议并终止它,不能因为绘制不在主线程就假设资源会自动归零。Worker 失败也应回到同一备用后端,而不是出现第二套错误页面。
回退应共享输入和语义
不要维护四个完全独立的产品。把动画输入抽象成与后端无关的状态,例如 seed、时间、指针、密度、颜色与文章节点;WebGPU、WebGL、Canvas 2D 都消费同一快照,DOM 则呈现稳定的最终构图。这样能力不足改变的是渲染质量,不是页面内容和操作。
推荐层级不是固定的:计算密集实验可以 WebGPU → WebGL2 → 静态图;少量粒子可以 WebGPU → Canvas 2D → DOM;装饰标题可能直接 WebGPU → CSS。每层都必须单独可测试、可销毁,并在 Reduced Motion 下选择静态状态。回退资源应与 HTML 一同提供,不能等 WebGPU 失败后再请求一个不存在的备用包。
质量降级也可以发生在 WebGPU 内部:降低实例数、纹理尺寸、采样次数或更新频率,比“全功能或黑屏”更平滑。但每一档必须保持数据含义一致,并在 UI 中避免伪装成同等精度。例如粒子只是装饰可以无提示减少;数据图若抽样会改变判断,就必须标明或切换静态准确表示。
“可用”不等于“更快”
Chrome WebGPU 故障排查列出安全上下文、硬件加速、adapter 不可用和设备配置等失败原因,也提醒软件路径或不成熟的移植可能让 WebGPU 表现更差。不要让用户为了作品集效果开启不安全 flag、关闭浏览器保护或修改系统设置;这不是兼容方案。
性能比较必须让输出、输入、尺寸与质量相同。记录设备、GPU、系统、浏览器、DPR、画布尺寸、粒子数、shader 版本、预热策略和采样区间;同时观察 CPU 提交、GPU 时间、长帧、内存与初始化开销。WebGPU 在稳态计算中更快,也可能因较大初始化和 chunk 让首屏更慢。本文未执行这些测试,因此不提供“提升倍数”。
失败模式与验收
| 失败模式 | 为什么错 | 验收方式 |
|---|---|---|
只检测 navigator.gpu |
adapter、feature、device 仍可能失败 | 模拟 null、拒绝和 pipeline error |
| 使用 UA 白名单 | 同版本也受 OS、驱动和策略影响 | 用真实能力协商与目标矩阵 |
| 要求所有可选 feature | 无谓缩小兼容集合 | 记录每个 required feature 的用途 |
| device lost 后刷新页面 | 丢失用户状态且可能再次失败 | 停止调度并切换备用后端 |
| WebGPU 与回退内容不同 | 能力不足导致功能缺失 | 共享状态模型与键盘路径 |
| 把可用写成更快 | 未测量仍下性能结论 | 同输入、同质量、同设备 trace |
测试矩阵至少包含:非安全上下文、navigator.gpu 缺失、adapter 为 null、缺少可选 feature、较低 limit、WGSL 编译失败、device lost、Reduced Motion、页面隐藏和反复切页。每种状态都应有可读内容、明确 cleanup、无控制台未捕获错误。
结论
WebGPU 的正确入口不是一条 feature flag,而是一段可失败的协商协议。按 secure context、API、adapter、features/limits、device 和 pipeline 逐层收窄;把运行时错误与 device lost 纳入状态机;让 WebGL、Canvas 或 DOM 消费同一份语义输入。这样浏览器支持扩大时可以自然升级,支持缺口出现时页面也不会把实验性能力变成用户故障。
Sources
- WebGPU API — MDN Web Docs,访问于 2026-07-16。
- GPU requestAdapter method — MDN Web Docs,访问于 2026-07-16。
- WebGPU Specification — W3C,访问于 2026-07-16。
- WebGPU publication history — W3C,访问于 2026-07-16。
- WebGPU overview — Chrome for Developers,访问于 2026-07-16。
- WebGPU troubleshooting tips and fixes — Chrome for Developers,访问于 2026-07-16。
- From WebGL to WebGPU — Chrome for Developers,访问于 2026-07-16。