nvml_wrapper/enums/
device.rs

1use std::convert::TryFrom;
2use std::fmt::Display;
3use std::os::raw::c_uint;
4
5use crate::enum_wrappers::device::{ClockLimitId, SampleValueType};
6use crate::error::NvmlError;
7use crate::ffi::bindings::*;
8#[cfg(feature = "serde")]
9use serde_derive::{Deserialize, Serialize};
10
11/// Respresents possible variants for a firmware version.
12#[derive(Debug, Clone, Eq, PartialEq, Hash)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14pub enum FirmwareVersion {
15    /// The version is unavailable.
16    Unavailable,
17    Version(u32),
18}
19
20impl From<u32> for FirmwareVersion {
21    fn from(value: u32) -> Self {
22        match value {
23            0 => FirmwareVersion::Unavailable,
24            _ => FirmwareVersion::Version(value),
25        }
26    }
27}
28
29/// Represents possible variants for used GPU memory.
30// Checked
31#[derive(Debug, Clone, Eq, PartialEq, Hash)]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33pub enum UsedGpuMemory {
34    /// Under WDDM, `NVML_VALUE_NOT_AVAILABLE` is always reported because
35    /// Windows KMD manages all the memory, not the NVIDIA driver.
36    Unavailable,
37    /// Memory used in bytes.
38    Used(u64),
39}
40
41impl From<u64> for UsedGpuMemory {
42    fn from(value: u64) -> Self {
43        let not_available = (NVML_VALUE_NOT_AVAILABLE) as u64;
44
45        match value {
46            v if v == not_available => UsedGpuMemory::Unavailable,
47            _ => UsedGpuMemory::Used(value),
48        }
49    }
50}
51
52/// Represents different types of sample values.
53// Checked against local
54#[derive(Debug, Clone, PartialEq)]
55#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
56pub enum SampleValue {
57    F64(f64),
58    U32(u32),
59    U64(u64),
60    I64(i64),
61}
62
63impl SampleValue {
64    pub fn from_tag_and_union(tag: &SampleValueType, union: nvmlValue_t) -> Self {
65        use self::SampleValueType::*;
66
67        unsafe {
68            match *tag {
69                Double => SampleValue::F64(union.dVal),
70                UnsignedInt => SampleValue::U32(union.uiVal),
71                // Methodology: NVML supports 32-bit Linux. UL is u32 on that platform.
72                // NVML wouldn't return anything larger
73                #[allow(clippy::unnecessary_cast)]
74                UnsignedLong => SampleValue::U32(union.ulVal as u32),
75                UnsignedLongLong => SampleValue::U64(union.ullVal),
76                SignedLongLong => SampleValue::I64(union.sllVal),
77            }
78        }
79    }
80}
81
82/// Represents different types of sample values.
83#[derive(Debug, Clone, Eq, PartialEq, Hash)]
84#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
85pub enum GpuLockedClocksSetting {
86    /// Numeric setting that allows you to explicitly define minimum and
87    /// maximum clock frequencies.
88    Numeric {
89        min_clock_mhz: u32,
90        max_clock_mhz: u32,
91    },
92    /// Symbolic setting that allows you to define lower and upper bounds for
93    /// clock speed with various possibilities.
94    ///
95    /// Not all combinations of `lower_bound` and `upper_bound` are valid.
96    /// Please see the docs for `nvmlDeviceSetGpuLockedClocks` in `nvml.h` to
97    /// learn more.
98    Symbolic {
99        lower_bound: ClockLimitId,
100        upper_bound: ClockLimitId,
101    },
102}
103
104impl GpuLockedClocksSetting {
105    /// Returns `(min_clock_mhz, max_clock_mhz)`.
106    pub fn into_min_and_max_clocks(self) -> (u32, u32) {
107        match self {
108            GpuLockedClocksSetting::Numeric {
109                min_clock_mhz,
110                max_clock_mhz,
111            } => (min_clock_mhz, max_clock_mhz),
112            GpuLockedClocksSetting::Symbolic {
113                lower_bound,
114                upper_bound,
115            } => (lower_bound.as_c(), upper_bound.as_c()),
116        }
117    }
118}
119
120/// Returned by [`crate::Device::bus_type()`].
121// TODO: technically this is an "enum wrapper" but the type on the C side isn't
122// an enum
123#[derive(Debug, Clone, Eq, PartialEq, Hash)]
124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
125pub enum BusType {
126    /// Unknown bus type.
127    Unknown,
128    /// PCI (Peripheral Component Interconnect) bus type.
129    Pci,
130    /// PCIE (Peripheral Component Interconnect Express) bus type.
131    ///
132    /// This is the most common bus type.
133    Pcie,
134    /// FPCI (Fast Peripheral Component Interconnect) bus type.
135    Fpci,
136    /// AGP (Accelerated Graphics Port) bus type.
137    ///
138    /// This is old and was dropped in favor of PCIE.
139    Agp,
140}
141
142impl BusType {
143    /// Returns the C constant equivalent for the given Rust enum variant.
144    pub fn as_c(&self) -> nvmlBusType_t {
145        match *self {
146            Self::Unknown => NVML_BUS_TYPE_UNKNOWN,
147            Self::Pci => NVML_BUS_TYPE_PCI,
148            Self::Pcie => NVML_BUS_TYPE_PCIE,
149            Self::Fpci => NVML_BUS_TYPE_FPCI,
150            Self::Agp => NVML_BUS_TYPE_AGP,
151        }
152    }
153}
154
155impl TryFrom<nvmlBusType_t> for BusType {
156    type Error = NvmlError;
157
158    fn try_from(data: nvmlBusType_t) -> Result<Self, Self::Error> {
159        match data {
160            NVML_BUS_TYPE_UNKNOWN => Ok(Self::Unknown),
161            NVML_BUS_TYPE_PCI => Ok(Self::Pci),
162            NVML_BUS_TYPE_PCIE => Ok(Self::Pcie),
163            NVML_BUS_TYPE_FPCI => Ok(Self::Fpci),
164            NVML_BUS_TYPE_AGP => Ok(Self::Agp),
165            _ => Err(NvmlError::UnexpectedVariant(data)),
166        }
167    }
168}
169
170/// Returned by [`crate::Device::power_source()`].
171// TODO: technically this is an "enum wrapper" but the type on the C side isn't
172// an enum
173#[derive(Debug, Clone, Eq, PartialEq, Hash)]
174#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
175pub enum PowerSource {
176    /// AC power (receiving power from some external source).
177    Ac,
178    /// Battery power.
179    Battery,
180}
181
182impl PowerSource {
183    /// Returns the C constant equivalent for the given Rust enum variant.
184    pub fn as_c(&self) -> nvmlPowerSource_t {
185        match *self {
186            Self::Ac => NVML_POWER_SOURCE_AC,
187            Self::Battery => NVML_POWER_SOURCE_BATTERY,
188        }
189    }
190}
191
192impl TryFrom<nvmlPowerSource_t> for PowerSource {
193    type Error = NvmlError;
194
195    fn try_from(data: nvmlPowerSource_t) -> Result<Self, Self::Error> {
196        match data {
197            NVML_POWER_SOURCE_AC => Ok(Self::Ac),
198            NVML_POWER_SOURCE_BATTERY => Ok(Self::Battery),
199            _ => Err(NvmlError::UnexpectedVariant(data)),
200        }
201    }
202}
203
204/// Returned by [`crate::Device::architecture()`].
205///
206/// This is the simplified chip architecture of the device.
207// TODO: technically this is an "enum wrapper" but the type on the C side isn't
208// an enum
209#[derive(Debug, Clone, Eq, PartialEq, Hash)]
210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
211pub enum DeviceArchitecture {
212    /// <https://en.wikipedia.org/wiki/Kepler_(microarchitecture)>
213    Kepler,
214    /// <https://en.wikipedia.org/wiki/Maxwell_(microarchitecture)>
215    Maxwell,
216    /// <https://en.wikipedia.org/wiki/Pascal_(microarchitecture)>
217    Pascal,
218    /// <https://en.wikipedia.org/wiki/Volta_(microarchitecture)>
219    Volta,
220    /// <https://en.wikipedia.org/wiki/Turing_(microarchitecture)>
221    Turing,
222    /// <https://en.wikipedia.org/wiki/Ampere_(microarchitecture)>
223    Ampere,
224    /// <https://en.wikipedia.org/wiki/Ada_Lovelace_(microarchitecture)>
225    Ada,
226    /// <https://en.wikipedia.org/wiki/Hopper_(microarchitecture)>
227    Hopper,
228    /// Unknown device architecture (most likely something newer).
229    Unknown,
230}
231
232impl DeviceArchitecture {
233    /// Returns the C constant equivalent for the given Rust enum variant.
234    pub fn as_c(&self) -> nvmlDeviceArchitecture_t {
235        match *self {
236            Self::Kepler => NVML_DEVICE_ARCH_KEPLER,
237            Self::Maxwell => NVML_DEVICE_ARCH_MAXWELL,
238            Self::Pascal => NVML_DEVICE_ARCH_PASCAL,
239            Self::Volta => NVML_DEVICE_ARCH_VOLTA,
240            Self::Turing => NVML_DEVICE_ARCH_TURING,
241            Self::Ampere => NVML_DEVICE_ARCH_AMPERE,
242            Self::Ada => NVML_DEVICE_ARCH_ADA,
243            Self::Hopper => NVML_DEVICE_ARCH_HOPPER,
244            Self::Unknown => NVML_DEVICE_ARCH_UNKNOWN,
245        }
246    }
247}
248
249impl TryFrom<nvmlDeviceArchitecture_t> for DeviceArchitecture {
250    type Error = NvmlError;
251
252    fn try_from(data: nvmlDeviceArchitecture_t) -> Result<Self, Self::Error> {
253        match data {
254            NVML_DEVICE_ARCH_KEPLER => Ok(Self::Kepler),
255            NVML_DEVICE_ARCH_MAXWELL => Ok(Self::Maxwell),
256            NVML_DEVICE_ARCH_PASCAL => Ok(Self::Pascal),
257            NVML_DEVICE_ARCH_VOLTA => Ok(Self::Volta),
258            NVML_DEVICE_ARCH_TURING => Ok(Self::Turing),
259            NVML_DEVICE_ARCH_AMPERE => Ok(Self::Ampere),
260            NVML_DEVICE_ARCH_ADA => Ok(Self::Ada),
261            NVML_DEVICE_ARCH_HOPPER => Ok(Self::Hopper),
262            NVML_DEVICE_ARCH_UNKNOWN => Ok(Self::Unknown),
263            _ => Err(NvmlError::UnexpectedVariant(data)),
264        }
265    }
266}
267
268impl Display for DeviceArchitecture {
269    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
270        match self {
271            Self::Kepler => f.write_str("Kepler"),
272            Self::Maxwell => f.write_str("Maxwell"),
273            Self::Pascal => f.write_str("Pascal"),
274            Self::Volta => f.write_str("Volta"),
275            Self::Turing => f.write_str("Turing"),
276            Self::Ampere => f.write_str("Ampere"),
277            Self::Ada => f.write_str("Ada"),
278            Self::Hopper => f.write_str("Hopper"),
279            Self::Unknown => f.write_str("Unknown"),
280        }
281    }
282}
283
284/// Returned by [`crate::Device::max_pcie_link_speed()`].
285///
286/// Note, the NVML header says these are all MBPS (Megabytes Per Second) but
287/// they don't line up with the throughput numbers on this page:
288/// <https://en.wikipedia.org/wiki/PCI_Express>
289///
290/// They _do_ line up with the "transfer rate per lane" numbers, though. This
291/// would mean they represent transfer speeds rather than throughput, in MT/s.
292///
293/// See also the discussion on [`crate::Device::pcie_link_speed()`].
294// TODO: technically this is an "enum wrapper" but the type on the C side isn't
295// an enum
296#[derive(Debug, Clone, Eq, PartialEq, Hash)]
297#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
298pub enum PcieLinkMaxSpeed {
299    Invalid,
300    MegaTransfersPerSecond2500,
301    MegaTransfersPerSecond5000,
302    MegaTransfersPerSecond8000,
303    MegaTransfersPerSecond16000,
304    MegaTransfersPerSecond32000,
305}
306
307impl PcieLinkMaxSpeed {
308    /// Returns the numerical equivalent for the given enum variant, if valid.
309    pub fn as_integer(&self) -> Option<u32> {
310        Some(match self {
311            PcieLinkMaxSpeed::Invalid => return None,
312            PcieLinkMaxSpeed::MegaTransfersPerSecond2500 => 2500,
313            PcieLinkMaxSpeed::MegaTransfersPerSecond5000 => 5000,
314            PcieLinkMaxSpeed::MegaTransfersPerSecond8000 => 8000,
315            PcieLinkMaxSpeed::MegaTransfersPerSecond16000 => 16000,
316            PcieLinkMaxSpeed::MegaTransfersPerSecond32000 => 32000,
317        })
318    }
319
320    /// Returns the C constant equivalent for the given Rust enum variant.
321    pub fn as_c(&self) -> c_uint {
322        match *self {
323            Self::Invalid => NVML_PCIE_LINK_MAX_SPEED_INVALID,
324            Self::MegaTransfersPerSecond2500 => NVML_PCIE_LINK_MAX_SPEED_2500MBPS,
325            Self::MegaTransfersPerSecond5000 => NVML_PCIE_LINK_MAX_SPEED_5000MBPS,
326            Self::MegaTransfersPerSecond8000 => NVML_PCIE_LINK_MAX_SPEED_8000MBPS,
327            Self::MegaTransfersPerSecond16000 => NVML_PCIE_LINK_MAX_SPEED_16000MBPS,
328            Self::MegaTransfersPerSecond32000 => NVML_PCIE_LINK_MAX_SPEED_32000MBPS,
329        }
330    }
331}
332
333impl TryFrom<c_uint> for PcieLinkMaxSpeed {
334    type Error = NvmlError;
335
336    fn try_from(data: c_uint) -> Result<Self, Self::Error> {
337        match data {
338            NVML_PCIE_LINK_MAX_SPEED_INVALID => Ok(Self::Invalid),
339            NVML_PCIE_LINK_MAX_SPEED_2500MBPS => Ok(Self::MegaTransfersPerSecond2500),
340            NVML_PCIE_LINK_MAX_SPEED_5000MBPS => Ok(Self::MegaTransfersPerSecond5000),
341            NVML_PCIE_LINK_MAX_SPEED_8000MBPS => Ok(Self::MegaTransfersPerSecond8000),
342            NVML_PCIE_LINK_MAX_SPEED_16000MBPS => Ok(Self::MegaTransfersPerSecond16000),
343            NVML_PCIE_LINK_MAX_SPEED_32000MBPS => Ok(Self::MegaTransfersPerSecond32000),
344            _ => Err(NvmlError::UnexpectedVariant(data)),
345        }
346    }
347}