Pass query change ticks to QueryParIter instead of always using change ticks from World. (#8029)
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com> Co-authored-by: James Liu <contact@jamessliu.com>
This commit is contained in:
parent
8a2502ce0f
commit
a63881905a
@ -61,8 +61,9 @@ impl<T> DebugCheckedUnwrap for Option<T> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{ReadOnlyWorldQuery, WorldQuery};
|
||||
use crate::prelude::{AnyOf, Entity, Or, QueryState, With, Without};
|
||||
use crate::prelude::{AnyOf, Changed, Entity, Or, QueryState, With, Without};
|
||||
use crate::query::{ArchetypeFilter, QueryCombinationIter};
|
||||
use crate::schedule::{IntoSystemConfigs, Schedule};
|
||||
use crate::system::{IntoSystem, Query, System, SystemState};
|
||||
use crate::{self as bevy_ecs, component::Component, world::World};
|
||||
use std::any::type_name;
|
||||
@ -749,4 +750,33 @@ mod tests {
|
||||
let _: [&Foo; 1] = q.many([e]);
|
||||
let _: &Foo = q.single();
|
||||
}
|
||||
|
||||
// regression test for https://github.com/bevyengine/bevy/pull/8029
|
||||
#[test]
|
||||
fn par_iter_mut_change_detection() {
|
||||
let mut world = World::new();
|
||||
world.spawn((A(1), B(1)));
|
||||
|
||||
fn propagate_system(mut query: Query<(&A, &mut B), Changed<A>>) {
|
||||
query.par_iter_mut().for_each_mut(|(a, mut b)| {
|
||||
b.0 = a.0;
|
||||
});
|
||||
}
|
||||
|
||||
fn modify_system(mut query: Query<&mut A>) {
|
||||
for mut a in &mut query {
|
||||
a.0 = 2;
|
||||
}
|
||||
}
|
||||
|
||||
let mut schedule = Schedule::new();
|
||||
schedule.add_systems((propagate_system, modify_system).chain());
|
||||
schedule.run(&mut world);
|
||||
world.clear_trackers();
|
||||
schedule.run(&mut world);
|
||||
world.clear_trackers();
|
||||
|
||||
let values = world.query::<&B>().iter(&world).collect::<Vec<&B>>();
|
||||
assert_eq!(values, vec![&B(2)]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::world::World;
|
||||
use crate::{component::Tick, world::World};
|
||||
use bevy_tasks::ComputeTaskPool;
|
||||
use std::ops::Range;
|
||||
|
||||
@ -81,6 +81,8 @@ impl BatchingStrategy {
|
||||
pub struct QueryParIter<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> {
|
||||
pub(crate) world: &'w World,
|
||||
pub(crate) state: &'s QueryState<Q, F>,
|
||||
pub(crate) last_run: Tick,
|
||||
pub(crate) this_run: Tick,
|
||||
pub(crate) batching_strategy: BatchingStrategy,
|
||||
}
|
||||
|
||||
@ -148,12 +150,8 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryParIter<'w, 's, Q, F> {
|
||||
) {
|
||||
let thread_count = ComputeTaskPool::get().thread_num();
|
||||
if thread_count <= 1 {
|
||||
self.state.for_each_unchecked_manual(
|
||||
self.world,
|
||||
func,
|
||||
self.world.last_change_tick(),
|
||||
self.world.read_change_tick(),
|
||||
);
|
||||
self.state
|
||||
.for_each_unchecked_manual(self.world, func, self.last_run, self.this_run);
|
||||
} else {
|
||||
// Need a batch size of at least 1.
|
||||
let batch_size = self.get_batch_size(thread_count).max(1);
|
||||
@ -161,8 +159,8 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryParIter<'w, 's, Q, F> {
|
||||
self.world,
|
||||
batch_size,
|
||||
func,
|
||||
self.world.last_change_tick(),
|
||||
self.world.read_change_tick(),
|
||||
self.last_run,
|
||||
self.this_run,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -820,6 +820,8 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
|
||||
QueryParIter {
|
||||
world,
|
||||
state: self,
|
||||
last_run: world.last_change_tick(),
|
||||
this_run: world.read_change_tick(),
|
||||
batching_strategy: BatchingStrategy::new(),
|
||||
}
|
||||
}
|
||||
@ -832,9 +834,12 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
|
||||
#[inline]
|
||||
pub fn par_iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryParIter<'w, 's, Q, F> {
|
||||
self.update_archetypes(world);
|
||||
let this_run = world.change_tick();
|
||||
QueryParIter {
|
||||
world,
|
||||
state: self,
|
||||
last_run: world.last_change_tick(),
|
||||
this_run,
|
||||
batching_strategy: BatchingStrategy::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -728,6 +728,8 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
|
||||
QueryParIter {
|
||||
world: self.world,
|
||||
state: self.state.as_readonly(),
|
||||
last_run: self.last_run,
|
||||
this_run: self.this_run,
|
||||
batching_strategy: BatchingStrategy::new(),
|
||||
}
|
||||
}
|
||||
@ -742,6 +744,8 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
|
||||
QueryParIter {
|
||||
world: self.world,
|
||||
state: self.state,
|
||||
last_run: self.last_run,
|
||||
this_run: self.this_run,
|
||||
batching_strategy: BatchingStrategy::new(),
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user