use std::sync::Arc;
#[derive(Debug)]
pub enum FrendererError {
NoUsableAdapter,
}
impl std::fmt::Display for FrendererError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FrendererError::NoUsableAdapter => {
f.write_str("No valid adapter found for GPU requirements")
}
}
}
}
impl std::error::Error for FrendererError {}
#[allow(dead_code)]
pub struct WGPU {
adapter: Arc<wgpu::Adapter>,
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
}
impl WGPU {
pub fn with_resources(
adapter: Arc<wgpu::Adapter>,
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
) -> Self {
Self {
adapter,
device,
queue,
}
}
pub async fn new<'inst>(
instance: &'inst wgpu::Instance,
surface: Option<&wgpu::Surface<'inst>>,
) -> Result<Self, Box<dyn std::error::Error>> {
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
force_fallback_adapter: false,
compatible_surface: surface,
})
.await
.ok_or(FrendererError::NoUsableAdapter)?;
let is_gl = adapter.get_info().backend == wgpu::Backend::Gl;
#[cfg(not(target_arch = "wasm32"))]
let is_web = false;
#[cfg(target_arch = "wasm32")]
let is_web = true;
let use_storage = !(is_web && is_gl);
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
required_features: wgpu::Features::empty(),
required_limits: if use_storage {
wgpu::Limits::downlevel_defaults()
} else {
wgpu::Limits::downlevel_webgl2_defaults()
}
.using_resolution(adapter.limits()),
},
None,
)
.await?;
Ok(Self::with_resources(
Arc::new(adapter),
Arc::new(device),
Arc::new(queue),
))
}
pub fn is_gl(&self) -> bool {
self.adapter.get_info().backend == wgpu::Backend::Gl
}
#[cfg(target_arch = "wasm32")]
pub fn is_web(&self) -> bool {
true
}
#[cfg(not(target_arch = "wasm32"))]
pub fn is_web(&self) -> bool {
false
}
pub fn supports_storage(&self) -> bool {
!(self.is_gl() && self.is_web())
&& self
.adapter
.get_downlevel_capabilities()
.flags
.contains(wgpu::DownlevelFlags::VERTEX_STORAGE)
&& self.device.limits().max_storage_buffers_per_shader_stage > 0
}
pub fn adapter(&self) -> &wgpu::Adapter {
&self.adapter
}
pub fn device(&self) -> &wgpu::Device {
&self.device
}
pub fn queue(&self) -> &wgpu::Queue {
&self.queue
}
}