mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 02:25:55 +00:00
* claim: #8341 Co-authored-by: Cursor <cursoragent@cursor.com> * Graphics: keep a preferred card when surface marks it incompatible (#8341) Prefer the saved adapter by exact then case-insensitive name, including when only listed as surface-incompatible, and explain in Preferences when another card is still in use. Co-authored-by: Cursor <cursoragent@cursor.com> * Format and clippy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1126,6 +1126,12 @@ fn main() -> eframe::Result {
|
||||
})
|
||||
.collect();
|
||||
let info = rs.adapter.get_info();
|
||||
if !app.preferences.graphics_adapter.is_empty() && !info.name.eq_ignore_ascii_case(app.preferences.graphics_adapter.as_str()) {
|
||||
eprintln!(
|
||||
"SolidCraft graphics: preferred adapter {:?} was not used; using {:?} instead",
|
||||
app.preferences.graphics_adapter, info.name
|
||||
);
|
||||
}
|
||||
let samples = scene_msaa_request(saved_samples);
|
||||
let supported = scene_sample_choices(depth_bits, STENCIL_BITS, |depth| {
|
||||
eframe::egui_wgpu::supported_msaa_samples(&rs.adapter, &rs.device, rs.target_format, depth)
|
||||
|
||||
@@ -137,8 +137,11 @@ pub struct AdapterChoice {
|
||||
pub compatible: bool,
|
||||
}
|
||||
|
||||
/// Choose only surface-compatible adapters. Names saved in preferences are exact; the
|
||||
/// environment override follows wgpu's case-insensitive substring convention.
|
||||
/// Choose an adapter by name. The environment override follows wgpu's case-insensitive
|
||||
/// substring convention among surface-compatible adapters. A saved preference prefers an
|
||||
/// exact (then case-insensitive) name among compatible adapters, and if the named card is
|
||||
/// only listed as incompatible with the surface still picks it (#8341: otherwise the
|
||||
/// preference is kept in the dialog while wgpu silently uses another GPU).
|
||||
/// No match leaves selection to the normal wgpu request.
|
||||
pub fn choose_adapter(adapters: &[AdapterChoice], environment: Option<&str>, preference: Option<&str>) -> Option<usize> {
|
||||
// wgpu's environment helper panics on a missing name; an override must remain recoverable.
|
||||
@@ -149,12 +152,14 @@ pub fn choose_adapter(adapters: &[AdapterChoice], environment: Option<&str>, pre
|
||||
return Some(index);
|
||||
}
|
||||
}
|
||||
if let Some(name) = preference.filter(|s| !s.is_empty())
|
||||
&& let Some((index, _)) = compatible().find(|(_, a)| a.name == name)
|
||||
{
|
||||
return Some(index);
|
||||
}
|
||||
None
|
||||
let name = preference.filter(|s| !s.is_empty())?;
|
||||
let find = |pred: &dyn Fn(&AdapterChoice) -> bool, only_compatible: bool| {
|
||||
adapters.iter().enumerate().find(|(_, a)| (!only_compatible || a.compatible) && pred(a)).map(|(i, _)| i)
|
||||
};
|
||||
find(&|a| a.name == name, true)
|
||||
.or_else(|| find(&|a| a.name.eq_ignore_ascii_case(name), true))
|
||||
.or_else(|| find(&|a| a.name == name, false))
|
||||
.or_else(|| find(&|a| a.name.eq_ignore_ascii_case(name), false))
|
||||
}
|
||||
|
||||
/// Leave Automatic on wgpu's normal request path; named choices may defer to it too.
|
||||
@@ -416,7 +421,8 @@ mod tests {
|
||||
assert_eq!(choose_adapter(&cards, None, Some("removed")), None);
|
||||
assert_eq!(choose_adapter(&cards, Some("missing"), Some("Discrete small")), Some(1));
|
||||
assert_eq!(choose_adapter(&cards, Some(""), Some("Discrete small")), Some(1));
|
||||
assert_eq!(choose_adapter(&cards, None, Some("Discrete")), None, "saved names are exact");
|
||||
assert_eq!(choose_adapter(&cards, None, Some("discrete small")), Some(1), "preference matches without regard to case");
|
||||
assert_eq!(choose_adapter(&cards, None, Some("Discrete")), None, "a preference is the full name, not a substring");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -425,11 +431,20 @@ mod tests {
|
||||
assert_eq!(choose_adapter(&cards, None, None), None);
|
||||
assert_eq!(choose_adapter(&cards, Some(""), Some("")), None);
|
||||
cards[2].compatible = false;
|
||||
assert_eq!(choose_adapter(&cards, Some("large"), Some("Discrete large")), None);
|
||||
// Environment still needs a compatible adapter; a preference keeps the named card (#8341).
|
||||
assert_eq!(choose_adapter(&cards, Some("large"), Some("Discrete large")), Some(2));
|
||||
assert_eq!(choose_adapter(&cards, Some("small"), None), Some(1));
|
||||
assert_eq!(choose_adapter(&[], None, None), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preference_keeps_a_named_card_even_when_surface_says_incompatible() {
|
||||
let mut cards = cards();
|
||||
cards[1].compatible = false;
|
||||
assert_eq!(choose_adapter(&cards, None, Some("Discrete small")), Some(1));
|
||||
assert_eq!(choose_adapter(&cards, None, Some("discrete SMALL")), Some(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn automatic_adapter_preserves_the_previous_request_configuration() {
|
||||
use eframe::egui_wgpu::WgpuSetupCreateNew;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"en": {
|
||||
"prefs.graphics_card_unused": "The saved graphics card was not used for this window; the card in use is shown in Help › About and in the status line. Try Automatic, or set WGPU_ADAPTER_NAME to a unique part of the card's name."
|
||||
},
|
||||
"ar": {
|
||||
"prefs.graphics_card_unused": "لم تُستخدم بطاقة الرسوميات المحفوظة لهذه النافذة؛ البطاقة المستخدمة تظهر في مساعدة › حول وفي شريط الحالة. جرّب تلقائي، أو عيّن WGPU_ADAPTER_NAME إلى جزء فريد من اسم البطاقة."
|
||||
},
|
||||
"de": {
|
||||
"prefs.graphics_card_unused": "Die gespeicherte Grafikkarte wurde für dieses Fenster nicht verwendet; die tatsächlich genutzte Karte steht unter Hilfe › Info und in der Statuszeile. Versuchen Sie Automatisch, oder setzen Sie WGPU_ADAPTER_NAME auf einen eindeutigen Teil des Kartennamens."
|
||||
},
|
||||
"he": {
|
||||
"prefs.graphics_card_unused": "כרטיס המסך השמור לא שימש לחלון זה; הכרטיס שבשימוש מוצג בעזרה › אודות ובשורת המצב. נסו אוטומטי, או הגדירו את WGPU_ADAPTER_NAME לחלק ייחודי משם הכרטיס."
|
||||
},
|
||||
"ja": {
|
||||
"prefs.graphics_card_unused": "保存したグラフィックスカードはこのウィンドウでは使われていません。使用中のカードは「ヘルプ › SolidCraft について」とステータス行に表示されます。自動を試すか、カード名の一意な部分を WGPU_ADAPTER_NAME に設定してください。"
|
||||
},
|
||||
"vi": {
|
||||
"prefs.graphics_card_unused": "Card đồ họa đã lưu không được dùng cho cửa sổ này; card đang dùng hiện trong Trợ giúp › Giới thiệu và trên dòng trạng thái. Thử Tự động, hoặc đặt WGPU_ADAPTER_NAME thành phần tên card mang tính duy nhất."
|
||||
},
|
||||
"zh": {
|
||||
"prefs.graphics_card_unused": "已保存的显卡未用于此窗口;实际使用的显卡显示在“帮助 › 关于”和状态栏中。请尝试“自动”,或将 WGPU_ADAPTER_NAME 设为显卡名称中的唯一部分。"
|
||||
},
|
||||
"zh-TW": {
|
||||
"prefs.graphics_card_unused": "已儲存的顯示卡未用於此視窗;實際使用的顯示卡顯示在「說明 › 關於」和狀態列中。請嘗試「自動」,或將 WGPU_ADAPTER_NAME 設為顯示卡名稱中的唯一部分。"
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,13 @@ pub(super) fn show(app: &mut SolveApp, ui: &mut egui::Ui) {
|
||||
ui_kit::text(ui, app.tr("prefs.graphics_card_restart"), ui_kit::Text::Hint("graphics_card_restart"));
|
||||
if missing {
|
||||
ui_kit::text(ui, app.tr("prefs.graphics_card_missing"), ui_kit::Text::Hint("graphics_card_missing"));
|
||||
} else if !app.preferences.graphics_adapter.is_empty() {
|
||||
// Status / Help show the adapter actually in use; the dropdown shows the saved
|
||||
// preference. When they differ the saved card was not applied (#8341).
|
||||
let active = app.viewport.adapter.rsplit(" · ").next().unwrap_or("");
|
||||
if !active.is_empty() && !active.eq_ignore_ascii_case(&app.preferences.graphics_adapter) {
|
||||
ui_kit::text(ui, app.tr("prefs.graphics_card_unused"), ui_kit::Text::Hint("graphics_card_unused"));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user