use eframe::egui_wgpu::RenderState;
#[derive(Debug, Clone, PartialEq)]
pub struct Diagnostics {
renderer: String,
backend: String,
adapter: String,
device_type: String,
driver: String,
max_texture_dimension_2d: u32,
version: &'static str,
platform: String,
}
impl Diagnostics {
pub fn from_render_state(render_state: &RenderState) -> Self {
let info = render_state.adapter.get_info();
let limits = render_state.adapter.limits();
Self {
renderer: renderer_name(info.backend).to_string(),
backend: format!("{:?}", info.backend),
adapter: info.name.clone(),
device_type: format!("{:?}", info.device_type),
driver: match (info.driver.trim(), info.driver_info.trim()) {
("", "") => String::new(),
("", detail) => detail.to_string(),
(name, "") => name.to_string(),
(name, detail) => format!("{name} {detail}"),
},
max_texture_dimension_2d: limits.max_texture_dimension_2d,
version: env!("CARGO_PKG_VERSION"),
platform: platform(),
}
}
pub fn rows(&self) -> Vec<(&'static str, String)> {
let rows = [
("Renderer", self.renderer.clone()),
("wgpu backend", self.backend.clone()),
("Adapter", self.adapter.clone()),
("Device type", self.device_type.clone()),
("Driver", self.driver.clone()),
("Max texture size", format!("{} px", self.max_texture_dimension_2d)),
("App version", self.version.to_string()),
("Platform", self.platform.clone()),
];
rows.into_iter().filter(|(_, value)| !value.is_empty()).collect()
}
pub fn report_text(&self) -> String {
let mut text = String::from("--- diagnostics ---");
for (label, value) in self.rows() {
text.push_str(&format!("\n{label}: {value}"));
}
text
}
pub fn json(&self) -> serde_json::Value {
serde_json::Value::Object(
self.rows()
.into_iter()
.map(|(label, value)| (label.to_string(), serde_json::Value::String(value)))
.collect(),
)
}
pub fn renderer(&self) -> &str {
&self.renderer
}
pub fn adapter_line(&self) -> String {
format!("{} ({}, {})", self.adapter, self.backend, self.device_type)
}
}
fn renderer_name(backend: wgpu::Backend) -> &'static str {
match backend {
wgpu::Backend::BrowserWebGpu => "WebGPU",
wgpu::Backend::Gl if cfg!(target_arch = "wasm32") => "WebGL2",
wgpu::Backend::Gl => "OpenGL",
wgpu::Backend::Vulkan => "Vulkan",
wgpu::Backend::Metal => "Metal",
wgpu::Backend::Dx12 => "Direct3D 12",
wgpu::Backend::Noop => "none (no-op device)",
}
}
fn platform() -> String {
#[cfg(target_arch = "wasm32")]
{
"wasm32 (browser)".to_string()
}
#[cfg(not(target_arch = "wasm32"))]
{
format!("native {}/{}", std::env::consts::OS, std::env::consts::ARCH)
}
}