catgirl_engine_client/window/
window_state.rs1use std::sync::Arc;
2
3use winit::{dpi::PhysicalSize, window::Window};
4
5use wgpu::{
6 Adapter, Device, DeviceDescriptor, Instance, Queue, RequestAdapterOptionsBase, Surface,
7 SurfaceConfiguration,
8};
9
10#[derive(Debug)]
12pub(crate) struct WindowState<'a> {
13 pub(crate) window: Arc<Window>,
15
16 instance: Option<Instance>,
18
19 pub(crate) adapter: Option<Adapter>,
21
22 pub(crate) surface: Option<Surface<'a>>,
24
25 surface_config: Option<SurfaceConfiguration>,
27
28 pub(crate) device: Option<Device>,
30
31 pub(crate) queue: Option<Queue>,
33}
34
35impl WindowState<'_> {
36 #[must_use]
42 pub(crate) fn new(window: Window) -> Self {
43 let window_arc: Arc<Window> = Arc::new(window);
44
45 Self {
46 window: window_arc,
47 instance: None,
48 surface: None,
49 surface_config: None,
50 adapter: None,
51 device: None,
52 queue: None,
53 }
54 }
55
56 fn get_limits(&self) -> wgpu::Limits {
58 if cfg!(target_family = "wasm") {
59 wgpu::Limits {
60 max_color_attachments: 4,
61 ..wgpu::Limits::downlevel_webgl2_defaults()
62 }
63 } else if cfg!(any(target_os = "android", target_os = "ios")) {
64 wgpu::Limits::downlevel_defaults()
65 } else {
66 wgpu::Limits::default()
67 }
68 }
69
70 pub(crate) async fn initialize_graphics(&mut self) {
76 debug!("Creating wgpu instance...");
79
80 self.instance = Some(if cfg!(target_family = "wasm") {
81 wgpu::util::new_instance_with_webgpu_detection(wgpu::InstanceDescriptor::default())
82 .await
83 } else {
84 wgpu::Instance::new(wgpu::InstanceDescriptor::default())
85 });
86
87 debug!("Creating wgpu surface...");
88 let instance: &Instance = self.instance.as_ref().unwrap();
89 self.surface = Some(
90 instance
91 .create_surface(self.window.clone())
92 .expect("Could not create surface!"),
93 );
94
95 debug!("Describing wgpu device...");
99 let mut device_descriptor: DeviceDescriptor = wgpu::DeviceDescriptor::default();
100
101 debug!("Setting WGPU limits...");
104
105 let limits: wgpu::Limits = self.get_limits();
106 device_descriptor.required_limits = limits;
107
108 let request_adapter_options: RequestAdapterOptionsBase<&Surface<'_>> =
110 RequestAdapterOptionsBase {
111 compatible_surface: self.surface.as_ref(),
112 ..Default::default()
113 };
114
115 debug!("Grabbing wgpu adapter...");
119 let adapter_future = instance.request_adapter(&request_adapter_options);
120 self.adapter = Some(adapter_future.await.expect("Could not grab WGPU adapter!"));
121
122 debug!("Opening connection with graphics device (e.g. GPU)...");
124 let device_future = self
125 .adapter
126 .as_ref()
127 .unwrap()
128 .request_device(&device_descriptor, None);
129
130 let (device, queue) = device_future
131 .await
132 .expect("Could not open a connection with the graphics device!");
133 self.device = Some(device);
134 self.queue = Some(queue);
135
136 let size: PhysicalSize<u32> = if cfg!(target_family = "wasm") {
137 PhysicalSize::new(400, 100)
138 } else {
139 self.window.inner_size()
140 };
141
142 trace!(
143 "Window inner size (Initialize Graphics): ({}, {})",
144 size.width,
145 size.height
146 );
147 let surface: &Surface<'_> = self.surface.as_ref().unwrap();
148 self.surface_config =
149 surface.get_default_config(self.adapter.as_ref().unwrap(), size.width, size.height);
150
151 let surface_config = self
152 .surface_config
153 .as_ref()
154 .expect("Could not get surface config!");
155 let texture_format: wgpu::TextureFormat = surface_config.format;
160
161 trace!(
162 "Texture Format: {:?}, SRGB: {}, Depth Aspect: {}, Color Aspect: {}, Stencil Aspect: {}",
163 texture_format,
164 texture_format.is_srgb(),
165 texture_format.has_depth_aspect(),
166 texture_format.has_color_aspect(),
167 texture_format.has_stencil_aspect()
168 );
169
170 trace!("Surface Present Mode: {:?}", surface_config.present_mode);
171 trace!("Texture Usages: {:?}", surface_config.usage);
172 trace!("Alpha Mode: {:?}", surface_config.alpha_mode);
173
174 surface.configure(self.device.as_ref().unwrap(), surface_config);
175 }
176
177 pub(crate) fn recreate_surface(&mut self) {
183 if self.device.is_none() {
184 warn!("Device is not setup... Have graphics been initialized?");
185 return;
186 }
187
188 if self.adapter.is_none() {
189 warn!("Adapter is not setup... Have graphics been initialized?");
190 return;
191 }
192
193 debug!("Creating wgpu surface...");
196 let surface: Surface<'_> = self
197 .instance
198 .as_ref()
199 .unwrap()
200 .create_surface(self.window.clone())
201 .expect("Could not create surface!");
202
203 let size: PhysicalSize<u32> = self.window.inner_size();
204 surface.configure(
205 self.device.as_ref().unwrap(),
206 &surface
207 .get_default_config(self.adapter.as_ref().unwrap(), size.width, size.height)
208 .expect("Could not get surface default config!"),
209 );
210
211 self.surface = Some(surface);
212 }
213}