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
	 Chris Russell
						Chris Russell