mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-22 19:52:27 -05:00
`export_falls_back_to_the_cpu_when_gpu_work_is_lost` asserted on `lightcraft_gpu::last_fallback()`, one value for the whole process that every other engine test's GPU render overwrites between the export and the assertion (out of device memory under parallel load, once "a GPU render panicked"). It also switched the GPU off for the whole process through the injected fault and cleared everyone's state with `reset_failures()`. A render now reports its own fallback: `lightcraft_gpu::try_render` returns `Result<Rendered, Fallback>` (`NotTried` when the GPU was not used, `Failed(reason)` when it was tried and the CPU must render), and `render` is a thin `.ok()` over it. `media::develop_reporting` passes the reason on as `RenderResult::gpu_fallback`, an export carries it as `Exported::gpu_fallback`, and each file in an `app.export` batch result has `gpuFallback` when its render fell back. `last_fallback()` stays as the process-wide diagnostic for `ui.inspect` → `perf.gpuFallback`. A simulated failure (`inject_fault`) is thread-local, and so are its consequences now: a fatal injected fault stops GPU use on the injecting thread only (`available()` false, `unavailable_reason()` set there); `reset_failures()` clears that and nothing else, so neither reaches the other tests in the process. Real failures still stop the whole process. The engine test asserts on its own export's reason and checks that another thread still has the GPU; `crates/gpu/tests/fallback.rs` uses `try_render` and checks the same; a new batch test checks `gpuFallback` lands on the file whose render fell back. Docs: gpu-pipeline.md, control-protocol.md (app.export result), parity.md.