srs2dge_core/
lib.rs

1// #![feature(generic_associated_types)]
2// #![feature(type_alias_impl_trait)]
3// #![feature(drain_filter)]
4// #![feature(const_fn_floating_point_arithmetic)]
5// #![feature(generic_const_exprs)]
6
7//
8
9use main_game_loop::event::EventLoopTarget;
10use std::sync::{Arc, RwLock};
11use target::Target;
12use wgpu::{util::backend_bits_from_env, Adapter, Backends, Device, Instance, Queue};
13use winit::{
14    error::OsError,
15    window::{Window, WindowBuilder},
16};
17
18//
19
20pub use frame::Frame;
21
22pub use colorful;
23pub use log;
24
25pub use glam;
26pub use main_game_loop;
27pub use naga;
28pub use wgpu;
29pub use winit;
30
31pub use image;
32pub use rapid_qoi;
33
34pub use bytemuck;
35pub use rand;
36pub use serde;
37
38pub use integer_sqrt;
39
40//
41
42pub mod batch;
43pub mod buffer;
44pub mod color;
45pub mod frame;
46pub mod packer;
47pub mod prelude;
48pub mod shader;
49pub mod target;
50pub mod texture;
51
52//
53
54pub type DeviceStorage = Arc<RwLock<Vec<(Arc<Adapter>, Arc<Device>, Arc<Queue>)>>>;
55
56//
57
58pub struct Engine {
59    instance: Arc<Instance>,
60
61    device_storage: DeviceStorage,
62}
63
64//
65
66impl Default for Engine {
67    fn default() -> Self {
68        Self {
69            instance: Self::make_instance(),
70
71            device_storage: Default::default(),
72        }
73    }
74}
75
76impl Engine {
77    pub fn new() -> Self {
78        Self::default()
79    }
80
81    pub async fn new_target(&self, window: Arc<Window>) -> Target {
82        #[cfg(target_arch = "wasm32")]
83        {
84            use winit::platform::web::WindowExtWebSys;
85
86            let win = web_sys::window().unwrap();
87            let doc = win.document().unwrap();
88
89            doc.body()
90                .unwrap()
91                .append_child(&web_sys::Element::from(window.canvas()))
92                .unwrap();
93        }
94
95        Target::new(self.instance.clone(), window, self.device_storage.clone()).await
96    }
97
98    pub async fn new_target_element_id(&self, window: Arc<Window>, canvas_div_id: &str) -> Target {
99        let _ = canvas_div_id;
100        #[cfg(target_arch = "wasm32")]
101        {
102            use winit::platform::web::WindowExtWebSys;
103
104            let win = web_sys::window().unwrap();
105            let doc = win.document().unwrap();
106
107            doc.get_element_by_id(canvas_div_id)
108                .unwrap()
109                .append_child(&web_sys::Element::from(window.canvas()))
110                .unwrap();
111        }
112
113        Target::new(self.instance.clone(), window, self.device_storage.clone()).await
114    }
115
116    pub async fn new_target_default(&self, target: &EventLoopTarget) -> Result<Target, OsError> {
117        Ok(self
118            .new_target(Arc::new(
119                WindowBuilder::new()
120                    .with_visible(false)
121                    .with_title(env!("CARGO_PKG_NAME"))
122                    .build(target)?,
123            ))
124            .await)
125    }
126
127    pub async fn new_target_headless(&self) -> Target {
128        Target::new_headless(self.instance.clone(), self.device_storage.clone()).await
129    }
130
131    fn make_instance() -> Arc<Instance> {
132        // detect renderdoc
133        #[cfg(not(target_arch = "wasm32"))]
134        let renderdoc = std::env::vars().map(|(name, _)| name).any(|name| {
135            matches!(
136                name.as_str(),
137                "ENABLE_VULKAN_RENDERDOC_CAPTURE"
138                    | "RENDERDOC_CAPFILE"
139                    | "RENDERDOC_CAPOPTS"
140                    | "RENDERDOC_DEBUG_LOG_FILE"
141            )
142        });
143        #[cfg(target_arch = "wasm32")]
144        let renderdoc = false;
145
146        // force default to vulkan if renderdoc was detected
147        let default = if renderdoc {
148            Backends::VULKAN
149        } else {
150            Backends::all()
151        };
152
153        Arc::new(Instance::new(backend_bits_from_env().unwrap_or(default)))
154    }
155}
156
157//
158
159// shamelessly stolen from: https://github.com/popzxc/stdext-rs
160#[macro_export]
161macro_rules! function_name {
162    () => {{
163        // Okay, this is ugly, I get it. However, this is the best we can get on a stable rust.
164        fn f() {}
165        fn type_name_of<T>(_: T) -> &'static str {
166            std::any::type_name::<T>()
167        }
168        let name = type_name_of(f);
169        // `3` is the length of the `::f`.
170        &name[..name.len() - 3]
171    }};
172}
173
174#[macro_export]
175macro_rules! label {
176    () => {
177        Some($crate::function_name!())
178    };
179}