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 {
65 self.config.view_formats = vec![format.add_srgb_suffix(), format.remove_srgb_suffix()];
66 }
67 self.surface.configure(&self.device, &self.config);
68 }
69}
70
71impl Deref for AppSurface {
72 type Target = IASDQContext;
73 fn deref(&self) -> &Self::Target {
74 &self.ctx
75 }
76}
77
78pub trait SurfaceFrame {
79 fn view_size(&self) -> ViewSize;
80 fn resize_surface(&mut self);
82 fn resize_surface_by_size(&mut self, size: (u32, u32));
83 fn pintch(&mut self, _touch: Touch, _scale: f32) {}
84 fn touch(&mut self, _touch: Touch) {}
85 fn normalize_touch_point(&self, _touch_point_x: f32, _touch_point_y: f32) -> (f32, f32) {
86 unimplemented!()
87 }
88 fn enter_frame(&mut self) {}
89 fn get_current_frame_view(
90 &self,
91 _view_format: Option<wgpu::TextureFormat>,
92 ) -> (wgpu::SurfaceTexture, wgpu::TextureView) {
93 unimplemented!()
94 }
95 fn create_current_frame_view(
96 &self,
97 device: &wgpu::Device,
98 surface: &wgpu::Surface,
99 config: &wgpu::SurfaceConfiguration,
100 view_format: Option<wgpu::TextureFormat>,
101 ) -> (wgpu::SurfaceTexture, wgpu::TextureView) {
102 let frame = match surface.get_current_texture() {
103 Ok(frame) => frame,
104 Err(_) => {
105 surface.configure(device, config);
106 surface
107 .get_current_texture()
108 .expect("Failed to acquire next swap chain texture!")
109 }
110 };
111 let view = frame.texture.create_view(&wgpu::TextureViewDescriptor {
112 label: Some("frame texture view"),
113 format: if view_format.is_none() {
114 Some(config.format.add_srgb_suffix())
116 } else {
117 view_format
118 },
119 ..Default::default()
120 });
121 (frame, view)
122 }
123}
124
125impl SurfaceFrame for AppSurface {
126 fn view_size(&self) -> ViewSize {
127 let size = self.get_view_size();
128 ViewSize {
129 width: size.0,
130 height: size.1,
131 }
132 }
133
134 fn resize_surface(&mut self) {
135 let size = self.get_view_size();
136 self.ctx.config.width = size.0;
137 self.ctx.config.height = size.1;
138 self.surface.configure(&self.device, &self.config);
139 }
140
141 fn resize_surface_by_size(&mut self, size: (u32, u32)) {
142 self.ctx.config.width = size.0;
143 self.ctx.config.height = size.1;
144 self.surface.configure(&self.device, &self.config);
145 }
146
147 fn normalize_touch_point(&self, touch_point_x: f32, touch_point_y: f32) -> (f32, f32) {
148 let size = self.get_view_size();
149 (
150 touch_point_x * self.scale_factor / size.0 as f32,
151 touch_point_y * self.scale_factor / size.1 as f32,
152 )
153 }
154
155 fn get_current_frame_view(
156 &self,
157 view_format: Option<wgpu::TextureFormat>,
158 ) -> (wgpu::SurfaceTexture, wgpu::TextureView) {
159 self.create_current_frame_view(&self.device, &self.surface, &self.config, view_format)
160 }
161}
162
163async fn create_iasdq_context(
164 instance: Instance,
165 surface: Surface<'static>,
166 physical_size: (u32, u32),
167) -> IASDQContext {
168 let (adapter, device, queue) = crate::request_device(&instance, &surface).await;
169
170 let caps = surface.get_capabilities(&adapter);
171 let prefered = caps.formats[0];
172
173 let format = if cfg!(all(target_arch = "wasm32", not(feature = "webgl"))) {
174 prefered.remove_srgb_suffix()
177 } else {
178 prefered
179 };
180 let view_formats = if cfg!(feature = "webgl") {
181 vec![]
185 } else if cfg!(target_os = "android") {
186 vec![format]
196 } else if format.is_srgb() {
197 vec![format, format.remove_srgb_suffix()]
198 } else {
199 vec![format.add_srgb_suffix(), format.remove_srgb_suffix()]
200 };
201
202 let mut config = surface
203 .get_default_config(&adapter, physical_size.0, physical_size.1)
204 .expect("Surface isn't supported by the adapter.");
205
206 config.view_formats = view_formats;
207 config.format = format;
208
209 surface.configure(&device, &config);
210
211 IASDQContext {
212 instance,
213 surface: SharedPtr::new(surface),
214 config,
215 adapter,
216 device,
217 queue,
218 }
219}
220
221async fn request_device(
222 instance: &Instance,
223 surface: &Surface<'static>,
224) -> (wgpu::Adapter, wgpu::Device, wgpu::Queue) {
225 let adapter = instance
226 .request_adapter(&wgpu::RequestAdapterOptions {
227 power_preference: wgpu::PowerPreference::from_env()
228 .unwrap_or(wgpu::PowerPreference::HighPerformance),
229 force_fallback_adapter: false,
230 compatible_surface: Some(surface),
231 })
232 .await
233 .expect("No suitable GPU adapters found on the system!");
234
235 let adapter_info = adapter.get_info();
236 println!("Using {} ({:?})", adapter_info.name, adapter_info.backend);
237
238 let base_dir = std::env::var("CARGO_MANIFEST_DIR");
239 let _trace_path = if let Ok(base_dir) = base_dir {
240 Some(std::path::PathBuf::from(&base_dir).join("WGPU_TRACE_ERROR"))
241 } else {
242 None
243 };
244
245 let mut adp_features = adapter.features();
248 #[cfg(target_family = "unix")]
249 {
250 if adapter_info.name.contains("NVIDIA") {
251 adp_features.remove(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE);
252 adp_features.remove(wgpu::Features::EXPERIMENTAL_RAY_QUERY);
253 }
254 }
255 let res = adapter
259 .request_device(
260 &wgpu::DeviceDescriptor {
261 label: None,
262 required_features: adp_features,
263 required_limits: adapter.limits(),
264 memory_hints: wgpu::MemoryHints::Performance,
265 trace: wgpu::Trace::Off,
266 }
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}