题干与适用场景
一个浏览器图形应用在后台恢复、驱动更新或系统资源紧张后出现黑屏。请设计 WebGPU 设备丢失处理:如何监听 GPUDevice.lost,区分主动销毁与瞬时丢失,重建设备和所有 GPU 资源,并避免多个恢复流程互相覆盖。还要说明不支持 WebGPU、适配器永久不可用和渲染状态恢复时的降级体验。
面试官考察点
- 是否理解
lost是设备生命周期 Promise,而不是普通渲染错误。 - 能否区分
destroyed与浏览器、驱动或资源管理造成的丢失。 - 能否重建 adapter、device、pipeline、buffer、texture 和 bind group。
- 能否设计单飞恢复、取消旧帧和幂等资源初始化。
- 能否处理安全上下文、Worker、兼容性和可观测性。
回答前需要澄清的问题
- 应用是实时画布、编辑器还是离线计算,允许多长恢复时间?
- 是否必须保留 CPU 侧场景、用户输入和未提交编辑?
- 目标浏览器、Worker、设备功耗和显存上限是什么?
- 恢复失败时应切换 WebGL、静态预览还是提示用户重载?
30 秒回答框架
我会把 GPU 设备视为可替换会话:CPU 侧场景与资源描述保持权威,GPU 对象只是缓存。监听 device.lost 后用单飞状态机暂停提交,读取 GPUDeviceLostInfo.reason,主动 destroyed 直接结束,其他原因尝试重新申请 adapter 和 device,再按描述重建资源并恢复渲染。连续失败或 adapter 只返回已丢失设备时切换降级路径,同时记录原因、恢复时长和资源重建失败点。
分步骤深入解答
1. 区分设备与应用状态
把场景树、材质参数、几何数据和纹理来源保存在 CPU 侧。device、queue、buffer、texture、pipeline 和 bind group 属于可丢弃的 GPU 会话,不能把它们当作业务真相。
2. 监听生命周期 Promise
GPUDevice.lost 在设备存活期间保持 pending,设备丢失时解析为 GPUDeviceLostInfo。初始化完成后只注册一次监听,并让监听回调进入统一恢复状态机。
3. 解释丢失原因
主动调用 GPUDevice.destroy() 通常对应 reason 为 destroyed,不应无条件重启。浏览器资源管理、驱动更新或临时设备故障可能可恢复;adapter 被拔出或禁用省电时,后续设备可能一创建就已丢失。
4. 使用单飞恢复门
恢复入口返回同一个 Promise,禁止每个渲染帧各自调用初始化。恢复期间暂停提交、丢弃旧 command encoder,并用 generation 标记拒绝旧设备的异步回调,避免旧资源覆盖新会话。
5. 按描述重建资源
保存 buffer usage、纹理尺寸和格式、采样器、bind group layout、shader 源码和 pipeline 配置。新 device 创建后按依赖顺序重建:shader 与 layout、pipeline、buffer/texture、view、bind group,最后恢复 canvas context 和渲染循环。
6. 管理 CPU 数据与预算
大纹理和几何数据可来自可重读的 URL、IndexedDB 或压缩缓存。恢复时按可见性和优先级分批上传,设置显存预算与取消信号,避免设备刚恢复就再次触发资源压力。
7. 处理并发与可见性
页面隐藏、Worker 消息和用户重试都可能触发恢复请求。用状态机约束 ready、lost、recovering、degraded,只有当前 generation 能提交帧;页面不可见时可延迟昂贵重建。
8. 设计降级与观测
先检测安全上下文和 navigator.gpu,再申请 adapter/device。连续恢复失败、设备永久丢失或浏览器不支持时切换 WebGL、静态预览或明确重载提示。记录 reason、adapter 信息、恢复次数、耗时、重建失败资源和降级比例,不把内部错误直接暴露给用户。
设计取舍与边界
重新申请 device 不会自动恢复旧的 buffers、textures 或 pipelines,它们必须从 CPU 侧描述重建。恢复策略不能假设所有丢失都是瞬时的,也不能在没有退避的情况下无限重试。WebGPU 需要安全上下文且仍是有限可用特性;Worker 可使用该 API,但浏览器矩阵和设备驱动差异必须纳入发布门槛。
落地计划与证据
- 建立 CPU 资源清单和 GPU 资源工厂,所有对象创建都可重复执行。
- 为 device、adapter、canvas context 和渲染循环加入 generation 与单飞恢复状态。
- 注入主动销毁、后台恢复、驱动重置、显存压力和 adapter 已丢失设备场景。
- 验证资源重建顺序、用户编辑保留、帧暂停和降级 UI,并覆盖 Worker。
- 以 MDN 的
lostPromise、GPUDeviceLostInfo、安全上下文和有限支持说明作为文档与兼容性依据。
常见误区与追问
误区一:只重新调用 requestDevice
新 device 不包含旧资源。必须从 CPU 描述重建 pipeline、buffer、texture、view 和 bind group。
误区二:所有 reason 都自动重试
主动销毁可能是应用正常关闭;adapter 永久不可用时重试只会制造循环。应按 reason 和退避策略分流。
误区三:在每个动画帧启动恢复
多个恢复流程会竞争共享状态。用单飞 Promise 和 generation 门保证只有一个当前会话。
误区四:把 GPU 对象当作业务状态
设备丢失会清空 GPU 会话。场景、用户输入和资源来源必须独立于 device 保存。
误区五:忽略不支持和降级路径
WebGPU 仍非 Baseline,且只在安全上下文可用。应提前检测并提供 WebGL、静态预览或重载方案。