ecs: call prepare() inside ParallelExecutor::run()
also moved some things around
This commit is contained in:
parent
50335e21e2
commit
1f6c9ece1d
@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
executor::ArchetypeAccess,
|
||||
resource_query::{FetchResource, ResourceQuery, UnsafeClone},
|
||||
system::{System, SystemId, ThreadLocalExecution},
|
||||
system::{ArchetypeAccess, System, SystemId, ThreadLocalExecution},
|
||||
Commands, Resources,
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
@ -27,7 +26,8 @@ where
|
||||
pub set_archetype_access: SetArchetypeAccess,
|
||||
}
|
||||
|
||||
impl<F, ThreadLocalF, Init, SetArchetypeAccess> System for SystemFn<F, ThreadLocalF, Init, SetArchetypeAccess>
|
||||
impl<F, ThreadLocalF, Init, SetArchetypeAccess> System
|
||||
for SystemFn<F, ThreadLocalF, Init, SetArchetypeAccess>
|
||||
where
|
||||
F: FnMut(&World, &Resources) + Send + Sync,
|
||||
ThreadLocalF: FnMut(&mut World, &mut Resources) + Send + Sync,
|
||||
@ -294,7 +294,10 @@ pub trait IntoThreadLocalSystem {
|
||||
fn thread_local_system(self) -> Box<dyn System>;
|
||||
}
|
||||
|
||||
impl<F> IntoThreadLocalSystem for F where F: ThreadLocalSystemFn {
|
||||
impl<F> IntoThreadLocalSystem for F
|
||||
where
|
||||
F: ThreadLocalSystemFn,
|
||||
{
|
||||
fn thread_local_system(mut self) -> Box<dyn System> {
|
||||
Box::new(SystemFn {
|
||||
thread_local_func: move |world, resources| {
|
||||
@ -322,4 +325,4 @@ where
|
||||
fn run(&mut self, world: &mut World, resources: &mut Resources) {
|
||||
self(world, resources);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
pub use hecs::{Query as HecsQuery, *};
|
||||
|
||||
mod commands;
|
||||
mod executor;
|
||||
mod parallel_executor;
|
||||
mod into_system;
|
||||
#[cfg(feature = "profiler")]
|
||||
pub mod profiler;
|
||||
@ -16,6 +16,6 @@ pub use into_system::{IntoForEachSystem, IntoQuerySystem, IntoThreadLocalSystem,
|
||||
pub use resource_query::{FetchResource, Local, Res, ResMut, ResourceQuery};
|
||||
pub use resources::{FromResources, Resource, Resources};
|
||||
pub use schedule::Schedule;
|
||||
pub use executor::Executor;
|
||||
pub use parallel_executor::ParallelExecutor;
|
||||
pub use system::{System, SystemId};
|
||||
pub use world_builder::{WorldBuilder, WorldBuilderSource};
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
use crate::{system::ThreadLocalExecution, Resources, Schedule, System};
|
||||
use crate::{system::{ArchetypeAccess, ThreadLocalExecution}, Resources, Schedule, System};
|
||||
use crossbeam_channel::{Receiver, Sender};
|
||||
use fixedbitset::FixedBitSet;
|
||||
use hecs::{Access, Query, World};
|
||||
use hecs::{World};
|
||||
use rayon::ScopeFifo;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Executor {
|
||||
pub struct ParallelExecutor {
|
||||
stages: Vec<ExecutorStage>,
|
||||
}
|
||||
|
||||
impl Executor {
|
||||
impl ParallelExecutor {
|
||||
pub fn prepare(&mut self, schedule: &mut Schedule, world: &World) {
|
||||
// TODO: if world archetype generation hasnt changed, dont update here
|
||||
|
||||
@ -27,6 +27,7 @@ impl Executor {
|
||||
}
|
||||
|
||||
pub fn run(&mut self, schedule: &mut Schedule, world: &mut World, resources: &mut Resources) {
|
||||
self.prepare(schedule, world);
|
||||
for (stage_name, executor_stage) in schedule.stage_order.iter().zip(self.stages.iter_mut())
|
||||
{
|
||||
if let Some(stage_systems) = schedule.stages.get_mut(stage_name) {
|
||||
@ -265,49 +266,9 @@ impl ExecutorStage {
|
||||
}
|
||||
}
|
||||
|
||||
// credit to Ratysz from the Yaks codebase
|
||||
#[derive(Default)]
|
||||
pub struct ArchetypeAccess {
|
||||
pub immutable: FixedBitSet,
|
||||
pub mutable: FixedBitSet,
|
||||
}
|
||||
|
||||
impl ArchetypeAccess {
|
||||
pub fn is_compatible(&self, other: &ArchetypeAccess) -> bool {
|
||||
self.mutable.is_disjoint(&other.mutable)
|
||||
&& self.mutable.is_disjoint(&other.immutable)
|
||||
&& self.immutable.is_disjoint(&other.mutable)
|
||||
}
|
||||
|
||||
pub fn union(&mut self, other: &ArchetypeAccess) {
|
||||
self.mutable.union_with(&other.mutable);
|
||||
self.immutable.union_with(&other.immutable);
|
||||
}
|
||||
|
||||
pub fn set_access_for_query<Q>(&mut self, world: &World)
|
||||
where
|
||||
Q: Query,
|
||||
{
|
||||
self.immutable.clear();
|
||||
self.mutable.clear();
|
||||
let iterator = world.archetypes();
|
||||
let bits = iterator.len();
|
||||
self.immutable.grow(bits);
|
||||
self.mutable.grow(bits);
|
||||
iterator
|
||||
.enumerate()
|
||||
.filter_map(|(index, archetype)| archetype.access::<Q>().map(|access| (index, access)))
|
||||
.for_each(|(archetype, access)| match access {
|
||||
Access::Read => self.immutable.set(archetype, true),
|
||||
Access::Write => self.mutable.set(archetype, true),
|
||||
Access::Iterate => (),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Executor;
|
||||
use super::ParallelExecutor;
|
||||
use crate::{IntoQuerySystem, IntoThreadLocalSystem, Query, Res, Resources, Schedule, World};
|
||||
use fixedbitset::FixedBitSet;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -403,14 +364,14 @@ mod tests {
|
||||
schedule.add_system_to_stage("B", thread_local_system.thread_local_system());
|
||||
schedule.add_system_to_stage("B", write_f32.system());
|
||||
|
||||
let mut executor = Executor::default();
|
||||
let mut executor = ParallelExecutor::default();
|
||||
run_executor_and_validate(&mut executor, &mut schedule, &mut world, &mut resources);
|
||||
// run again (with counter reset) to ensure executor works correctly across runs
|
||||
*resources.get::<Counter>().unwrap().count.lock().unwrap() = 0;
|
||||
run_executor_and_validate(&mut executor, &mut schedule, &mut world, &mut resources);
|
||||
}
|
||||
|
||||
fn run_executor_and_validate(executor: &mut Executor, schedule: &mut Schedule, world: &mut World, resources: &mut Resources) {
|
||||
fn run_executor_and_validate(executor: &mut ParallelExecutor, schedule: &mut Schedule, world: &mut World, resources: &mut Resources) {
|
||||
executor.prepare(schedule, world);
|
||||
|
||||
assert_eq!(
|
||||
@ -1,5 +1,7 @@
|
||||
use crate::{Resources, World, executor::ArchetypeAccess};
|
||||
use crate::{Resources, World};
|
||||
use std::borrow::Cow;
|
||||
use fixedbitset::FixedBitSet;
|
||||
use hecs::{Query, Access};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum ThreadLocalExecution {
|
||||
@ -26,3 +28,43 @@ pub trait System: Send + Sync {
|
||||
fn run_thread_local(&mut self, world: &mut World, resources: &mut Resources);
|
||||
fn initialize(&mut self, _resources: &mut Resources) {}
|
||||
}
|
||||
|
||||
// credit to Ratysz from the Yaks codebase
|
||||
#[derive(Default)]
|
||||
pub struct ArchetypeAccess {
|
||||
pub immutable: FixedBitSet,
|
||||
pub mutable: FixedBitSet,
|
||||
}
|
||||
|
||||
impl ArchetypeAccess {
|
||||
pub fn is_compatible(&self, other: &ArchetypeAccess) -> bool {
|
||||
self.mutable.is_disjoint(&other.mutable)
|
||||
&& self.mutable.is_disjoint(&other.immutable)
|
||||
&& self.immutable.is_disjoint(&other.mutable)
|
||||
}
|
||||
|
||||
pub fn union(&mut self, other: &ArchetypeAccess) {
|
||||
self.mutable.union_with(&other.mutable);
|
||||
self.immutable.union_with(&other.immutable);
|
||||
}
|
||||
|
||||
pub fn set_access_for_query<Q>(&mut self, world: &World)
|
||||
where
|
||||
Q: Query,
|
||||
{
|
||||
self.immutable.clear();
|
||||
self.mutable.clear();
|
||||
let iterator = world.archetypes();
|
||||
let bits = iterator.len();
|
||||
self.immutable.grow(bits);
|
||||
self.mutable.grow(bits);
|
||||
iterator
|
||||
.enumerate()
|
||||
.filter_map(|(index, archetype)| archetype.access::<Q>().map(|access| (index, access)))
|
||||
.for_each(|(archetype, access)| match access {
|
||||
Access::Read => self.immutable.set(archetype, true),
|
||||
Access::Write => self.mutable.set(archetype, true),
|
||||
Access::Iterate => (),
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user