bevy_render/view/visibility/
render_layers.rs

1use 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
7/// An identifier for a rendering layer.
8pub type Layer = usize;
9
10/// Describes which rendering layers an entity belongs to.
11///
12/// Cameras with this component will only render entities with intersecting
13/// layers.
14///
15/// Entities may belong to one or more layers, or no layer at all.
16///
17/// The [`Default`] instance of `RenderLayers` contains layer `0`, the first layer.
18///
19/// An entity with this component without any layers is invisible.
20///
21/// Entities without this component belong to layer `0`.
22#[derive(Component, Clone, Reflect, PartialEq, Eq, PartialOrd, Ord)]
23#[reflect(Component, Default, PartialEq, Debug)]
24pub struct RenderLayers(SmallVec<[u64; INLINE_BLOCKS]>);
25
26/// The number of memory blocks stored inline
27const 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    /// By default, this structure includes layer `0`, which represents the first layer.
51    ///
52    /// This is distinct from [`RenderLayers::none`], which doesn't belong to any layers.
53    fn default() -> Self {
54        const { Self::layer(0) }
55    }
56}
57
58impl RenderLayers {
59    /// Create a new `RenderLayers` belonging to the given layer.
60    ///
61    /// This `const` constructor is limited to `size_of::<usize>()` layers.
62    /// If you need to support an arbitrary number of layers, use [`with`](RenderLayers::with)
63    /// or [`from_layers`](RenderLayers::from_layers).
64    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    /// Create a new `RenderLayers` that belongs to no layers.
76    ///
77    /// This is distinct from [`RenderLayers::default`], which belongs to the first layer.
78    pub const fn none() -> Self {
79        RenderLayers(SmallVec::from_const([0; INLINE_BLOCKS]))
80    }
81
82    /// Create a `RenderLayers` from a list of layers.
83    pub fn from_layers(layers: &[Layer]) -> Self {
84        layers.iter().copied().collect()
85    }
86
87    /// Add the given layer.
88    ///
89    /// This may be called multiple times to allow an entity to belong
90    /// to multiple rendering layers.
91    #[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    /// Removes the given rendering layer.
100    #[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            // Drop trailing zero memory blocks.
106            // NOTE: This is not just an optimization, it is necessary for the derived PartialEq impl to be correct.
107            if buffer_index == self.0.len() - 1 {
108                self = self.shrink();
109            }
110        }
111        self
112    }
113
114    /// Get an iterator of the layers.
115    pub fn iter(&self) -> impl Iterator<Item = Layer> + '_ {
116        self.0.iter().copied().zip(0..).flat_map(Self::iter_layers)
117    }
118
119    /// Determine if a `RenderLayers` intersects another.
120    ///
121    /// `RenderLayers`s intersect if they share any common layers.
122    ///
123    /// A `RenderLayers` with no layers will not match any other
124    /// `RenderLayers`, even another with no layers.
125    pub fn intersects(&self, other: &RenderLayers) -> bool {
126        // Check for the common case where the view layer and entity layer
127        // both point towards our default layer.
128        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    /// Get the bitmask representation of the contained layers.
142    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    /// Returns the set of [layers](Layer) shared by two instances of [`RenderLayers`].
175    ///
176    /// This corresponds to the `self & other` operation.
177    pub fn intersection(&self, other: &Self) -> Self {
178        self.combine_blocks(other, |a, b| a & b).shrink()
179    }
180
181    /// Returns all [layers](Layer) included in either instance of [`RenderLayers`].
182    ///
183    /// This corresponds to the `self | other` operation.
184    pub fn union(&self, other: &Self) -> Self {
185        self.combine_blocks(other, |a, b| a | b) // doesn't need to be shrunk, if the inputs are nonzero then the result will be too
186    }
187
188    /// Returns all [layers](Layer) included in exactly one of the instances of [`RenderLayers`].
189    ///
190    /// This corresponds to the "exclusive or" (XOR) operation: `self ^ other`.
191    pub fn symmetric_difference(&self, other: &Self) -> Self {
192        self.combine_blocks(other, |a, b| a ^ b).shrink()
193    }
194
195    /// Deallocates any trailing-zero memory blocks from this instance
196    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    /// Creates a new instance of [`RenderLayers`] by applying a function to the memory blocks
209    /// of self and another instance.
210    ///
211    /// If the function `f` might return `0` for non-zero inputs, you should call [`Self::shrink`]
212    /// on the output to ensure that there are no trailing zero memory blocks that would break
213    /// this type's equality comparison.
214    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        // Since it has layers greater than 64, the instance should take up two memory blocks
359        let layers = RenderLayers::from_layers(&[1, 77]);
360        assert!(layers.0.len() == 2);
361        // When excluding that layer, it should drop the extra memory block
362        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}