bevy_render/view/visibility/
render_layers.rs1use bevy_ecs::prelude::{Component, ReflectComponent};
2use bevy_reflect::{std_traits::ReflectDefault, Reflect};
3use smallvec::SmallVec;
4
5pub const DEFAULT_LAYERS: &RenderLayers = &RenderLayers::layer(0);
6
7pub type Layer = usize;
9
10#[derive(Component, Clone, Reflect, PartialEq, Eq, PartialOrd, Ord)]
23#[reflect(Component, Default, PartialEq, Debug)]
24pub struct RenderLayers(SmallVec<[u64; INLINE_BLOCKS]>);
25
26const INLINE_BLOCKS: usize = 1;
28
29impl Default for &RenderLayers {
30 fn default() -> Self {
31 DEFAULT_LAYERS
32 }
33}
34
35impl core::fmt::Debug for RenderLayers {
36 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
37 f.debug_tuple("RenderLayers")
38 .field(&self.iter().collect::<Vec<_>>())
39 .finish()
40 }
41}
42
43impl FromIterator<Layer> for RenderLayers {
44 fn from_iter<T: IntoIterator<Item = Layer>>(i: T) -> Self {
45 i.into_iter().fold(Self::none(), RenderLayers::with)
46 }
47}
48
49impl Default for RenderLayers {
50 fn default() -> Self {
54 const { Self::layer(0) }
55 }
56}
57
58impl RenderLayers {
59 pub const fn layer(n: Layer) -> Self {
65 let (buffer_index, bit) = Self::layer_info(n);
66 assert!(
67 buffer_index < INLINE_BLOCKS,
68 "layer is out of bounds for const construction"
69 );
70 let mut buffer = [0; INLINE_BLOCKS];
71 buffer[buffer_index] = bit;
72 RenderLayers(SmallVec::from_const(buffer))
73 }
74
75 pub const fn none() -> Self {
79 RenderLayers(SmallVec::from_const([0; INLINE_BLOCKS]))
80 }
81
82 pub fn from_layers(layers: &[Layer]) -> Self {
84 layers.iter().copied().collect()
85 }
86
87 #[must_use]
92 pub fn with(mut self, layer: Layer) -> Self {
93 let (buffer_index, bit) = Self::layer_info(layer);
94 self.extend_buffer(buffer_index + 1);
95 self.0[buffer_index] |= bit;
96 self
97 }
98
99 #[must_use]
101 pub fn without(mut self, layer: Layer) -> Self {
102 let (buffer_index, bit) = Self::layer_info(layer);
103 if buffer_index < self.0.len() {
104 self.0[buffer_index] &= !bit;
105 if buffer_index == self.0.len() - 1 {
108 self = self.shrink();
109 }
110 }
111 self
112 }
113
114 pub fn iter(&self) -> impl Iterator<Item = Layer> + '_ {
116 self.0.iter().copied().zip(0..).flat_map(Self::iter_layers)
117 }
118
119 pub fn intersects(&self, other: &RenderLayers) -> bool {
126 if self.0.as_ptr() == other.0.as_ptr() {
129 return true;
130 }
131
132 for (self_layer, other_layer) in self.0.iter().zip(other.0.iter()) {
133 if (*self_layer & *other_layer) != 0 {
134 return true;
135 }
136 }
137
138 false
139 }
140
141 pub fn bits(&self) -> &[u64] {
143 self.0.as_slice()
144 }
145
146 const fn layer_info(layer: usize) -> (usize, u64) {
147 let buffer_index = layer / 64;
148 let bit_index = layer % 64;
149 let bit = 1u64 << bit_index;
150
151 (buffer_index, bit)
152 }
153
154 fn extend_buffer(&mut self, other_len: usize) {
155 let new_size = core::cmp::max(self.0.len(), other_len);
156 self.0.reserve_exact(new_size - self.0.len());
157 self.0.resize(new_size, 0u64);
158 }
159
160 fn iter_layers(buffer_and_offset: (u64, usize)) -> impl Iterator<Item = Layer> + 'static {
161 let (mut buffer, mut layer) = buffer_and_offset;
162 layer *= 64;
163 core::iter::from_fn(move || {
164 if buffer == 0 {
165 return None;
166 }
167 let next = buffer.trailing_zeros() + 1;
168 buffer = buffer.checked_shr(next).unwrap_or(0);
169 layer += next as usize;
170 Some(layer - 1)
171 })
172 }
173
174 pub fn intersection(&self, other: &Self) -> Self {
178 self.combine_blocks(other, |a, b| a & b).shrink()
179 }
180
181 pub fn union(&self, other: &Self) -> Self {
185 self.combine_blocks(other, |a, b| a | b) }
187
188 pub fn symmetric_difference(&self, other: &Self) -> Self {
192 self.combine_blocks(other, |a, b| a ^ b).shrink()
193 }
194
195 fn shrink(mut self) -> Self {
197 let mut any_dropped = false;
198 while self.0.len() > INLINE_BLOCKS && self.0.last() == Some(&0) {
199 self.0.pop();
200 any_dropped = true;
201 }
202 if any_dropped && self.0.len() <= INLINE_BLOCKS {
203 self.0.shrink_to_fit();
204 }
205 self
206 }
207
208 fn combine_blocks(&self, other: &Self, mut f: impl FnMut(u64, u64) -> u64) -> Self {
215 let mut a = self.0.iter();
216 let mut b = other.0.iter();
217 let mask = core::iter::from_fn(|| {
218 let a = a.next().copied();
219 let b = b.next().copied();
220 if a.is_none() && b.is_none() {
221 return None;
222 }
223 Some(f(a.unwrap_or_default(), b.unwrap_or_default()))
224 });
225 Self(mask.collect())
226 }
227}
228
229impl core::ops::BitAnd for RenderLayers {
230 type Output = Self;
231 fn bitand(self, rhs: Self) -> Self::Output {
232 self.intersection(&rhs)
233 }
234}
235
236impl core::ops::BitOr for RenderLayers {
237 type Output = Self;
238 fn bitor(self, rhs: Self) -> Self::Output {
239 self.union(&rhs)
240 }
241}
242
243impl core::ops::BitXor for RenderLayers {
244 type Output = Self;
245 fn bitxor(self, rhs: Self) -> Self::Output {
246 self.symmetric_difference(&rhs)
247 }
248}
249
250#[cfg(test)]
251mod rendering_mask_tests {
252 use super::{Layer, RenderLayers};
253 use smallvec::SmallVec;
254
255 #[test]
256 fn rendering_mask_sanity() {
257 let layer_0 = RenderLayers::layer(0);
258 assert_eq!(layer_0.0.len(), 1, "layer 0 is one buffer");
259 assert_eq!(layer_0.0[0], 1, "layer 0 is mask 1");
260 let layer_1 = RenderLayers::layer(1);
261 assert_eq!(layer_1.0.len(), 1, "layer 1 is one buffer");
262 assert_eq!(layer_1.0[0], 2, "layer 1 is mask 2");
263 let layer_0_1 = RenderLayers::layer(0).with(1);
264 assert_eq!(layer_0_1.0.len(), 1, "layer 0 + 1 is one buffer");
265 assert_eq!(layer_0_1.0[0], 3, "layer 0 + 1 is mask 3");
266 let layer_0_1_without_0 = layer_0_1.without(0);
267 assert_eq!(
268 layer_0_1_without_0.0.len(),
269 1,
270 "layer 0 + 1 - 0 is one buffer"
271 );
272 assert_eq!(layer_0_1_without_0.0[0], 2, "layer 0 + 1 - 0 is mask 2");
273 let layer_0_2345 = RenderLayers::layer(0).with(2345);
274 assert_eq!(layer_0_2345.0.len(), 37, "layer 0 + 2345 is 37 buffers");
275 assert_eq!(layer_0_2345.0[0], 1, "layer 0 + 2345 is mask 1");
276 assert_eq!(
277 layer_0_2345.0[36], 2199023255552,
278 "layer 0 + 2345 is mask 2199023255552"
279 );
280 assert!(
281 layer_0_2345.intersects(&layer_0),
282 "layer 0 + 2345 intersects 0"
283 );
284 assert!(
285 RenderLayers::layer(1).intersects(&RenderLayers::layer(1)),
286 "layers match like layers"
287 );
288 assert!(
289 RenderLayers::layer(0).intersects(&RenderLayers(SmallVec::from_const([1]))),
290 "a layer of 0 means the mask is just 1 bit"
291 );
292
293 assert!(
294 RenderLayers::layer(0)
295 .with(3)
296 .intersects(&RenderLayers::layer(3)),
297 "a mask will match another mask containing any similar layers"
298 );
299
300 assert!(
301 RenderLayers::default().intersects(&RenderLayers::default()),
302 "default masks match each other"
303 );
304
305 assert!(
306 !RenderLayers::layer(0).intersects(&RenderLayers::layer(1)),
307 "masks with differing layers do not match"
308 );
309 assert!(
310 !RenderLayers::none().intersects(&RenderLayers::none()),
311 "empty masks don't match"
312 );
313 assert_eq!(
314 RenderLayers::from_layers(&[0, 2, 16, 30])
315 .iter()
316 .collect::<Vec<_>>(),
317 vec![0, 2, 16, 30],
318 "from_layers and get_layers should roundtrip"
319 );
320 assert_eq!(
321 format!("{:?}", RenderLayers::from_layers(&[0, 1, 2, 3])).as_str(),
322 "RenderLayers([0, 1, 2, 3])",
323 "Debug instance shows layers"
324 );
325 assert_eq!(
326 RenderLayers::from_layers(&[0, 1, 2]),
327 <RenderLayers as FromIterator<Layer>>::from_iter(vec![0, 1, 2]),
328 "from_layers and from_iter are equivalent"
329 );
330
331 let tricky_layers = vec![0, 5, 17, 55, 999, 1025, 1026];
332 let layers = RenderLayers::from_layers(&tricky_layers);
333 let out = layers.iter().collect::<Vec<_>>();
334 assert_eq!(tricky_layers, out, "tricky layers roundtrip");
335 }
336
337 const MANY: RenderLayers = RenderLayers(SmallVec::from_const([u64::MAX]));
338
339 #[test]
340 fn render_layer_ops() {
341 let a = RenderLayers::from_layers(&[2, 4, 6]);
342 let b = RenderLayers::from_layers(&[1, 2, 3, 4, 5]);
343
344 assert_eq!(
345 a.clone() | b.clone(),
346 RenderLayers::from_layers(&[1, 2, 3, 4, 5, 6])
347 );
348 assert_eq!(a.clone() & b.clone(), RenderLayers::from_layers(&[2, 4]));
349 assert_eq!(a ^ b, RenderLayers::from_layers(&[1, 3, 5, 6]));
350
351 assert_eq!(RenderLayers::none() & MANY, RenderLayers::none());
352 assert_eq!(RenderLayers::none() | MANY, MANY);
353 assert_eq!(RenderLayers::none() ^ MANY, MANY);
354 }
355
356 #[test]
357 fn render_layer_shrink() {
358 let layers = RenderLayers::from_layers(&[1, 77]);
360 assert!(layers.0.len() == 2);
361 let layers = layers.without(77);
363 assert!(layers.0.len() == 1);
364 }
365
366 #[test]
367 fn render_layer_iter_no_overflow() {
368 let layers = RenderLayers::from_layers(&[63]);
369 layers.iter().count();
370 }
371}