bevy_render/render_resource/
resource_macros.rs1#[cfg(debug_assertions)]
9#[macro_export]
10macro_rules! render_resource_wrapper {
11 ($wrapper_type:ident, $wgpu_type:ty) => {
12 #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))]
13 #[derive(Debug)]
14 pub struct $wrapper_type(*const ());
16
17 #[cfg(all(target_arch = "wasm32", target_feature = "atomics"))]
18 #[derive(Debug)]
19 pub struct $wrapper_type(send_wrapper::SendWrapper<*const ()>);
20
21 impl $wrapper_type {
22 pub fn new(value: $wgpu_type) -> Self {
23 let arc = std::sync::Arc::new(value);
24 let value_ptr = std::sync::Arc::into_raw(arc);
25 let unit_ptr = value_ptr.cast::<()>();
26
27 #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))]
28 return Self(unit_ptr);
29 #[cfg(all(target_arch = "wasm32", target_feature = "atomics"))]
30 return Self(send_wrapper::SendWrapper::new(unit_ptr));
31 }
32
33 pub fn try_unwrap(self) -> Option<$wgpu_type> {
34 let value_ptr = self.0.cast::<$wgpu_type>();
35 let arc = unsafe { std::sync::Arc::from_raw(value_ptr) };
37
38 std::mem::forget(self);
40
41 std::sync::Arc::try_unwrap(arc).ok()
42 }
43 }
44
45 impl std::ops::Deref for $wrapper_type {
46 type Target = $wgpu_type;
47
48 fn deref(&self) -> &Self::Target {
49 let value_ptr = self.0.cast::<$wgpu_type>();
50 let value_ref = unsafe { value_ptr.as_ref() };
52 value_ref.unwrap()
53 }
54 }
55
56 impl Drop for $wrapper_type {
57 fn drop(&mut self) {
58 let value_ptr = self.0.cast::<$wgpu_type>();
59 unsafe { std::sync::Arc::from_raw(value_ptr) };
62 }
63 }
64
65 #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))]
66 unsafe impl Send for $wrapper_type {}
71 #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))]
72 unsafe impl Sync for $wrapper_type {}
74 #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))]
75 const _: () = {
76 trait AssertSendSyncBound: Send + Sync {}
77 impl AssertSendSyncBound for $wgpu_type {}
78 };
79
80 impl Clone for $wrapper_type {
81 fn clone(&self) -> Self {
82 let value_ptr = self.0.cast::<$wgpu_type>();
83 let arc = unsafe { std::sync::Arc::from_raw(value_ptr.cast::<$wgpu_type>()) };
85 let cloned = std::sync::Arc::clone(&arc);
86 std::mem::forget(arc);
88 let cloned_value_ptr = std::sync::Arc::into_raw(cloned);
89 let cloned_unit_ptr = cloned_value_ptr.cast::<()>();
90
91 #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))]
92 return Self(cloned_unit_ptr);
93
94 #[cfg(all(target_arch = "wasm32", target_feature = "atomics"))]
97 return Self(send_wrapper::SendWrapper::new(cloned_unit_ptr));
98 }
99 }
100 };
101}
102
103#[cfg(not(debug_assertions))]
104#[macro_export]
105macro_rules! render_resource_wrapper {
106 ($wrapper_type:ident, $wgpu_type:ty) => {
107 #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))]
108 #[derive(Clone, Debug)]
109 pub struct $wrapper_type(std::sync::Arc<$wgpu_type>);
110 #[cfg(all(target_arch = "wasm32", target_feature = "atomics"))]
111 #[derive(Clone, Debug)]
112 pub struct $wrapper_type(std::sync::Arc<send_wrapper::SendWrapper<$wgpu_type>>);
113
114 impl $wrapper_type {
115 pub fn new(value: $wgpu_type) -> Self {
116 #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))]
117 return Self(std::sync::Arc::new(value));
118
119 #[cfg(all(target_arch = "wasm32", target_feature = "atomics"))]
120 return Self(std::sync::Arc::new(send_wrapper::SendWrapper::new(value)));
121 }
122
123 pub fn try_unwrap(self) -> Option<$wgpu_type> {
124 #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))]
125 return std::sync::Arc::try_unwrap(self.0).ok();
126
127 #[cfg(all(target_arch = "wasm32", target_feature = "atomics"))]
128 return std::sync::Arc::try_unwrap(self.0).ok().map(|p| p.take());
129 }
130 }
131
132 impl std::ops::Deref for $wrapper_type {
133 type Target = $wgpu_type;
134
135 fn deref(&self) -> &Self::Target {
136 self.0.as_ref()
137 }
138 }
139
140 #[cfg(not(all(target_arch = "wasm32", target_feature = "atomics")))]
141 const _: () = {
142 trait AssertSendSyncBound: Send + Sync {}
143 impl AssertSendSyncBound for $wgpu_type {}
144 };
145 };
146}
147
148#[macro_export]
149macro_rules! define_atomic_id {
150 ($atomic_id_type:ident) => {
151 #[derive(Copy, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)]
152 pub struct $atomic_id_type(core::num::NonZeroU32);
153
154 #[allow(clippy::new_without_default)]
156 impl $atomic_id_type {
157 pub fn new() -> Self {
158 use std::sync::atomic::{AtomicU32, Ordering};
159
160 static COUNTER: AtomicU32 = AtomicU32::new(1);
161
162 let counter = COUNTER.fetch_add(1, Ordering::Relaxed);
163 Self(core::num::NonZeroU32::new(counter).unwrap_or_else(|| {
164 panic!(
165 "The system ran out of unique `{}`s.",
166 stringify!($atomic_id_type)
167 );
168 }))
169 }
170 }
171
172 impl From<$atomic_id_type> for core::num::NonZeroU32 {
173 fn from(value: $atomic_id_type) -> Self {
174 value.0
175 }
176 }
177
178 impl From<core::num::NonZeroU32> for $atomic_id_type {
179 fn from(value: core::num::NonZeroU32) -> Self {
180 Self(value)
181 }
182 }
183 };
184}
185
186pub use render_resource_wrapper;