dspk_app_core/data/
device.rs1use dspk_core::ComputeTarget;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct DeviceInfo {
11 pub label: String,
13 pub adapters: Vec<String>,
15}
16
17impl DeviceInfo {
18 pub fn discover() -> DeviceInfo {
20 match ComputeTarget::from_env() {
21 Ok(ComputeTarget::Wgpu) => wgpu_device(),
22 Ok(ComputeTarget::Cuda) => DeviceInfo { label: "GPU · CUDA".into(), adapters: Vec::new() },
23 Ok(ComputeTarget::Hip) => DeviceInfo { label: "GPU · ROCm".into(), adapters: Vec::new() },
24 Ok(ComputeTarget::Cpu) => DeviceInfo { label: "CPU".into(), adapters: Vec::new() },
25 Err(e) => DeviceInfo { label: format!("No compute device: {e}"), adapters: Vec::new() },
26 }
27 }
28}
29
30#[cfg(feature = "wgpu")]
31fn wgpu_device() -> DeviceInfo {
32 use wgpu::DeviceType as T;
33 let found = tokio::runtime::Builder::new_current_thread().build().map(|rt| rt.block_on(wgpu::Instance::default().enumerate_adapters(wgpu::Backends::all())));
34 let infos: Vec<wgpu::AdapterInfo> = found.map(|list| list.iter().map(|a| a.get_info()).collect()).unwrap_or_default();
35 let rank = |t: T| match t {
36 T::DiscreteGpu => 0,
37 T::IntegratedGpu => 1,
38 T::VirtualGpu => 2,
39 T::Other => 3,
40 T::Cpu => 4,
41 };
42 let kind = |t: T| match t {
43 T::DiscreteGpu => "discrete",
44 T::IntegratedGpu => "integrated",
45 T::VirtualGpu => "virtual",
46 T::Other => "other",
47 T::Cpu => "software",
48 };
49 let adapters = infos.iter().map(|i| format!("{} ({}, {:?})", i.name, kind(i.device_type), i.backend)).collect();
50 let label = match infos.iter().min_by_key(|i| rank(i.device_type)) {
51 Some(i) if i.device_type == T::Cpu => format!("GPU · {:?} · {} (software)", i.backend, i.name),
52 Some(i) => format!("GPU · {:?} · {}", i.backend, i.name),
53 None => "GPU · Vulkan / Metal (no adapter found)".to_string(),
54 };
55 DeviceInfo { label, adapters }
56}
57
58#[cfg(not(feature = "wgpu"))]
59fn wgpu_device() -> DeviceInfo {
60 DeviceInfo { label: "GPU · wgpu (not compiled in)".into(), adapters: Vec::new() }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
69 fn the_device_is_named() {
70 let d = DeviceInfo::discover();
71 eprintln!("compute device: {} · adapters: {:?}", d.label, d.adapters);
72 assert!(!d.label.is_empty());
73 if ComputeTarget::from_env().ok() == Some(ComputeTarget::Wgpu) {
74 assert!(d.label.starts_with("GPU · "), "{}", d.label);
75 }
76 }
77}