diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 21c1e1c917b177..6e7a533f46e55c 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -467,23 +467,6 @@ pub trait WorldQueryBatch: ) -> >::FullBatch; } -impl WorldQueryBatch for Entity -where - Entity: AlignedBatchGat, -{ - #[inline] - unsafe fn table_fetch_batched_aligned<'w>( - fetch: &mut >::Fetch, - table_row_start: usize, - len: usize, - ) -> >::FullBatch { - let entities = fetch - .entities - .unwrap_or_else(|| debug_checked_unreachable()); - entities.get_batch_aligned::(table_row_start, len) - } -} - /// A helper trait for [`WorldQueryBatch`] that works around Rust's lack of Generic Associated Types. /// /// **Note**: Consider using the type alias [`QueryBatch`] for conenvience instead of referring to `FullBatch` directly. @@ -597,6 +580,23 @@ unsafe impl WorldQuery for Entity { } } +impl WorldQueryBatch for Entity +where + Entity: AlignedBatchGat, +{ + #[inline] + unsafe fn table_fetch_batched_aligned<'w>( + fetch: &mut >::Fetch, + table_row_start: usize, + len: usize, + ) -> >::FullBatch { + let entities = fetch + .entities + .unwrap_or_else(|| debug_checked_unreachable()); + entities.get_batch_aligned::(table_row_start, len) + } +} + impl<'w> WorldQueryGats<'w> for Entity { type Fetch = EntityFetch<'w>; type Item = Entity; @@ -622,29 +622,6 @@ pub struct ReadFetch<'w, T> { sparse_set: Option<&'w ComponentSparseSet>, } -impl WorldQueryBatch for &T -where - T: AlignedBatchGat, -{ - #[inline] - unsafe fn table_fetch_batched_aligned<'w>( - fetch: &mut >::Fetch, - table_row_start: usize, - len: usize, - ) -> >::FullBatch - where - T: AlignedBatchGat, - { - //TODO: when generalized const expresions are stable, want the following: - //gcd::euclid_usize(ptr::MAX_SIMD_ALIGNMENT, N * core::mem::size_of::()); - - let components = fetch - .table_components - .unwrap_or_else(|| debug_checked_unreachable()); - components.get_batch_aligned_deref::(table_row_start, len) - } -} - /// SAFETY: `ROQueryFetch` is the same as `QueryFetch` unsafe impl WorldQuery for &T { type ReadOnly = Self; @@ -775,6 +752,29 @@ unsafe impl WorldQuery for &T { } } +impl WorldQueryBatch for &T +where + T: AlignedBatchGat, +{ + #[inline] + unsafe fn table_fetch_batched_aligned<'w>( + fetch: &mut >::Fetch, + table_row_start: usize, + len: usize, + ) -> >::FullBatch + where + T: AlignedBatchGat, + { + //TODO: when generalized const expresions are stable, want the following: + //gcd::euclid_usize(ptr::MAX_SIMD_ALIGNMENT, N * core::mem::size_of::()); + + let components = fetch + .table_components + .unwrap_or_else(|| debug_checked_unreachable()); + components.get_batch_aligned_deref::(table_row_start, len) + } +} + impl Clone for ReadFetch<'_, T> { fn clone(&self) -> Self { Self { @@ -815,39 +815,6 @@ pub struct WriteFetch<'w, T> { change_tick: u32, } -//TODO: inlines - -impl<'__w, T: Component, const N: usize, const ALIGN: usize> WorldQueryBatch - for &'__w mut T -where - T: AlignedBatchGat, - ComponentTicks: AlignedBatchGat, -{ - #[inline] - unsafe fn table_fetch_batched_aligned<'w>( - fetch: &mut >::Fetch, - table_row_start: usize, - len: usize, - ) -> >::FullBatch { - let (table_components, table_ticks) = fetch - .table_components - .zip(fetch.table_ticks) - .unwrap_or_else(|| debug_checked_unreachable()); - - MutBatch:: { - value: table_components.get_batch_aligned_deref_mut::(table_row_start, len), - ticks: TicksBatch { - // SAFETY: [table_row_start..+batch.len()] is in range - component_ticks: table_ticks - .get_batch_aligned_deref_mut::(table_row_start, len), - change_tick: fetch.change_tick, - last_change_tick: fetch.last_change_tick, - }, - _marker: PhantomData, - } - } -} - /// SAFETY: access of `&T` is a subset of `&mut T` unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T { type ReadOnly = &'__w T; @@ -1010,6 +977,37 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T { } } +impl<'__w, T: Component, const N: usize, const ALIGN: usize> WorldQueryBatch + for &'__w mut T +where + T: AlignedBatchGat, + ComponentTicks: AlignedBatchGat, +{ + #[inline] + unsafe fn table_fetch_batched_aligned<'w>( + fetch: &mut >::Fetch, + table_row_start: usize, + len: usize, + ) -> >::FullBatch { + let (table_components, table_ticks) = fetch + .table_components + .zip(fetch.table_ticks) + .unwrap_or_else(|| debug_checked_unreachable()); + + MutBatch:: { + value: table_components.get_batch_aligned_deref_mut::(table_row_start, len), + ticks: TicksBatch { + // SAFETY: [table_row_start..+batch.len()] is in range + component_ticks: table_ticks + .get_batch_aligned_deref_mut::(table_row_start, len), + change_tick: fetch.change_tick, + last_change_tick: fetch.last_change_tick, + }, + _marker: PhantomData, + } + } +} + impl Clone for WriteFetch<'_, T> { fn clone(&self) -> Self { Self { @@ -1055,28 +1053,6 @@ where } } -impl WorldQueryBatch for Option -where - T: WorldQueryBatch, -{ - #[inline] - unsafe fn table_fetch_batched_aligned<'w>( - fetch: &mut >::Fetch, - table_row_start: usize, - len: usize, - ) -> >::FullBatch { - if fetch.matches { - Some(T::table_fetch_batched_aligned( - &mut fetch.fetch, - table_row_start, - len, - )) - } else { - None - } - } -} - // SAFETY: defers to soundness of `T: WorldQuery` impl unsafe impl WorldQuery for Option { type ReadOnly = Option; @@ -1179,6 +1155,28 @@ unsafe impl WorldQuery for Option { } } +impl WorldQueryBatch for Option +where + T: WorldQueryBatch, +{ + #[inline] + unsafe fn table_fetch_batched_aligned<'w>( + fetch: &mut >::Fetch, + table_row_start: usize, + len: usize, + ) -> >::FullBatch { + if fetch.matches { + Some(T::table_fetch_batched_aligned( + &mut fetch.fetch, + table_row_start, + len, + )) + } else { + None + } + } +} + /// SAFETY: [`OptionFetch`] is read only because `T` is read only unsafe impl ReadOnlyWorldQuery for Option {} @@ -1259,6 +1257,8 @@ impl ChangeTrackers { } } +/// A batch of [`ChangeTrackers`]. This is used when performing queries with Change Trackers using the +/// [`Query::for_each_mut_batched`](crate::system::Query::for_each_mut_batched) and [`Query::for_each_batched`](crate::system::Query::for_each_batched) functions. #[derive(Clone)] pub struct ChangeTrackersBatch<'a, T, const N: usize, const ALIGN: usize> where @@ -1275,6 +1275,7 @@ where ComponentTicks: AlignedBatchGat, { /// Returns true if this component has been added since the last execution of this system. + #[inline] pub fn is_added(&self) -> bool { self.component_ticks .as_array() @@ -1283,6 +1284,7 @@ where } /// Returns true if this component has been changed since the last execution of this system. + #[inline] pub fn is_changed(&self) -> bool { self.component_ticks .as_array() @@ -1615,15 +1617,6 @@ macro_rules! impl_tuple_fetch { } } - /// SAFETY: each item in the tuple is read only - unsafe impl<$($name: ReadOnlyWorldQuery),*> ReadOnlyWorldQuery for ($($name,)*) {} - - #[allow(unused_variables)] - #[allow(non_snake_case)] - impl<'w, const N: usize, const ALIGN: usize, $($name: WorldQueryBatchGats<'w, N, ALIGN>),*> WorldQueryBatchGats<'w, N, ALIGN> for ($($name,)*) { - type FullBatch = ($($name::FullBatch,)*); - } - #[allow(unused_variables)] #[allow(non_snake_case)] #[allow(clippy::unused_unit)] @@ -1641,6 +1634,16 @@ macro_rules! impl_tuple_fetch { ($($name::table_fetch_batched_aligned($name, _table_row_start, _len),)*) } } + + /// SAFETY: each item in the tuple is read only + unsafe impl<$($name: ReadOnlyWorldQuery),*> ReadOnlyWorldQuery for ($($name,)*) {} + + #[allow(unused_variables)] + #[allow(non_snake_case)] + impl<'w, const N: usize, const ALIGN: usize, $($name: WorldQueryBatchGats<'w, N, ALIGN>),*> WorldQueryBatchGats<'w, N, ALIGN> for ($($name,)*) { + type FullBatch = ($($name::FullBatch,)*); + } + }; }