use crate::{GpuDeviceInfo, HypomnesisError, ProcessGpuInfo, Result};
#[cfg(any(
feature = "nvml",
all(windows, feature = "dxgi"),
feature = "nvidia-smi-fallback"
))]
use crate::GpuQuerySource;
#[cfg(feature = "nvml")]
mod nvml;
#[cfg(all(windows, feature = "dxgi"))]
mod dxgi;
#[cfg(feature = "nvidia-smi-fallback")]
mod nvidia_smi;
#[allow(clippy::missing_const_for_fn)] pub fn device_count() -> Result<u32> {
#[cfg(feature = "nvml")]
if let Some(count) = nvml::device_count() {
return Ok(count);
}
#[cfg(all(windows, feature = "dxgi"))]
if let Some(count) = dxgi::device_count() {
return Ok(count);
}
Err(HypomnesisError::NoGpuSource)
}
#[allow(unused_variables)] #[allow(clippy::missing_const_for_fn)] pub fn device_info(index: u32) -> Result<GpuDeviceInfo> {
#[cfg(feature = "nvml")]
if let Some(snap) = nvml::query(index) {
#[cfg(all(windows, feature = "dxgi"))]
let name = dxgi::adapter_name(index).or(snap.device_name);
#[cfg(not(all(windows, feature = "dxgi")))]
let name = snap.device_name;
return Ok(GpuDeviceInfo {
index,
name,
total_bytes: snap.device_total,
free_bytes: snap.device_free,
used_bytes: snap.device_used,
});
}
#[cfg(all(windows, feature = "dxgi"))]
if let Some(d) = dxgi::query(index) {
return Ok(GpuDeviceInfo {
index,
name: d.adapter_name,
total_bytes: d.dedicated_video_memory,
free_bytes: d.dedicated_video_memory.saturating_sub(d.current_usage),
used_bytes: d.current_usage,
});
}
#[cfg(feature = "nvidia-smi-fallback")]
if let Some(result) = nvidia_smi::query(index) {
return Ok(GpuDeviceInfo {
index,
name: None,
total_bytes: result.total_bytes,
free_bytes: result.total_bytes.saturating_sub(result.used_bytes),
used_bytes: result.used_bytes,
});
}
bounds_check(index)?;
Err(HypomnesisError::NoGpuSource)
}
#[allow(unused_variables)] #[allow(clippy::missing_const_for_fn)] pub fn process_gpu_info(device_index: u32) -> Result<ProcessGpuInfo> {
#[cfg(all(windows, feature = "dxgi"))]
if let Some(d) = dxgi::query(device_index) {
return Ok(ProcessGpuInfo {
used_bytes: d.current_usage,
is_per_process: true,
source: GpuQuerySource::Dxgi,
});
}
#[cfg(feature = "nvml")]
if let Some(snap) = nvml::query(device_index)
&& let Some(used) = snap.process_used_bytes
{
return Ok(ProcessGpuInfo {
used_bytes: used,
is_per_process: true,
source: GpuQuerySource::Nvml,
});
}
#[cfg(feature = "nvidia-smi-fallback")]
if let Some(result) = nvidia_smi::query(device_index) {
return Ok(ProcessGpuInfo {
used_bytes: result.used_bytes,
is_per_process: false,
source: GpuQuerySource::NvidiaSmi,
});
}
bounds_check(device_index)?;
Err(HypomnesisError::NoGpuSource)
}
#[allow(unused_variables)] #[allow(clippy::missing_const_for_fn)] #[allow(clippy::unnecessary_wraps)] fn bounds_check(index: u32) -> Result<()> {
#[cfg(feature = "nvml")]
if let Some(count) = nvml::device_count() {
return if index >= count {
Err(HypomnesisError::DeviceIndexOutOfRange { index, count })
} else {
Ok(())
};
}
#[cfg(all(windows, feature = "dxgi"))]
if let Some(count) = dxgi::device_count() {
return if index >= count {
Err(HypomnesisError::DeviceIndexOutOfRange { index, count })
} else {
Ok(())
};
}
Ok(())
}