Fixed criteria-less systems being re-ran unnecessarily (#1754)
Fixes #1753. The problem was introduced while reworking the logic around stages' own criteria. Before #1675 they used to be stored and processed inline with the systems' criteria, and systems without criteria used that of their stage. After, criteria-less systems think they should run, always. This PR more or less restores previous behavior; a less cludge solution can wait until after 0.5 - ideally, until stageless. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
		
							parent
							
								
									bf053218bf
								
							
						
					
					
						commit
						500d7469e7
					
				| @ -747,12 +747,6 @@ impl Stage for SystemStage { | |||||||
|             self.world_id = Some(world.id()); |             self.world_id = Some(world.id()); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if let ShouldRun::No | ShouldRun::NoAndCheckAgain = |  | ||||||
|             self.stage_run_criteria.should_run(world) |  | ||||||
|         { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if self.systems_modified { |         if self.systems_modified { | ||||||
|             self.initialize_systems(world); |             self.initialize_systems(world); | ||||||
|             self.rebuild_orders_and_dependencies(); |             self.rebuild_orders_and_dependencies(); | ||||||
| @ -767,7 +761,19 @@ impl Stage for SystemStage { | |||||||
|             self.executor_modified = false; |             self.executor_modified = false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Evaluate run criteria.
 |         let mut run_stage_loop = true; | ||||||
|  |         while run_stage_loop { | ||||||
|  |             let should_run = self.stage_run_criteria.should_run(world); | ||||||
|  |             match should_run { | ||||||
|  |                 ShouldRun::No => return, | ||||||
|  |                 ShouldRun::NoAndCheckAgain => continue, | ||||||
|  |                 ShouldRun::YesAndCheckAgain => (), | ||||||
|  |                 ShouldRun::Yes => { | ||||||
|  |                     run_stage_loop = false; | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             // Evaluate system run criteria.
 | ||||||
|             for index in 0..self.run_criteria.len() { |             for index in 0..self.run_criteria.len() { | ||||||
|                 let (run_criteria, tail) = self.run_criteria.split_at_mut(index); |                 let (run_criteria, tail) = self.run_criteria.split_at_mut(index); | ||||||
|                 let mut criteria = &mut tail[0]; |                 let mut criteria = &mut tail[0]; | ||||||
| @ -781,23 +787,28 @@ impl Stage for SystemStage { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|         let mut has_work = true; |             let mut run_system_loop = true; | ||||||
|         while has_work { |             let mut default_should_run = ShouldRun::Yes; | ||||||
|  |             while run_system_loop { | ||||||
|  |                 run_system_loop = false; | ||||||
|  | 
 | ||||||
|                 fn should_run( |                 fn should_run( | ||||||
|                     container: &impl SystemContainer, |                     container: &impl SystemContainer, | ||||||
|                     run_criteria: &[RunCriteriaContainer], |                     run_criteria: &[RunCriteriaContainer], | ||||||
|  |                     default: ShouldRun, | ||||||
|                 ) -> bool { |                 ) -> bool { | ||||||
|                     matches!( |                     matches!( | ||||||
|                         container |                         container | ||||||
|                             .run_criteria() |                             .run_criteria() | ||||||
|                         .map(|index| run_criteria[index].should_run), |                             .map(|index| run_criteria[index].should_run) | ||||||
|                     None | Some(ShouldRun::Yes) | Some(ShouldRun::YesAndCheckAgain) |                             .unwrap_or(default), | ||||||
|  |                         ShouldRun::Yes | ShouldRun::YesAndCheckAgain | ||||||
|                     ) |                     ) | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 // Run systems that want to be at the start of stage.
 |                 // Run systems that want to be at the start of stage.
 | ||||||
|                 for container in &mut self.exclusive_at_start { |                 for container in &mut self.exclusive_at_start { | ||||||
|                 if should_run(container, &self.run_criteria) { |                     if should_run(container, &self.run_criteria, default_should_run) { | ||||||
|                         container.system_mut().run(world); |                         container.system_mut().run(world); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @ -805,13 +816,14 @@ impl Stage for SystemStage { | |||||||
|                 // Run parallel systems using the executor.
 |                 // Run parallel systems using the executor.
 | ||||||
|                 // TODO: hard dependencies, nested sets, whatever... should be evaluated here.
 |                 // TODO: hard dependencies, nested sets, whatever... should be evaluated here.
 | ||||||
|                 for container in &mut self.parallel { |                 for container in &mut self.parallel { | ||||||
|                 container.should_run = should_run(container, &self.run_criteria); |                     container.should_run = | ||||||
|  |                         should_run(container, &self.run_criteria, default_should_run); | ||||||
|                 } |                 } | ||||||
|                 self.executor.run_systems(&mut self.parallel, world); |                 self.executor.run_systems(&mut self.parallel, world); | ||||||
| 
 | 
 | ||||||
|                 // Run systems that want to be between parallel systems and their command buffers.
 |                 // Run systems that want to be between parallel systems and their command buffers.
 | ||||||
|                 for container in &mut self.exclusive_before_commands { |                 for container in &mut self.exclusive_before_commands { | ||||||
|                 if should_run(container, &self.run_criteria) { |                     if should_run(container, &self.run_criteria, default_should_run) { | ||||||
|                         container.system_mut().run(world); |                         container.system_mut().run(world); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @ -825,7 +837,7 @@ impl Stage for SystemStage { | |||||||
| 
 | 
 | ||||||
|                 // Run systems that want to be at the end of stage.
 |                 // Run systems that want to be at the end of stage.
 | ||||||
|                 for container in &mut self.exclusive_at_end { |                 for container in &mut self.exclusive_at_end { | ||||||
|                 if should_run(container, &self.run_criteria) { |                     if should_run(container, &self.run_criteria, default_should_run) { | ||||||
|                         container.system_mut().run(world); |                         container.system_mut().run(world); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @ -833,8 +845,7 @@ impl Stage for SystemStage { | |||||||
|                 // Check for old component and system change ticks
 |                 // Check for old component and system change ticks
 | ||||||
|                 self.check_change_ticks(world); |                 self.check_change_ticks(world); | ||||||
| 
 | 
 | ||||||
|             // Reevaluate run criteria.
 |                 // Evaluate run criteria.
 | ||||||
|             has_work = false; |  | ||||||
|                 let run_criteria = &mut self.run_criteria; |                 let run_criteria = &mut self.run_criteria; | ||||||
|                 for index in 0..run_criteria.len() { |                 for index in 0..run_criteria.len() { | ||||||
|                     let (run_criteria, tail) = run_criteria.split_at_mut(index); |                     let (run_criteria, tail) = run_criteria.split_at_mut(index); | ||||||
| @ -857,12 +868,21 @@ impl Stage for SystemStage { | |||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|                             match criteria.should_run { |                             match criteria.should_run { | ||||||
|                             ShouldRun::Yes | ShouldRun::YesAndCheckAgain => has_work = true, |                                 ShouldRun::Yes => { | ||||||
|                             ShouldRun::No | ShouldRun::NoAndCheckAgain => (), |                                     run_system_loop = true; | ||||||
|  |                                 } | ||||||
|  |                                 ShouldRun::YesAndCheckAgain | ShouldRun::NoAndCheckAgain => { | ||||||
|  |                                     run_system_loop = true; | ||||||
|  |                                 } | ||||||
|  |                                 ShouldRun::No => (), | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | 
 | ||||||
|  |                 // after the first loop, default to not running systems without run criteria
 | ||||||
|  |                 default_should_run = ShouldRun::No; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -652,4 +652,33 @@ mod test { | |||||||
|             &MyState::Final |             &MyState::Final | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn issue_1753() { | ||||||
|  |         #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||||||
|  |         enum AppState { | ||||||
|  |             Main, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fn should_run_once(mut flag: ResMut<bool>, test_name: Res<&'static str>) { | ||||||
|  |             assert!(!*flag, "{:?}", *test_name); | ||||||
|  |             *flag = true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let mut world = World::new(); | ||||||
|  |         world.insert_resource(State::new(AppState::Main)); | ||||||
|  |         world.insert_resource(false); | ||||||
|  |         world.insert_resource("control"); | ||||||
|  |         let mut stage = SystemStage::parallel().with_system(should_run_once.system()); | ||||||
|  |         stage.run(&mut world); | ||||||
|  |         assert!(*world.get_resource::<bool>().unwrap(), "after control"); | ||||||
|  | 
 | ||||||
|  |         world.insert_resource(false); | ||||||
|  |         world.insert_resource("test"); | ||||||
|  |         let mut stage = SystemStage::parallel() | ||||||
|  |             .with_system_set(State::<AppState>::get_driver()) | ||||||
|  |             .with_system(should_run_once.system()); | ||||||
|  |         stage.run(&mut world); | ||||||
|  |         assert!(*world.get_resource::<bool>().unwrap(), "after test"); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Alexander Sepity
						Alexander Sepity