跳到主要内容

WebGPU适配与降级

WebGPU 不是「探测到 navigator.gpu 就能上生产」。adapter 为 null、feature 申请失败、非安全上下文,都是 产品路径。失败降到 WebGL2(再失败才 2D),不要弹「请升级浏览器」了事。

核对日期 2026-08 的覆盖面:Chrome / Edge 桌面可用;Safari 26 / iOS 26 起;Firefox 已进 WindowsmacOS Apple SiliconLinux / Android 上的 Firefox 不完整。Android Chrome 与桌面不是同一矩阵。以 requestAdapter() 为准,不以 UA 为准。

1. 安全上下文与 navigator.gpu

WebGPU 只在安全上下文(HTTPS 或 localhost)。局域网 HTTP、部分 WebView、混合内容页:navigator.gpuundefined。这不是「浏览器太旧」。

Worker 里用 self.navigator.gpu(实现提供时)。主线程有、Worker 没有:把 GPU 工作留在能拿到 adapter 的线程,不要假设 Offscreen 一定能 webgpu

2. adapter null 是常态

export type GpuBackend = "webgpu" | "webgl2" | "none";

export async function pickBackend(
canvas: HTMLCanvasElement,
): Promise<GpuBackend> {
if (navigator.gpu) {
const adapter = await navigator.gpu.requestAdapter({
powerPreference: "high-performance",
});
if (adapter) {
try {
const device = await adapter.requestDevice();
const ctx = canvas.getContext("webgpu");
if (ctx) {
ctx.configure({
device,
format: navigator.gpu.getPreferredCanvasFormat(),
alphaMode: "premultiplied",
});
return "webgpu";
}
} catch {
// requestDevice 可因 limits / 特性失败
}
}
}
const gl = canvas.getContext("webgl2", {
failIfMajorPerformanceCaveat: true,
preserveDrawingBuffer: false,
});
return gl ? "webgl2" : "none";
}

同一 &lt;canvas> 第一次 getContext 定死。探测 WebGPU 失败后再 webgl2 可以(尚未成功绑上 webgpu 时)。已经 configure 过的节点不能改绑 webgl2。生产:先临时 canvas 探 adapter,视图 canvas 只绑最终后端。创建细节见 01

forceFallbackAdapter: true 拿软件实现,只给测试。生产不要靠它冒充性能。

3. feature 与 limits:请求时就要说

adapter.features / adapter.limits 是设备上限。requestDevice({ requiredFeatures, requiredLimits }) 要的比 adapter 多,promise reject。常用可选:timestamp-querytexture-compression-bc / etc2 / astcbgra8unorm-storage。没有压缩格式就走未压缩或离线转码,不要假设桌面 BC 在 iOS 有。

export async function requestShapedDevice(
adapter: GPUAdapter,
): Promise<GPUDevice> {
const features: GPUFeatureName[] = [];
if (adapter.features.has("texture-compression-bc")) {
features.push("texture-compression-bc");
}
const maxBuffer = Math.min(adapter.limits.maxBufferSize, 256 * 1024 * 1024);
return adapter.requestDevice({
requiredFeatures: features,
requiredLimits: { maxBufferSize: maxBuffer },
});
}

适用:在已知 feature 上开 HDR / 计算着色 / 时间戳。
不适用:把 Chrome 桌面 limits 写进 iOS 常量。超 maxTextureDimension2D 的失败是 requestDevice 或运行时 validation,视实现而定。

device.lost 后整表作废,见 04。重建时 adapter 可能已变,从 requestAdapter 再走一遍。

4. compatibility mode(一笔)

部分实现对 requestAdapter({ featureLevel: "compatibility" }) 提供 兼容模式:在达不到 core WebGPU 的 GPU / 驱动上,映射到 D3D11 / GLES 一类后端,换更窄的 limits 与特性集。岗位是 扩大可启动面,不是「core 的免费替身」。要 geometry shader 级能力、完整 compute 边界时,compatibility 可能直接给你 null 或更小 limits。探测仍以返回的 adapter / device 为准;失败就 WebGL2。不要对用户解释这个词。

5. 失败形态

症状原因
HTTP 局域网 navigator.gpu非安全上下文
requestAdapter()nullLinux / Android Firefox、策略禁用、无适配驱动
requestDevice() rejectrequired feature / limits 超 adapter
已绑 webgpu 再要 webgl2 为 null上下文互斥
configure 后黑屏未重绘;或 format 没用 getPreferredCanvasFormat()
iOS 能进页、compute 挂feature 未申请或 compatibility 子集

对象少、要读屏,降级应落到 SVG / DOM,而不是再开一张失败的 canvas。

权威资料

核对日期:2026-08-26