mirror of
https://github.com/storytold/gridcraft.git
synced 2026-11-01 14:46:51 -06:00
* Fix #2812: Intel Macs skip wgpu's indirect-call validation shaders Metal's Intel compiler aborts on wgpu's indirect-validation compute shaders ("Compiler encountered an internal error"; MTLCompilerService crashes in reportUnsupportedMaxWorkGroupSizeMetadataError), the device is lost inside request_device and GridCraft exits before its window opens. GridCraft issues no indirect draws or dispatches, so on Intel Macs the instance leaves VALIDATION_INDIRECT_CALL out; WGPU_VALIDATION_INDIRECT_CALL=1 turns it back on. Every other platform keeps wgpu's default. Same as WordCraft (#2652 there). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JadgGo4G2GHaAMNb3qyygk * Review: test that WGPU_VALIDATION_INDIRECT_CALL=1 still turns it on; qualify the doc line The override is checked in a child test process with the variable set, since tests can't set environment variables without unsafe code. The revision line no longer says Intel Macs start: OpenCore Legacy Patcher Macs on macOS 15 can still fail on the MSL version (#1116). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JadgGo4G2GHaAMNb3qyygk --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
15c9d8c10b
commit
5e415cdd34
@@ -1,4 +1,5 @@
|
||||
//! Windows graphics instance configuration, applied before wgpu can initialize any driver.
|
||||
//! Graphics instance configuration, applied before wgpu can initialize any driver: Windows
|
||||
//! backends and the DirectX 12 shader compiler, and the Intel Mac indirect-validation skip.
|
||||
//!
|
||||
//! Vulkan is never initialized unless `WGPU_BACKEND` asks for it: enumerating Vulkan adapters
|
||||
//! crashes inside Intel's `igvk64.dll` on some UHD Graphics drivers (#120), and that access
|
||||
@@ -8,12 +9,38 @@
|
||||
//! whichever `dxcompiler.dll` the DLL search path happens to find (#339, #354): see
|
||||
//! [`dx12_compiler`].
|
||||
|
||||
// On macOS only the indirect-validation items are used outside tests; on Windows the other way
|
||||
// round, so those two carry their own `allow`.
|
||||
#![cfg_attr(target_os = "macos", allow(dead_code))]
|
||||
|
||||
use eframe::{
|
||||
NativeOptions,
|
||||
egui_wgpu::WgpuSetup,
|
||||
wgpu::{Backends, DeviceType, Dx12Compiler},
|
||||
wgpu::{Backends, DeviceType, Dx12Compiler, InstanceFlags},
|
||||
};
|
||||
|
||||
/// wgpu compiles its indirect-call validation compute shaders inside `request_device`. On Intel
|
||||
/// Macs (Iris 5100 in a Mac mini 2014) Metal's compiler aborts on them ("Compiler encountered an
|
||||
/// internal error"), the device is lost and eframe exits before the window opens. GridCraft issues
|
||||
/// no indirect draws or dispatches, so Intel Macs skip them; every other GPU keeps wgpu's default.
|
||||
/// Same as WordCraft (storytold/wordcraft#2652) and PhotoCraft (storytold/PhotoCraft#3171).
|
||||
#[cfg_attr(not(target_os = "macos"), allow(dead_code))]
|
||||
pub fn skips_indirect_validation(macos: bool, intel: bool) -> bool {
|
||||
macos && intel
|
||||
}
|
||||
|
||||
/// Leaves wgpu's indirect-call validation out of the instance eframe creates when `skip`.
|
||||
/// `WGPU_VALIDATION_INDIRECT_CALL=1` still turns it back on.
|
||||
#[cfg_attr(not(target_os = "macos"), allow(dead_code))]
|
||||
pub fn configure_indirect_validation(options: &mut NativeOptions, skip: bool) {
|
||||
if !skip {
|
||||
return;
|
||||
}
|
||||
if let WgpuSetup::CreateNew(create) = &mut options.wgpu_options.wgpu_setup {
|
||||
create.instance_descriptor.flags = create.instance_descriptor.flags.difference(InstanceFlags::VALIDATION_INDIRECT_CALL).with_env();
|
||||
}
|
||||
}
|
||||
|
||||
/// What the start-up probe learned about one DirectX 12 adapter.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Dx12Adapter {
|
||||
@@ -141,6 +168,55 @@ fn probe_dx12(options: &NativeOptions) -> Vec<Dx12Adapter> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn instance_flags(options: &NativeOptions) -> InstanceFlags {
|
||||
let WgpuSetup::CreateNew(create) = &options.wgpu_options.wgpu_setup else {
|
||||
panic!("default native options must create a wgpu instance");
|
||||
};
|
||||
create.instance_descriptor.flags
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn intel_macs_skip_the_indirect_validation_shaders() {
|
||||
// Metal's Intel compiler aborted on them, losing the device before the window opened.
|
||||
assert!(skips_indirect_validation(true, true));
|
||||
// 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}");
|
||||
}
|
||||
let mut options = NativeOptions::default();
|
||||
let before = instance_flags(&options);
|
||||
configure_indirect_validation(&mut options, false);
|
||||
assert_eq!(instance_flags(&options), before, "flags untouched when not skipping");
|
||||
if std::env::var_os("WGPU_VALIDATION_INDIRECT_CALL").is_none() {
|
||||
configure_indirect_validation(&mut options, true);
|
||||
assert!(!instance_flags(&options).contains(InstanceFlags::VALIDATION_INDIRECT_CALL));
|
||||
}
|
||||
}
|
||||
|
||||
/// `WGPU_VALIDATION_INDIRECT_CALL=1` turns the validation back on even when it is skipped.
|
||||
/// Tests can't set environment variables (`set_var` is unsafe, and unsafe code is forbidden),
|
||||
/// so this runs itself again as a child process with the variable set.
|
||||
#[test]
|
||||
fn the_environment_turns_indirect_validation_back_on() {
|
||||
const NAME: &str = "graphics::tests::the_environment_turns_indirect_validation_back_on";
|
||||
if std::env::var_os("GRIDCRAFT_INDIRECT_VALIDATION_CHILD").is_some() {
|
||||
let mut options = NativeOptions::default();
|
||||
configure_indirect_validation(&mut options, true);
|
||||
assert!(instance_flags(&options).contains(InstanceFlags::VALIDATION_INDIRECT_CALL));
|
||||
return;
|
||||
}
|
||||
let exe = std::env::current_exe().unwrap();
|
||||
let out = std::process::Command::new(exe)
|
||||
.args(["--exact", NAME, "--test-threads=1"])
|
||||
.env("GRIDCRAFT_INDIRECT_VALIDATION_CHILD", "1")
|
||||
.env("WGPU_VALIDATION_INDIRECT_CALL", "1")
|
||||
.output()
|
||||
.unwrap();
|
||||
let stdout = String::from_utf8_lossy(&out.stdout);
|
||||
// `--exact` matching nothing would pass too, so the child must report this one test.
|
||||
assert!(out.status.success() && stdout.contains("1 passed"), "child test failed:\n{stdout}{}", String::from_utf8_lossy(&out.stderr));
|
||||
}
|
||||
|
||||
fn configured_backends(backends: Backends) -> Backends {
|
||||
let mut options = NativeOptions::default();
|
||||
configure_backends(&mut options, backends);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#[cfg(target_os = "macos")]
|
||||
mod apple_events;
|
||||
mod control_server;
|
||||
#[cfg(any(target_os = "windows", test))]
|
||||
#[cfg(any(target_os = "windows", target_os = "macos", test))]
|
||||
mod graphics;
|
||||
mod logging;
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -341,8 +341,11 @@ fn main() -> eframe::Result<()> {
|
||||
}
|
||||
let window_builder = viewport.clone();
|
||||
let options = eframe::NativeOptions { viewport, ..Default::default() };
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
#[cfg(unix)]
|
||||
let mut options = options;
|
||||
// Intel Macs: Metal's compiler aborts on wgpu's indirect-validation shaders (see graphics.rs).
|
||||
#[cfg(target_os = "macos")]
|
||||
graphics::configure_indirect_validation(&mut options, graphics::skips_indirect_validation(true, cfg!(target_arch = "x86_64")));
|
||||
// winit has no file drag-and-drop on Wayland (only on X11), so dropping files from the file
|
||||
// manager showed a "no" cursor. Run through XWayland when it's there; GRIDCRAFT_WAYLAND=1
|
||||
// keeps the native Wayland backend.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Hardware parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-22 · **Change:** minor (Arrange All) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-31 · **Change:** trivial (Intel Mac start-up) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4
|
||||
|
||||
The hardware Excel uses, per platform, against GridCraft. Part of
|
||||
[target-app-parity.md](target-app-parity.md). **Hardware: ~40% ready, 25–40 h** (estimated).
|
||||
@@ -8,7 +8,7 @@ The hardware Excel uses, per platform, against GridCraft. Part of
|
||||
| Hardware feature | Excel | GridCraft (macOS · Windows · Linux · BSD · web) | Gap and estimate |
|
||||
|---|---|---|---|
|
||||
| Multi-core recalculation | Multi-threaded recalculation on all cores (Windows and Mac), configurable thread count | Single-threaded everywhere (no threading in `crates/calc`) | Parallel recalc of independent dependency chains on native builds; WASM stays single-threaded or uses workers later: 12–18 h |
|
||||
| GPU rendering of the grid and charts | DirectX / Metal accelerated drawing | wgpu: Metal · DirectX 12 (default since 10-08; OpenGL when DirectX 12 has no GPU driver or fails to start; Vulkan only on request, so the Intel UHD `igvk64.dll` crash (#120) can't happen; shaders compiled with FXC, so no DXC runtime is needed, #339) · Vulkan/GL · Vulkan/GL · WebGPU or WebGL2 | At parity in kind. Driver problems: screen flashing on Windows 11 (#76): 2–4 h |
|
||||
| GPU rendering of the grid and charts | DirectX / Metal accelerated drawing | wgpu: Metal (Intel Macs skip wgpu's indirect-call validation shaders, which Metal's Intel compiler aborts on, #2812) · DirectX 12 (default since 10-08; OpenGL when DirectX 12 has no GPU driver or fails to start; Vulkan only on request, so the Intel UHD `igvk64.dll` crash (#120) can't happen; shaders compiled with FXC, so no DXC runtime is needed, #339) · Vulkan/GL · Vulkan/GL · WebGPU or WebGL2 | At parity in kind. Driver problems: screen flashing on Windows 11 (#76): 2–4 h |
|
||||
| Pen and touch (Draw tab) | Pen pressure and tilt, eraser end, touch mode, Ink to Shape, ink replay | Pen, highlighter, eraser, Ink to Shape with mouse/pen input; **no pressure or tilt**, no touch mode | Pressure-sensitive strokes where winit reports force; touch-friendly ribbon spacing: 4–6 h |
|
||||
| Trackpad and mouse | Smooth scrolling, pinch zoom, horizontal scroll, Magic Mouse | Smooth scrolling and zoom via egui | Verify pinch zoom on each platform: 1–2 h |
|
||||
| Multiple windows and monitors | One window per workbook, New Window for the same workbook, per-monitor DPI | A native window per workbook window on the desktop, New Window for the same workbook; new windows cascade from the last one on its monitor; View › Arrange All tiles, stacks or cascades them over the main window's monitor (web: one window) | Arrange All across monitors; verify per-monitor DPI with windows on two monitors: 2–3 h |
|
||||
@@ -20,6 +20,7 @@ The hardware Excel uses, per platform, against GridCraft. Part of
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-31 | trivial | macOS: Intel Macs skip wgpu's indirect-call validation shaders, so they no longer exit on Metal's compiler error there (#2812). Macs run with OpenCore Legacy Patcher on macOS 15 can still fail earlier, on the MSL version (#1116). |
|
||||
| 2026-10-22 | minor | View › Arrange All over the main window's monitor. |
|
||||
| 2026-10-22 | minor | Multiple windows: each workbook window is a native window of its own (desktop). |
|
||||
| 2026-10-12 | minor | Desktop File > Print now discovers printers and submits PDF jobs through pinned craft-print with printer choice, copies, duplex and grayscale; browser printing and PDF export remain available. Remaining print parity includes page ranges and driver-specific tray/options UI; physical printer fidelity needs hardware validation. |
|
||||
|
||||
Reference in New Issue
Block a user