use super::{LevelZeroFanReadout, LevelZeroMemoryKind, LevelZeroReadout};
use crate::device::readers::detail_keys::note_metrics_source;
use crate::device::types::{GpuInfo, MAX_GPU_FAN_RPM};
#[derive(Debug, Clone, Copy)]
pub enum ApplyPlatform {
Linux,
Windows,
}
pub fn apply_to_gpu_info(
gpu_info: &mut GpuInfo,
readout: &LevelZeroReadout,
platform: ApplyPlatform,
) {
if !readout.has_fresh_data() {
return;
}
for (label, pct) in &readout.engines {
gpu_info
.detail
.insert(format!("Engine: {label} (L0)"), format!("{pct:.2}%"));
}
if let Some(watts) = readout.power_watts {
gpu_info
.detail
.insert("Power (L0)".to_string(), format!("{:.2} W", watts.value));
}
if let Some(temp) = readout.temperature_celsius {
gpu_info.temperature = temp.value;
set_source(gpu_info, "Temperature", temp.source);
}
if let Some(watts) = readout.power_watts {
gpu_info.power_consumption = watts.value.clamp(0.0, 750.0);
set_source(gpu_info, "Power", watts.source);
}
if let Some(memory) = readout.memory {
match memory.kind {
LevelZeroMemoryKind::DedicatedLocal
if memory.total_bytes > 0
&& !dxgi_resolved_a_shared_aperture(gpu_info, platform) =>
{
gpu_info.total_memory = memory.total_bytes;
gpu_info.used_memory = memory.used_bytes.min(memory.total_bytes);
set_source(gpu_info, "Memory", memory.source);
set_source(gpu_info, "Memory Used", memory.source);
gpu_info.detail.insert(
"VRAM Total".to_string(),
format!("{} bytes", memory.total_bytes),
);
}
LevelZeroMemoryKind::DedicatedLocal => {
if memory.total_bytes > 0 {
gpu_info.detail.insert(
"VRAM Dedicated (L0)".to_string(),
format!("{} bytes", memory.total_bytes),
);
}
}
LevelZeroMemoryKind::SharedSystem => {
gpu_info.detail.insert(
"Memory (L0)".to_string(),
"Shared/system memory; dedicated VRAM budget unavailable".to_string(),
);
}
}
}
if let Some(freq) = readout.frequency_mhz {
gpu_info.frequency = freq.value;
set_source(gpu_info, "Frequency", freq.source);
}
for (domain, mhz) in &readout.frequency_domains {
gpu_info
.detail
.insert(format!("Frequency: {domain} (L0)"), format!("{mhz} MHz"));
}
match platform {
ApplyPlatform::Linux => {
if let Some(primary) = readout.primary_engine_utilization {
gpu_info.utilization = primary.value.clamp(0.0, 100.0);
set_source(gpu_info, "Utilization", primary.source);
gpu_info.detail.remove("Utilization");
}
apply_fan(gpu_info, readout.fan, false);
if !gpu_info.detail.contains_key("Metrics Source") {
note_metrics_source(&mut gpu_info.detail, "sysfs");
}
note_metrics_source(&mut gpu_info.detail, "Level Zero Sysman");
}
ApplyPlatform::Windows => {
if let Some(primary) = readout.primary_engine_utilization {
gpu_info.utilization = primary.value.clamp(0.0, 100.0);
set_source(gpu_info, "Utilization", primary.source);
}
apply_fan(gpu_info, readout.fan, true);
note_metrics_source(&mut gpu_info.detail, "Level Zero Sysman");
}
}
}
fn dxgi_resolved_a_shared_aperture(gpu_info: &GpuInfo, platform: ApplyPlatform) -> bool {
matches!(platform, ApplyPlatform::Windows)
&& gpu_info
.detail
.get("Source: Memory")
.is_some_and(|source| source.contains("shared"))
}
fn set_source(gpu_info: &mut GpuInfo, field: &str, source: &str) {
gpu_info
.detail
.insert(format!("Source: {field}"), source.to_string());
}
fn apply_fan(gpu_info: &mut GpuInfo, fan: Option<LevelZeroFanReadout>, overwrite_existing: bool) {
let Some(fan) = fan else {
return;
};
if !overwrite_existing && gpu_info.detail.contains_key("Fan Speed") {
return;
}
let rpm = fan.rpm.map(|rpm| rpm.min(MAX_GPU_FAN_RPM));
let value = match (rpm, fan.percent) {
(Some(rpm), Some(percent)) => format!("{rpm} RPM ({percent}%)"),
(Some(rpm), None) => format!("{rpm} RPM"),
(None, Some(percent)) => format!("{percent}%"),
(None, None) => return,
};
gpu_info.detail.insert("Fan Speed".to_string(), value);
gpu_info.fan_speed_rpm = rpm;
set_source(gpu_info, "Fan", fan.source);
}