mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-14 19:26:51 -04:00
fix(gpu): require consent to persist CPU recovery (#3539)
This commit is contained in:
1 parent
52fcca883e
commit
0df333f623
3 files changed
+31
-15
No files matched your search
@@ -177,6 +177,12 @@ pub fn plan_with_mode(pref: GpuBackend, mode: RenderingMode, crashed: Option<&Ma
|
||||
plan(backend, crashed, env, safe_gpu, os)
|
||||
}
|
||||
|
||||
/// Persist successful hardware fallbacks, but never silently pin CPU mode.
|
||||
/// The recovery dialog explicitly stores CPU mode when the user chooses it.
|
||||
pub fn backend_to_remember(plan: &Plan) -> Option<GpuBackend> {
|
||||
(plan.remember && plan.backend != GpuBackend::Cpu).then_some(plan.backend)
|
||||
}
|
||||
|
||||
/// Instance backends for `plan` (`None`: egui's default, which honours `WGPU_BACKEND`).
|
||||
pub fn backends(plan: &Plan, os: Os) -> Option<wgpu::Backends> {
|
||||
if plan.env.is_some() {
|
||||
@@ -541,6 +547,27 @@ mod tests {
|
||||
assert_eq!(plan(Auto, None, Some("dx12"), true, Os::Windows).backend, Cpu);
|
||||
}
|
||||
|
||||
/// #3483: A temporary CPU recovery must not change the next launch.
|
||||
#[test]
|
||||
fn cpu_recovery_requires_explicit_confirmation_to_persist() {
|
||||
let gl_crash = crashed("gl", "gl");
|
||||
let cpu = plan_with_mode(Auto, RenderingMode::Auto, Some(&gl_crash), None, false, Os::Other);
|
||||
assert_eq!((cpu.backend, cpu.remember), (Cpu, true));
|
||||
assert_eq!(backend_to_remember(&cpu), None);
|
||||
|
||||
let safe = plan_with_mode(Auto, RenderingMode::Auto, None, None, true, Os::Other);
|
||||
assert_eq!(safe.backend, Cpu);
|
||||
assert_eq!(backend_to_remember(&safe), None);
|
||||
// An unconfirmed fallback leaves the original automatic selection intact.
|
||||
assert_eq!(plan_with_mode(Auto, RenderingMode::Auto, None, None, false, Os::Other).backend, Auto);
|
||||
// A working hardware fallback can still be remembered.
|
||||
let vk_crash = crashed("auto", "vulkan");
|
||||
let gl = plan_with_mode(Auto, RenderingMode::Auto, Some(&vk_crash), None, false, Os::Other);
|
||||
assert_eq!(backend_to_remember(&gl), Some(Gl));
|
||||
// CPU explicitly selected in preferences still works.
|
||||
assert_eq!(plan_with_mode(Auto, RenderingMode::Cpu, None, None, false, Os::Other).backend, Cpu);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safe_gpu_forces_the_cpu_for_one_launch() {
|
||||
let p = plan(Vulkan, Some(&crashed("vulkan", "vulkan")), None, true, Os::Other);
|
||||
|
||||
@@ -449,24 +449,13 @@ fn main() -> eframe::Result {
|
||||
photocraft_ui_egui::gpu_status::queue_fallback_notice(&mut app, &reason);
|
||||
}
|
||||
app.perf.span("gpuSentinel", sentinel_ms);
|
||||
// Once the first frames rendered: clear the marker, and keep a crash fallback.
|
||||
let remember_cpu =
|
||||
std::env::var_os("PHOTOCRAFT_GPU_STARTUP_FAILURE").is_some() || (plan.remember && plan.backend == photocraft_engine::prefs::GpuBackend::Cpu);
|
||||
let remember = plan.remember.then_some(plan.backend);
|
||||
// CPU rendering after a failed GPU start is temporary. Only the
|
||||
// recovery-dialog choice may persist it (#3483).
|
||||
let remember = gpu_startup::backend_to_remember(&plan);
|
||||
app.on_started(move |app| {
|
||||
if let Some(s) = started_sentinel.lock().unwrap_or_else(std::sync::PoisonError::into_inner).take() {
|
||||
s.finish();
|
||||
}
|
||||
if remember_cpu
|
||||
&& let Err(error) = app.run(
|
||||
"prefs.set",
|
||||
serde_json::json!({"values": {
|
||||
"performance.renderingMode": "cpu", "performance.useGpu": false
|
||||
}}),
|
||||
)
|
||||
{
|
||||
log::warn!("couldn't remember CPU recovery: {error}");
|
||||
}
|
||||
if let Some(b) = remember
|
||||
&& app.session.prefs().performance.gpu_backend != b
|
||||
&& let Err(e) = app.run("prefs.set", serde_json::json!({"path": "performance.gpuBackend", "value": b.name()}))
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ CRAFT_FONTS_DIR="$PWD/../craft-fonts" cargo test --workspace # runs the Japa
|
||||
|
||||
## Graphics startup and device loss
|
||||
|
||||
`--safe-gpu` starts with the CPU renderer for one launch (no GPU canvas; a software adapter for the window where the platform has one: WARP on Windows, llvmpipe over GL on Linux). Before creating the wgpu device the app writes and locks `gpu-starting.json` in the config directory; it clears it once the first frames have rendered. A launch that finds an unlocked marker knows the previous start died inside the graphics driver (#4) and uses the next safer backend (Windows: Vulkan → DX12 → CPU; Linux: Vulkan → GL → CPU; macOS: Metal → CPU), remembering it in `performance.gpuBackend` (Preferences › Performance › GPU Backend, with **Reset GPU Backend**). With `auto`, Intel adapters on Windows use DX12. Help › System Info shows the adapter, backend, driver and fallback state.
|
||||
`--safe-gpu` starts with the CPU renderer for one launch (no GPU canvas; a software adapter for the window where the platform has one: WARP on Windows, llvmpipe over GL on Linux). Before creating the wgpu device the app writes and locks `gpu-starting.json` in the config directory; it clears it once the first frames have rendered. A launch that finds an unlocked marker knows the previous start died inside the graphics driver (#4) and uses the next safer backend (Windows: Vulkan → DX12 → CPU; Linux: Vulkan → GL → CPU; macOS: Metal → CPU), remembering a working hardware backend in `performance.gpuBackend` (Preferences › Performance › GPU Backend, with **Reset GPU Backend**). CPU recovery is temporary until **Keep Using CPU** is chosen in the recovery dialog; dismissing the dialog or quitting without a choice preserves the previous GPU preference (#3483). With `auto`, Intel adapters on Windows use DX12. Help › System Info shows the adapter, backend, driver and fallback state.
|
||||
|
||||
On DX12 the shader compiler is FXC (`d3dcompiler_47.dll`, part of Windows), or a `dxcompiler.dll` placed beside `photocraft.exe`, loaded by its full path. wgpu's default looks `dxcompiler.dll` up by name, which reaches the current directory and `PATH` and loaded other programs' incompatible builds (#712).
|
||||
|
||||
|
||||
Reference in new issue
Block a user