forked from 1b-agent/opencadstudio-upstream
feat(gpu): route legacy hardware to OpenGL, add hardware info to About, and expose Graphics options tab
This commit is contained in:
1 parent
81bb8d48cf
commit
abf302eba5
12 files changed
+838
-21
No files matched your search
@@ -44,6 +44,39 @@ fn info_card<'a>(
|
||||
.into()
|
||||
}
|
||||
|
||||
/// A full-width label/value line. CPU and GPU names are too long for the
|
||||
/// fixed-width cards above.
|
||||
fn info_row<'a>(
|
||||
label: std::borrow::Cow<'static, str>,
|
||||
value: impl iced::widget::text::IntoFragment<'a>,
|
||||
width: Length,
|
||||
) -> Element<'a, Message> {
|
||||
container(
|
||||
row![
|
||||
text(label).size(11).style(muted_style).width(Length::Fixed(110.0)),
|
||||
text(value).size(13).width(Fill),
|
||||
]
|
||||
.spacing(8)
|
||||
.align_y(iced::Center),
|
||||
)
|
||||
.padding([8, 12])
|
||||
.width(width)
|
||||
.style(surface_style)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// `Adapter (backend)` for the GPU row.
|
||||
fn gpu_summary() -> String {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
"WebGPU / WebGL".to_string()
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
crate::gpu_backend::active_gpu_summary()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn platform_name() -> &'static str {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
@@ -69,6 +102,59 @@ pub(crate) fn architecture_name() -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
/// The text `Copy Info` puts on the clipboard: everything a bug report needs
|
||||
/// about the build and the machine, including which graphics backend the
|
||||
/// resolver picked and why.
|
||||
pub(crate) fn report() -> String {
|
||||
use crate::sysinfo::{format_bytes, system_info};
|
||||
let sys = system_info();
|
||||
#[allow(unused_mut)]
|
||||
let mut out = format!(
|
||||
"Open CAD Studio v{}\nRevision: {}\nCommit date: {}\nProfile: {}\nFeatures: {}\n\n\
|
||||
[System]\nOS: {} ({} {})\nCPU: {}\nLogical processors: {}\nRAM: {} total, {} available\n",
|
||||
env!("OCS_FULL_VERSION"),
|
||||
env!("OCS_GIT_REV"),
|
||||
env!("OCS_COMMIT_DATE"),
|
||||
env!("OCS_BUILD_PROFILE"),
|
||||
env!("OCS_BUILD_FEATURES"),
|
||||
sys.os,
|
||||
platform_name(),
|
||||
architecture_name(),
|
||||
sys.cpu,
|
||||
sys.logical_cores,
|
||||
format_bytes(sys.ram_total),
|
||||
format_bytes(sys.ram_available),
|
||||
);
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
use crate::gpu_backend::{active_gpu, load_prefs};
|
||||
let gpu = active_gpu();
|
||||
let prefs = load_prefs();
|
||||
let or_unknown = |s: &str| {
|
||||
if s.is_empty() {
|
||||
"Unknown".to_string()
|
||||
} else {
|
||||
s.to_string()
|
||||
}
|
||||
};
|
||||
out.push_str(&format!(
|
||||
"\n[Graphics]\nGPU: {}\nDriver: {}\nBackend: {}\nSelected by: {}\n\
|
||||
Below WebGPU baseline: {}\nWGPU_BACKEND: {}\n\
|
||||
Saved options: backend={}, compat renderer={}, OpenGL on older GPUs={}\n",
|
||||
or_unknown(gpu.adapter.as_deref().unwrap_or("")),
|
||||
or_unknown(&gpu.driver),
|
||||
or_unknown(gpu.backend.as_deref().unwrap_or("")),
|
||||
or_unknown(&gpu.origin),
|
||||
if gpu.legacy { "yes" } else { "no" },
|
||||
std::env::var("WGPU_BACKEND").unwrap_or_else(|_| "(unset)".into()),
|
||||
prefs.backend.as_str().unwrap_or("auto"),
|
||||
prefs.compat_renderer,
|
||||
prefs.legacy_gl,
|
||||
));
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Build card text: the metadata suffix without its leading `+`
|
||||
/// (`194.gef189d77`, `gef189d77.dirty`), or "Release" for a clean build on
|
||||
/// the release tag.
|
||||
@@ -137,6 +223,19 @@ pub fn view_window(
|
||||
.spacing(8)
|
||||
.width(content_width);
|
||||
|
||||
let row_width = if matches!(sizing.width, Length::Fill) {
|
||||
Fill
|
||||
} else {
|
||||
Length::Fixed(148.0 * 3.0 + 16.0)
|
||||
};
|
||||
let system = column![
|
||||
info_row(t!("CPU"), crate::sysinfo::cpu_summary(), row_width),
|
||||
info_row(t!("RAM"), crate::sysinfo::ram_summary(), row_width),
|
||||
info_row(t!("GPU (backend)"), gpu_summary(), row_width),
|
||||
]
|
||||
.spacing(6)
|
||||
.width(content_width);
|
||||
|
||||
let copy = dialog_button(t!("Copy Info"), Message::AboutCopyInfo, true);
|
||||
|
||||
container(
|
||||
@@ -144,6 +243,7 @@ pub fn view_window(
|
||||
hero,
|
||||
metadata,
|
||||
build_info,
|
||||
system,
|
||||
row![Space::new().width(content_width), copy]
|
||||
.width(sizing.width)
|
||||
.align_y(iced::Center),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(crate) mod graphics;
|
||||
pub(crate) mod spacemouse;
|
||||
use crate::app::config::UiThemeConfig;
|
||||
use crate::app::settings;
|
||||
@@ -35,6 +37,7 @@ pub enum OptionsTab {
|
||||
Modeling,
|
||||
Selection,
|
||||
UserPreferences,
|
||||
Graphics,
|
||||
}
|
||||
|
||||
/// Application preferences the dialog reads that are plain scalars on the app.
|
||||
@@ -201,6 +204,7 @@ pub fn view_window<'a>(
|
||||
selection: SelectionPrefs,
|
||||
prefs: AppPrefs,
|
||||
spacemouse: Element<'a, Message>,
|
||||
graphics: Element<'a, Message>,
|
||||
snap_angle_input: &'a str,
|
||||
zoom_factor_input: &'a str,
|
||||
drawing_prefs: DrawingPrefs,
|
||||
@@ -1675,6 +1679,7 @@ pub fn view_window<'a>(
|
||||
OptionsTab::Drafting => drafting.into(),
|
||||
OptionsTab::Modeling => modeling.into(),
|
||||
OptionsTab::UserPreferences => user_prefs.into(),
|
||||
OptionsTab::Graphics => graphics,
|
||||
};
|
||||
|
||||
// A vertical rail rather than a horizontal strip: the tab names are
|
||||
@@ -1697,7 +1702,11 @@ pub fn view_window<'a>(
|
||||
tab_button(crate::t!("3D Modeling"), OptionsTab::Modeling),
|
||||
tab_button(crate::t!("Selection"), OptionsTab::Selection),
|
||||
tab_button(crate::t!("User Preferences"), OptionsTab::UserPreferences),
|
||||
]
|
||||
];
|
||||
// The web build has no backend to choose, so it has no Graphics page.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let tabs = tabs.push(tab_button(crate::t!("Graphics"), OptionsTab::Graphics));
|
||||
let tabs = tabs
|
||||
.spacing(2)
|
||||
.width(iced::Length::Fixed(TAB_RAIL_WIDTH));
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
//! Options > Graphics: which graphics backend the next launch uses.
|
||||
//!
|
||||
//! Everything here is read before the application boots (the backend is
|
||||
//! chosen first), so changes are saved at once and apply on restart rather
|
||||
//! than going through OK / Apply.
|
||||
|
||||
use crate::app::Message;
|
||||
use crate::gpu_backend::{ActiveGpu, BackendChoice, GraphicsPrefs};
|
||||
use iced::widget::{checkbox, column, pick_list, row, text, Space};
|
||||
use iced::{Element, Fill};
|
||||
|
||||
fn current_row(label: std::borrow::Cow<'static, str>, value: String) -> Element<'static, Message> {
|
||||
row![
|
||||
text(label).size(12).width(150),
|
||||
text(value).size(12).width(Fill),
|
||||
]
|
||||
.spacing(10)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn unknown(s: &str) -> String {
|
||||
if s.is_empty() {
|
||||
crate::t!("Unknown").into_owned()
|
||||
} else {
|
||||
s.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn view(prefs: GraphicsPrefs, active: ActiveGpu) -> Element<'static, Message> {
|
||||
let backend = pick_list(
|
||||
Some(prefs.backend),
|
||||
BackendChoice::available(),
|
||||
|choice: &BackendChoice| crate::t!(choice.label()).into_owned(),
|
||||
)
|
||||
.on_select(Message::GraphicsBackendChanged)
|
||||
.width(260);
|
||||
|
||||
column![
|
||||
text(crate::t!("Graphics")).size(15),
|
||||
Space::new().height(6),
|
||||
text(crate::t!(
|
||||
"Saved immediately. Changes take effect the next time Open CAD Studio starts."
|
||||
))
|
||||
.size(11)
|
||||
.width(Fill),
|
||||
Space::new().height(16),
|
||||
text(crate::t!("This session")).size(13),
|
||||
Space::new().height(8),
|
||||
current_row(
|
||||
crate::t!("GPU"),
|
||||
unknown(active.adapter.as_deref().unwrap_or(""))
|
||||
),
|
||||
Space::new().height(4),
|
||||
current_row(crate::t!("Driver"), unknown(&active.driver)),
|
||||
Space::new().height(4),
|
||||
current_row(
|
||||
crate::t!("Backend"),
|
||||
unknown(active.backend.as_deref().unwrap_or(""))
|
||||
),
|
||||
Space::new().height(4),
|
||||
current_row(crate::t!("Selected by"), unknown(&active.origin)),
|
||||
Space::new().height(20),
|
||||
text(crate::t!("Next launch")).size(13),
|
||||
Space::new().height(8),
|
||||
row![text(crate::t!("Graphics backend")).size(12).width(150), backend]
|
||||
.spacing(10)
|
||||
.align_y(iced::Center),
|
||||
Space::new().height(12),
|
||||
row![
|
||||
checkbox(prefs.compat_renderer)
|
||||
.on_toggle(Message::GraphicsCompatToggled)
|
||||
.size(15),
|
||||
text(crate::t!(
|
||||
"Use the compatibility renderer (for GPUs without shader storage buffers)"
|
||||
))
|
||||
.size(12),
|
||||
]
|
||||
.spacing(8)
|
||||
.align_y(iced::Center),
|
||||
Space::new().height(10),
|
||||
row![
|
||||
checkbox(prefs.legacy_gl)
|
||||
.on_toggle(Message::GraphicsLegacyGlToggled)
|
||||
.size(15),
|
||||
text(crate::t!(
|
||||
"Prefer OpenGL on older GPUs (Windows, automatic backend only)"
|
||||
))
|
||||
.size(12),
|
||||
]
|
||||
.spacing(8)
|
||||
.align_y(iced::Center),
|
||||
Space::new().height(16),
|
||||
text(crate::t!(
|
||||
"If a pinned backend fails to start, the next launch falls back to automatic selection. \
|
||||
The --backend option and the WGPU_BACKEND variable override this page."
|
||||
))
|
||||
.size(11)
|
||||
.width(Fill),
|
||||
]
|
||||
.spacing(0)
|
||||
.into()
|
||||
}
|
||||
Reference in new issue
Block a user