From 94cbdeb4cba9daa607f59cef9b8905cb52a9e91c Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Thu, 5 Nov 2026 09:13:57 +0100 Subject: [PATCH] Keep wgpu indirect validation for x86_64 builds on Apple silicon (#5244) Fixes #5199 Co-authored-by: Claude Opus 5.5 --- apps/wordcraft/src/graphics.rs | 53 ++++++++++++++++++++++++++++++++-- apps/wordcraft/src/main.rs | 3 +- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/apps/wordcraft/src/graphics.rs b/apps/wordcraft/src/graphics.rs index 0edd57666f..c05df03de7 100644 --- a/apps/wordcraft/src/graphics.rs +++ b/apps/wordcraft/src/graphics.rs @@ -15,9 +15,25 @@ use eframe::{ /// compiler aborts on them, the device is lost and eframe exits before the window opens. WordCraft /// issues no indirect draws or dispatches, so Intel Macs skip them; every other GPU keeps wgpu's /// default. Same fix as PhotoCraft's storytold/PhotoCraft#3171. +/// +/// `x86_64` is the build's architecture. An x86_64 build also runs on Apple silicon under Rosetta +/// (#5199), so it skips only when the machine itself isn't Apple silicon. #[cfg_attr(not(target_os = "macos"), allow(dead_code))] -pub fn skips_indirect_validation(macos: bool, intel: bool) -> bool { - macos && intel +pub fn skips_indirect_validation(macos: bool, x86_64: bool) -> bool { + // Short-circuits: only x86_64 macOS builds ask the system. + macos && x86_64 && !runs_on_apple_silicon() +} + +/// Whether the machine is Apple silicon, also when this process is translated by Rosetta: +/// `hw.optional.arm64` describes the hardware, not the process. Assumes not (an Intel Mac) when +/// the system can't tell. +#[cfg_attr(not(target_os = "macos"), allow(dead_code))] +fn runs_on_apple_silicon() -> bool { + cfg!(target_os = "macos") + && std::process::Command::new("/usr/sbin/sysctl") + .args(["-n", "hw.optional.arm64"]) + .output() + .is_ok_and(|out| out.status.success() && out.stdout.trim_ascii() == b"1") } /// Leaves wgpu's indirect-call validation out of the instance eframe creates when `skip`. @@ -181,7 +197,8 @@ mod tests { #[test] fn intel_macs_skip_the_indirect_validation_shaders() { // #2652: Metal's Intel compiler aborted on them, losing the device before the window opened. - assert!(skips_indirect_validation(true, true)); + // An x86_64 build on Apple silicon (Rosetta) isn't an Intel Mac (#5199). + assert_eq!(skips_indirect_validation(true, true), !host_is_apple_silicon()); // Apple silicon, Windows and Linux keep wgpu's validation. for (macos, intel) in [(true, false), (false, true), (false, false)] { assert!(!skips_indirect_validation(macos, intel), "macos={macos} intel={intel}"); @@ -205,6 +222,36 @@ mod tests { } } + /// Whether the machine running the tests is Apple silicon, whatever this build's architecture. + fn host_is_apple_silicon() -> bool { + cfg!(target_os = "macos") + && std::process::Command::new("/usr/sbin/sysctl") + .args(["-n", "hw.optional.arm64"]) + .output() + .is_ok_and(|out| out.status.success() && out.stdout.trim_ascii() == b"1") + } + + /// #5199: an x86_64 build running under Rosetta on Apple silicon isn't an Intel Mac and keeps + /// wgpu's indirect-call validation. + #[test] + fn x86_64_builds_on_apple_silicon_keep_indirect_validation() { + if !host_is_apple_silicon() { + return; + } + // What main.rs passes from an x86_64 build. + assert!(!skips_indirect_validation(true, true), "Rosetta build on Apple silicon must keep validation"); + let mut options = NativeOptions::default(); + let WgpuSetup::CreateNew(before) = &options.wgpu_options.wgpu_setup else { + panic!("default native options must create a wgpu instance"); + }; + let before = before.instance_descriptor.flags; + configure_indirect_validation(&mut options, skips_indirect_validation(true, true)); + let WgpuSetup::CreateNew(create) = &options.wgpu_options.wgpu_setup else { + panic!("default native options must create a wgpu instance"); + }; + assert_eq!(create.instance_descriptor.flags, before, "indirect-call validation kept"); + } + fn configured_backends(backends: Backends) -> Backends { let mut options = NativeOptions::default(); configure_backends(&mut options, backends); diff --git a/apps/wordcraft/src/main.rs b/apps/wordcraft/src/main.rs index 6b723be720..ab4e5c57e7 100644 --- a/apps/wordcraft/src/main.rs +++ b/apps/wordcraft/src/main.rs @@ -486,7 +486,8 @@ fn main() -> eframe::Result { // FXC, which needs no DLL of ours (#603; see graphics.rs). #[cfg(target_os = "windows")] graphics::configure(&mut options, eframe::wgpu::Backends::from_env()); - // Intel Macs: Metal's compiler aborts on wgpu's indirect-validation shaders (#2652). + // Intel Macs: Metal's compiler aborts on wgpu's indirect-validation shaders (#2652). An x86_64 + // build under Rosetta on Apple silicon keeps them (#5199). #[cfg(target_os = "macos")] graphics::configure_indirect_validation(&mut options, graphics::skips_indirect_validation(true, cfg!(target_arch = "x86_64"))); load_user_fonts();