Skip to content

Commit 4d7b3ee

Browse files
committed
Have Entity(Ref|Mut)Except look up the component ids on initialization and store them in an Access that can be borrowed by each row.
1 parent e0b6063 commit 4d7b3ee

File tree

2 files changed

+99
-75
lines changed

2 files changed

+99
-75
lines changed

crates/bevy_ecs/src/query/fetch.rs

+50-47
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use crate::{
1313
};
1414
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
1515
use bevy_utils::all_tuples;
16-
use smallvec::SmallVec;
1716
use std::{cell::UnsafeCell, marker::PhantomData};
1817

1918
/// Types that can be fetched from a [`World`] using a [`Query`].
@@ -857,13 +856,13 @@ unsafe impl<'w, 's> QueryData for FilteredEntityMut<'w, 's> {
857856
/// SAFETY: `EntityRefExcept` guards access to all components in the bundle `B`
858857
/// and populates `Access` values so that queries that conflict with this access
859858
/// are rejected.
860-
unsafe impl<'a, B> WorldQuery for EntityRefExcept<'a, B>
859+
unsafe impl<B> WorldQuery for EntityRefExcept<'_, '_, B>
861860
where
862861
B: Bundle,
863862
{
864-
type Fetch<'w, 's> = UnsafeWorldCell<'w>;
865-
type Item<'w, 's> = EntityRefExcept<'w, B>;
866-
type State = SmallVec<[ComponentId; 4]>;
863+
type Fetch<'w, 's> = (UnsafeWorldCell<'w>, &'s Access<ComponentId>);
864+
type Item<'w, 's> = EntityRefExcept<'w, 's, B>;
865+
type State = Access<ComponentId>;
867866

868867
fn shrink<'wlong: 'wshort, 'wshort, 's>(
869868
item: Self::Item<'wlong, 's>,
@@ -879,11 +878,11 @@ where
879878

880879
unsafe fn init_fetch<'w, 's>(
881880
world: UnsafeWorldCell<'w>,
882-
_: &'s Self::State,
881+
state: &'s Self::State,
883882
_: Tick,
884883
_: Tick,
885884
) -> Self::Fetch<'w, 's> {
886-
world
885+
(world, state)
887886
}
888887

889888
const IS_DENSE: bool = true;
@@ -899,45 +898,47 @@ where
899898
unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w, 's>, _: &'s Self::State, _: &'w Table) {}
900899

901900
unsafe fn fetch<'w, 's>(
902-
world: &mut Self::Fetch<'w, 's>,
901+
(world, access): &mut Self::Fetch<'w, 's>,
903902
entity: Entity,
904903
_: TableRow,
905904
) -> Self::Item<'w, 's> {
906905
let cell = world.get_entity(entity).unwrap();
907-
EntityRefExcept::new(cell)
906+
EntityRefExcept::new(cell, access)
908907
}
909908

910909
fn update_component_access(
911910
state: &Self::State,
912911
filtered_access: &mut FilteredAccess<ComponentId>,
913912
) {
914-
let mut my_access = Access::new();
915-
my_access.read_all_components();
916-
for id in state {
917-
my_access.remove_component_read(*id);
918-
}
919-
920-
let access = filtered_access.access_mut();
921913
assert!(
922-
access.is_compatible(&my_access),
914+
filtered_access.access().is_compatible(state),
923915
"`EntityRefExcept<{}>` conflicts with a previous access in this query.",
924916
std::any::type_name::<B>(),
925917
);
926-
access.extend(&my_access);
918+
filtered_access.access.extend(state);
927919
}
928920

929921
fn init_state(world: &mut World) -> Self::State {
930-
Self::get_state(world.components()).unwrap()
922+
let mut access = Access::new();
923+
access.read_all_components();
924+
B::component_ids(&mut world.components, &mut world.storages, &mut |id| {
925+
access.remove_component_read(id);
926+
});
927+
access
931928
}
932929

933930
fn get_state(components: &Components) -> Option<Self::State> {
934-
let mut ids = SmallVec::new();
931+
let mut access = Access::new();
932+
access.read_all_components();
933+
let mut all_initialized = true;
935934
B::get_component_ids(components, &mut |maybe_id| {
936935
if let Some(id) = maybe_id {
937-
ids.push(id);
936+
access.remove_component_read(id);
937+
} else {
938+
all_initialized = false;
938939
}
939940
});
940-
Some(ids)
941+
all_initialized.then_some(access)
941942
}
942943

943944
fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool {
@@ -946,7 +947,7 @@ where
946947
}
947948

948949
/// SAFETY: `Self` is the same as `Self::ReadOnly`.
949-
unsafe impl<'a, B> QueryData for EntityRefExcept<'a, B>
950+
unsafe impl<B> QueryData for EntityRefExcept<'_, '_, B>
950951
where
951952
B: Bundle,
952953
{
@@ -955,18 +956,18 @@ where
955956

956957
/// SAFETY: `EntityRefExcept` enforces read-only access to its contained
957958
/// components.
958-
unsafe impl<'a, B> ReadOnlyQueryData for EntityRefExcept<'a, B> where B: Bundle {}
959+
unsafe impl<B> ReadOnlyQueryData for EntityRefExcept<'_, '_, B> where B: Bundle {}
959960

960961
/// SAFETY: `EntityMutExcept` guards access to all components in the bundle `B`
961962
/// and populates `Access` values so that queries that conflict with this access
962963
/// are rejected.
963-
unsafe impl<'a, B> WorldQuery for EntityMutExcept<'a, B>
964+
unsafe impl<B> WorldQuery for EntityMutExcept<'_, '_, B>
964965
where
965966
B: Bundle,
966967
{
967-
type Fetch<'w, 's> = UnsafeWorldCell<'w>;
968-
type Item<'w, 's> = EntityMutExcept<'w, B>;
969-
type State = SmallVec<[ComponentId; 4]>;
968+
type Fetch<'w, 's> = (UnsafeWorldCell<'w>, &'s Access<ComponentId>);
969+
type Item<'w, 's> = EntityMutExcept<'w, 's, B>;
970+
type State = Access<ComponentId>;
970971

971972
fn shrink<'wlong: 'wshort, 'wshort, 's>(
972973
item: Self::Item<'wlong, 's>,
@@ -982,11 +983,11 @@ where
982983

983984
unsafe fn init_fetch<'w, 's>(
984985
world: UnsafeWorldCell<'w>,
985-
_: &'s Self::State,
986+
state: &'s Self::State,
986987
_: Tick,
987988
_: Tick,
988989
) -> Self::Fetch<'w, 's> {
989-
world
990+
(world, state)
990991
}
991992

992993
const IS_DENSE: bool = true;
@@ -1002,45 +1003,47 @@ where
10021003
unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w, 's>, _: &'s Self::State, _: &'w Table) {}
10031004

10041005
unsafe fn fetch<'w, 's>(
1005-
world: &mut Self::Fetch<'w, 's>,
1006+
(world, access): &mut Self::Fetch<'w, 's>,
10061007
entity: Entity,
10071008
_: TableRow,
10081009
) -> Self::Item<'w, 's> {
10091010
let cell = world.get_entity(entity).unwrap();
1010-
EntityMutExcept::new(cell)
1011+
EntityMutExcept::new(cell, access)
10111012
}
10121013

10131014
fn update_component_access(
10141015
state: &Self::State,
10151016
filtered_access: &mut FilteredAccess<ComponentId>,
10161017
) {
1017-
let mut my_access = Access::new();
1018-
my_access.write_all_components();
1019-
for id in state {
1020-
my_access.remove_component_read(*id);
1021-
}
1022-
1023-
let access = filtered_access.access_mut();
10241018
assert!(
1025-
access.is_compatible(&my_access),
1019+
filtered_access.access().is_compatible(state),
10261020
"`EntityMutExcept<{}>` conflicts with a previous access in this query.",
10271021
std::any::type_name::<B>()
10281022
);
1029-
access.extend(&my_access);
1023+
filtered_access.access.extend(state);
10301024
}
10311025

10321026
fn init_state(world: &mut World) -> Self::State {
1033-
Self::get_state(world.components()).unwrap()
1027+
let mut access = Access::new();
1028+
access.write_all_components();
1029+
B::component_ids(&mut world.components, &mut world.storages, &mut |id| {
1030+
access.remove_component_read(id);
1031+
});
1032+
access
10341033
}
10351034

10361035
fn get_state(components: &Components) -> Option<Self::State> {
1037-
let mut ids = SmallVec::new();
1036+
let mut access = Access::new();
1037+
access.write_all_components();
1038+
let mut all_initialized = true;
10381039
B::get_component_ids(components, &mut |maybe_id| {
10391040
if let Some(id) = maybe_id {
1040-
ids.push(id);
1041+
access.remove_component_read(id);
1042+
} else {
1043+
all_initialized = false;
10411044
}
10421045
});
1043-
Some(ids)
1046+
all_initialized.then_some(access)
10441047
}
10451048

10461049
fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool {
@@ -1050,11 +1053,11 @@ where
10501053

10511054
/// SAFETY: All accesses that `EntityRefExcept` provides are also accesses that
10521055
/// `EntityMutExcept` provides.
1053-
unsafe impl<'a, B> QueryData for EntityMutExcept<'a, B>
1056+
unsafe impl<'w, 's, B> QueryData for EntityMutExcept<'w, 's, B>
10541057
where
10551058
B: Bundle,
10561059
{
1057-
type ReadOnly = EntityRefExcept<'a, B>;
1060+
type ReadOnly = EntityRefExcept<'w, 's, B>;
10581061
}
10591062

10601063
/// SAFETY:

0 commit comments

Comments
 (0)