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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{ReadOnlyWorldQuery, WorldQuery};
|
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::query::{ArchetypeFilter, QueryCombinationIter};
|
||||||
|
use crate::schedule::{IntoSystemConfigs, Schedule};
|
||||||
use crate::system::{IntoSystem, Query, System, SystemState};
|
use crate::system::{IntoSystem, Query, System, SystemState};
|
||||||
use crate::{self as bevy_ecs, component::Component, world::World};
|
use crate::{self as bevy_ecs, component::Component, world::World};
|
||||||
use std::any::type_name;
|
use std::any::type_name;
|
||||||
@ -749,4 +750,33 @@ mod tests {
|
|||||||
let _: [&Foo; 1] = q.many([e]);
|
let _: [&Foo; 1] = q.many([e]);
|
||||||
let _: &Foo = q.single();
|
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 bevy_tasks::ComputeTaskPool;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
@ -81,6 +81,8 @@ impl BatchingStrategy {
|
|||||||
pub struct QueryParIter<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> {
|
pub struct QueryParIter<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> {
|
||||||
pub(crate) world: &'w World,
|
pub(crate) world: &'w World,
|
||||||
pub(crate) state: &'s QueryState<Q, F>,
|
pub(crate) state: &'s QueryState<Q, F>,
|
||||||
|
pub(crate) last_run: Tick,
|
||||||
|
pub(crate) this_run: Tick,
|
||||||
pub(crate) batching_strategy: BatchingStrategy,
|
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();
|
let thread_count = ComputeTaskPool::get().thread_num();
|
||||||
if thread_count <= 1 {
|
if thread_count <= 1 {
|
||||||
self.state.for_each_unchecked_manual(
|
self.state
|
||||||
self.world,
|
.for_each_unchecked_manual(self.world, func, self.last_run, self.this_run);
|
||||||
func,
|
|
||||||
self.world.last_change_tick(),
|
|
||||||
self.world.read_change_tick(),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
// Need a batch size of at least 1.
|
// Need a batch size of at least 1.
|
||||||
let batch_size = self.get_batch_size(thread_count).max(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,
|
self.world,
|
||||||
batch_size,
|
batch_size,
|
||||||
func,
|
func,
|
||||||
self.world.last_change_tick(),
|
self.last_run,
|
||||||
self.world.read_change_tick(),
|
self.this_run,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -820,6 +820,8 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
|
|||||||
QueryParIter {
|
QueryParIter {
|
||||||
world,
|
world,
|
||||||
state: self,
|
state: self,
|
||||||
|
last_run: world.last_change_tick(),
|
||||||
|
this_run: world.read_change_tick(),
|
||||||
batching_strategy: BatchingStrategy::new(),
|
batching_strategy: BatchingStrategy::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -832,9 +834,12 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn par_iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryParIter<'w, 's, Q, F> {
|
pub fn par_iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryParIter<'w, 's, Q, F> {
|
||||||
self.update_archetypes(world);
|
self.update_archetypes(world);
|
||||||
|
let this_run = world.change_tick();
|
||||||
QueryParIter {
|
QueryParIter {
|
||||||
world,
|
world,
|
||||||
state: self,
|
state: self,
|
||||||
|
last_run: world.last_change_tick(),
|
||||||
|
this_run,
|
||||||
batching_strategy: BatchingStrategy::new(),
|
batching_strategy: BatchingStrategy::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -728,6 +728,8 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
|
|||||||
QueryParIter {
|
QueryParIter {
|
||||||
world: self.world,
|
world: self.world,
|
||||||
state: self.state.as_readonly(),
|
state: self.state.as_readonly(),
|
||||||
|
last_run: self.last_run,
|
||||||
|
this_run: self.this_run,
|
||||||
batching_strategy: BatchingStrategy::new(),
|
batching_strategy: BatchingStrategy::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -742,6 +744,8 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
|
|||||||
QueryParIter {
|
QueryParIter {
|
||||||
world: self.world,
|
world: self.world,
|
||||||
state: self.state,
|
state: self.state,
|
||||||
|
last_run: self.last_run,
|
||||||
|
this_run: self.this_run,
|
||||||
batching_strategy: BatchingStrategy::new(),
|
batching_strategy: BatchingStrategy::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user