#[cfg(feature = "cuda-monitor")]
use super::GpuMemoryMetrics;
#[cfg(any(all(feature = "gpu", not(target_arch = "wasm32")), feature = "cuda-monitor"))]
use super::MonitorError;
#[cfg(any(all(feature = "gpu", not(target_arch = "wasm32")), feature = "cuda-monitor"))]
use super::{GpuBackend, GpuDeviceInfo, GpuVendor};
#[cfg(all(feature = "gpu", not(target_arch = "wasm32")))]
pub(crate) fn query_wgpu_device_info(device_index: u32) -> Result<GpuDeviceInfo, MonitorError> {
use crate::backends::gpu::runtime;
runtime::block_on(async {
let instance = wgpu::Instance::default();
let adapters = instance.enumerate_adapters(wgpu::Backends::all());
if adapters.is_empty() {
return Err(MonitorError::NoDevice);
}
let adapter =
adapters.get(device_index as usize).ok_or(MonitorError::InvalidDevice(device_index))?;
let info = adapter.get_info();
let backend = match info.backend {
wgpu::Backend::Vulkan => GpuBackend::Vulkan,
wgpu::Backend::Metal => GpuBackend::Metal,
wgpu::Backend::Dx12 => GpuBackend::Dx12,
wgpu::Backend::Gl => GpuBackend::OpenGl,
wgpu::Backend::BrowserWebGpu => GpuBackend::WebGpu,
wgpu::Backend::Noop => GpuBackend::Cpu,
};
let vendor = GpuVendor::from_vendor_id(info.vendor);
let limits = adapter.limits();
let vram_estimate = limits.max_buffer_size;
Ok(GpuDeviceInfo::new(device_index, info.name, vendor, backend)
.with_vram(vram_estimate)
.with_driver_version(format!("{:?}", info.driver_info)))
})
}
#[cfg(all(feature = "gpu", not(target_arch = "wasm32")))]
pub(crate) fn enumerate_wgpu_devices() -> Result<Vec<GpuDeviceInfo>, MonitorError> {
use crate::backends::gpu::runtime;
runtime::block_on(async {
let instance = wgpu::Instance::default();
let adapters = instance.enumerate_adapters(wgpu::Backends::all());
if adapters.is_empty() {
return Err(MonitorError::NoDevice);
}
let mut devices = Vec::with_capacity(adapters.len());
for (idx, adapter) in adapters.iter().enumerate() {
let info: wgpu::AdapterInfo = adapter.get_info();
let backend = match info.backend {
wgpu::Backend::Vulkan => GpuBackend::Vulkan,
wgpu::Backend::Metal => GpuBackend::Metal,
wgpu::Backend::Dx12 => GpuBackend::Dx12,
wgpu::Backend::Gl => GpuBackend::OpenGl,
wgpu::Backend::BrowserWebGpu => GpuBackend::WebGpu,
wgpu::Backend::Noop => GpuBackend::Cpu,
};
let vendor = GpuVendor::from_vendor_id(info.vendor);
let limits = adapter.limits();
devices.push(
GpuDeviceInfo::new(idx as u32, info.name, vendor, backend)
.with_vram(limits.max_buffer_size)
.with_driver_version(format!("{:?}", info.driver_info)),
);
}
Ok(devices)
})
}
#[cfg(feature = "cuda-monitor")]
pub fn query_cuda_device_info(device_index: u32) -> Result<GpuDeviceInfo, MonitorError> {
use trueno_gpu::CudaDeviceInfo;
let cuda_info = CudaDeviceInfo::query(device_index)
.map_err(|e| MonitorError::BackendInit(format!("CUDA query failed: {}", e)))?;
Ok(GpuDeviceInfo::new(
cuda_info.index,
cuda_info.name,
GpuVendor::Nvidia, GpuBackend::Cuda,
)
.with_vram(cuda_info.total_memory))
}
#[cfg(feature = "cuda-monitor")]
pub fn enumerate_cuda_devices() -> Result<Vec<GpuDeviceInfo>, MonitorError> {
use trueno_gpu::CudaDeviceInfo;
let cuda_devices = CudaDeviceInfo::enumerate()
.map_err(|e| MonitorError::BackendInit(format!("CUDA enumerate failed: {}", e)))?;
Ok(cuda_devices
.into_iter()
.map(|cuda_info| {
GpuDeviceInfo::new(cuda_info.index, cuda_info.name, GpuVendor::Nvidia, GpuBackend::Cuda)
.with_vram(cuda_info.total_memory)
})
.collect())
}
#[cfg(feature = "cuda-monitor")]
pub fn query_cuda_memory(device_index: u32) -> Result<GpuMemoryMetrics, MonitorError> {
use trueno_gpu::driver::CudaContext;
use trueno_gpu::CudaMemoryInfo;
let ctx = CudaContext::new(device_index as i32)
.map_err(|e| MonitorError::BackendInit(format!("CUDA context failed: {}", e)))?;
let mem = CudaMemoryInfo::query(&ctx)
.map_err(|e| MonitorError::QueryFailed(format!("CUDA memory query failed: {}", e)))?;
Ok(GpuMemoryMetrics::new(mem.total, mem.used(), mem.free))
}
#[cfg(feature = "cuda-monitor")]
#[must_use]
pub fn cuda_monitor_available() -> bool {
trueno_gpu::cuda_monitoring_available()
}
#[cfg(not(feature = "cuda-monitor"))]
#[must_use]
pub fn cuda_monitor_available() -> bool {
false
}