use std::sync::Arc;
use winit::window::Window;
use crate::error::WgpuBackendError;
pub struct GpuDevice {
pub instance: wgpu::Instance,
pub adapter: wgpu::Adapter,
pub device: wgpu::Device,
pub queue: wgpu::Queue,
}
impl GpuDevice {
pub fn new(window: &Arc<Window>) -> Result<Self, WgpuBackendError> {
let instance = wgpu::Instance::default();
let surface_target = unsafe { wgpu::SurfaceTargetUnsafe::from_window(window.as_ref()) }
.map_err(|error| WgpuBackendError::CreateSurface(error.to_string()))?;
let surface = unsafe { instance.create_surface_unsafe(surface_target) }
.map_err(|error| WgpuBackendError::CreateSurface(error.to_string()))?;
let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
compatible_surface: Some(&surface),
force_fallback_adapter: false,
}))
.ok_or(WgpuBackendError::NoAdapter)?;
let (device, queue) = pollster::block_on(adapter.request_device(
&wgpu::DeviceDescriptor {
label: Some("cotis-wgpu device"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
memory_hints: wgpu::MemoryHints::default(),
},
None,
))
.map_err(|error| WgpuBackendError::RequestDevice(error.to_string()))?;
Ok(Self {
instance,
adapter,
device,
queue,
})
}
}
pub fn choose_surface_format(formats: &[wgpu::TextureFormat]) -> wgpu::TextureFormat {
formats
.iter()
.copied()
.find(wgpu::TextureFormat::is_srgb)
.unwrap_or(formats[0])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn prefers_srgb_surface_format() {
let formats = [
wgpu::TextureFormat::Rgba16Float,
wgpu::TextureFormat::Bgra8UnormSrgb,
];
assert_eq!(
choose_surface_format(&formats),
wgpu::TextureFormat::Bgra8UnormSrgb
);
}
}