fix(ui): start with an anti-aliasing the graphics device can't do (#329)

Choosing 8x anti-aliasing in Preferences › Graphics on a device that
only allows 1x and 4x for the window's format made every later start
panic in wgpu's pipeline validation (`Sample count 8 is not supported
by format Bgra8Unorm on this device`), so the app could not be opened
again without editing graphics.json by hand.

- egui-wgpu (vendored): request TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES
  when the adapter has it (WebGPU only guarantees 1x and 4x), and clamp
  the sample count to the largest one the device supports for both the
  colour target and the depth/stencil format. The supported counts are
  exposed as `RenderState::msaa_supported`.
- At start, a saved count the device can't do goes back to the default
  (4x, or the largest supported count below it), is written back, and a
  "Settings were changed" notice says what changed.
- The Anti-aliasing list greys out unsupported counts, `ui.prefs`
  rejects them, and an invalid saved `msaa` loads as the default.
- New messages translated in en, de, ja and ko.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Tobias BreckleandClaude Opus 5.5 authored and GitHub committed 2026-10-12 13:46:54 -04:00
1 parent 6dab0fb2c1
commit e6a95615a0
10 files changed
+277 -7

No files matched your search

+13 -1
View File
@@ -239,6 +239,11 @@ pub struct SolveApp {
pub recoverable: Vec<solvecraft_engine::recovery::Entry>,
/// The bodies of a just-opened Y-up file, offered to be stood up (`stand_up`).
pub stand_up: Option<Vec<String>>,
/// The anti-aliasing sample counts the graphics device supports (empty without a GPU).
pub msaa_supported: Vec<u32>,
/// Settings put back at start because they kept SolidCraft from starting, one line each,
/// shown until dismissed (`prefs::show_reset_notice`).
pub settings_reset: Vec<prefs::SettingReset>,
/// The last command was a big operation: autosave after it.
pub big_operation: bool,
/// Autosave interval (minutes; 0 = only after big operations). A preference.
@@ -300,6 +305,8 @@ impl SolveApp {
autosave: None,
recoverable: Vec::new(),
stand_up: None,
msaa_supported: Vec::new(),
settings_reset: Vec::new(),
big_operation: false,
autosave_minutes: 5.0,
custom_titlebar: false,
@@ -335,6 +342,7 @@ impl SolveApp {
/// stencil buffer bits and MSAA sample count). Without it the viewport renders on the CPU.
pub fn set_wgpu(&mut self, rs: &egui_wgpu::RenderState, depth_bits: u8, stencil_bits: u8, samples: u32) {
self.viewport.gpu = Some(gpu::install(rs, depth_bits, stencil_bits, samples));
self.msaa_supported = rs.msaa_supported.clone();
let info = rs.adapter.get_info();
self.help.gpu = Some(format!("{} ({:?}, {:?})", info.name.trim(), info.backend, info.device_type));
}
@@ -412,7 +420,10 @@ impl SolveApp {
if let Some(t) = v.get("toolbar") {
self.toolbar_custom.load(t);
}
if let Some(p) = v.get("preferences").and_then(|p| serde_json::from_value::<prefs::Prefs>(p.clone()).ok()) {
if let Some(mut p) = v.get("preferences").and_then(|p| serde_json::from_value::<prefs::Prefs>(p.clone()).ok()) {
if !prefs::MSAA.contains(&p.msaa) {
p.msaa = prefs::Prefs::default().msaa;
}
self.preferences = p;
}
// Saved before the theme was a preference: the Dark/Light flag says which.
@@ -1004,6 +1015,7 @@ impl SolveApp {
params_dialog::show(self, ui.ctx());
recovery_ui::show(self, ui.ctx());
stand_up::show(self, ui.ctx());
prefs::show_reset_notice(self, ui.ctx());
context_menu::show(self, ui.ctx());
delete::show(self, ui.ctx());
if self.custom_titlebar {