Improve Performance in Scenes With Many Lights #14

Merged
SeanOMik merged 8 commits from bugfix/many-lights-poor-performance into main 2024-04-24 23:55:16 +00:00
2 changed files with 52 additions and 16 deletions
Showing only changes of commit 53837d469b - Show all commits

View File

@ -1,9 +1,9 @@
use lyra_ecs::World; use lyra_ecs::World;
use tracing::debug_span; use tracing::{debug_span, instrument};
use crate::Access; use crate::Access;
use super::{System, Criteria, IntoSystem}; use super::{Criteria, GraphExecutorError, IntoSystem, System};
/// A system that executes a batch of systems in order that they were given. /// A system that executes a batch of systems in order that they were given.
/// You can optionally add criteria that must pass before the systems are /// You can optionally add criteria that must pass before the systems are
@ -13,6 +13,7 @@ pub struct BatchedSystem {
systems: Vec<Box<dyn System>>, systems: Vec<Box<dyn System>>,
criteria: Vec<Box<dyn Criteria>>, criteria: Vec<Box<dyn Criteria>>,
criteria_checks: u32, criteria_checks: u32,
did_run: bool,
} }
impl BatchedSystem { impl BatchedSystem {
@ -47,6 +48,7 @@ impl System for BatchedSystem {
} }
} }
#[instrument(skip(self, world))]
fn execute(&mut self, world: std::ptr::NonNull<World>) -> anyhow::Result<()> { fn execute(&mut self, world: std::ptr::NonNull<World>) -> anyhow::Result<()> {
let mut can_run = true; let mut can_run = true;
let mut check_again = false; let mut check_again = false;
@ -69,13 +71,26 @@ impl System for BatchedSystem {
} }
if can_run { if can_run {
for criteria in self.criteria.iter_mut() {
criteria.modify_world(world);
}
for (idx, system) in self.systems.iter_mut().enumerate() { for (idx, system) in self.systems.iter_mut().enumerate() {
let sys_span = debug_span!("batch", system=tracing::field::Empty); let span = debug_span!("batch", system=idx);
sys_span.record("system", idx); let _e = span.enter();
let _e = sys_span.enter();
system.execute(world)?; system.execute(world)?;
/* let deferred_span = debug_span!("deferred_exec");
let _e = deferred_span.enter();
if let Err(e) = system.execute_deferred(world)
.map_err(|e| GraphExecutorError::Command(e)) {
return Err(e.into());
} */
} }
self.did_run = true;
} }
if check_again { if check_again {
@ -88,8 +103,25 @@ impl System for BatchedSystem {
Ok(()) Ok(())
} }
fn execute_deferred(&mut self, _: std::ptr::NonNull<World>) -> anyhow::Result<()> { #[instrument(skip(self, world))]
todo!() fn execute_deferred(&mut self, world: std::ptr::NonNull<World>) -> anyhow::Result<()> {
if self.did_run {
for (idx, system) in self.systems.iter_mut().enumerate() {
let span = debug_span!("batch", system=idx);
let _e = span.enter();
system.execute_deferred(world)
.map_err(|e| GraphExecutorError::Command(e))?;
}
for criteria in self.criteria.iter_mut() {
criteria.undo_world_modifications(world);
}
}
self.did_run = false;
Ok(())
} }
} }

View File

@ -26,13 +26,17 @@ pub trait Criteria {
/// * `world` - The ecs world. /// * `world` - The ecs world.
/// * `check_count` - The amount of times the Criteria has been checked this tick. /// * `check_count` - The amount of times the Criteria has been checked this tick.
fn can_run(&mut self, world: NonNull<World>, check_count: u32) -> CriteriaSchedule; fn can_run(&mut self, world: NonNull<World>, check_count: u32) -> CriteriaSchedule;
}
impl<F> Criteria for F /// Modify the world after the [`Criteria`] in the system batch allows the systems to run.
where F: FnMut(&mut World, u32) -> CriteriaSchedule ///
{ /// This can be great if this Criteria limits the execution of systems based off of resources.
fn can_run(&mut self, mut world: NonNull<World>, check_count: u32) -> CriteriaSchedule { /// A `FixedTimestep` criteria would use this to replace the [`DeltaTime`] resource in the
let world_mut = unsafe { world.as_mut() }; /// world to match the timestep time.
self(world_mut, check_count) fn modify_world(&mut self, world: NonNull<World>);
}
/// Undo modifications to the world after the systems in the batch have been executed.
///
/// The `FixedTimestep` criteria (see docs for [`Criteria::modify_world`]) uses this
/// to replace the [`DeltaTime`] resource with its original value before it was replaced.
fn undo_world_modifications(&mut self, world: NonNull<World>);
} }