1use std::sync::Arc;
2use winit::window::Window;
3
4pub struct GpuContext {
5 pub device: Arc<wgpu::Device>,
6 pub queue: Arc<wgpu::Queue>,
7 pub surface: wgpu::Surface<'static>,
8 pub config: wgpu::SurfaceConfiguration,
9 pub size: winit::dpi::PhysicalSize<u32>,
10 pub scale_factor: f64,
11}
12
13impl GpuContext {
14 pub async fn new(window: Arc<Window>) -> Self {
15 let size = window.inner_size();
16
17 let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
18 backends: wgpu::Backends::all(),
19 flags: wgpu::InstanceFlags::default(),
20 memory_budget_thresholds: Default::default(),
21 backend_options: Default::default(),
22 display: Default::default(),
23 });
24 let surface = instance.create_surface(window.clone()).unwrap();
25
26 let adapter = instance
27 .request_adapter(&wgpu::RequestAdapterOptions {
28 power_preference: wgpu::PowerPreference::HighPerformance,
29 compatible_surface: Some(&surface),
30 force_fallback_adapter: false,
31 })
32 .await
33 .unwrap();
34
35 let (device, queue) = adapter
36 .request_device(&wgpu::DeviceDescriptor {
37 label: Some("Zenthra Device"),
38 required_features: wgpu::Features::empty(),
39 required_limits: wgpu::Limits::default(),
40 memory_hints: Default::default(),
41 trace: wgpu::Trace::Off,
42 experimental_features: wgpu::ExperimentalFeatures::disabled(),
43 })
44 .await
45 .unwrap();
46
47 let surface_caps = surface.get_capabilities(&adapter);
48 let surface_format = surface_caps
49 .formats
50 .iter()
51 .find(|f| f.is_srgb())
52 .copied()
53 .unwrap_or(surface_caps.formats[0]);
54
55 let alpha_mode = if surface_caps.alpha_modes.contains(&wgpu::CompositeAlphaMode::PostMultiplied) {
56 wgpu::CompositeAlphaMode::PostMultiplied
57 } else if surface_caps.alpha_modes.contains(&wgpu::CompositeAlphaMode::PreMultiplied) {
58 wgpu::CompositeAlphaMode::PreMultiplied
59 } else {
60 surface_caps.alpha_modes[0]
61 };
62
63 let config = wgpu::SurfaceConfiguration {
64 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
65 format: surface_format,
66 width: size.width,
67 height: size.height,
68 present_mode: wgpu::PresentMode::AutoVsync,
69 alpha_mode,
70 view_formats: vec![],
71 desired_maximum_frame_latency: 2,
72 };
73 surface.configure(&device, &config);
74
75 let scale_factor = window.scale_factor();
76
77 Self {
78 device: Arc::new(device),
79 queue: Arc::new(queue),
80 surface,
81 config,
82 size,
83 scale_factor,
84 }
85 }
86
87 pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>, scale_factor: f64) {
88 if new_size.width > 0 && new_size.height > 0 {
89 self.size = new_size;
90 self.scale_factor = scale_factor;
91 self.config.width = new_size.width;
92 self.config.height = new_size.height;
93 self.surface.configure(&self.device, &self.config);
94 }
95 }
96}