1#[cfg(all(feature = "gpu", not(target_arch = "wasm32")))]
4use super::backends::{enumerate_wgpu_devices, query_wgpu_device_info};
5#[cfg(all(feature = "gpu", not(target_arch = "wasm32")))]
6use super::MonitorError;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20pub enum GpuVendor {
21 Nvidia,
23 Amd,
25 Intel,
27 Apple,
29 Unknown(u32),
31}
32
33impl GpuVendor {
34 #[must_use]
36 pub const fn from_vendor_id(id: u32) -> Self {
37 match id {
38 0x10de => Self::Nvidia,
39 0x1002 => Self::Amd,
40 0x8086 => Self::Intel,
41 0x106b => Self::Apple,
42 other => Self::Unknown(other),
43 }
44 }
45
46 #[must_use]
48 pub const fn name(&self) -> &'static str {
49 match self {
50 Self::Nvidia => "NVIDIA",
51 Self::Amd => "AMD",
52 Self::Intel => "Intel",
53 Self::Apple => "Apple",
54 Self::Unknown(_) => "Unknown",
55 }
56 }
57
58 #[must_use]
60 pub const fn is_nvidia(&self) -> bool {
61 matches!(self, Self::Nvidia)
62 }
63}
64
65impl std::fmt::Display for GpuVendor {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 match self {
68 Self::Unknown(id) => write!(f, "Unknown (0x{id:04x})"),
69 Self::Nvidia | Self::Amd | Self::Intel | Self::Apple => write!(f, "{}", self.name()),
70 }
71 }
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
80pub enum GpuBackend {
81 Vulkan,
83 Metal,
85 Dx12,
87 Dx11,
89 WebGpu,
91 Cuda,
93 OpenGl,
95 Cpu,
97}
98
99impl GpuBackend {
100 #[must_use]
102 pub const fn name(&self) -> &'static str {
103 match self {
104 Self::Vulkan => "Vulkan",
105 Self::Metal => "Metal",
106 Self::Dx12 => "DirectX 12",
107 Self::Dx11 => "DirectX 11",
108 Self::WebGpu => "WebGPU",
109 Self::Cuda => "CUDA",
110 Self::OpenGl => "OpenGL",
111 Self::Cpu => "CPU",
112 }
113 }
114
115 #[must_use]
117 pub const fn is_gpu(&self) -> bool {
118 !matches!(self, Self::Cpu)
119 }
120
121 #[must_use]
123 pub const fn supports_compute(&self) -> bool {
124 matches!(self, Self::Vulkan | Self::Metal | Self::Dx12 | Self::WebGpu | Self::Cuda)
125 }
126}
127
128impl std::fmt::Display for GpuBackend {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 write!(f, "{}", self.name())
131 }
132}
133
134#[derive(Debug, Clone)]
142pub struct GpuDeviceInfo {
143 pub index: u32,
145 pub name: String,
147 pub vendor: GpuVendor,
149 pub vram_total: u64,
151 pub compute_capability: Option<(u32, u32)>,
153 pub driver_version: Option<String>,
155 pub pci_bus_id: Option<String>,
157 pub backend: GpuBackend,
159}
160
161impl GpuDeviceInfo {
162 #[must_use]
164 pub fn new(
165 index: u32,
166 name: impl Into<String>,
167 vendor: GpuVendor,
168 backend: GpuBackend,
169 ) -> Self {
170 Self {
171 index,
172 name: name.into(),
173 vendor,
174 vram_total: 0,
175 compute_capability: None,
176 driver_version: None,
177 pci_bus_id: None,
178 backend,
179 }
180 }
181
182 #[must_use]
184 pub fn with_vram(mut self, bytes: u64) -> Self {
185 self.vram_total = bytes;
186 self
187 }
188
189 #[must_use]
191 pub fn with_compute_capability(mut self, major: u32, minor: u32) -> Self {
192 self.compute_capability = Some((major, minor));
193 self
194 }
195
196 #[must_use]
198 pub fn with_driver_version(mut self, version: impl Into<String>) -> Self {
199 self.driver_version = Some(version.into());
200 self
201 }
202
203 #[must_use]
205 pub fn with_pci_bus_id(mut self, bus_id: impl Into<String>) -> Self {
206 self.pci_bus_id = Some(bus_id.into());
207 self
208 }
209
210 #[cfg(all(feature = "gpu", not(target_arch = "wasm32")))]
218 pub fn query() -> Result<Self, MonitorError> {
219 query_wgpu_device_info(0)
220 }
221
222 #[cfg(all(feature = "gpu", not(target_arch = "wasm32")))]
230 pub fn query_device(index: u32) -> Result<Self, MonitorError> {
231 query_wgpu_device_info(index)
232 }
233
234 #[cfg(all(feature = "gpu", not(target_arch = "wasm32")))]
242 pub fn enumerate() -> Result<Vec<Self>, MonitorError> {
243 enumerate_wgpu_devices()
244 }
245
246 #[must_use]
248 pub fn vram_mb(&self) -> u64 {
249 self.vram_total / (1024 * 1024)
250 }
251
252 #[must_use]
254 pub fn vram_gb(&self) -> f64 {
255 self.vram_total as f64 / (1024.0 * 1024.0 * 1024.0)
256 }
257
258 #[must_use]
260 pub fn supports_cuda(&self) -> bool {
261 self.vendor.is_nvidia()
262 }
263}
264
265impl std::fmt::Display for GpuDeviceInfo {
266 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
267 write!(
268 f,
269 "[{}] {} ({}) - {:.1} GB VRAM",
270 self.index,
271 self.name,
272 self.backend,
273 self.vram_gb()
274 )
275 }
276}