use wgpu;
use crate::error::{WebGpuError, WebGpuResult};
pub struct WebGpuDevice {
#[allow(dead_code)]
pub(crate) instance: wgpu::Instance,
#[allow(dead_code)]
pub(crate) adapter: wgpu::Adapter,
pub(crate) device: wgpu::Device,
pub(crate) queue: wgpu::Queue,
pub adapter_name: String,
}
impl WebGpuDevice {
pub fn new() -> WebGpuResult<Self> {
pollster::block_on(Self::new_async())
}
async fn new_async() -> WebGpuResult<Self> {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle());
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: None,
force_fallback_adapter: false,
})
.await
.map_err(|e| WebGpuError::DeviceRequest(e.to_string()))?;
let adapter_name = adapter.get_info().name.clone();
let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor {
label: Some("oxicuda-webgpu"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
memory_hints: wgpu::MemoryHints::default(),
..Default::default()
})
.await
.map_err(|e| WebGpuError::DeviceRequest(e.to_string()))?;
Ok(Self {
instance,
adapter,
device,
queue,
adapter_name,
})
}
}
impl std::fmt::Debug for WebGpuDevice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "WebGpuDevice({})", self.adapter_name)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn webgpu_device_new_graceful() {
match WebGpuDevice::new() {
Ok(dev) => {
assert!(!dev.adapter_name.is_empty());
let _ = format!("{dev:?}");
}
Err(WebGpuError::NoAdapter) => {
}
Err(e) => {
let _ = format!("device init error (non-fatal): {e}");
}
}
}
}