1use 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
18pub 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
40pub 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
52pub type DeviceStorage = Arc<RwLock<Vec<(Arc<Adapter>, Arc<Device>, Arc<Queue>)>>>;
55
56pub struct Engine {
59 instance: Arc<Instance>,
60
61 device_storage: DeviceStorage,
62}
63
64impl 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 #[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 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#[macro_export]
161macro_rules! function_name {
162 () => {{
163 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 &name[..name.len() - 3]
171 }};
172}
173
174#[macro_export]
175macro_rules! label {
176 () => {
177 Some($crate::function_name!())
178 };
179}