diff --git a/apps/photocraft/src/gpu_startup.rs b/apps/photocraft/src/gpu_startup.rs index 56dbbb9400..d945e3897e 100644 --- a/apps/photocraft/src/gpu_startup.rs +++ b/apps/photocraft/src/gpu_startup.rs @@ -282,6 +282,16 @@ pub fn wanted_missed(adapters: &[Candidate], wanted: Option<&str>) -> bool { wanted.is_some() && !adapters.iter().any(|a| a.surface_ok && a.wanted) } +/// Choosing an adapter is Linux-only for now: Windows has its own Intel/DX12 selection and macOS a +/// single Metal path, and neither is tested with a requested adapter. +pub const ADAPTER_CHOICE: bool = cfg!(target_os = "linux"); + +/// The adapter request that applies to this launch: none off Linux (`linux`), and none in CPU mode, +/// which wants a software adapter whatever the preference says. +pub fn applicable_adapter(wanted: Option, backend: GpuBackend, linux: bool) -> Option { + wanted.filter(|_| linux && backend != GpuBackend::Cpu) +} + /// The adapter to ask for: `PHOTOCRAFT_GPU_ADAPTER` when set (for one launch), else /// `performance.gpuAdapter`; `None` is automatic. pub fn wanted_adapter(env: Option<&str>, pref: &str) -> Option { @@ -322,8 +332,7 @@ pub fn configure(setup: &mut egui_wgpu::WgpuSetup, plan: &Plan, os: Os, wanted: let env = std::env::var("WGPU_DX12_COMPILER").ok(); create.instance_descriptor.backend_options.dx12.shader_compiler = dx12_compiler(env.as_deref(), exe.as_deref().and_then(Path::parent)); } - // CPU mode wants a software adapter, whatever the preference says. - let wanted = wanted.filter(|_| plan.backend != GpuBackend::Cpu); + let wanted = applicable_adapter(wanted, plan.backend, ADAPTER_CHOICE); let select = wanted.is_some() || (plan.env.is_none() && (plan.backend == GpuBackend::Cpu || (plan.backend == GpuBackend::Auto && os == Os::Windows))); if select { let backend = plan.backend; @@ -669,6 +678,16 @@ mod tests { assert_eq!(pick(&gl, Auto, Os::Other), Some(1)); } + #[test] + fn an_adapter_request_applies_on_linux_outside_cpu_mode() { + let w = || Some("nvidia".to_string()); + assert_eq!(applicable_adapter(w(), Auto, true), w()); + assert_eq!(applicable_adapter(w(), Vulkan, true), w()); + assert_eq!(applicable_adapter(w(), Cpu, true), None); + assert_eq!(applicable_adapter(w(), Auto, false), None, "Windows and macOS keep their own selection"); + assert_eq!(applicable_adapter(None, Auto, true), None); + } + #[test] fn adapter_names_match_loosely_and_the_environment_wins() { assert!(adapter_matches("NVIDIA GeForce RTX 5060 Ti", "nvidia")); diff --git a/apps/photocraft/src/main.rs b/apps/photocraft/src/main.rs index 0c2be25232..d110f849b7 100644 --- a/apps/photocraft/src/main.rs +++ b/apps/photocraft/src/main.rs @@ -517,7 +517,7 @@ fn main() -> eframe::Result { } // An adapter named in the environment is chosen at startup, which a forwarded launch never reaches. - if std::env::var("PHOTOCRAFT_GPU_ADAPTER").is_ok_and(|v| !v.trim().is_empty()) { + if gpu_startup::ADAPTER_CHOICE && std::env::var("PHOTOCRAFT_GPU_ADAPTER").is_ok_and(|v| !v.trim().is_empty()) { launch_options.push("PHOTOCRAFT_GPU_ADAPTER"); } // One PhotoCraft per user (#3708): files opened from Explorer or a file manager while it runs diff --git a/docs/development.md b/docs/development.md index 2691f55d1c..8a63b825c9 100644 --- a/docs/development.md +++ b/docs/development.md @@ -88,7 +88,7 @@ On Windows and Linux the first PhotoCraft holds an exclusive lock on `instance.l `--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 a machine with several GPUs (say an eGPU, a discrete laptop GPU and an iGPU), `auto` takes the first discrete adapter the driver lists; choose another in Preferences › Performance › Advanced › GPU adapter (`performance.gpuAdapter`, Linux; a case-insensitive piece of the adapter's name, empty is automatic), or for one launch with `PHOTOCRAFT_GPU_ADAPTER=nvidia`. An adapter that is missing or can't present to the window falls back to the automatic choice, with a note in System Info. +On Linux, on a machine with several GPUs (say an eGPU, a discrete laptop GPU and an iGPU), `auto` takes the first discrete adapter the driver lists; choose another in Preferences › Performance › Advanced › GPU adapter (`performance.gpuAdapter`, Linux; a case-insensitive piece of the adapter's name, empty is automatic), or for one launch with `PHOTOCRAFT_GPU_ADAPTER=nvidia`. An adapter that is missing or can't present to the window falls back to the automatic choice, with a note in System Info. 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). @@ -118,7 +118,7 @@ By default PhotoCraft's own crates log at `info` and everything else at `warn`. | `PHOTOCRAFT_AUTOMATION_WRITE_ROOT` | Desktop app only: automation write root. Headless CLI modes require the `--automation-write-root` flag | | `PHOTOCRAFT_CPU_CANVAS=1` | Force the CPU canvas path instead of the wgpu shader canvas | | `PHOTOCRAFT_NATIVE_WAYLAND=1` | Linux: stay on native Wayland when a pen is attached (by default the window then opens through Xwayland, because Wayland gives the app no pen input; #639). A pen is an input device with `BTN_TOOL_PEN` and the `ABS_X`/`ABS_Y` axes; virtual keyboards that claim every key are not pens (#1072) | -| `PHOTOCRAFT_GPU_ADAPTER=nvidia` | Use the graphics adapter whose name contains this (case-insensitive); overrides `performance.gpuAdapter` for one launch | +| `PHOTOCRAFT_GPU_ADAPTER=nvidia` | Linux: use the graphics adapter whose name contains this (case-insensitive); overrides `performance.gpuAdapter` for one launch | | `WGPU_BACKEND=dx12` | Pick the wgpu backend(s) (`vulkan`, `dx12`, `metal`, `gl`); overrides `performance.gpuBackend` and the startup fallback | | `WGPU_DX12_COMPILER=fxc` | DX12 shader compiler (`fxc`, `dxc`, `auto`); `dxc` and `auto` look `dxcompiler.dll` up through the DLL search path | | `PHOTOCRAFT_GPU_TILE=2048` | Force GPU canvas tiling (tests tile seams) | diff --git a/docs/hardware-parity.md b/docs/hardware-parity.md index 1417821f0d..391c92f0ce 100644 --- a/docs/hardware-parity.md +++ b/docs/hardware-parity.md @@ -22,7 +22,7 @@ HDR display to verify. | GPU filters (Blur Gallery, Liquify, Smart Sharpen, Camera Raw) | yes | CPU (rayon) for filters; GPU for compose and effects | partial | | Documents larger than the GPU texture limit | yes (tiled) | CPU fallback; tiling in progress (#49) | partial | | CPU-only fallback when no GPU | yes, reduced | `cpu` canvas preference; fails to start without an adapter on some Linux systems (#2519, #2412) | partial | -| Choosing the GPU on a multi-GPU machine | Preferences › Performance › Use Graphics Processor | Linux: Preferences › Performance › Advanced › GPU adapter and `PHOTOCRAFT_GPU_ADAPTER` (#1885); Windows and macOS not yet | partial | +| Choosing the GPU on a multi-GPU machine | Preferences › Performance › Use Graphics Processor | Linux only: Preferences › Performance › Advanced › GPU adapter and `PHOTOCRAFT_GPU_ADAPTER` (#1885); ignored on Windows and macOS | partial | | Old / integrated GPUs | yes | black line on Intel HD (#2426), OpenCore Macs fail (#1859), Rgba32Float panic (#2020) | partial | ## Pen tablets