use super::types::WebGpuError;
use std::sync::Arc;
pub struct DeviceManager {
instance: wgpu::Instance,
adapter: Option<wgpu::Adapter>,
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
}
impl DeviceManager {
pub async fn new() -> Result<Self, WebGpuError> {
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..Default::default()
});
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
compatible_surface: None,
force_fallback_adapter: false,
})
.await
.map_err(|e| WebGpuError::AdapterRequestFailed(format!("{:?}", e)))?;
let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor {
label: None,
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
memory_hints: wgpu::MemoryHints::default(),
trace: wgpu::Trace::default(),
})
.await?;
Ok(Self {
instance,
adapter: Some(adapter),
device: Arc::new(device),
queue: Arc::new(queue),
})
}
pub fn instance(&self) -> &wgpu::Instance {
&self.instance
}
pub fn adapter(&self) -> Option<&wgpu::Adapter> {
self.adapter.as_ref()
}
pub fn device(&self) -> Arc<wgpu::Device> {
self.device.clone()
}
pub fn queue(&self) -> Arc<wgpu::Queue> {
self.queue.clone()
}
pub fn create_surface(&self, _window: &dyn std::any::Any) -> Result<wgpu::Surface, WebGpuError> {
Err(WebGpuError::SurfaceCreationFailed("Surface creation not implemented without winit".to_string()))
}
pub fn configure_surface(
&self,
surface: &wgpu::Surface,
width: u32,
height: u32,
) -> Result<wgpu::SurfaceConfiguration, WebGpuError> {
let surface_caps = surface.get_capabilities(&self.adapter().unwrap());
let surface_format = surface_caps
.formats
.iter()
.copied()
.find(|f| f.is_srgb())
.unwrap_or(surface_caps.formats[0]);
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface_format,
width,
height,
present_mode: surface_caps.present_modes[0],
alpha_mode: surface_caps.alpha_modes[0],
view_formats: vec![],
desired_maximum_frame_latency: 2,
};
surface.configure(&self.device, &config);
Ok(config)
}
pub fn get_adapter_info(&self) -> Option<wgpu::AdapterInfo> {
self.adapter.as_ref().map(|adapter| adapter.get_info())
}
pub fn supports_features(&self, features: wgpu::Features) -> bool {
self.adapter
.as_ref()
.map(|adapter| adapter.features().contains(features))
.unwrap_or(false)
}
pub fn get_limits(&self) -> Option<wgpu::Limits> {
self.adapter.as_ref().map(|adapter| adapter.limits())
}
}