#[derive(Debug, Clone)]
pub struct HostInfo {
pub os: &'static str,
pub arch: &'static str,
pub logical_cpus: Option<usize>,
pub worker_threads: Option<usize>,
}
impl HostInfo {
pub fn collect() -> Self {
Self {
os: os_name(std::env::consts::OS),
arch: std::env::consts::ARCH,
logical_cpus: logical_cpus(),
worker_threads: Some(rayon::current_num_threads()),
}
}
}
fn os_name(os: &'static str) -> &'static str {
if os.is_empty() { "browser" } else { os }
}
#[cfg(not(target_arch = "wasm32"))]
fn logical_cpus() -> Option<usize> {
std::thread::available_parallelism()
.ok()
.map(std::num::NonZeroUsize::get)
}
#[cfg(target_arch = "wasm32")]
fn logical_cpus() -> Option<usize> {
let cores = web_sys::window()?.navigator().hardware_concurrency();
(cores >= 1.0).then_some(cores as usize)
}
#[derive(Debug, Clone)]
pub struct RuntimeInfo {
pub host: HostInfo,
pub adapter: wgpu::AdapterInfo,
pub granted: wgpu::Limits,
pub available: wgpu::Limits,
pub timestamp_query: bool,
pub vertex_storage: bool,
}
impl RuntimeInfo {
pub fn collect(adapter: &wgpu::Adapter, device: &wgpu::Device) -> Self {
Self {
host: HostInfo::collect(),
adapter: adapter.get_info(),
granted: device.limits(),
available: adapter.limits(),
timestamp_query: device.features().contains(wgpu::Features::TIMESTAMP_QUERY),
vertex_storage: adapter
.get_downlevel_capabilities()
.flags
.contains(wgpu::DownlevelFlags::VERTEX_STORAGE),
}
}
pub fn display_cap(&self) -> u32 {
crate::display_scale::MAX_DISPLAY_DIM.min(self.granted.max_texture_dimension_2d)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum GpuVerdict {
Capable,
Uncertain,
Absent,
}
pub fn supports_compute(info: &wgpu::AdapterInfo) -> bool {
info.backend != wgpu::Backend::Gl
}
pub fn classify_adapter(info: &wgpu::AdapterInfo) -> GpuVerdict {
if info.device_type == wgpu::DeviceType::Cpu {
GpuVerdict::Absent
} else if info.device_type == wgpu::DeviceType::DiscreteGpu {
GpuVerdict::Capable
} else {
GpuVerdict::Uncertain
}
}
#[cfg(test)]
mod tests {
use super::{HostInfo, os_name};
#[test]
fn an_unnamed_os_reads_as_browser() {
assert_eq!(os_name(""), "browser");
assert_eq!(os_name("macos"), "macos");
assert!(!HostInfo::collect().os.is_empty());
}
}