#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
pub fn intel_gpu_marketing_name(device_id: u32) -> String {
let id = device_id & 0xFFFF;
match id {
0x5690..=0x5692 => "Intel Arc A770M / A730M / A550M".to_string(),
0x5693..=0x5695 => "Intel Arc A370M / A350M".to_string(),
0x56A0 | 0x56A1 => "Intel Arc A770".to_string(),
0x56A2 => "Intel Arc A750".to_string(),
0x56A3 | 0x56A4 => "Intel Arc A580".to_string(),
0x56A5 | 0x56A6 => "Intel Arc A380 / A310".to_string(),
0x56B0..=0x56B3 => "Intel Arc Pro A-series".to_string(),
0x56BA..=0x56BD => "Intel Arc A-series (mobile)".to_string(),
0xE202 | 0xE20B | 0xE20C | 0xE20D | 0xE210 | 0xE211 | 0xE212 | 0xE215 | 0xE216 => {
"Intel Arc B-series (Battlemage)".to_string()
}
0x7D40 | 0x7D41 | 0x7D45 | 0x7D55 | 0x7DD5 => {
"Intel Arc Graphics (Core Ultra / Meteor Lake)".to_string()
}
0x7D50 | 0x7D51 | 0x7D60 => "Intel Graphics (Core Ultra / Meteor Lake)".to_string(),
0x9A40 | 0x9A49 | 0x9A60 | 0x9A68 | 0x9A70 | 0x9A78 | 0x9AC0 | 0x9AC9 | 0x9AD9 | 0x9AF8 => {
"Intel Iris Xe Graphics (Tiger Lake)".to_string()
}
0x4680 | 0x4682 | 0x4688 | 0x468A | 0x468B | 0x4690 | 0x4692 | 0x4693 | 0x46A0 | 0x46A3
| 0x46A6 | 0x46A8 | 0x46AA | 0x46B0 | 0x46B3 | 0x46C0 | 0x46C3 | 0x46D0 | 0x46D1
| 0x46D2 | 0x46D3 | 0x46D4 => {
"Intel UHD / Iris Xe Graphics (Alder/Raptor Lake)".to_string()
}
0x4C8A | 0x4C8B | 0x4C8C | 0x4C90 | 0x4C9A => {
"Intel UHD Graphics (Rocket Lake)".to_string()
}
0x8A50 | 0x8A51 | 0x8A52 | 0x8A53 | 0x8A56 | 0x8A57 | 0x8A58 | 0x8A59 | 0x8A5A | 0x8A5B
| 0x8A5C | 0x8A5D | 0x8A71 => "Intel Iris Plus / UHD Graphics (Ice Lake)".to_string(),
0xA780 | 0xA781 | 0xA782 | 0xA783 | 0xA788 | 0xA789 | 0xA78A | 0xA78B | 0xA7A0 | 0xA7A1
| 0xA7A8 | 0xA7A9 | 0xA7AA | 0xA7AB | 0xA7AC | 0xA7AD => {
"Intel Graphics (Arrow/Lunar Lake)".to_string()
}
_ => String::new(),
}
}
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
pub fn resolve_intel_gpu_name(device_id: u32) -> String {
let curated = intel_gpu_marketing_name(device_id);
if curated.is_empty() {
format!("Intel Graphics (device {:#06x})", device_id & 0xFFFF)
} else {
curated
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IntelArchitecture {
Alchemist,
Battlemage,
XeLpg,
XeLpgPlus,
IrisXe,
OlderIntegrated,
Unknown,
}
impl IntelArchitecture {
pub fn is_sycl_capable(self) -> bool {
matches!(
self,
Self::Alchemist | Self::Battlemage | Self::XeLpg | Self::XeLpgPlus | Self::IrisXe,
)
}
pub fn label(self) -> &'static str {
match self {
Self::Alchemist => "Alchemist (Xe-HPG, A-series)",
Self::Battlemage => "Battlemage (Xe2, B-series)",
Self::XeLpg => "Xe-LPG (Meteor Lake)",
Self::XeLpgPlus => "Xe-LPG+ (Lunar Lake)",
Self::IrisXe => "Iris Xe (Tiger/Alder/Raptor Lake)",
Self::OlderIntegrated => "Pre-Xe (HD/UHD Graphics)",
Self::Unknown => "Unknown",
}
}
pub fn sycl_capable_label(self) -> &'static str {
match self {
Self::Unknown => "Unknown",
_ if self.is_sycl_capable() => "Yes",
_ => "No",
}
}
}
pub fn classify_intel_architecture(name: &str) -> IntelArchitecture {
let n = name.to_lowercase();
if (n.contains("hd graphics") || n.contains("uhd graphics"))
&& !n.contains("iris")
&& !n.contains("arc")
&& !n.contains("xe")
{
return IntelArchitecture::OlderIntegrated;
}
if n.contains("battlemage")
|| (n.contains("arc") && (n.contains("b580") || n.contains("b570") || n.contains("b380")))
{
return IntelArchitecture::Battlemage;
}
if n.contains("arc") && (n.contains("a3") || n.contains("a5") || n.contains("a7")) {
return IntelArchitecture::Alchemist;
}
if n.contains("lunarlake")
|| n.contains("lunar lake")
|| (n.contains("arc") && (n.contains("140v") || n.contains("130v")))
{
return IntelArchitecture::XeLpgPlus;
}
if (n.contains("xe") && n.contains("lpg")) || (n.contains("arc") && n.contains("graphics")) {
return IntelArchitecture::XeLpg;
}
if n.contains("iris") && n.contains("xe") {
return IntelArchitecture::IrisXe;
}
IntelArchitecture::Unknown
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn known_families_resolve() {
assert!(intel_gpu_marketing_name(0x56A0).contains("Arc A770"));
assert!(intel_gpu_marketing_name(0x56A2).contains("Arc A750"));
assert!(intel_gpu_marketing_name(0xE20B).contains("Battlemage"));
assert!(intel_gpu_marketing_name(0x7D40).contains("Meteor Lake"));
assert!(intel_gpu_marketing_name(0x9A49).contains("Tiger Lake"));
assert!(intel_gpu_marketing_name(0x46A6).contains("Alder/Raptor Lake"));
assert!(intel_gpu_marketing_name(0x4C8A).contains("Rocket Lake"));
assert!(intel_gpu_marketing_name(0x8A50).contains("Ice Lake"));
assert!(intel_gpu_marketing_name(0xA780).contains("Arrow/Lunar Lake"));
}
#[test]
fn unknown_falls_back_to_generic() {
let n = resolve_intel_gpu_name(0x1234);
assert!(n.starts_with("Intel Graphics (device"));
assert!(n.contains("0x1234"));
}
#[test]
fn high_bits_ignored() {
assert!(resolve_intel_gpu_name(0x0000_56A0).contains("Arc A770"));
assert!(resolve_intel_gpu_name(0xFFFF_56A0).contains("Arc A770"));
}
#[test]
fn classifies_arc_a_series_as_alchemist() {
for name in &[
"Intel Arc A770 Graphics",
"Intel Arc A750",
"Intel Arc A580",
"Intel Arc A380",
"Intel Arc A310",
"Intel(R) Arc(TM) A770 Graphics",
] {
assert_eq!(
classify_intel_architecture(name),
IntelArchitecture::Alchemist,
"mis-classified: {name}"
);
assert!(IntelArchitecture::Alchemist.is_sycl_capable());
}
}
#[test]
fn classifies_battlemage_b_series() {
for name in &[
"Intel Battlemage Graphics",
"Intel(R) Battlemage(TM) Graphics",
"Intel Arc B580",
"Intel(R) Arc(TM) B580 Graphics",
] {
assert_eq!(
classify_intel_architecture(name),
IntelArchitecture::Battlemage,
"mis-classified: {name}"
);
assert!(IntelArchitecture::Battlemage.is_sycl_capable());
}
}
#[test]
fn classifies_core_ultra_integrated_arc_as_xe_lpg() {
assert_eq!(
classify_intel_architecture("Intel Arc Graphics"),
IntelArchitecture::XeLpg,
);
assert_eq!(
classify_intel_architecture("Intel(R) Arc(TM) Graphics"),
IntelArchitecture::XeLpg,
);
assert!(IntelArchitecture::XeLpg.is_sycl_capable());
}
#[test]
fn classifies_lunar_lake_arc_140v() {
let result = classify_intel_architecture("Intel Arc 140V Graphics");
assert!(
matches!(
result,
IntelArchitecture::XeLpgPlus | IntelArchitecture::XeLpg
),
"Arc 140V should classify as a Lunar Lake / Xe-LPG-family part, got {result:?}",
);
assert!(result.is_sycl_capable());
let result_130v = classify_intel_architecture("Intel Arc 130V Graphics");
assert!(
matches!(
result_130v,
IntelArchitecture::XeLpgPlus | IntelArchitecture::XeLpg
),
"Arc 130V should classify as a Lunar Lake / Xe-LPG-family part, got {result_130v:?}",
);
}
#[test]
fn classifies_iris_xe_as_iris_xe() {
for name in &["Intel Iris Xe Graphics", "Intel(R) Iris(R) Xe Graphics"] {
assert_eq!(
classify_intel_architecture(name),
IntelArchitecture::IrisXe,
"mis-classified: {name}"
);
assert!(IntelArchitecture::IrisXe.is_sycl_capable());
}
}
#[test]
fn classifies_xe_lpg_meteor_lake() {
assert_eq!(
classify_intel_architecture("Intel Xe-LPG Graphics"),
IntelArchitecture::XeLpg,
);
}
#[test]
fn classifies_lunar_lake_explicit() {
for name in &[
"Intel LunarLake Graphics",
"Intel(R) LunarLake(TM) Graphics",
"Intel Lunar Lake Graphics",
] {
assert_eq!(
classify_intel_architecture(name),
IntelArchitecture::XeLpgPlus,
"mis-classified: {name}"
);
assert!(IntelArchitecture::XeLpgPlus.is_sycl_capable());
}
}
#[test]
fn older_integrated_is_not_sycl_capable() {
for name in &[
"Intel HD Graphics 630",
"Intel UHD Graphics 770",
"Intel HD Graphics 520",
"Intel UHD Graphics 620",
] {
let arch = classify_intel_architecture(name);
assert_eq!(
arch,
IntelArchitecture::OlderIntegrated,
"mis-classified: {name}"
);
assert!(!arch.is_sycl_capable(), "{name} should not be SYCL capable");
}
}
#[test]
fn unknown_names_classified_as_unknown() {
let arch = classify_intel_architecture("Definitely Not An Intel GPU");
assert_eq!(arch, IntelArchitecture::Unknown);
assert!(!arch.is_sycl_capable());
assert_eq!(classify_intel_architecture(""), IntelArchitecture::Unknown);
}
#[test]
fn architecture_labels_are_stable() {
assert_eq!(
IntelArchitecture::Alchemist.label(),
"Alchemist (Xe-HPG, A-series)"
);
assert_eq!(
IntelArchitecture::Battlemage.label(),
"Battlemage (Xe2, B-series)"
);
assert_eq!(IntelArchitecture::XeLpg.label(), "Xe-LPG (Meteor Lake)");
assert_eq!(IntelArchitecture::XeLpgPlus.label(), "Xe-LPG+ (Lunar Lake)");
assert_eq!(
IntelArchitecture::IrisXe.label(),
"Iris Xe (Tiger/Alder/Raptor Lake)"
);
assert_eq!(
IntelArchitecture::OlderIntegrated.label(),
"Pre-Xe (HD/UHD Graphics)"
);
assert_eq!(IntelArchitecture::Unknown.label(), "Unknown");
}
#[test]
fn sycl_capability_matches_backend_ai_go() {
assert!(IntelArchitecture::Alchemist.is_sycl_capable());
assert!(IntelArchitecture::Battlemage.is_sycl_capable());
assert!(IntelArchitecture::XeLpg.is_sycl_capable());
assert!(IntelArchitecture::XeLpgPlus.is_sycl_capable());
assert!(IntelArchitecture::IrisXe.is_sycl_capable());
assert!(!IntelArchitecture::OlderIntegrated.is_sycl_capable());
assert!(!IntelArchitecture::Unknown.is_sycl_capable());
}
#[test]
fn sycl_capable_label_distinguishes_unknown_from_no() {
assert_eq!(IntelArchitecture::Alchemist.sycl_capable_label(), "Yes");
assert_eq!(IntelArchitecture::Battlemage.sycl_capable_label(), "Yes");
assert_eq!(IntelArchitecture::XeLpg.sycl_capable_label(), "Yes");
assert_eq!(IntelArchitecture::XeLpgPlus.sycl_capable_label(), "Yes");
assert_eq!(IntelArchitecture::IrisXe.sycl_capable_label(), "Yes");
assert_eq!(
IntelArchitecture::OlderIntegrated.sycl_capable_label(),
"No"
);
assert_eq!(IntelArchitecture::Unknown.sycl_capable_label(), "Unknown");
}
}