Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove archetype_component_access from QueryState #12474

69 changes: 48 additions & 21 deletions crates/bevy_ecs/src/query/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ pub struct QueryState<D: QueryData, F: QueryFilter = ()> {
pub(crate) archetype_generation: ArchetypeGeneration,
pub(crate) matched_tables: FixedBitSet,
pub(crate) matched_archetypes: FixedBitSet,
pub(crate) archetype_component_access: Access<ArchetypeComponentId>,
pub(crate) component_access: FilteredAccess<ComponentId>,
// NOTE: we maintain both a TableId bitset and a vec because iterating the vec is faster
pub(crate) matched_table_ids: Vec<TableId>,
Expand Down Expand Up @@ -96,11 +95,6 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
&*ptr::from_ref(self).cast::<QueryState<NewD, NewF>>()
}

/// Returns the archetype components accessed by this query.
pub fn archetype_component_access(&self) -> &Access<ArchetypeComponentId> {
&self.archetype_component_access
}

/// Returns the components accessed by this query.
pub fn component_access(&self) -> &FilteredAccess<ComponentId> {
&self.component_access
Expand All @@ -120,6 +114,26 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
/// Creates a new [`QueryState`] from a given [`World`] and inherits the result of `world.id()`.
pub fn new(world: &mut World) -> Self {
let mut state = Self::new_internal(world);
state.update_archetypes(world);
state
}

pub(crate) fn new_with_access(
world: &mut World,
access: &mut Access<ArchetypeComponentId>,
) -> Self {
let mut state = Self::new_internal(world);
for archetype in world.archetypes.iter() {
if state.new_archetype_internal(archetype) {
state.update_archetype_component_access(archetype, access);
}
}
state.archetype_generation = world.archetypes.generation();
state
}

fn new_internal(world: &mut World) -> Self {
james7132 marked this conversation as resolved.
Show resolved Hide resolved
let fetch_state = D::init_state(world);
let filter_state = F::init_state(world);

Expand All @@ -136,7 +150,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
// properly considered in a global "cross-query" context (both within systems and across systems).
component_access.extend(&filter_component_access);

let mut state = Self {
Self {
world_id: world.id(),
archetype_generation: ArchetypeGeneration::initial(),
matched_table_ids: Vec::new(),
Expand All @@ -146,16 +160,13 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
component_access,
matched_tables: Default::default(),
matched_archetypes: Default::default(),
archetype_component_access: Default::default(),
#[cfg(feature = "trace")]
par_iter_span: bevy_utils::tracing::info_span!(
"par_for_each",
query = std::any::type_name::<D>(),
filter = std::any::type_name::<F>(),
),
};
state.update_archetypes(world);
state
}
}

/// Creates a new [`QueryState`] from a given [`QueryBuilder`] and inherits it's [`FilteredAccess`].
Expand All @@ -174,7 +185,6 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
component_access: builder.access().clone(),
matched_tables: Default::default(),
matched_archetypes: Default::default(),
archetype_component_access: Default::default(),
#[cfg(feature = "trace")]
par_iter_span: bevy_utils::tracing::info_span!(
"par_for_each",
Expand Down Expand Up @@ -268,7 +278,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
std::mem::replace(&mut self.archetype_generation, archetypes.generation());

for archetype in &archetypes[old_generation..] {
self.new_archetype(archetype);
self.new_archetype_internal(archetype);
}
}

Expand All @@ -295,13 +305,23 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {

/// Update the current [`QueryState`] with information from the provided [`Archetype`]
/// (if applicable, i.e. if the archetype has any intersecting [`ComponentId`] with the current [`QueryState`]).
pub fn new_archetype(&mut self, archetype: &Archetype) {
///
/// The passed in `access` will be updated with any new accesses introduced by the new archetype.
pub fn new_archetype(
&mut self,
archetype: &Archetype,
access: &mut Access<ArchetypeComponentId>,
) {
if self.new_archetype_internal(archetype) {
self.update_archetype_component_access(archetype, access);
}
}

fn new_archetype_internal(&mut self, archetype: &Archetype) -> bool {
if D::matches_component_set(&self.fetch_state, &|id| archetype.contains(id))
&& F::matches_component_set(&self.filter_state, &|id| archetype.contains(id))
&& self.matches_component_set(&|id| archetype.contains(id))
{
self.update_archetype_component_access(archetype);

let archetype_index = archetype.id().index();
if !self.matched_archetypes.contains(archetype_index) {
self.matched_archetypes.grow(archetype_index + 1);
Expand All @@ -314,6 +334,9 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
self.matched_tables.set(table_index, true);
self.matched_table_ids.push(archetype.table_id());
}
true
} else {
false
}
}

Expand All @@ -331,15 +354,21 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
}

/// For the given `archetype`, adds any component accessed used by this query's underlying [`FilteredAccess`] to `access`.
pub fn update_archetype_component_access(&mut self, archetype: &Archetype) {
///
/// The passed in `access` will be updated with any new accesses introduced by the new archetype.
pub fn update_archetype_component_access(
&mut self,
archetype: &Archetype,
access: &mut Access<ArchetypeComponentId>,
) {
self.component_access.access.reads().for_each(|id| {
if let Some(id) = archetype.get_archetype_component_id(id) {
self.archetype_component_access.add_read(id);
access.add_read(id);
}
});
self.component_access.access.writes().for_each(|id| {
if let Some(id) = archetype.get_archetype_component_id(id) {
self.archetype_component_access.add_write(id);
access.add_write(id);
}
});
}
Expand Down Expand Up @@ -391,7 +420,6 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
component_access: self.component_access.clone(),
matched_tables: self.matched_tables.clone(),
matched_archetypes: self.matched_archetypes.clone(),
archetype_component_access: self.archetype_component_access.clone(),
#[cfg(feature = "trace")]
par_iter_span: bevy_utils::tracing::info_span!(
"par_for_each",
Expand Down Expand Up @@ -499,7 +527,6 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
component_access: joined_component_access,
matched_tables,
matched_archetypes,
archetype_component_access: self.archetype_component_access.clone(),
#[cfg(feature = "trace")]
par_iter_span: bevy_utils::tracing::info_span!(
"par_for_each",
Expand Down
10 changes: 2 additions & 8 deletions crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Qu
type Item<'w, 's> = Query<'w, 's, D, F>;

fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
let state = QueryState::new(world);
let state = QueryState::new_with_access(world, &mut system_meta.archetype_component_access);
assert_component_access_compatibility(
&system_meta.name,
std::any::type_name::<D>(),
Expand All @@ -205,17 +205,11 @@ unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Qu
system_meta
.component_access_set
.add(state.component_access.clone());
system_meta
.archetype_component_access
.extend(&state.archetype_component_access);
state
}

fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) {
state.new_archetype(archetype);
system_meta
.archetype_component_access
.extend(&state.archetype_component_access);
state.new_archetype(archetype, &mut system_meta.archetype_component_access);
}

#[inline]
Expand Down