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