1use core::ops::Deref;
2use wgpu::{Instance, Surface};
3
4mod touch;
5pub use touch::*;
6
7#[cfg_attr(
8 any(target_os = "ios", all(feature = "mac_catalyst", target_os = "macos")),
9 path = "ios.rs"
10)]
11#[cfg_attr(target_os = "android", path = "android.rs")]
12#[cfg_attr(
13 all(target_arch = "wasm32", feature = "web_rwh"),
14 path = "web_rwh/mod.rs"
15)]
16#[cfg_attr(
17 any(
18 all(not(feature = "mac_catalyst"), target_os = "macos"),
19 target_os = "windows",
20 target_os = "linux",
21 ),
22 path = "app_surface_use_winit.rs"
23)]
24#[cfg_attr(
25 all(target_arch = "wasm32", not(feature = "web_rwh")),
26 path = "app_surface_use_winit.rs"
27)]
28mod app_surface;
29pub use app_surface::*;
30
31#[repr(C)]
38#[derive(Debug)]
39pub struct ViewSize {
40 pub width: u32,
41 pub height: u32,
42}
43
44#[cfg(target_arch = "wasm32")]
45use std::rc::Rc as SharedPtr;
46#[cfg(not(target_arch = "wasm32"))]
47use std::sync::Arc as SharedPtr;
48#[derive(Clone)]
50pub struct IASDQContext {
51 pub instance: wgpu::Instance,
52 pub surface: SharedPtr<wgpu::Surface<'static>>,
53 pub config: wgpu::SurfaceConfiguration,
54 pub adapter: wgpu::Adapter,
55 pub device: wgpu::Device,
56 pub queue: wgpu::Queue,
57}
58
59impl IASDQContext {
60 pub fn update_config_format(&mut self, format: wgpu::TextureFormat) {
61 self.config.format = format;
62 if cfg!(feature = "webgl") {
63 } else if format == format.remove_srgb_suffix() {
65 self.config.view_formats = vec![format.add_srgb_suffix()];
66 } else {
67 self.config.view_formats = vec![format];
68 }
69 self.surface.configure(&self.device, &self.config);
70 }
71}
72
73impl Deref for AppSurface {
74 type Target = IASDQContext;
75 fn deref(&self) -> &Self::Target {
76 &self.ctx
77 }
78}
79
80pub trait SurfaceFrame {
81 fn view_size(&self) -> ViewSize;
82 fn resize_surface(&mut self);
84 fn resize_surface_by_size(&mut self, size: (u32, u32));
85 fn pintch(&mut self, _touch: Touch, _scale: f32) {}
86 fn touch(&mut self, _touch: Touch) {}
87 fn normalize_touch_point(&self, _touch_point_x: f32, _touch_point_y: f32) -> (f32, f32) {
88 unimplemented!()
89 }
90 fn enter_frame(&mut self) {}
91 fn get_current_frame_view(
92 &self,
93 _view_format: Option<wgpu::TextureFormat>,
94 ) -> (wgpu::SurfaceTexture, wgpu::TextureView) {
95 unimplemented!()
96 }
97 fn create_current_frame_view(
98 &self,
99 device: &wgpu::Device,
100 surface: &wgpu::Surface,
101 config: &wgpu::SurfaceConfiguration,
102 view_format: Option<wgpu::TextureFormat>,
103 ) -> (wgpu::SurfaceTexture, wgpu::TextureView) {
104 let frame = match surface.get_current_texture() {
105 Ok(frame) => frame,
106 Err(_) => {
107 surface.configure(device, config);
108 surface
109 .get_current_texture()
110 .expect("Failed to acquire next swap chain texture!")
111 }
112 };
113 let view = frame.texture.create_view(&wgpu::TextureViewDescriptor {
114 label: Some("frame texture view"),
115 format: if view_format.is_none() {
116 Some(config.format.add_srgb_suffix())
118 } else {
119 view_format
120 },
121 ..Default::default()
122 });
123 (frame, view)
124 }
125}
126
127impl SurfaceFrame for AppSurface {
128 fn view_size(&self) -> ViewSize {
129 let size = self.get_view_size();
130 ViewSize {
131 width: size.0,
132 height: size.1,
133 }
134 }
135
136 fn resize_surface(&mut self) {
137 let size = self.get_view_size();
138 self.ctx.config.width = size.0;
139 self.ctx.config.height = size.1;
140 self.surface.configure(&self.device, &self.config);
141 }
142
143 fn resize_surface_by_size(&mut self, size: (u32, u32)) {
144 self.ctx.config.width = size.0;
145 self.ctx.config.height = size.1;
146 self.surface.configure(&self.device, &self.config);
147 }
148
149 fn normalize_touch_point(&self, touch_point_x: f32, touch_point_y: f32) -> (f32, f32) {
150 let size = self.get_view_size();
151 (
152 touch_point_x * self.scale_factor / size.0 as f32,
153 touch_point_y * self.scale_factor / size.1 as f32,
154 )
155 }
156
157 fn get_current_frame_view(
158 &self,
159 view_format: Option<wgpu::TextureFormat>,
160 ) -> (wgpu::SurfaceTexture, wgpu::TextureView) {
161 self.create_current_frame_view(&self.device, &self.surface, &self.config, view_format)
162 }
163}
164
165async fn create_iasdq_context(
166 instance: Instance,
167 surface: Surface<'static>,
168 physical_size: (u32, u32),
169) -> IASDQContext {
170 let (adapter, device, queue) = crate::request_device(&instance, &surface).await;
171
172 let caps = surface.get_capabilities(&adapter);
173 let prefered = caps.formats[0];
174
175 let format = if cfg!(all(target_arch = "wasm32", not(feature = "webgl"))) {
176 prefered.remove_srgb_suffix()
179 } else {
180 prefered
181 };
182 let view_formats = if cfg!(feature = "webgl") {
183 vec![]
187 } else if cfg!(target_os = "android") {
188 vec![format]
198 } else if format.is_srgb() {
199 vec![format, format.remove_srgb_suffix()]
200 } else {
201 vec![format.add_srgb_suffix(), format.remove_srgb_suffix()]
202 };
203
204 let mut config = surface
205 .get_default_config(&adapter, physical_size.0, physical_size.1)
206 .expect("Surface isn't supported by the adapter.");
207
208 config.view_formats = view_formats;
209 config.format = format;
210
211 surface.configure(&device, &config);
212
213 IASDQContext {
214 instance,
215 surface: SharedPtr::new(surface),
216 config,
217 adapter,
218 device,
219 queue,
220 }
221}
222
223async fn request_device(
224 instance: &Instance,
225 surface: &Surface<'static>,
226) -> (wgpu::Adapter, wgpu::Device, wgpu::Queue) {
227 let adapter = instance
228 .request_adapter(&wgpu::RequestAdapterOptions {
229 power_preference: wgpu::PowerPreference::from_env()
230 .unwrap_or(wgpu::PowerPreference::HighPerformance),
231 force_fallback_adapter: false,
232 compatible_surface: Some(surface),
233 })
234 .await
235 .expect("No suitable GPU adapters found on the system!");
236
237 let adapter_info = adapter.get_info();
238 println!("Using {} ({:?})", adapter_info.name, adapter_info.backend);
239
240 let base_dir = std::env::var("CARGO_MANIFEST_DIR");
241 let _trace_path = if let Ok(base_dir) = base_dir {
242 Some(std::path::PathBuf::from(&base_dir).join("WGPU_TRACE_ERROR"))
243 } else {
244 None
245 };
246
247 let mut adp_features = adapter.features();
250 #[cfg(target_family = "unix")]
251 {
252 if adapter_info.name.contains("NVIDIA") {
253 adp_features.remove(wgpu::Features::EXPERIMENTAL_RAY_QUERY);
254 }
255 }
256 let res = adapter
260 .request_device(&wgpu::DeviceDescriptor {
261 label: None,
262 required_features: adp_features,
263 required_limits: adapter.limits(),
264 experimental_features: unsafe { wgpu::ExperimentalFeatures::enabled() },
265 memory_hints: wgpu::MemoryHints::Performance,
266 trace: wgpu::Trace::Off,
267 })
268 .await;
269
270 match res {
271 Err(err) => {
272 panic!("request_device failed: {err:?}");
273 }
274 Ok(tuple) => (adapter, tuple.0, tuple.1),
275 }
276}