fix: keep Windows per-GPU VRAM aligned with adapter order (#1164)

* preserve zero-VRAM Windows adapter slots
This commit is contained in:
Apex 2026-08-04 06:32:39 +00:00 committed by GitHub
parent 66c40d6e4b
commit 735dc004ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 59 additions and 6 deletions

View file

@ -235,6 +235,17 @@ fn read_windows_total_ram_bytes() -> Option<u64> {
parse_windows_total_physical_memory(&output)
}
/// Per-GPU VRAM in adapter order.
///
/// Adapters that report no VRAM (virtual and headless displays commonly report
/// none) keep a zero entry so this stays index-aligned with the adapter name
/// list that `hydrate_gpu_facts_with_identities` indexes into. Dropping those
/// entries shifts every later adapter's VRAM onto the wrong device.
#[cfg(any(target_os = "windows", test))]
fn windows_per_gpu_vram(controllers: &[(String, u64)]) -> Vec<u64> {
controllers.iter().map(|(_, ram)| *ram).collect()
}
#[cfg(target_os = "windows")]
fn read_windows_video_controllers() -> Vec<(String, u64)> {
let Some(output) = powershell_output(
@ -677,14 +688,10 @@ impl Collector for DefaultCollector {
survey.vram_bytes = total + (ram_offload as f64 * 0.90) as u64;
}
} else {
let per_gpu: Vec<u64> = windows_gpus
.iter()
.map(|(_, ram)| *ram)
.filter(|ram| *ram > 0)
.collect();
let per_gpu: Vec<u64> = windows_per_gpu_vram(&windows_gpus);
let total: u64 = per_gpu.iter().sum();
survey.gpu_vram = per_gpu;
if total > 0 {
survey.gpu_vram = per_gpu;
let ram_offload = system_ram.saturating_sub(total);
survey.vram_bytes = total + (ram_offload as f64 * 0.90) as u64;
} else if system_ram > 0 {

View file

@ -833,6 +833,52 @@ fn test_parse_windows_video_controller_json_single_object() {
);
}
#[test]
fn test_windows_per_gpu_vram_keeps_zero_vram_adapters_aligned() {
let controllers = vec![
("Virtual Display Adapter".to_string(), 0),
("AMD Radeon RX 9070 XT".to_string(), 4_293_918_720),
];
assert_eq!(
windows_per_gpu_vram(&controllers),
vec![0, 4_293_918_720],
"adapters reporting no VRAM must keep a slot so later adapters stay aligned"
);
}
#[test]
fn test_windows_per_gpu_vram_keeps_all_zero_adapters_aligned() {
let controllers = vec![
("Virtual Display Adapter".to_string(), 0),
("Headless Display Adapter".to_string(), 0),
];
assert_eq!(windows_per_gpu_vram(&controllers), vec![0, 0]);
}
#[test]
fn test_windows_zero_vram_adapter_does_not_shift_vram_onto_wrong_gpu() {
let controllers = vec![
("Virtual Display Adapter".to_string(), 0),
("AMD Radeon RX 9070 XT".to_string(), 4_293_918_720),
];
let names: Vec<String> = controllers.iter().map(|(name, _)| name.clone()).collect();
let mut survey = HardwareSurvey {
gpu_count: 2,
gpu_vram: windows_per_gpu_vram(&controllers),
..Default::default()
};
hydrate_gpu_facts_with_identities(&mut survey, &[Metric::GpuFacts], &[], names, 2, false);
assert_eq!(survey.gpus.len(), 2);
assert_eq!(survey.gpus[0].display_name, "Virtual Display Adapter");
assert_eq!(survey.gpus[0].vram_bytes, 0);
assert_eq!(survey.gpus[1].display_name, "AMD Radeon RX 9070 XT");
assert_eq!(survey.gpus[1].vram_bytes, 4_293_918_720);
}
#[test]
fn test_parse_windows_total_physical_memory() {
assert_eq!(