diff --git a/docs/01-rainbow-triangle.md b/docs/01-rainbow-triangle.md index e837ce1..a19fb72 100644 --- a/docs/01-rainbow-triangle.md +++ b/docs/01-rainbow-triangle.md @@ -1004,7 +1004,10 @@ fn render(&mut self) { return; } wgpu::CurrentSurfaceTexture::Lost => { - log::error!("Surface lost — cannot recover without re-creating State"); + log::error!("Surface lost — GPU resources invalidated; full re-init required"); + // Production recovery: signal App to drop `self.state`, + // then recreate on the next RedrawRequested or in a + // dedicated recovery callback. See callout below. return; } wgpu::CurrentSurfaceTexture::Validation { source, description } => { @@ -1067,6 +1070,17 @@ from the [swapchain](concepts/GLOSSARY.md#swapchain). The swapchain cycles throu 2–3 pre-allocated back buffers. This call returns immediately if a buffer is available; it does not block on the GPU. +> **Surface Lost recovery pattern:** `Lost` means the compositor destroyed the +> surface (display server restart, GPU reset, hotplug, etc.). Every GPU +> resource tied to that surface — the `Surface`, `Device`, `Queue`, pipeline, +> buffers — is irrecoverably invalidated. You cannot reuse any of them. The +> production pattern is to set `self.state = None` in `App`, then on the next +> `RedrawRequested` (or in a dedicated recovery callback), re-run the full +> `State::new()` initialization chain from S3. This recreates the adapter, +> device, surface, and all child resources. Without this, continued renders +> against a lost surface will either panic or silently produce corrupted +> output. + **`device.poll(wgpu::PollType::Wait { submission_index: None, timeout: None })`** — **Synchronous** call that drives in-flight GPU work to completion: shader compilation fences, memory allocation, and queue signaling. Without this, resources accumulate because the device does