Build bodies on the CPU on AMD FirePro under Metal (GPU hang on Mac Pro 2013) (#1171)

The AMD FirePro D300/D500/D700 Metal driver hangs on the tessellation compute shader and macOS resets the GPU, freezing the desktop. Bodies are built on the CPU on that device, and SOLIDCRAFT_CPU_TESS=1 forces the CPU path on any GPU. The check is a tested predicate, and the troubleshooting guide documents the variable.
This commit is contained in:
devrosx authored and GitHub committed 2026-10-14 18:25:31 -04:00
1 parent 01b1b70586
commit 78079587ad
2 files changed
+30 -1

No files matched your search

+23 -1
View File
@@ -834,6 +834,10 @@ fn tessellation(adapter: &wgpu::Adapter, device: &wgpu::Device, queue: &wgpu::Qu
return None;
}
let info = adapter.get_info();
if hangs_on_gpu_tessellation(info.backend, &info.name) || std::env::var_os("SOLIDCRAFT_CPU_TESS").is_some() {
log::warn!("bodies are built on the CPU on {} ({:?})", info.name, info.backend);
return None;
}
match solidcraft_gpu::TessGpu::with_shader(info.name.clone(), device.clone(), queue.clone(), shader) {
Ok(t) => Some(t),
Err(e) => {
@@ -843,6 +847,13 @@ fn tessellation(adapter: &wgpu::Adapter, device: &wgpu::Device, queue: &wgpu::Qu
}
}
/// A device whose driver hangs on the evaluation shader, so bodies are built on the CPU there:
/// the AMD FirePro D300/D500/D700 (Mac Pro 2013, Tahiti) under Metal, where macOS resets the GPU
/// and the whole desktop freezes. `SOLIDCRAFT_CPU_TESS=1` forces CPU evaluation on any device.
fn hangs_on_gpu_tessellation(backend: wgpu::Backend, name: &str) -> bool {
backend == wgpu::Backend::Metal && name.contains("FirePro")
}
/// Create the pipelines. Call once with the app's render state and its depth/stencil/MSAA
/// settings. Without a stencil the section cap does not hide the inside of cut bodies. Without
/// `gpu_meshing` (safe mode) bodies are meshed on the CPU.
@@ -1182,7 +1193,18 @@ pub fn analysis_colors(c: &crate::theme::AnalysisColors) -> [f32; 36] {
#[cfg(test)]
mod tests {
use egui_wgpu::wgpu::naga;
use egui_wgpu::wgpu::{self, naga};
/// Only the FirePro under Metal skips GPU evaluation; the same card under another backend
/// and other Metal GPUs keep it.
#[test]
fn firepro_under_metal_builds_bodies_on_the_cpu() {
assert!(super::hangs_on_gpu_tessellation(wgpu::Backend::Metal, "AMD FirePro D500"));
assert!(super::hangs_on_gpu_tessellation(wgpu::Backend::Metal, "AMD FirePro D700"));
assert!(!super::hangs_on_gpu_tessellation(wgpu::Backend::Metal, "Apple M2"));
assert!(!super::hangs_on_gpu_tessellation(wgpu::Backend::Metal, "AMD Radeon Pro 560X"));
assert!(!super::hangs_on_gpu_tessellation(wgpu::Backend::Vulkan, "AMD FirePro W5100"));
}
/// The viewport shader parses and validates (a bad shader would only fail at run time).
#[test]