use once_cell::sync::Lazy;
use std::sync::Arc;
pub static GPU_CONTEXT: Lazy<GpuContext> =
Lazy::new(|| pollster::block_on(GpuContext::init()).expect("Failed to initialize GPU context"));
static GPU_CONTEXT_RESULT: Lazy<Result<GpuContext, String>> =
Lazy::new(|| pollster::block_on(GpuContext::init()));
pub struct GpuContext {
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
}
impl GpuContext {
async fn init() -> Result<Self, String> {
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..Default::default()
});
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: None,
force_fallback_adapter: false,
})
.await
.ok_or("No GPU adapter found")?;
let info = adapter.get_info();
eprintln!(
"[gpu] backend={:?} device='{}' vendor={} device_type={:?}",
info.backend, info.name, info.vendor, info.device_type
);
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: Some("Reflow Shared GPU"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
memory_hints: wgpu::MemoryHints::default(),
},
None,
)
.await
.map_err(|e| format!("GPU device request failed: {}", e))?;
Ok(Self {
device: Arc::new(device),
queue: Arc::new(queue),
})
}
pub fn device(&self) -> &wgpu::Device {
&self.device
}
pub fn queue(&self) -> &wgpu::Queue {
&self.queue
}
pub fn submit_and_poll(&self, command_buffer: wgpu::CommandBuffer) {
self.queue.submit(std::iter::once(command_buffer));
}
}
pub fn try_gpu_context() -> Result<&'static GpuContext, String> {
match &*GPU_CONTEXT_RESULT {
Ok(ctx) => Ok(ctx),
Err(err) => Err(err.clone()),
}
}