use std::sync::{Arc, OnceLock};
use wgpu;
pub struct GpuDevice {
pub device: wgpu::Device,
pub queue: wgpu::Queue,
pub adapter_name: String,
pub backend: String,
}
static GPU_DEVICE: OnceLock<Option<Arc<GpuDevice>>> = OnceLock::new();
impl GpuDevice {
pub fn get() -> Option<Arc<GpuDevice>> {
GPU_DEVICE.get_or_init(|| Self::init_device()).clone()
}
pub fn is_available() -> bool {
Self::get().is_some()
}
fn init_device() -> Option<Arc<GpuDevice>> {
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..Default::default()
});
let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: None,
force_fallback_adapter: false,
}))?;
let adapter_name = adapter.get_info().name.clone();
let backend = format!("{:?}", adapter.get_info().backend);
let (device, queue) = pollster::block_on(adapter.request_device(
&wgpu::DeviceDescriptor {
label: Some("tl-gpu"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
..Default::default()
},
None,
))
.ok()?;
Some(Arc::new(GpuDevice {
device,
queue,
adapter_name,
backend,
}))
}
}
impl std::fmt::Debug for GpuDevice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "GpuDevice({}, {})", self.adapter_name, self.backend)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gpu_available() {
let _available = GpuDevice::is_available();
}
}