上下文生命周期
<canvas> 上的 GPU 上下文是 单例且排他。创建参数、丢失、WebGPU device 死亡,全部是产品路径,不是初始化边角。
1. WebGL2 创建
export type GlOptions = {
alpha?: boolean;
antialias?: boolean;
depth?: boolean;
preserveDrawingBuffer?: boolean;
powerPreference?: WebGLPowerPreference;
failIfMajorPerformanceCaveat?: boolean;
premultipliedAlpha?: boolean;
};
export function getWebGL2(
canvas: HTMLCanvasElement,
options: GlOptions = {},
): WebGL2RenderingContext | null {
return canvas.getContext("webgl2", {
alpha: options.alpha ?? true,
antialias: options.antialias ?? false,
depth: options.depth ?? true,
preserveDrawingBuffer: options.preserveDrawingBuffer ?? false,
powerPreference: options.powerPreference ?? "high-performance",
failIfMajorPerformanceCaveat: options.failIfMajorPerformanceCaveat ?? true,
premultipliedAlpha: options.premultipliedAlpha ?? true,
});
}
| 选项 | 生产默认 | 不要默认打开的原因 |
|---|---|---|
antialias | false | 隐式 MSAA,移动端带宽;需要时 FBO 自己做 |
preserveDrawingBuffer | false | 合成后保留缓冲,吃显存 |
failIfMajorPerformanceCaveat | true | 否则软件实现会假装成功 |
alpha | 按是否要透到 DOM 决定 | 不透明场景应 false,少一层混合 |
第一次调用锁定选项。第二次改 antialias 不会生效,仍返回旧上下文。
getContext("2d") / getContext("webgpu") 在已有 webgl2 的元素上返回 null。2D UI 和 GL 场景用 两张 canvas 叠,见 与 2D 叠层。
2. WebGPU 创建
export async function getWebGPU(canvas: HTMLCanvasElement): Promise<{
device: GPUDevice;
context: GPUCanvasContext;
format: GPUTextureFormat;
} | null> {
if (!navigator.gpu) return null;
const adapter = await navigator.gpu.requestAdapter({
powerPreference: "high-performance",
});
if (!adapter) return null;
const device = await adapter.requestDevice();
const context = canvas.getContext("webgpu");
if (!context) return null;
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({
device,
format,
alphaMode: "premultiplied",
});
return { device, context, format };
}
- 必须是安全上下文(HTTPS 或 localhost)。
requestAdapter()为null是常态(Linux、旧 Android、策略禁用)。降级 WebGL2,不要抛给用户「浏览器太旧」了事。configure会把画布清成透明黑。resize 后要重新configure或重建 canvas 纹理,见 05。navigator.gpu在 Worker 里走self.navigator(有实现的环境)。
核对日期时的覆盖面:Chrome / Edge 桌面可用;Safari 26 与 iOS 26 起;Firefox 已覆盖 Windows 与 macOS Apple Silicon。Android / Linux 仍要当二等公民。见 WebGPU 适配与降级。
3. 丢失
WebGL:听 webglcontextlost(event.preventDefault() 才能恢复)和 webglcontextrestored。恢复后 所有 buffer / texture / program / VAO 句柄无效,必须按资源表重建。测试用 WEBGL_lose_context.loseContext()。
WebGPU:device.lost 是 Promise,resolve 后 device 不可用。重新 requestAdapter → requestDevice → configure。不要缓存旧 GPUBuffer。
4. 失败形态
| 症状 | 原因 |
|---|---|
想叠 2D 文字,getContext("2d") 为 null | 已经要过 webgl2 |
| 截图全透明 | 未 preserve 且读回跨帧 |
| iOS 切后台回来白屏 | 丢失后还在 useProgram(旧句柄) |
| WebGPU 示例在 HTTP 局域网挂了 | 非安全上下文 |
configure 后画面闪黑 | resize 时重复 configure 没立刻重绘 |
权威资料
- WHATWG — getContext
- WebGL — Context Lost
- MDN — GPU.requestAdapter()
- MDN — GPUCanvasContext.configure()
核对日期:2026-08-26