use std::sync::Arc;
use winit::window::Window;
pub struct GpuContext {
pub device: Arc<wgpu::Device>,
pub queue: Arc<wgpu::Queue>,
pub surface: wgpu::Surface<'static>,
pub config: wgpu::SurfaceConfiguration,
pub size: winit::dpi::PhysicalSize<u32>,
pub scale_factor: f64,
}
impl GpuContext {
pub async fn new(window: Arc<Window>) -> Self {
let size = window.inner_size();
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
flags: wgpu::InstanceFlags::default(),
memory_budget_thresholds: Default::default(),
backend_options: Default::default(),
display: Default::default(),
});
let surface = instance.create_surface(window.clone()).unwrap();
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: Some(&surface),
force_fallback_adapter: false,
})
.await
.unwrap();
let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor {
label: Some("Zenthra Device"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
memory_hints: Default::default(),
trace: wgpu::Trace::Off,
experimental_features: wgpu::ExperimentalFeatures::disabled(),
})
.await
.unwrap();
let surface_caps = surface.get_capabilities(&adapter);
let surface_format = surface_caps
.formats
.iter()
.find(|f| f.is_srgb())
.copied()
.unwrap_or(surface_caps.formats[0]);
let alpha_mode = if surface_caps.alpha_modes.contains(&wgpu::CompositeAlphaMode::PostMultiplied) {
wgpu::CompositeAlphaMode::PostMultiplied
} else if surface_caps.alpha_modes.contains(&wgpu::CompositeAlphaMode::PreMultiplied) {
wgpu::CompositeAlphaMode::PreMultiplied
} else {
surface_caps.alpha_modes[0]
};
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface_format,
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::AutoVsync,
alpha_mode,
view_formats: vec![],
desired_maximum_frame_latency: 2,
};
surface.configure(&device, &config);
let scale_factor = window.scale_factor();
Self {
device: Arc::new(device),
queue: Arc::new(queue),
surface,
config,
size,
scale_factor,
}
}
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>, scale_factor: f64) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.scale_factor = scale_factor;
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
}