Skip to main content

zenthra_render/
gpu.rs

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}