1use std::sync::{Arc, OnceLock};
4use wgpu;
5
6pub struct GpuDevice {
8 pub device: wgpu::Device,
9 pub queue: wgpu::Queue,
10 pub adapter_name: String,
11 pub backend: String,
12}
13
14static GPU_DEVICE: OnceLock<Option<Arc<GpuDevice>>> = OnceLock::new();
15
16impl GpuDevice {
17 pub fn get() -> Option<Arc<GpuDevice>> {
20 GPU_DEVICE.get_or_init(|| Self::init_device()).clone()
21 }
22
23 pub fn is_available() -> bool {
25 Self::get().is_some()
26 }
27
28 fn init_device() -> Option<Arc<GpuDevice>> {
29 let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
30 backends: wgpu::Backends::all(),
31 ..Default::default()
32 });
33
34 let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
35 power_preference: wgpu::PowerPreference::HighPerformance,
36 compatible_surface: None,
37 force_fallback_adapter: false,
38 }))?;
39
40 let adapter_name = adapter.get_info().name.clone();
41 let backend = format!("{:?}", adapter.get_info().backend);
42
43 let (device, queue) = pollster::block_on(adapter.request_device(
44 &wgpu::DeviceDescriptor {
45 label: Some("tl-gpu"),
46 required_features: wgpu::Features::empty(),
47 required_limits: wgpu::Limits::default(),
48 ..Default::default()
49 },
50 None,
51 ))
52 .ok()?;
53
54 Some(Arc::new(GpuDevice {
55 device,
56 queue,
57 adapter_name,
58 backend,
59 }))
60 }
61}
62
63impl std::fmt::Debug for GpuDevice {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 write!(f, "GpuDevice({}, {})", self.adapter_name, self.backend)
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_gpu_available() {
75 let _available = GpuDevice::is_available();
77 }
78}