Skip to main content

nuvec_gpu/
info.rs

1//! Device facts.
2
3/// What the GPU is and what it can do.
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct DeviceInfo {
6    /// Marketing name, e.g. `Apple M4 Pro`.
7    pub name: String,
8    /// Metal's architecture string, e.g. `applegpu_g16s`.
9    pub architecture: String,
10    /// GPU generation parsed from the architecture string (16 for `applegpu_g16s`), if any.
11    /// Neural-accelerator kernels need generation 17 or later.
12    pub generation: Option<u32>,
13    /// Class letter after the generation (`s` for `applegpu_g16s`), if any. Kept verbatim:
14    /// the letter-to-tier mapping is not documented by Apple.
15    pub class: Option<char>,
16    /// Bytes the GPU can use without hurting performance.
17    pub recommended_working_set: u64,
18    /// Maximum threads per threadgroup along one dimension.
19    pub max_threads_per_threadgroup: usize,
20}
21
22/// Generation and class letter of an `applegpu_g<NN><class>` architecture string.
23#[cfg_attr(not(target_os = "macos"), allow(dead_code))]
24pub(crate) fn parse_architecture(arch: &str) -> (Option<u32>, Option<char>) {
25    let Some(rest) = arch.strip_prefix("applegpu_g") else {
26        return (None, None);
27    };
28    let digits = rest.chars().take_while(char::is_ascii_digit).count();
29    let generation = rest[..digits].parse().ok();
30    let class = rest[digits..]
31        .chars()
32        .next()
33        .filter(char::is_ascii_lowercase);
34    (generation, class)
35}
36
37#[cfg(test)]
38mod tests {
39    use super::parse_architecture;
40
41    #[test]
42    fn parses_apple_gpu_architectures() {
43        assert_eq!(parse_architecture("applegpu_g16s"), (Some(16), Some('s')));
44        assert_eq!(parse_architecture("applegpu_g17p"), (Some(17), Some('p')));
45        assert_eq!(parse_architecture("applegpu_g13"), (Some(13), None));
46        assert_eq!(parse_architecture("Paravirtual"), (None, None));
47    }
48}