use super::types::{GpuDevice, GpuVendor};
pub(super) fn detect_intel() -> Vec<GpuDevice> {
#[cfg(windows)]
{
return super::detect_windows_vendor(GpuVendor::Intel, 0x8086);
}
#[cfg(target_os = "linux")]
{
if let Ok(entries) = std::fs::read_dir("/sys/bus/pci/devices") {
let mut idx = 0u32;
return entries
.filter_map(|e| e.ok())
.filter_map(|entry| {
let vendor_path = entry.path().join("vendor");
let class_path = entry.path().join("class");
let device_path = entry.path().join("device");
let vendor = std::fs::read_to_string(&vendor_path).ok()?;
let class = std::fs::read_to_string(&class_path).ok()?;
if vendor.trim() == "0x8086" && class.trim().starts_with("0x0300") {
let device_id_str = std::fs::read_to_string(&device_path)
.ok()
.map(|s| s.trim().to_string())
.unwrap_or_default();
let name = intel_label_from_device_id(&device_id_str);
let pci_id = if device_id_str.starts_with("0x") {
format!("0x8086:{device_id_str}")
} else {
String::new()
};
let live_vram = super::sysfs::read_drm_vram_mib(&entry.path());
let vram_mib = if live_vram > 0 {
live_vram
} else {
intel_vram_mib_from_device_id(&device_id_str)
.map(u64::from)
.unwrap_or(0)
};
let generation = intel_generation_from_device_id(&device_id_str);
let host_pci_address =
super::sysfs::host_pci_address_from_sysfs(&entry.path());
let serial = super::sysfs::read_drm_serial(&entry.path());
let dev = GpuDevice {
vendor: GpuVendor::Intel,
name,
index: idx,
vendor_index: idx,
generation,
pci_id,
vram_mib,
serial,
host_pci_address,
vendor_id_hex: "0x8086".into(),
};
idx += 1;
Some(dev)
} else {
None
}
})
.collect();
}
}
Vec::new()
}
pub(super) fn intel_generation_from_device_id(device_id: &str) -> String {
let id_u16 = device_id
.strip_prefix("0x")
.and_then(|s| u16::from_str_radix(s, 16).ok());
match id_u16 {
Some(id) if (0x5690..=0x56af).contains(&id) => "Alchemist DG2".into(),
Some(id) if (0xe200..=0xe21f).contains(&id) => "Battlemage BMG".into(),
Some(id) if (0x6420..=0x643f).contains(&id) => "Lunar Lake".into(),
Some(id) if (0x7d40..=0x7d6f).contains(&id) => "Meteor Lake".into(),
Some(id) if (0xa780..=0xa7ff).contains(&id) => "Raptor Lake".into(),
Some(id) if (0x4680..=0x46ff).contains(&id) => "Alder Lake".into(),
Some(id) if (0x9a00..=0x9aff).contains(&id) => "Tiger Lake".into(),
_ => "Unknown".into(),
}
}
fn intel_vram_mib_from_device_id(device_id: &str) -> Option<u32> {
let id_u16 = device_id
.strip_prefix("0x")
.and_then(|s| u16::from_str_radix(s, 16).ok())?;
Some(match id_u16 {
0x56a5 => 6 * 1024, 0x56a6 => 4 * 1024, 0x5693 => 4 * 1024, 0x56a0 => 8 * 1024, 0x56a1 => 8 * 1024, 0x56a2 => 8 * 1024, 0x5690 => 16 * 1024, 0x5691 => 12 * 1024, 0x5692 => 8 * 1024, 0xe20b => 12 * 1024, 0xe20c => 10 * 1024, _ => return None,
})
}
fn intel_label_from_device_id(device_id: &str) -> String {
let id_u16 = device_id
.strip_prefix("0x")
.and_then(|s| u16::from_str_radix(s, 16).ok());
match id_u16 {
Some(0x56a5) => "Intel Arc A380".into(),
Some(0x56a6) => "Intel Arc A310".into(),
Some(0x5693) => "Intel Arc A350M".into(),
Some(0x56a0) => "Intel Arc A770".into(),
Some(0x56a1) => "Intel Arc A750".into(),
Some(0x56a2) => "Intel Arc A580".into(),
Some(0x5690) => "Intel Arc A770M".into(),
Some(0x5691) => "Intel Arc A730M".into(),
Some(0x5692) => "Intel Arc A550M".into(),
Some(id) if (0x5690..=0x56af).contains(&id) => {
format!("Intel Arc Alchemist (DG2 0x{id:04x})")
}
Some(0xe20b) => "Intel Arc B580".into(),
Some(0xe20c) => "Intel Arc B570".into(),
Some(id) if (0xe200..=0xe21f).contains(&id) => {
format!("Intel Arc Battlemage (BMG 0x{id:04x})")
}
Some(id) if (0x6420..=0x643f).contains(&id) => "Intel Lunar Lake iGPU".into(),
Some(id) if (0x7d40..=0x7d6f).contains(&id) => "Intel Meteor Lake iGPU".into(),
Some(id) => format!("Intel iGPU 0x{id:04x}"),
None => "Intel GPU".into(),
}
}