題幹與適用場景
一個瀏覽器圖形應用在背景恢復、驅動程式更新或系統資源緊張後出現黑屏。請設計 WebGPU 裝置遺失處理:如何監聽 GPUDevice.lost,區分主動銷毀與瞬時遺失,重建裝置和所有 GPU 資源,並避免多個復原流程互相覆蓋。還要說明不支援 WebGPU、配接器永久不可用和渲染狀態恢復時的降級體驗。
面試官考察點
- 是否理解
lost是裝置生命週期 Promise,而不是普通渲染錯誤。 - 能否區分
destroyed與瀏覽器、驅動程式或資源管理造成的遺失。 - 能否重建 adapter、device、pipeline、buffer、texture 和 bind group。
- 能否設計 single-flight 復原、取消舊幀和冪等資源初始化。
- 能否處理安全內容、Worker、相容性和可觀測性。
回答前需要釐清的問題
- 應用是即時畫布、編輯器還是離線計算,允許多長復原時間?
- 是否必須保留 CPU 端場景、使用者輸入和未提交編輯?
- 目標瀏覽器、Worker、裝置功耗和顯存上限是什麼?
- 復原失敗時應切換 WebGL、靜態預覽還是提示使用者重新載入?
30 秒回答框架
我會把 GPU 裝置視為可替換的工作階段:CPU 端場景與資源描述保持權威,GPU 物件只是快取。監聽 device.lost 後用 single-flight 狀態機暫停提交,讀取 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. 使用 single-flight 復原門
復原入口回傳同一個 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 與 single-flight 復原狀態。
- 注入主動銷毀、背景恢復、驅動程式重置、顯存壓力和 adapter 已遺失裝置情境。
- 驗證資源重建順序、使用者編輯保留、幀暫停和降級 UI,並涵蓋 Worker。
- 以 MDN 的
lostPromise、GPUDeviceLostInfo、安全內容和有限支援說明作為文件與相容性依據。
常見誤區與追問
誤區一:只重新呼叫 requestDevice
新 device 不包含舊資源。必須從 CPU 描述重建 pipeline、buffer、texture、view 和 bind group。
誤區二:所有 reason 都自動重試
主動銷毀可能是應用正常關閉;adapter 永久不可用時重試只會製造迴圈。應按 reason 和退避策略分流。
誤區三:在每個動畫幀啟動復原
多個復原流程會競爭共享狀態。用 single-flight Promise 和 generation 門保證只有一個目前工作階段。
誤區四:把 GPU 物件當作業務狀態
裝置遺失會清空 GPU 工作階段。場景、使用者輸入和資源來源必須獨立於 device 保存。
誤區五:忽略不支援和降級路徑
WebGPU 仍非 Baseline,且只在安全內容可用。應提前檢查並提供 WebGL、靜態預覽或重新載入方案。