use std::fmt;
#[derive(Debug)]
pub enum GpuError {
NoAdapter,
DeviceError(wgpu::RequestDeviceError),
}
impl fmt::Display for GpuError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NoAdapter => write!(f, "no suitable GPU adapter found"),
Self::DeviceError(e) => write!(f, "GPU device error: {e}"),
}
}
}
impl std::error::Error for GpuError {}
impl From<wgpu::RequestDeviceError> for GpuError {
fn from(e: wgpu::RequestDeviceError) -> Self {
Self::DeviceError(e)
}
}
pub struct GpuDevice {
pub(crate) device: wgpu::Device,
pub(crate) queue: wgpu::Queue,
}
impl GpuDevice {
pub async fn new() -> Result<Self, GpuError> {
let instance = wgpu::Instance::default();
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: None,
force_fallback_adapter: false,
})
.await
.ok_or(GpuError::NoAdapter)?;
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: Some("tang-gpu"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
memory_hints: wgpu::MemoryHints::Performance,
},
None,
)
.await?;
Ok(Self { device, queue })
}
pub fn new_sync() -> Result<Self, GpuError> {
pollster::block_on(Self::new())
}
}