diff --git a/src-tauri/src/core/hardware/amd.rs b/src-tauri/src/core/hardware/amd.rs index c87aef8c7..cbaea172d 100644 --- a/src-tauri/src/core/hardware/amd.rs +++ b/src-tauri/src/core/hardware/amd.rs @@ -20,40 +20,58 @@ impl GpuInfo { } }; - for card_idx in 0.. { - let device_path = format!("/sys/class/drm/card{}/device", card_idx); - if !Path::new(&device_path).exists() { - break; - } + let closure = || -> Result> { + for subdir in fs::read_dir("/sys/class/drm")? { + let device_path = subdir?.path().join("device"); - // Check if this is an AMD GPU by looking for amdgpu directory - if !Path::new(&format!("{}/driver/module/drivers/pci:amdgpu", device_path)).exists() { - continue; - } + // Check if this is an AMD GPU by looking for amdgpu directory + if !device_path + .join("driver/module/drivers/pci:amdgpu") + .exists() + { + continue; + } - // match device_id from Vulkan info - let this_device_id = fs::read_to_string(format!("{}/device", device_path)) - .map(|s| u32::from_str_radix(s.trim(), 16).unwrap_or(0)) - .unwrap_or(0); - if this_device_id != device_id { - continue; - } + // match device_id from Vulkan info + let this_device_id_str = fs::read_to_string(device_path.join("device"))?; + let this_device_id = u32::from_str_radix( + this_device_id_str + .strip_prefix("0x") + .unwrap_or(&this_device_id_str) + .trim(), + 16, + )?; + if this_device_id != device_id { + continue; + } - let read_mem = |path: &str| -> u64 { - fs::read_to_string(path) - .map(|content| content.trim().parse::().unwrap_or(0)) - .unwrap_or(0) - / 1024 - / 1024 // Convert bytes to MiB - }; - return GpuUsage { - uuid: self.uuid.clone(), - total_memory: read_mem(&format!("{}/mem_info_vram_total", device_path)), - used_memory: read_mem(&format!("{}/mem_info_vram_used", device_path)), - }; + let read_mem = |path: &Path| -> u64 { + fs::read_to_string(path) + .map(|content| content.trim().parse::().unwrap_or(0)) + .unwrap_or(0) + / 1024 + / 1024 // Convert bytes to MiB + }; + return Ok(GpuUsage { + uuid: self.uuid.clone(), + total_memory: read_mem(&device_path.join("mem_info_vram_total")), + used_memory: read_mem(&device_path.join("mem_info_vram_used")), + }); + } + Err(format!("GPU not found").into()) + }; + + match closure() { + Ok(usage) => usage, + Err(e) => { + log::error!( + "Failed to get memory usage for AMD GPU {:#x}: {}", + device_id, + e + ); + self.get_usage_unsupported() + } } - - self.get_usage_unsupported() } #[cfg(target_os = "windows")] diff --git a/src-tauri/src/core/hardware/mod.rs b/src-tauri/src/core/hardware/mod.rs index 5d1dc47d8..d1bd41d38 100644 --- a/src-tauri/src/core/hardware/mod.rs +++ b/src-tauri/src/core/hardware/mod.rs @@ -28,21 +28,10 @@ impl CpuStaticInfo { .unwrap_or("unknown") .to_string(); - // cortex only returns amd64, arm64, or Unsupported - // TODO: find how Jan uses this value, if we can use - // std::env::consts::ARCH directly - let arch = match std::env::consts::ARCH { - "x86" => "amd64", - "x86_64" => "amd64", - "arm" => "arm64", - "aarch64" => "arm64", - _ => "Unsupported", - }; - CpuStaticInfo { name, core_count: System::physical_core_count().unwrap_or(0), - arch: arch.to_string(), + arch: std::env::consts::ARCH.to_string(), extensions: CpuStaticInfo::get_extensions(), } } @@ -220,7 +209,8 @@ impl GpuInfo { #[derive(serde::Serialize, Clone, Debug)] pub struct SystemInfo { cpu: CpuStaticInfo, - os: String, + os_type: String, + os_name: String, total_memory: u64, gpus: Vec, } @@ -293,9 +283,21 @@ pub fn get_system_info(app: tauri::AppHandle) -> SystemInf } } + let os_type = if cfg!(target_os = "windows") { + "windows" + } else if cfg!(target_os = "macos") { + "macos" + } else if cfg!(target_os = "linux") { + "linux" + } else { + "unknown" + }; + let os_name = System::long_os_version().unwrap_or("Unknown".to_string()); + SystemInfo { cpu: CpuStaticInfo::new(), - os: System::long_os_version().unwrap_or("Unknown".to_string()), + os_type: os_type.to_string(), + os_name, total_memory: system.total_memory() / 1024 / 1024, // bytes to MiB gpus: gpu_map.into_values().collect(), } diff --git a/src-tauri/src/core/hardware/nvidia.rs b/src-tauri/src/core/hardware/nvidia.rs index c703947dc..6dced3448 100644 --- a/src-tauri/src/core/hardware/nvidia.rs +++ b/src-tauri/src/core/hardware/nvidia.rs @@ -10,9 +10,28 @@ pub struct NvidiaInfo { pub compute_capability: String, } -// NvmlError doesn't implement Copy, so we have to store an Option in OnceLock fn get_nvml() -> Option<&'static Nvml> { - NVML.get_or_init(|| Nvml::init().ok()).as_ref() + NVML.get_or_init(|| { + let result = Nvml::init().or_else(|e| { + // fallback + if cfg!(target_os = "linux") { + let lib_path = std::ffi::OsStr::new("libnvidia-ml.so.1"); + Nvml::builder().lib_path(lib_path).init() + } else { + Err(e) + } + }); + + // NvmlError doesn't implement Copy, so we have to store an Option in OnceLock + match result { + Ok(nvml) => Some(nvml), + Err(e) => { + log::error!("Unable to initialize NVML: {}", e); + None + } + } + }) + .as_ref() } impl GpuInfo {