Files
yawn/core/renderer/wgpu.rs
T

92 lines
3.0 KiB
Rust

pub struct Wgpu {
_instance: wgpu::Instance,
pub surface: wgpu::Surface<'static>,
pub device: wgpu::Device,
pub queue: wgpu::Queue,
pub config: wgpu::SurfaceConfiguration,
pub format: wgpu::TextureFormat,
pub width: u32,
pub height: u32,
pub timestamp_queries: bool,
/// Optional features the device was created with, in WebGPU spelling.
pub features: Vec<&'static str>,
pub adapter: String,
}
const OPTIONAL_FEATURES: [(wgpu::Features, &str); 2] = [
(wgpu::Features::TIMESTAMP_QUERY, "timestamp-query"),
(
wgpu::Features::INDIRECT_FIRST_INSTANCE,
"indirect-first-instance",
),
];
impl Wgpu {
pub async fn new(canvas: web_sys::OffscreenCanvas) -> Result<Self, String> {
let width = canvas.width();
let height = canvas.height();
if width == 0 || height == 0 {
return Err("CANVAS_SIZE".into());
}
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends: wgpu::Backends::BROWSER_WEBGPU,
..Default::default()
});
let surface = instance
.create_surface(wgpu::SurfaceTarget::OffscreenCanvas(canvas))
.map_err(|_| "SURFACE")?;
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
compatible_surface: Some(&surface),
power_preference: wgpu::PowerPreference::HighPerformance,
force_fallback_adapter: false,
})
.await
.map_err(|_| "WEBGPU_UNAVAILABLE")?;
let required_features = OPTIONAL_FEATURES
.iter()
.fold(wgpu::Features::empty(), |features, (feature, _)| {
features | *feature
})
& adapter.features();
let info = adapter.get_info();
let adapter_name = if info.name.is_empty() {
format!("{:?} · {:?}", info.device_type, info.backend)
} else {
format!(
"{} · {:?} · {:?}",
info.name, info.device_type, info.backend
)
};
let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor {
required_features,
..Default::default()
})
.await
.map_err(|_| "DEVICE")?;
let config = surface
.get_default_config(&adapter, width, height)
.ok_or("SURFACE")?;
let format = config.format;
surface.configure(&device, &config);
Ok(Self {
_instance: instance,
surface,
device,
queue,
config,
format,
width,
height,
timestamp_queries: required_features.contains(wgpu::Features::TIMESTAMP_QUERY),
features: OPTIONAL_FEATURES
.iter()
.filter(|(feature, _)| required_features.contains(*feature))
.map(|(_, name)| *name)
.collect(),
adapter: adapter_name,
})
}
}