mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 06:30:19 +00:00
update archetypes if needed before running system in SingleThreadedExecutor (#1586)
fixes #1585 I copied most of the logic from the `ParallelSystemExecutor` impl, simplifying it a little as systems can't run in parallel
This commit is contained in:
parent
2a3a32b66f
commit
dabf419095
2 changed files with 87 additions and 3 deletions
|
@ -1,4 +1,4 @@
|
||||||
use crate::{schedule::ParallelSystemContainer, world::World};
|
use crate::{archetype::ArchetypeGeneration, schedule::ParallelSystemContainer, world::World};
|
||||||
use downcast_rs::{impl_downcast, Downcast};
|
use downcast_rs::{impl_downcast, Downcast};
|
||||||
|
|
||||||
pub trait ParallelSystemExecutor: Downcast + Send + Sync {
|
pub trait ParallelSystemExecutor: Downcast + Send + Sync {
|
||||||
|
@ -10,13 +10,25 @@ pub trait ParallelSystemExecutor: Downcast + Send + Sync {
|
||||||
|
|
||||||
impl_downcast!(ParallelSystemExecutor);
|
impl_downcast!(ParallelSystemExecutor);
|
||||||
|
|
||||||
#[derive(Default)]
|
pub struct SingleThreadedExecutor {
|
||||||
pub struct SingleThreadedExecutor;
|
/// Last archetypes generation observed by parallel systems.
|
||||||
|
archetype_generation: ArchetypeGeneration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SingleThreadedExecutor {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
// MAX ensures access information will be initialized on first run.
|
||||||
|
archetype_generation: ArchetypeGeneration::new(usize::MAX),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl ParallelSystemExecutor for SingleThreadedExecutor {
|
impl ParallelSystemExecutor for SingleThreadedExecutor {
|
||||||
fn rebuild_cached_data(&mut self, _: &[ParallelSystemContainer]) {}
|
fn rebuild_cached_data(&mut self, _: &[ParallelSystemContainer]) {}
|
||||||
|
|
||||||
fn run_systems(&mut self, systems: &mut [ParallelSystemContainer], world: &mut World) {
|
fn run_systems(&mut self, systems: &mut [ParallelSystemContainer], world: &mut World) {
|
||||||
|
self.update_archetypes(systems, world);
|
||||||
|
|
||||||
for system in systems {
|
for system in systems {
|
||||||
if system.should_run() {
|
if system.should_run() {
|
||||||
system.system_mut().run((), world);
|
system.system_mut().run((), world);
|
||||||
|
@ -24,3 +36,30 @@ impl ParallelSystemExecutor for SingleThreadedExecutor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SingleThreadedExecutor {
|
||||||
|
/// Calls system.new_archetype() for each archetype added since the last call to [update_archetypes] and
|
||||||
|
/// updates cached archetype_component_access.
|
||||||
|
fn update_archetypes(&mut self, systems: &mut [ParallelSystemContainer], world: &World) {
|
||||||
|
let archetypes = world.archetypes();
|
||||||
|
let old_generation = self.archetype_generation;
|
||||||
|
let new_generation = archetypes.generation();
|
||||||
|
if old_generation == new_generation {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let archetype_index_range = if old_generation.value() == usize::MAX {
|
||||||
|
0..archetypes.len()
|
||||||
|
} else {
|
||||||
|
old_generation.value()..archetypes.len()
|
||||||
|
};
|
||||||
|
for archetype in archetypes.archetypes[archetype_index_range].iter() {
|
||||||
|
for container in systems.iter_mut() {
|
||||||
|
let system = container.system_mut();
|
||||||
|
system.new_archetype(archetype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.archetype_generation = new_generation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1528,4 +1528,49 @@ mod tests {
|
||||||
stage.run(&mut world_a);
|
stage.run(&mut world_a);
|
||||||
stage.run(&mut world_b);
|
stage.run(&mut world_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn archetype_update_single_executor() {
|
||||||
|
fn query_count_system(
|
||||||
|
mut entity_count: ResMut<usize>,
|
||||||
|
query: Query<crate::entity::Entity>,
|
||||||
|
) {
|
||||||
|
*entity_count = query.iter().count();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut world = World::new();
|
||||||
|
world.insert_resource(0_usize);
|
||||||
|
let mut stage = SystemStage::single(query_count_system.system());
|
||||||
|
|
||||||
|
let entity = world.spawn().insert_bundle(()).id();
|
||||||
|
stage.run(&mut world);
|
||||||
|
assert_eq!(*world.get_resource::<usize>().unwrap(), 1);
|
||||||
|
|
||||||
|
world.get_entity_mut(entity).unwrap().insert(1);
|
||||||
|
stage.run(&mut world);
|
||||||
|
assert_eq!(*world.get_resource::<usize>().unwrap(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn archetype_update_parallel_executor() {
|
||||||
|
fn query_count_system(
|
||||||
|
mut entity_count: ResMut<usize>,
|
||||||
|
query: Query<crate::entity::Entity>,
|
||||||
|
) {
|
||||||
|
*entity_count = query.iter().count();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut world = World::new();
|
||||||
|
world.insert_resource(0_usize);
|
||||||
|
let mut stage = SystemStage::parallel();
|
||||||
|
stage.add_system(query_count_system.system());
|
||||||
|
|
||||||
|
let entity = world.spawn().insert_bundle(()).id();
|
||||||
|
stage.run(&mut world);
|
||||||
|
assert_eq!(*world.get_resource::<usize>().unwrap(), 1);
|
||||||
|
|
||||||
|
world.get_entity_mut(entity).unwrap().insert(1);
|
||||||
|
stage.run(&mut world);
|
||||||
|
assert_eq!(*world.get_resource::<usize>().unwrap(), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue