bevy/crates/bevy_ecs/src/schedule/schedule.rs

1723 lines
62 KiB
Rust
Raw Normal View History

use std::{
fmt::{Debug, Write},
result::Result,
};
use bevy_utils::default;
#[cfg(feature = "trace")]
use bevy_utils::tracing::info_span;
use bevy_utils::{
petgraph::{algo::TarjanScc, prelude::*},
thiserror::Error,
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
tracing::{error, warn},
HashMap, HashSet,
};
use fixedbitset::FixedBitSet;
use crate::{
self as bevy_ecs,
component::{ComponentId, Components, Tick},
schedule::*,
system::{BoxedSystem, Resource, System},
world::World,
};
/// Resource that stores [`Schedule`]s mapped to [`ScheduleLabel`]s.
#[derive(Default, Resource)]
pub struct Schedules {
inner: HashMap<BoxedScheduleLabel, Schedule>,
}
impl Schedules {
/// Constructs an empty `Schedules` with zero initial capacity.
pub fn new() -> Self {
Self {
inner: HashMap::new(),
}
}
/// Inserts a labeled schedule into the map.
///
/// If the map already had an entry for `label`, `schedule` is inserted,
/// and the old schedule is returned. Otherwise, `None` is returned.
pub fn insert(&mut self, schedule: Schedule) -> Option<Schedule> {
let label = schedule.name.dyn_clone();
self.inner.insert(label, schedule)
}
/// Removes the schedule corresponding to the `label` from the map, returning it if it existed.
pub fn remove(&mut self, label: &dyn ScheduleLabel) -> Option<Schedule> {
self.inner.remove(label)
}
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
/// Removes the (schedule, label) pair corresponding to the `label` from the map, returning it if it existed.
pub fn remove_entry(
&mut self,
label: &dyn ScheduleLabel,
) -> Option<(Box<dyn ScheduleLabel>, Schedule)> {
self.inner.remove_entry(label)
}
/// Does a schedule with the provided label already exist?
pub fn contains(&self, label: &dyn ScheduleLabel) -> bool {
self.inner.contains_key(label)
}
/// Returns a reference to the schedule associated with `label`, if it exists.
pub fn get(&self, label: &dyn ScheduleLabel) -> Option<&Schedule> {
self.inner.get(label)
}
/// Returns a mutable reference to the schedule associated with `label`, if it exists.
pub fn get_mut(&mut self, label: &dyn ScheduleLabel) -> Option<&mut Schedule> {
self.inner.get_mut(label)
}
/// Returns an iterator over all schedules. Iteration order is undefined.
pub fn iter(&self) -> impl Iterator<Item = (&dyn ScheduleLabel, &Schedule)> {
self.inner
.iter()
.map(|(label, schedule)| (&**label, schedule))
}
/// Returns an iterator over mutable references to all schedules. Iteration order is undefined.
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&dyn ScheduleLabel, &mut Schedule)> {
self.inner
.iter_mut()
.map(|(label, schedule)| (&**label, schedule))
}
/// Iterates the change ticks of all systems in all stored schedules and clamps any older than
/// [`MAX_CHANGE_AGE`](crate::change_detection::MAX_CHANGE_AGE).
/// This prevents overflow and thus prevents false positives.
pub(crate) fn check_change_ticks(&mut self, change_tick: Tick) {
#[cfg(feature = "trace")]
let _all_span = info_span!("check stored schedule ticks").entered();
// label used when trace feature is enabled
#[allow(unused_variables)]
for (label, schedule) in self.inner.iter_mut() {
#[cfg(feature = "trace")]
let name = format!("{label:?}");
#[cfg(feature = "trace")]
let _one_span = info_span!("check schedule ticks", name = &name).entered();
schedule.check_change_ticks(change_tick);
}
}
/// Applies the provided [`ScheduleBuildSettings`] to all schedules.
pub fn configure_schedules(&mut self, schedule_build_settings: ScheduleBuildSettings) {
for (_, schedule) in self.inner.iter_mut() {
schedule.set_build_settings(schedule_build_settings.clone());
}
}
}
fn make_executor(kind: ExecutorKind) -> Box<dyn SystemExecutor> {
match kind {
ExecutorKind::Simple => Box::new(SimpleExecutor::new()),
ExecutorKind::SingleThreaded => Box::new(SingleThreadedExecutor::new()),
ExecutorKind::MultiThreaded => Box::new(MultiThreadedExecutor::new()),
}
}
/// A collection of systems, and the metadata and executor needed to run them
/// in a certain order under certain conditions.
///
/// # Example
/// Here is an example of a `Schedule` running a "Hello world" system:
/// ```
/// # use bevy_ecs::prelude::*;
/// fn hello_world() { println!("Hello world!") }
///
/// fn main() {
/// let mut world = World::new();
/// let mut schedule = Schedule::default();
/// schedule.add_systems(hello_world);
///
/// schedule.run(&mut world);
/// }
/// ```
///
/// A schedule can also run several systems in an ordered way:
/// ```
/// # use bevy_ecs::prelude::*;
/// fn system_one() { println!("System 1 works!") }
/// fn system_two() { println!("System 2 works!") }
/// fn system_three() { println!("System 3 works!") }
///
/// fn main() {
/// let mut world = World::new();
/// let mut schedule = Schedule::default();
/// schedule.add_systems((
/// system_two,
/// system_one.before(system_two),
/// system_three.after(system_two),
/// ));
///
/// schedule.run(&mut world);
/// }
/// ```
pub struct Schedule {
name: BoxedScheduleLabel,
graph: ScheduleGraph,
executable: SystemSchedule,
executor: Box<dyn SystemExecutor>,
executor_initialized: bool,
}
#[derive(ScheduleLabel, Hash, PartialEq, Eq, Debug, Clone)]
struct DefaultSchedule;
/// Creates a schedule with a default label. Only use in situations where
/// where you don't care about the [`ScheduleLabel`]. Inserting a default schedule
/// into the world risks overwriting another schedule. For most situations you should use
/// [`Schedule::new`].
impl Default for Schedule {
fn default() -> Self {
Self::new(DefaultSchedule)
}
}
impl Schedule {
/// Constructs an empty `Schedule`.
pub fn new(label: impl ScheduleLabel) -> Self {
Self {
name: label.dyn_clone(),
graph: ScheduleGraph::new(),
executable: SystemSchedule::new(),
executor: make_executor(ExecutorKind::default()),
executor_initialized: false,
}
}
/// Add a collection of systems to the schedule.
pub fn add_systems<M>(&mut self, systems: impl IntoSystemConfigs<M>) -> &mut Self {
self.graph.add_systems_inner(systems.into_configs(), false);
self
}
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
/// Configures a system set in this schedule, adding it if it does not exist.
clean up configure_set(s) erroring (#9577) # Objective - have errors in configure_set and configure_sets show the line number of the user calling location rather than pointing to schedule.rs - use display formatting for the errors ## Example Error Text ```text // dependency loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DependencyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:39 // after thread 'main' panicked at 'System set `A` depends on itself.', examples/stress_tests/bevymark.rs:16:9 // hierarchy loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: HierarchyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:3 // after thread 'main' panicked at 'System set `A` contains itself.', examples/stress_tests/bevymark.rs:16:9 // configuring a system type set // before thread 'main' panicked at 'configuring system type sets is not allowed', crates\bevy_ecs\src\schedule\config.rs:394:9 //after thread 'main' panicked at 'configuring system type sets is not allowed', examples/stress_tests/bevymark.rs:16:9 ``` Code to produce errors: ```rust use bevy::prelude::*; #[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)] enum TestSet { A, } fn main() { fn foo() {} let mut app = App::empty(); // Hierarchy Loop app.configure_set(Main, TestSet::A.in_set(TestSet::A)); // Dependency Loop app.configure_set(Main, TestSet::A.after(TestSet::A)); // Configure System Type Set app.configure_set(Main, foo.into_system_set()); } ```
2023-08-28 17:44:52 +00:00
#[track_caller]
pub fn configure_set(&mut self, set: impl IntoSystemSetConfig) -> &mut Self {
self.graph.configure_set(set);
self
}
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
/// Configures a collection of system sets in this schedule, adding them if they does not exist.
clean up configure_set(s) erroring (#9577) # Objective - have errors in configure_set and configure_sets show the line number of the user calling location rather than pointing to schedule.rs - use display formatting for the errors ## Example Error Text ```text // dependency loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DependencyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:39 // after thread 'main' panicked at 'System set `A` depends on itself.', examples/stress_tests/bevymark.rs:16:9 // hierarchy loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: HierarchyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:3 // after thread 'main' panicked at 'System set `A` contains itself.', examples/stress_tests/bevymark.rs:16:9 // configuring a system type set // before thread 'main' panicked at 'configuring system type sets is not allowed', crates\bevy_ecs\src\schedule\config.rs:394:9 //after thread 'main' panicked at 'configuring system type sets is not allowed', examples/stress_tests/bevymark.rs:16:9 ``` Code to produce errors: ```rust use bevy::prelude::*; #[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)] enum TestSet { A, } fn main() { fn foo() {} let mut app = App::empty(); // Hierarchy Loop app.configure_set(Main, TestSet::A.in_set(TestSet::A)); // Dependency Loop app.configure_set(Main, TestSet::A.after(TestSet::A)); // Configure System Type Set app.configure_set(Main, foo.into_system_set()); } ```
2023-08-28 17:44:52 +00:00
#[track_caller]
pub fn configure_sets(&mut self, sets: impl IntoSystemSetConfigs) -> &mut Self {
self.graph.configure_sets(sets);
self
}
/// Changes miscellaneous build settings.
pub fn set_build_settings(&mut self, settings: ScheduleBuildSettings) -> &mut Self {
self.graph.settings = settings;
self
}
/// Returns the schedule's current `ScheduleBuildSettings`.
pub fn get_build_settings(&self) -> ScheduleBuildSettings {
self.graph.settings.clone()
}
/// Returns the schedule's current execution strategy.
pub fn get_executor_kind(&self) -> ExecutorKind {
self.executor.kind()
}
/// Sets the schedule's execution strategy.
pub fn set_executor_kind(&mut self, executor: ExecutorKind) -> &mut Self {
if executor != self.executor.kind() {
self.executor = make_executor(executor);
self.executor_initialized = false;
}
self
}
/// Set whether the schedule applies deferred system buffers on final time or not. This is a catch-all
/// in case a system uses commands but was not explicitly ordered before an instance of
/// [`apply_deferred`](crate::prelude::apply_deferred). By default this
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
/// setting is true, but may be disabled if needed.
pub fn set_apply_final_deferred(&mut self, apply_final_deferred: bool) -> &mut Self {
self.executor.set_apply_final_deferred(apply_final_deferred);
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
self
}
/// Runs all systems in this schedule on the `world`, using its current execution strategy.
pub fn run(&mut self, world: &mut World) {
#[cfg(feature = "trace")]
let _span = bevy_utils::tracing::info_span!("schedule", name = ?self.name).entered();
world.check_change_ticks();
self.initialize(world)
.unwrap_or_else(|e| panic!("Error when intializing schedule {:?}: {e}", self.name));
self.executor.run(&mut self.executable, world);
}
/// Initializes any newly-added systems and conditions, rebuilds the executable schedule,
/// and re-initializes the executor.
///
/// Moves all systems and run conditions out of the [`ScheduleGraph`].
pub fn initialize(&mut self, world: &mut World) -> Result<(), ScheduleBuildError> {
if self.graph.changed {
self.graph.initialize(world);
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
self.graph
.update_schedule(&mut self.executable, world.components(), &self.name)?;
self.graph.changed = false;
self.executor_initialized = false;
}
if !self.executor_initialized {
self.executor.init(&self.executable);
self.executor_initialized = true;
}
Ok(())
}
/// Returns the [`ScheduleGraph`].
pub fn graph(&self) -> &ScheduleGraph {
&self.graph
}
/// Returns a mutable reference to the [`ScheduleGraph`].
pub fn graph_mut(&mut self) -> &mut ScheduleGraph {
&mut self.graph
}
/// Iterates the change ticks of all systems in the schedule and clamps any older than
/// [`MAX_CHANGE_AGE`](crate::change_detection::MAX_CHANGE_AGE).
/// This prevents overflow and thus prevents false positives.
pub(crate) fn check_change_ticks(&mut self, change_tick: Tick) {
for system in &mut self.executable.systems {
if !is_apply_deferred(system) {
system.check_change_tick(change_tick);
}
}
for conditions in &mut self.executable.system_conditions {
for system in conditions.iter_mut() {
system.check_change_tick(change_tick);
}
}
for conditions in &mut self.executable.set_conditions {
for system in conditions.iter_mut() {
system.check_change_tick(change_tick);
}
}
}
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
/// Directly applies any accumulated [`Deferred`](crate::system::Deferred) system parameters (like [`Commands`](crate::prelude::Commands)) to the `world`.
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
///
/// Like always, deferred system parameters are applied in the "topological sort order" of the schedule graph.
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
/// As a result, buffers from one system are only guaranteed to be applied before those of other systems
/// if there is an explicit system ordering between the two systems.
///
/// This is used in rendering to extract data from the main world, storing the data in system buffers,
/// before applying their buffers in a different world.
pub fn apply_deferred(&mut self, world: &mut World) {
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
for system in &mut self.executable.systems {
system.apply_deferred(world);
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
}
}
}
/// A directed acyclic graph structure.
#[derive(Default)]
pub struct Dag {
/// A directed graph.
graph: DiGraphMap<NodeId, ()>,
/// A cached topological ordering of the graph.
topsort: Vec<NodeId>,
}
impl Dag {
fn new() -> Self {
Self {
graph: DiGraphMap::new(),
topsort: Vec::new(),
}
}
/// The directed graph of the stored systems, connected by their ordering dependencies.
pub fn graph(&self) -> &DiGraphMap<NodeId, ()> {
&self.graph
}
/// A cached topological ordering of the graph.
///
/// The order is determined by the ordering dependencies between systems.
pub fn cached_topsort(&self) -> &[NodeId] {
&self.topsort
}
}
/// A [`SystemSet`] with metadata, stored in a [`ScheduleGraph`].
struct SystemSetNode {
inner: BoxedSystemSet,
}
impl SystemSetNode {
pub fn new(set: BoxedSystemSet) -> Self {
Self { inner: set }
}
pub fn name(&self) -> String {
format!("{:?}", &self.inner)
}
pub fn is_system_type(&self) -> bool {
self.inner.system_type().is_some()
}
`run_if` for `SystemConfigs` via anonymous system sets (#7676) # Objective - Fixes #7659 ## Solution The idea of anonymous system sets or "implicit hidden organizational sets" was briefly mentioned by @cart here: https://github.com/bevyengine/bevy/pull/7634#issuecomment-1428619449. - `Schedule::add_systems` creates an implicit, anonymous system set of all systems in `SystemConfigs`. - All dependencies and conditions from the `SystemConfigs` are now applied to the implicit system set, instead of being applied to each individual system. This should not change the behavior, AFAIU, because `before`, `after`, `run_if` and `ambiguous_with` are transitive properties from a set to its members. - The newly added `AnonymousSystemSet` stores the names of its members to provide better error messages. - The names are stored in a reference counted slice, allowing fast clones of the `AnonymousSystemSet`. - However, only the pointer of the slice is used for hash and equality operations - This ensures that two `AnonymousSystemSet` are not equal, even if they have the same members / member names. - So two identical `add_systems` calls will produce two different `AnonymousSystemSet`s. - Clones of the same `AnonymousSystemSet` will be equal. ## Drawbacks If my assumptions are correct, the observed behavior should stay the same. But the number of system sets in the `Schedule` will increase with each `add_systems` call. If this has negative performance implications, `add_systems` could be changed to only create the implicit system set if necessary / when a run condition was added. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-03-30 21:39:10 +00:00
pub fn is_anonymous(&self) -> bool {
self.inner.is_anonymous()
}
}
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
/// A [`BoxedSystem`] with metadata, stored in a [`ScheduleGraph`].
struct SystemNode {
inner: Option<BoxedSystem>,
}
impl SystemNode {
pub fn new(system: BoxedSystem) -> Self {
Self {
inner: Some(system),
}
}
pub fn get(&self) -> Option<&BoxedSystem> {
self.inner.as_ref()
}
pub fn get_mut(&mut self) -> Option<&mut BoxedSystem> {
self.inner.as_mut()
}
}
/// Metadata for a [`Schedule`].
#[derive(Default)]
pub struct ScheduleGraph {
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
systems: Vec<SystemNode>,
system_conditions: Vec<Vec<BoxedCondition>>,
system_sets: Vec<SystemSetNode>,
system_set_conditions: Vec<Vec<BoxedCondition>>,
system_set_ids: HashMap<BoxedSystemSet, NodeId>,
uninit: Vec<(NodeId, usize)>,
hierarchy: Dag,
dependency: Dag,
ambiguous_with: UnGraphMap<NodeId, ()>,
ambiguous_with_all: HashSet<NodeId>,
conflicting_systems: Vec<(NodeId, NodeId, Vec<ComponentId>)>,
changed: bool,
settings: ScheduleBuildSettings,
}
impl ScheduleGraph {
/// Creates an empty [`ScheduleGraph`] with default settings.
pub fn new() -> Self {
Self {
systems: Vec::new(),
system_conditions: Vec::new(),
system_sets: Vec::new(),
system_set_conditions: Vec::new(),
system_set_ids: HashMap::new(),
uninit: Vec::new(),
hierarchy: Dag::new(),
dependency: Dag::new(),
ambiguous_with: UnGraphMap::new(),
ambiguous_with_all: HashSet::new(),
conflicting_systems: Vec::new(),
changed: false,
settings: default(),
}
}
/// Returns the system at the given [`NodeId`], if it exists.
pub fn get_system_at(&self, id: NodeId) -> Option<&dyn System<In = (), Out = ()>> {
if !id.is_system() {
return None;
}
self.systems
.get(id.index())
.and_then(|system| system.inner.as_deref())
}
/// Returns the system at the given [`NodeId`].
///
/// Panics if it doesn't exist.
#[track_caller]
pub fn system_at(&self, id: NodeId) -> &dyn System<In = (), Out = ()> {
self.get_system_at(id)
.ok_or_else(|| format!("system with id {id:?} does not exist in this Schedule"))
.unwrap()
}
/// Returns the set at the given [`NodeId`], if it exists.
pub fn get_set_at(&self, id: NodeId) -> Option<&dyn SystemSet> {
if !id.is_set() {
return None;
}
self.system_sets.get(id.index()).map(|set| &*set.inner)
}
/// Returns the set at the given [`NodeId`].
///
/// Panics if it doesn't exist.
#[track_caller]
pub fn set_at(&self, id: NodeId) -> &dyn SystemSet {
self.get_set_at(id)
.ok_or_else(|| format!("set with id {id:?} does not exist in this Schedule"))
.unwrap()
}
/// Returns an iterator over all systems in this schedule.
pub fn systems(
&self,
) -> impl Iterator<Item = (NodeId, &dyn System<In = (), Out = ()>, &[BoxedCondition])> {
self.systems
.iter()
.zip(self.system_conditions.iter())
.enumerate()
.filter_map(|(i, (system_node, condition))| {
let system = system_node.inner.as_deref()?;
Some((NodeId::System(i), system, condition.as_slice()))
})
}
/// Returns an iterator over all system sets in this schedule.
pub fn system_sets(&self) -> impl Iterator<Item = (NodeId, &dyn SystemSet, &[BoxedCondition])> {
self.system_set_ids.iter().map(|(_, &node_id)| {
let set_node = &self.system_sets[node_id.index()];
let set = &*set_node.inner;
let conditions = self.system_set_conditions[node_id.index()].as_slice();
(node_id, set, conditions)
})
}
/// Returns the [`Dag`] of the hierarchy.
///
/// The hierarchy is a directed acyclic graph of the systems and sets,
/// where an edge denotes that a system or set is the child of another set.
pub fn hierarchy(&self) -> &Dag {
&self.hierarchy
}
/// Returns the [`Dag`] of the dependencies in the schedule.
///
/// Nodes in this graph are systems and sets, and edges denote that
/// a system or set has to run before another system or set.
pub fn dependency(&self) -> &Dag {
&self.dependency
}
/// Returns the list of systems that conflict with each other, i.e. have ambiguities in their access.
///
/// If the `Vec<ComponentId>` is empty, the systems conflict on [`World`] access.
/// Must be called after [`ScheduleGraph::build_schedule`] to be non-empty.
pub fn conflicting_systems(&self) -> &[(NodeId, NodeId, Vec<ComponentId>)] {
&self.conflicting_systems
}
/// Adds the systems to the graph. Returns a vector of all node ids contained the nested `SystemConfigs`
/// if `ancestor_chained` is true. Also returns true if "densely chained", meaning that all nested items
/// are linearly chained in the order they are defined
fn add_systems_inner(
&mut self,
configs: SystemConfigs,
ancestor_chained: bool,
) -> AddSystemsInnerResult {
match configs {
SystemConfigs::SystemConfig(config) => {
let node_id = self.add_system_inner(config).unwrap();
if ancestor_chained {
AddSystemsInnerResult {
densely_chained: true,
nodes: vec![node_id],
}
} else {
AddSystemsInnerResult {
densely_chained: true,
nodes: Vec::new(),
}
}
}
`run_if` for `SystemConfigs` via anonymous system sets (#7676) # Objective - Fixes #7659 ## Solution The idea of anonymous system sets or "implicit hidden organizational sets" was briefly mentioned by @cart here: https://github.com/bevyengine/bevy/pull/7634#issuecomment-1428619449. - `Schedule::add_systems` creates an implicit, anonymous system set of all systems in `SystemConfigs`. - All dependencies and conditions from the `SystemConfigs` are now applied to the implicit system set, instead of being applied to each individual system. This should not change the behavior, AFAIU, because `before`, `after`, `run_if` and `ambiguous_with` are transitive properties from a set to its members. - The newly added `AnonymousSystemSet` stores the names of its members to provide better error messages. - The names are stored in a reference counted slice, allowing fast clones of the `AnonymousSystemSet`. - However, only the pointer of the slice is used for hash and equality operations - This ensures that two `AnonymousSystemSet` are not equal, even if they have the same members / member names. - So two identical `add_systems` calls will produce two different `AnonymousSystemSet`s. - Clones of the same `AnonymousSystemSet` will be equal. ## Drawbacks If my assumptions are correct, the observed behavior should stay the same. But the number of system sets in the `Schedule` will increase with each `add_systems` call. If this has negative performance implications, `add_systems` could be changed to only create the implicit system set if necessary / when a run condition was added. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-03-30 21:39:10 +00:00
SystemConfigs::Configs {
mut configs,
collective_conditions,
chained,
} => {
let more_than_one_entry = configs.len() > 1;
if !collective_conditions.is_empty() {
if more_than_one_entry {
let set = AnonymousSet::new();
for config in &mut configs {
Make `run_if_inner` public and rename to `run_if_dyn` (#9576) # Objective Sometimes you want to create a plugin with a custom run condition. In a function, you take the `Condition` trait and then make a `BoxedCondition` from it to store it. And then you want to add that condition to a system, but you can't, because there is only the `run_if` function available which takes `impl Condition<M>` instead of `BoxedCondition`. So you have to create a wrapper type for the `BoxedCondition` and implement the `System` and `ReadOnlySystem` traits for the wrapper (Like it's done in the picture below). It's very inconvenient and boilerplate. But there is an easy solution for that: make the `run_if_inner` system that takes a `BoxedCondition` public. Also, it makes sense to make `in_set_inner` function public as well with the same motivation. ![image](https://github.com/bevyengine/bevy/assets/61053971/a4455180-7e0c-4c2b-9372-cd8b4a9e682e) A chunk of the source code of the `bevy-inspector-egui` crate. ## Solution Make `run_if_inner` function public. Rename `run_if_inner` to `run_if_dyn`. Make `in_set_inner` function public. Rename `in_set_inner` to `in_set_dyn`. ## Changelog Changed visibility of `run_if_inner` from `pub(crate)` to `pub`. Renamed `run_if_inner` to `run_if_dyn`. Changed visibility of `in_set_inner` from `pub(crate)` to `pub`. Renamed `in_set_inner` to `in_set_dyn`. ## Migration Guide --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
2023-08-27 17:53:37 +00:00
config.in_set_dyn(set.dyn_clone());
`run_if` for `SystemConfigs` via anonymous system sets (#7676) # Objective - Fixes #7659 ## Solution The idea of anonymous system sets or "implicit hidden organizational sets" was briefly mentioned by @cart here: https://github.com/bevyengine/bevy/pull/7634#issuecomment-1428619449. - `Schedule::add_systems` creates an implicit, anonymous system set of all systems in `SystemConfigs`. - All dependencies and conditions from the `SystemConfigs` are now applied to the implicit system set, instead of being applied to each individual system. This should not change the behavior, AFAIU, because `before`, `after`, `run_if` and `ambiguous_with` are transitive properties from a set to its members. - The newly added `AnonymousSystemSet` stores the names of its members to provide better error messages. - The names are stored in a reference counted slice, allowing fast clones of the `AnonymousSystemSet`. - However, only the pointer of the slice is used for hash and equality operations - This ensures that two `AnonymousSystemSet` are not equal, even if they have the same members / member names. - So two identical `add_systems` calls will produce two different `AnonymousSystemSet`s. - Clones of the same `AnonymousSystemSet` will be equal. ## Drawbacks If my assumptions are correct, the observed behavior should stay the same. But the number of system sets in the `Schedule` will increase with each `add_systems` call. If this has negative performance implications, `add_systems` could be changed to only create the implicit system set if necessary / when a run condition was added. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-03-30 21:39:10 +00:00
}
let mut set_config = set.into_config();
set_config.conditions.extend(collective_conditions);
self.configure_set(set_config);
} else {
for condition in collective_conditions {
Make `run_if_inner` public and rename to `run_if_dyn` (#9576) # Objective Sometimes you want to create a plugin with a custom run condition. In a function, you take the `Condition` trait and then make a `BoxedCondition` from it to store it. And then you want to add that condition to a system, but you can't, because there is only the `run_if` function available which takes `impl Condition<M>` instead of `BoxedCondition`. So you have to create a wrapper type for the `BoxedCondition` and implement the `System` and `ReadOnlySystem` traits for the wrapper (Like it's done in the picture below). It's very inconvenient and boilerplate. But there is an easy solution for that: make the `run_if_inner` system that takes a `BoxedCondition` public. Also, it makes sense to make `in_set_inner` function public as well with the same motivation. ![image](https://github.com/bevyengine/bevy/assets/61053971/a4455180-7e0c-4c2b-9372-cd8b4a9e682e) A chunk of the source code of the `bevy-inspector-egui` crate. ## Solution Make `run_if_inner` function public. Rename `run_if_inner` to `run_if_dyn`. Make `in_set_inner` function public. Rename `in_set_inner` to `in_set_dyn`. ## Changelog Changed visibility of `run_if_inner` from `pub(crate)` to `pub`. Renamed `run_if_inner` to `run_if_dyn`. Changed visibility of `in_set_inner` from `pub(crate)` to `pub`. Renamed `in_set_inner` to `in_set_dyn`. ## Migration Guide --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
2023-08-27 17:53:37 +00:00
configs[0].run_if_dyn(condition);
`run_if` for `SystemConfigs` via anonymous system sets (#7676) # Objective - Fixes #7659 ## Solution The idea of anonymous system sets or "implicit hidden organizational sets" was briefly mentioned by @cart here: https://github.com/bevyengine/bevy/pull/7634#issuecomment-1428619449. - `Schedule::add_systems` creates an implicit, anonymous system set of all systems in `SystemConfigs`. - All dependencies and conditions from the `SystemConfigs` are now applied to the implicit system set, instead of being applied to each individual system. This should not change the behavior, AFAIU, because `before`, `after`, `run_if` and `ambiguous_with` are transitive properties from a set to its members. - The newly added `AnonymousSystemSet` stores the names of its members to provide better error messages. - The names are stored in a reference counted slice, allowing fast clones of the `AnonymousSystemSet`. - However, only the pointer of the slice is used for hash and equality operations - This ensures that two `AnonymousSystemSet` are not equal, even if they have the same members / member names. - So two identical `add_systems` calls will produce two different `AnonymousSystemSet`s. - Clones of the same `AnonymousSystemSet` will be equal. ## Drawbacks If my assumptions are correct, the observed behavior should stay the same. But the number of system sets in the `Schedule` will increase with each `add_systems` call. If this has negative performance implications, `add_systems` could be changed to only create the implicit system set if necessary / when a run condition was added. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-03-30 21:39:10 +00:00
}
}
}
let mut config_iter = configs.into_iter();
let mut nodes_in_scope = Vec::new();
let mut densely_chained = true;
if chained {
let Some(prev) = config_iter.next() else {
return AddSystemsInnerResult {
nodes: Vec::new(),
densely_chained: true,
};
};
let mut previous_result = self.add_systems_inner(prev, true);
densely_chained = previous_result.densely_chained;
for current in config_iter {
let current_result = self.add_systems_inner(current, true);
densely_chained = densely_chained && current_result.densely_chained;
match (
previous_result.densely_chained,
current_result.densely_chained,
) {
// Both groups are "densely" chained, so we can simplify the graph by only
// chaining the last in the previous list to the first in the current list
(true, true) => {
let last_in_prev = previous_result.nodes.last().unwrap();
let first_in_current = current_result.nodes.first().unwrap();
self.dependency.graph.add_edge(
*last_in_prev,
*first_in_current,
(),
);
}
// The previous group is "densely" chained, so we can simplify the graph by only
// chaining the last item from the previous list to every item in the current list
(true, false) => {
let last_in_prev = previous_result.nodes.last().unwrap();
for current_node in &current_result.nodes {
self.dependency.graph.add_edge(
*last_in_prev,
*current_node,
(),
);
}
}
// The current list is currently "densely" chained, so we can simplify the graph by
// only chaining every item in the previous list to the first item in the current list
(false, true) => {
let first_in_current = current_result.nodes.first().unwrap();
for previous_node in &previous_result.nodes {
self.dependency.graph.add_edge(
*previous_node,
*first_in_current,
(),
);
}
}
// Neither of the lists are "densely" chained, so we must chain every item in the first
// list to every item in the second list
(false, false) => {
for previous_node in &previous_result.nodes {
for current_node in &current_result.nodes {
self.dependency.graph.add_edge(
*previous_node,
*current_node,
(),
);
}
}
}
}
if ancestor_chained {
nodes_in_scope.append(&mut previous_result.nodes);
}
previous_result = current_result;
}
// ensure the last config's nodes are added
if ancestor_chained {
nodes_in_scope.append(&mut previous_result.nodes);
}
} else {
for config in config_iter {
let result = self.add_systems_inner(config, ancestor_chained);
densely_chained = densely_chained && result.densely_chained;
if ancestor_chained {
nodes_in_scope.extend(result.nodes);
}
}
// an "unchained" SystemConfig is only densely chained if it has exactly one densely chained entry
if more_than_one_entry {
densely_chained = false;
}
}
AddSystemsInnerResult {
nodes: nodes_in_scope,
densely_chained,
}
}
}
}
fn add_system_inner(&mut self, config: SystemConfig) -> Result<NodeId, ScheduleBuildError> {
let id = NodeId::System(self.systems.len());
// graph updates are immediate
self.update_graphs(id, config.graph_info)?;
// system init has to be deferred (need `&mut World`)
self.uninit.push((id, 0));
self.systems.push(SystemNode::new(config.system));
self.system_conditions.push(config.conditions);
Ok(id)
}
clean up configure_set(s) erroring (#9577) # Objective - have errors in configure_set and configure_sets show the line number of the user calling location rather than pointing to schedule.rs - use display formatting for the errors ## Example Error Text ```text // dependency loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DependencyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:39 // after thread 'main' panicked at 'System set `A` depends on itself.', examples/stress_tests/bevymark.rs:16:9 // hierarchy loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: HierarchyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:3 // after thread 'main' panicked at 'System set `A` contains itself.', examples/stress_tests/bevymark.rs:16:9 // configuring a system type set // before thread 'main' panicked at 'configuring system type sets is not allowed', crates\bevy_ecs\src\schedule\config.rs:394:9 //after thread 'main' panicked at 'configuring system type sets is not allowed', examples/stress_tests/bevymark.rs:16:9 ``` Code to produce errors: ```rust use bevy::prelude::*; #[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)] enum TestSet { A, } fn main() { fn foo() {} let mut app = App::empty(); // Hierarchy Loop app.configure_set(Main, TestSet::A.in_set(TestSet::A)); // Dependency Loop app.configure_set(Main, TestSet::A.after(TestSet::A)); // Configure System Type Set app.configure_set(Main, foo.into_system_set()); } ```
2023-08-28 17:44:52 +00:00
#[track_caller]
fn configure_sets(&mut self, sets: impl IntoSystemSetConfigs) {
let SystemSetConfigs { sets, chained } = sets.into_configs();
let mut set_iter = sets.into_iter();
if chained {
let Some(prev) = set_iter.next() else { return };
let mut prev_id = self.configure_set_inner(prev).unwrap();
for next in set_iter {
let next_id = self.configure_set_inner(next).unwrap();
self.dependency.graph.add_edge(prev_id, next_id, ());
prev_id = next_id;
}
} else {
for set in set_iter {
clean up configure_set(s) erroring (#9577) # Objective - have errors in configure_set and configure_sets show the line number of the user calling location rather than pointing to schedule.rs - use display formatting for the errors ## Example Error Text ```text // dependency loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DependencyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:39 // after thread 'main' panicked at 'System set `A` depends on itself.', examples/stress_tests/bevymark.rs:16:9 // hierarchy loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: HierarchyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:3 // after thread 'main' panicked at 'System set `A` contains itself.', examples/stress_tests/bevymark.rs:16:9 // configuring a system type set // before thread 'main' panicked at 'configuring system type sets is not allowed', crates\bevy_ecs\src\schedule\config.rs:394:9 //after thread 'main' panicked at 'configuring system type sets is not allowed', examples/stress_tests/bevymark.rs:16:9 ``` Code to produce errors: ```rust use bevy::prelude::*; #[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)] enum TestSet { A, } fn main() { fn foo() {} let mut app = App::empty(); // Hierarchy Loop app.configure_set(Main, TestSet::A.in_set(TestSet::A)); // Dependency Loop app.configure_set(Main, TestSet::A.after(TestSet::A)); // Configure System Type Set app.configure_set(Main, foo.into_system_set()); } ```
2023-08-28 17:44:52 +00:00
if let Err(e) = self.configure_set_inner(set) {
// using `unwrap_or_else(panic!)` led to the error being reported
// from this line instead of in the user code
panic!("{e}");
};
}
}
}
clean up configure_set(s) erroring (#9577) # Objective - have errors in configure_set and configure_sets show the line number of the user calling location rather than pointing to schedule.rs - use display formatting for the errors ## Example Error Text ```text // dependency loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DependencyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:39 // after thread 'main' panicked at 'System set `A` depends on itself.', examples/stress_tests/bevymark.rs:16:9 // hierarchy loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: HierarchyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:3 // after thread 'main' panicked at 'System set `A` contains itself.', examples/stress_tests/bevymark.rs:16:9 // configuring a system type set // before thread 'main' panicked at 'configuring system type sets is not allowed', crates\bevy_ecs\src\schedule\config.rs:394:9 //after thread 'main' panicked at 'configuring system type sets is not allowed', examples/stress_tests/bevymark.rs:16:9 ``` Code to produce errors: ```rust use bevy::prelude::*; #[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)] enum TestSet { A, } fn main() { fn foo() {} let mut app = App::empty(); // Hierarchy Loop app.configure_set(Main, TestSet::A.in_set(TestSet::A)); // Dependency Loop app.configure_set(Main, TestSet::A.after(TestSet::A)); // Configure System Type Set app.configure_set(Main, foo.into_system_set()); } ```
2023-08-28 17:44:52 +00:00
#[track_caller]
fn configure_set(&mut self, set: impl IntoSystemSetConfig) {
clean up configure_set(s) erroring (#9577) # Objective - have errors in configure_set and configure_sets show the line number of the user calling location rather than pointing to schedule.rs - use display formatting for the errors ## Example Error Text ```text // dependency loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DependencyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:39 // after thread 'main' panicked at 'System set `A` depends on itself.', examples/stress_tests/bevymark.rs:16:9 // hierarchy loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: HierarchyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:3 // after thread 'main' panicked at 'System set `A` contains itself.', examples/stress_tests/bevymark.rs:16:9 // configuring a system type set // before thread 'main' panicked at 'configuring system type sets is not allowed', crates\bevy_ecs\src\schedule\config.rs:394:9 //after thread 'main' panicked at 'configuring system type sets is not allowed', examples/stress_tests/bevymark.rs:16:9 ``` Code to produce errors: ```rust use bevy::prelude::*; #[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)] enum TestSet { A, } fn main() { fn foo() {} let mut app = App::empty(); // Hierarchy Loop app.configure_set(Main, TestSet::A.in_set(TestSet::A)); // Dependency Loop app.configure_set(Main, TestSet::A.after(TestSet::A)); // Configure System Type Set app.configure_set(Main, foo.into_system_set()); } ```
2023-08-28 17:44:52 +00:00
if let Err(e) = self.configure_set_inner(set) {
// using `unwrap_or_else(panic!)` led to the error being reported
// from this line instead of in the user code
panic!("{e}");
};
}
clean up configure_set(s) erroring (#9577) # Objective - have errors in configure_set and configure_sets show the line number of the user calling location rather than pointing to schedule.rs - use display formatting for the errors ## Example Error Text ```text // dependency loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DependencyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:39 // after thread 'main' panicked at 'System set `A` depends on itself.', examples/stress_tests/bevymark.rs:16:9 // hierarchy loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: HierarchyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:3 // after thread 'main' panicked at 'System set `A` contains itself.', examples/stress_tests/bevymark.rs:16:9 // configuring a system type set // before thread 'main' panicked at 'configuring system type sets is not allowed', crates\bevy_ecs\src\schedule\config.rs:394:9 //after thread 'main' panicked at 'configuring system type sets is not allowed', examples/stress_tests/bevymark.rs:16:9 ``` Code to produce errors: ```rust use bevy::prelude::*; #[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)] enum TestSet { A, } fn main() { fn foo() {} let mut app = App::empty(); // Hierarchy Loop app.configure_set(Main, TestSet::A.in_set(TestSet::A)); // Dependency Loop app.configure_set(Main, TestSet::A.after(TestSet::A)); // Configure System Type Set app.configure_set(Main, foo.into_system_set()); } ```
2023-08-28 17:44:52 +00:00
#[track_caller]
fn configure_set_inner(
&mut self,
set: impl IntoSystemSetConfig,
) -> Result<NodeId, ScheduleBuildError> {
let SystemSetConfig {
set,
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
graph_info,
mut conditions,
} = set.into_config();
let id = match self.system_set_ids.get(&set) {
Some(&id) => id,
None => self.add_set(set.dyn_clone()),
};
// graph updates are immediate
self.update_graphs(id, graph_info)?;
// system init has to be deferred (need `&mut World`)
let system_set_conditions = &mut self.system_set_conditions[id.index()];
self.uninit.push((id, system_set_conditions.len()));
system_set_conditions.append(&mut conditions);
Ok(id)
}
fn add_set(&mut self, set: BoxedSystemSet) -> NodeId {
let id = NodeId::Set(self.system_sets.len());
self.system_sets.push(SystemSetNode::new(set.dyn_clone()));
self.system_set_conditions.push(Vec::new());
self.system_set_ids.insert(set, id);
id
}
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
fn check_set(&mut self, id: &NodeId, set: &dyn SystemSet) -> Result<(), ScheduleBuildError> {
match self.system_set_ids.get(set) {
Some(set_id) => {
if id == set_id {
`run_if` for `SystemConfigs` via anonymous system sets (#7676) # Objective - Fixes #7659 ## Solution The idea of anonymous system sets or "implicit hidden organizational sets" was briefly mentioned by @cart here: https://github.com/bevyengine/bevy/pull/7634#issuecomment-1428619449. - `Schedule::add_systems` creates an implicit, anonymous system set of all systems in `SystemConfigs`. - All dependencies and conditions from the `SystemConfigs` are now applied to the implicit system set, instead of being applied to each individual system. This should not change the behavior, AFAIU, because `before`, `after`, `run_if` and `ambiguous_with` are transitive properties from a set to its members. - The newly added `AnonymousSystemSet` stores the names of its members to provide better error messages. - The names are stored in a reference counted slice, allowing fast clones of the `AnonymousSystemSet`. - However, only the pointer of the slice is used for hash and equality operations - This ensures that two `AnonymousSystemSet` are not equal, even if they have the same members / member names. - So two identical `add_systems` calls will produce two different `AnonymousSystemSet`s. - Clones of the same `AnonymousSystemSet` will be equal. ## Drawbacks If my assumptions are correct, the observed behavior should stay the same. But the number of system sets in the `Schedule` will increase with each `add_systems` call. If this has negative performance implications, `add_systems` could be changed to only create the implicit system set if necessary / when a run condition was added. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-03-30 21:39:10 +00:00
return Err(ScheduleBuildError::HierarchyLoop(self.get_node_name(id)));
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
}
}
None => {
self.add_set(set.dyn_clone());
}
}
Ok(())
}
fn check_sets(
&mut self,
id: &NodeId,
graph_info: &GraphInfo,
) -> Result<(), ScheduleBuildError> {
for set in &graph_info.sets {
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
self.check_set(id, &**set)?;
}
Ok(())
}
fn check_edges(
&mut self,
id: &NodeId,
graph_info: &GraphInfo,
) -> Result<(), ScheduleBuildError> {
for Dependency { kind: _, set } in &graph_info.dependencies {
match self.system_set_ids.get(set) {
Some(set_id) => {
if id == set_id {
`run_if` for `SystemConfigs` via anonymous system sets (#7676) # Objective - Fixes #7659 ## Solution The idea of anonymous system sets or "implicit hidden organizational sets" was briefly mentioned by @cart here: https://github.com/bevyengine/bevy/pull/7634#issuecomment-1428619449. - `Schedule::add_systems` creates an implicit, anonymous system set of all systems in `SystemConfigs`. - All dependencies and conditions from the `SystemConfigs` are now applied to the implicit system set, instead of being applied to each individual system. This should not change the behavior, AFAIU, because `before`, `after`, `run_if` and `ambiguous_with` are transitive properties from a set to its members. - The newly added `AnonymousSystemSet` stores the names of its members to provide better error messages. - The names are stored in a reference counted slice, allowing fast clones of the `AnonymousSystemSet`. - However, only the pointer of the slice is used for hash and equality operations - This ensures that two `AnonymousSystemSet` are not equal, even if they have the same members / member names. - So two identical `add_systems` calls will produce two different `AnonymousSystemSet`s. - Clones of the same `AnonymousSystemSet` will be equal. ## Drawbacks If my assumptions are correct, the observed behavior should stay the same. But the number of system sets in the `Schedule` will increase with each `add_systems` call. If this has negative performance implications, `add_systems` could be changed to only create the implicit system set if necessary / when a run condition was added. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-03-30 21:39:10 +00:00
return Err(ScheduleBuildError::DependencyLoop(self.get_node_name(id)));
}
}
None => {
self.add_set(set.dyn_clone());
}
}
}
if let Ambiguity::IgnoreWithSet(ambiguous_with) = &graph_info.ambiguous_with {
for set in ambiguous_with {
if !self.system_set_ids.contains_key(set) {
self.add_set(set.dyn_clone());
}
}
}
Ok(())
}
fn update_graphs(
&mut self,
id: NodeId,
graph_info: GraphInfo,
) -> Result<(), ScheduleBuildError> {
self.check_sets(&id, &graph_info)?;
self.check_edges(&id, &graph_info)?;
self.changed = true;
let GraphInfo {
sets,
dependencies,
ambiguous_with,
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
..
} = graph_info;
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
self.hierarchy.graph.add_node(id);
self.dependency.graph.add_node(id);
for set in sets.into_iter().map(|set| self.system_set_ids[&set]) {
self.hierarchy.graph.add_edge(set, id, ());
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
// ensure set also appears in dependency graph
self.dependency.graph.add_node(set);
}
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
if !self.dependency.graph.contains_node(id) {
self.dependency.graph.add_node(id);
}
for (kind, set) in dependencies
.into_iter()
.map(|Dependency { kind, set }| (kind, self.system_set_ids[&set]))
{
let (lhs, rhs) = match kind {
DependencyKind::Before => (id, set),
DependencyKind::After => (set, id),
};
self.dependency.graph.add_edge(lhs, rhs, ());
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
// ensure set also appears in hierarchy graph
self.hierarchy.graph.add_node(set);
}
match ambiguous_with {
Ambiguity::Check => (),
Ambiguity::IgnoreWithSet(ambiguous_with) => {
for set in ambiguous_with
.into_iter()
.map(|set| self.system_set_ids[&set])
{
self.ambiguous_with.add_edge(id, set, ());
}
}
Ambiguity::IgnoreAll => {
self.ambiguous_with_all.insert(id);
}
}
Ok(())
}
/// Initializes any newly-added systems and conditions by calling [`System::initialize`]
pub fn initialize(&mut self, world: &mut World) {
for (id, i) in self.uninit.drain(..) {
match id {
NodeId::System(index) => {
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
self.systems[index].get_mut().unwrap().initialize(world);
for condition in &mut self.system_conditions[index] {
condition.initialize(world);
}
}
NodeId::Set(index) => {
for condition in self.system_set_conditions[index].iter_mut().skip(i) {
condition.initialize(world);
}
}
}
}
}
/// Build a [`SystemSchedule`] optimized for scheduler access from the [`ScheduleGraph`].
///
/// This method also
/// - checks for dependency or hierarchy cycles
/// - checks for system access conflicts and reports ambiguities
pub fn build_schedule(
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
&mut self,
components: &Components,
schedule_label: &BoxedScheduleLabel,
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
) -> Result<SystemSchedule, ScheduleBuildError> {
// check hierarchy for cycles
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
self.hierarchy.topsort =
self.topsort_graph(&self.hierarchy.graph, ReportCycles::Hierarchy)?;
let hier_results = check_graph(&self.hierarchy.graph, &self.hierarchy.topsort);
self.optionally_check_hierarchy_conflicts(&hier_results.transitive_edges, schedule_label)?;
// remove redundant edges
self.hierarchy.graph = hier_results.transitive_reduction;
// check dependencies for cycles
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
self.dependency.topsort =
self.topsort_graph(&self.dependency.graph, ReportCycles::Dependency)?;
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
// check for systems or system sets depending on sets they belong to
let dep_results = check_graph(&self.dependency.graph, &self.dependency.topsort);
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
self.check_for_cross_dependencies(&dep_results, &hier_results.connected)?;
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
// map all system sets to their systems
// go in reverse topological order (bottom-up) for efficiency
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
let (set_systems, set_system_bitsets) =
self.map_sets_to_systems(&self.hierarchy.topsort, &self.hierarchy.graph);
self.check_order_but_intersect(&dep_results.connected, &set_system_bitsets)?;
// check that there are no edges to system-type sets that have multiple instances
self.check_system_type_set_ambiguity(&set_systems)?;
let dependency_flattened = self.get_dependency_flattened(&set_systems);
// topsort
let mut dependency_flattened_dag = Dag {
topsort: self.topsort_graph(&dependency_flattened, ReportCycles::Dependency)?,
graph: dependency_flattened,
};
let flat_results = check_graph(
&dependency_flattened_dag.graph,
&dependency_flattened_dag.topsort,
);
// remove redundant edges
dependency_flattened_dag.graph = flat_results.transitive_reduction;
// flatten: combine `in_set` with `ambiguous_with` information
let ambiguous_with_flattened = self.get_ambiguous_with_flattened(&set_systems);
// check for conflicts
let conflicting_systems =
self.get_conflicting_systems(&flat_results.disconnected, &ambiguous_with_flattened);
self.optionally_check_conflicts(&conflicting_systems, components, schedule_label)?;
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
self.conflicting_systems = conflicting_systems;
// build the schedule
Ok(self.build_schedule_inner(dependency_flattened_dag, hier_results.reachable))
}
fn map_sets_to_systems(
&self,
hierarchy_topsort: &[NodeId],
hierarchy_graph: &GraphMap<NodeId, (), Directed>,
) -> (HashMap<NodeId, Vec<NodeId>>, HashMap<NodeId, FixedBitSet>) {
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
let mut set_systems: HashMap<NodeId, Vec<NodeId>> =
HashMap::with_capacity(self.system_sets.len());
let mut set_system_bitsets = HashMap::with_capacity(self.system_sets.len());
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
for &id in hierarchy_topsort.iter().rev() {
if id.is_system() {
continue;
}
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
let mut systems = Vec::new();
let mut system_bitset = FixedBitSet::with_capacity(self.systems.len());
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
for child in hierarchy_graph.neighbors_directed(id, Direction::Outgoing) {
match child {
NodeId::System(_) => {
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
systems.push(child);
system_bitset.insert(child.index());
}
NodeId::Set(_) => {
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
let child_systems = set_systems.get(&child).unwrap();
let child_system_bitset = set_system_bitsets.get(&child).unwrap();
systems.extend_from_slice(child_systems);
system_bitset.union_with(child_system_bitset);
}
}
}
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
set_systems.insert(id, systems);
set_system_bitsets.insert(id, system_bitset);
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
(set_systems, set_system_bitsets)
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
fn get_dependency_flattened(
&self,
set_systems: &HashMap<NodeId, Vec<NodeId>>,
) -> GraphMap<NodeId, (), Directed> {
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
// flatten: combine `in_set` with `before` and `after` information
// have to do it like this to preserve transitivity
let mut dependency_flattened = self.dependency.graph.clone();
let mut temp = Vec::new();
for (&set, systems) in set_systems.iter() {
if systems.is_empty() {
for a in dependency_flattened.neighbors_directed(set, Direction::Incoming) {
for b in dependency_flattened.neighbors_directed(set, Direction::Outgoing) {
temp.push((a, b));
}
}
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
} else {
for a in dependency_flattened.neighbors_directed(set, Direction::Incoming) {
for &sys in systems {
temp.push((a, sys));
}
}
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
for b in dependency_flattened.neighbors_directed(set, Direction::Outgoing) {
for &sys in systems {
temp.push((sys, b));
}
}
}
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
dependency_flattened.remove_node(set);
for (a, b) in temp.drain(..) {
dependency_flattened.add_edge(a, b, ());
}
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
dependency_flattened
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
fn get_ambiguous_with_flattened(
&self,
set_systems: &HashMap<NodeId, Vec<NodeId>>,
) -> GraphMap<NodeId, (), Undirected> {
let mut ambiguous_with_flattened = UnGraphMap::new();
for (lhs, rhs, _) in self.ambiguous_with.all_edges() {
match (lhs, rhs) {
(NodeId::System(_), NodeId::System(_)) => {
ambiguous_with_flattened.add_edge(lhs, rhs, ());
}
(NodeId::Set(_), NodeId::System(_)) => {
for &lhs_ in set_systems.get(&lhs).unwrap_or(&Vec::new()) {
ambiguous_with_flattened.add_edge(lhs_, rhs, ());
}
}
(NodeId::System(_), NodeId::Set(_)) => {
for &rhs_ in set_systems.get(&rhs).unwrap_or(&Vec::new()) {
ambiguous_with_flattened.add_edge(lhs, rhs_, ());
}
}
(NodeId::Set(_), NodeId::Set(_)) => {
for &lhs_ in set_systems.get(&lhs).unwrap_or(&Vec::new()) {
for &rhs_ in set_systems.get(&rhs).unwrap_or(&vec![]) {
ambiguous_with_flattened.add_edge(lhs_, rhs_, ());
}
}
}
}
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
ambiguous_with_flattened
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
fn get_conflicting_systems(
&self,
flat_results_disconnected: &Vec<(NodeId, NodeId)>,
ambiguous_with_flattened: &GraphMap<NodeId, (), Undirected>,
) -> Vec<(NodeId, NodeId, Vec<ComponentId>)> {
let mut conflicting_systems = Vec::new();
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
for &(a, b) in flat_results_disconnected {
if ambiguous_with_flattened.contains_edge(a, b)
|| self.ambiguous_with_all.contains(&a)
|| self.ambiguous_with_all.contains(&b)
{
continue;
}
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
let system_a = self.systems[a.index()].get().unwrap();
let system_b = self.systems[b.index()].get().unwrap();
if system_a.is_exclusive() || system_b.is_exclusive() {
conflicting_systems.push((a, b, Vec::new()));
} else {
let access_a = system_a.component_access();
let access_b = system_b.component_access();
if !access_a.is_compatible(access_b) {
let conflicts = access_a.get_conflicts(access_b);
conflicting_systems.push((a, b, conflicts));
}
}
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
conflicting_systems
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
fn build_schedule_inner(
&self,
dependency_flattened_dag: Dag,
hier_results_reachable: FixedBitSet,
) -> SystemSchedule {
let dg_system_ids = dependency_flattened_dag.topsort.clone();
let dg_system_idx_map = dg_system_ids
.iter()
.cloned()
.enumerate()
.map(|(i, id)| (id, i))
.collect::<HashMap<_, _>>();
let hg_systems = self
.hierarchy
.topsort
.iter()
.cloned()
.enumerate()
.filter(|&(_i, id)| id.is_system())
.collect::<Vec<_>>();
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
let (hg_set_with_conditions_idxs, hg_set_ids): (Vec<_>, Vec<_>) = self
.hierarchy
.topsort
.iter()
.cloned()
.enumerate()
.filter(|&(_i, id)| {
// ignore system sets that have no conditions
// ignore system type sets (already covered, they don't have conditions)
id.is_set() && !self.system_set_conditions[id.index()].is_empty()
})
.unzip();
let sys_count = self.systems.len();
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
let set_with_conditions_count = hg_set_ids.len();
let hg_node_count = self.hierarchy.graph.node_count();
// get the number of dependencies and the immediate dependents of each system
// (needed by multi-threaded executor to run systems in the correct order)
let mut system_dependencies = Vec::with_capacity(sys_count);
let mut system_dependents = Vec::with_capacity(sys_count);
for &sys_id in &dg_system_ids {
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
let num_dependencies = dependency_flattened_dag
.graph
.neighbors_directed(sys_id, Direction::Incoming)
.count();
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
let dependents = dependency_flattened_dag
.graph
.neighbors_directed(sys_id, Direction::Outgoing)
.map(|dep_id| dg_system_idx_map[&dep_id])
.collect::<Vec<_>>();
system_dependencies.push(num_dependencies);
system_dependents.push(dependents);
}
// get the rows and columns of the hierarchy graph's reachability matrix
// (needed to we can evaluate conditions in the correct order)
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
let mut systems_in_sets_with_conditions =
vec![FixedBitSet::with_capacity(sys_count); set_with_conditions_count];
for (i, &row) in hg_set_with_conditions_idxs.iter().enumerate() {
let bitset = &mut systems_in_sets_with_conditions[i];
for &(col, sys_id) in &hg_systems {
let idx = dg_system_idx_map[&sys_id];
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
let is_descendant = hier_results_reachable[index(row, col, hg_node_count)];
bitset.set(idx, is_descendant);
}
}
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
let mut sets_with_conditions_of_systems =
vec![FixedBitSet::with_capacity(set_with_conditions_count); sys_count];
for &(col, sys_id) in &hg_systems {
let i = dg_system_idx_map[&sys_id];
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
let bitset = &mut sets_with_conditions_of_systems[i];
for (idx, &row) in hg_set_with_conditions_idxs
.iter()
.enumerate()
.take_while(|&(_idx, &row)| row < col)
{
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
let is_ancestor = hier_results_reachable[index(row, col, hg_node_count)];
bitset.set(idx, is_ancestor);
}
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
SystemSchedule {
systems: Vec::with_capacity(sys_count),
system_conditions: Vec::with_capacity(sys_count),
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
set_conditions: Vec::with_capacity(set_with_conditions_count),
system_ids: dg_system_ids,
set_ids: hg_set_ids,
system_dependencies,
system_dependents,
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
sets_with_conditions_of_systems,
systems_in_sets_with_conditions,
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
}
}
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
fn update_schedule(
&mut self,
schedule: &mut SystemSchedule,
components: &Components,
schedule_label: &BoxedScheduleLabel,
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
) -> Result<(), ScheduleBuildError> {
if !self.uninit.is_empty() {
return Err(ScheduleBuildError::Uninitialized);
}
// move systems out of old schedule
for ((id, system), conditions) in schedule
.system_ids
.drain(..)
.zip(schedule.systems.drain(..))
.zip(schedule.system_conditions.drain(..))
{
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
self.systems[id.index()].inner = Some(system);
self.system_conditions[id.index()] = conditions;
}
for (id, conditions) in schedule
.set_ids
.drain(..)
.zip(schedule.set_conditions.drain(..))
{
self.system_set_conditions[id.index()] = conditions;
}
*schedule = self.build_schedule(components, schedule_label)?;
// move systems into new schedule
for &id in &schedule.system_ids {
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
let system = self.systems[id.index()].inner.take().unwrap();
let conditions = std::mem::take(&mut self.system_conditions[id.index()]);
schedule.systems.push(system);
schedule.system_conditions.push(conditions);
}
for &id in &schedule.set_ids {
let conditions = std::mem::take(&mut self.system_set_conditions[id.index()]);
schedule.set_conditions.push(conditions);
}
Ok(())
}
}
Base Sets (#7466) # Objective NOTE: This depends on #7267 and should not be merged until #7267 is merged. If you are reviewing this before that is merged, I highly recommend viewing the Base Sets commit instead of trying to find my changes amongst those from #7267. "Default sets" as described by the [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) have some [unfortunate consequences](https://github.com/bevyengine/bevy/discussions/7365). ## Solution This adds "base sets" as a variant of `SystemSet`: A set is a "base set" if `SystemSet::is_base` returns `true`. Typically this will be opted-in to using the `SystemSet` derive: ```rust #[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[system_set(base)] enum MyBaseSet { A, B, } ``` **Base sets are exclusive**: a system can belong to at most one "base set". Adding a system to more than one will result in an error. When possible we fail immediately during system-config-time with a nice file + line number. For the more nested graph-ey cases, this will fail at the final schedule build. **Base sets cannot belong to other sets**: this is where the word "base" comes from Systems and Sets can only be added to base sets using `in_base_set`. Calling `in_set` with a base set will fail. As will calling `in_base_set` with a normal set. ```rust app.add_system(foo.in_base_set(MyBaseSet::A)) // X must be a normal set ... base sets cannot be added to base sets .configure_set(X.in_base_set(MyBaseSet::A)) ``` Base sets can still be configured like normal sets: ```rust app.add_system(MyBaseSet::B.after(MyBaseSet::Ap)) ``` The primary use case for base sets is enabling a "default base set": ```rust schedule.set_default_base_set(CoreSet::Update) // this will belong to CoreSet::Update by default .add_system(foo) // this will override the default base set with PostUpdate .add_system(bar.in_base_set(CoreSet::PostUpdate)) ``` This allows us to build apis that work by default in the standard Bevy style. This is a rough analog to the "default stage" model, but it use the new "stageless sets" model instead, with all of the ordering flexibility (including exclusive systems) that it provides. --- ## Changelog - Added "base sets" and ported CoreSet to use them. ## Migration Guide TODO
2023-02-06 03:10:08 +00:00
/// Values returned by `ScheduleGraph::add_systems_inner`
struct AddSystemsInnerResult {
/// All nodes contained inside this add_systems_inner call's SystemConfigs hierarchy
nodes: Vec<NodeId>,
/// True if and only if all nodes are "densely chained"
densely_chained: bool,
}
/// Used to select the appropriate reporting function.
enum ReportCycles {
Hierarchy,
Dependency,
}
// methods for reporting errors
impl ScheduleGraph {
fn get_node_name(&self, id: &NodeId) -> String {
let mut name = match id {
Add `report_sets` option to `ScheduleBuildSettings` (#7756) # Objective - Fixes #7442. ## Solution - Added `report_sets` option to `ScheduleBuildSettings` like described in the linked issue. The output of the `3d_scene` example when reporting ambiguities with `report_sets` and `use_shortnames` set to `true` (and with #7755 applied) now looks like this: ``` 82 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- filesystem_watcher_system (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<DynamicScene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Scene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Shader> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Mesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<SkinnedMeshInverseBindposes> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Image> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<TextureAtlas> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<ColorMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Font> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<FontAtlasSet> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<StandardMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Gltf> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfNode> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfPrimitive> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfMesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSource> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSink> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AnimationClip> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- scene_spawner_system (Update) and close_when_requested (Update) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- calculate_bounds (CalculateBounds, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and visibility_propagate_system (PostUpdate, VisibilityPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_text2d_layout (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and ui_stack_system (PostUpdate, Stack) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and text_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_image_calculated_size_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and flex_node_system (Flex, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and add_clusters (AddClusters, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- visibility_propagate_system (PostUpdate, VisibilityPropagate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_text2d_layout (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- ui_stack_system (PostUpdate, Stack) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- text_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_image_calculated_size_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and animation_player (PostUpdate) conflict on: ["bevy_transform::components::transform::Transform"] -- apply_system_buffers (AddClustersFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and check_visibility (CheckVisibility, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_frusta (PostUpdate, UpdateLightFrusta) conflict on: bevy_ecs::world::World -- Assets<Scene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Shader>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Mesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<SkinnedMeshInverseBindposes>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Image>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<TextureAtlas>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<ColorMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Font>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<FontAtlasSet>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<StandardMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Gltf>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfNode>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfPrimitive>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfMesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSource>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSink>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AnimationClip>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<DynamicScene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World ``` Co-authored-by: Edgar Geier <geieredgar@gmail.com>
2023-02-20 15:31:10 +00:00
NodeId::System(_) => {
let name = self.systems[id.index()].get().unwrap().name().to_string();
if self.settings.report_sets {
let sets = self.names_of_sets_containing_node(id);
if sets.is_empty() {
name
} else if sets.len() == 1 {
format!("{name} (in set {})", sets[0])
} else {
format!("{name} (in sets {})", sets.join(", "))
}
} else {
name
}
}
`run_if` for `SystemConfigs` via anonymous system sets (#7676) # Objective - Fixes #7659 ## Solution The idea of anonymous system sets or "implicit hidden organizational sets" was briefly mentioned by @cart here: https://github.com/bevyengine/bevy/pull/7634#issuecomment-1428619449. - `Schedule::add_systems` creates an implicit, anonymous system set of all systems in `SystemConfigs`. - All dependencies and conditions from the `SystemConfigs` are now applied to the implicit system set, instead of being applied to each individual system. This should not change the behavior, AFAIU, because `before`, `after`, `run_if` and `ambiguous_with` are transitive properties from a set to its members. - The newly added `AnonymousSystemSet` stores the names of its members to provide better error messages. - The names are stored in a reference counted slice, allowing fast clones of the `AnonymousSystemSet`. - However, only the pointer of the slice is used for hash and equality operations - This ensures that two `AnonymousSystemSet` are not equal, even if they have the same members / member names. - So two identical `add_systems` calls will produce two different `AnonymousSystemSet`s. - Clones of the same `AnonymousSystemSet` will be equal. ## Drawbacks If my assumptions are correct, the observed behavior should stay the same. But the number of system sets in the `Schedule` will increase with each `add_systems` call. If this has negative performance implications, `add_systems` could be changed to only create the implicit system set if necessary / when a run condition was added. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-03-30 21:39:10 +00:00
NodeId::Set(_) => {
let set = &self.system_sets[id.index()];
if set.is_anonymous() {
self.anonymous_set_name(id)
} else {
set.name()
}
}
};
if self.settings.use_shortnames {
name = bevy_utils::get_short_name(&name);
}
name
}
`run_if` for `SystemConfigs` via anonymous system sets (#7676) # Objective - Fixes #7659 ## Solution The idea of anonymous system sets or "implicit hidden organizational sets" was briefly mentioned by @cart here: https://github.com/bevyengine/bevy/pull/7634#issuecomment-1428619449. - `Schedule::add_systems` creates an implicit, anonymous system set of all systems in `SystemConfigs`. - All dependencies and conditions from the `SystemConfigs` are now applied to the implicit system set, instead of being applied to each individual system. This should not change the behavior, AFAIU, because `before`, `after`, `run_if` and `ambiguous_with` are transitive properties from a set to its members. - The newly added `AnonymousSystemSet` stores the names of its members to provide better error messages. - The names are stored in a reference counted slice, allowing fast clones of the `AnonymousSystemSet`. - However, only the pointer of the slice is used for hash and equality operations - This ensures that two `AnonymousSystemSet` are not equal, even if they have the same members / member names. - So two identical `add_systems` calls will produce two different `AnonymousSystemSet`s. - Clones of the same `AnonymousSystemSet` will be equal. ## Drawbacks If my assumptions are correct, the observed behavior should stay the same. But the number of system sets in the `Schedule` will increase with each `add_systems` call. If this has negative performance implications, `add_systems` could be changed to only create the implicit system set if necessary / when a run condition was added. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-03-30 21:39:10 +00:00
fn anonymous_set_name(&self, id: &NodeId) -> String {
format!(
"({})",
self.hierarchy
.graph
.edges_directed(*id, Direction::Outgoing)
.map(|(_, member_id, _)| self.get_node_name(&member_id))
.reduce(|a, b| format!("{a}, {b}"))
.unwrap_or_default()
)
}
fn get_node_kind(&self, id: &NodeId) -> &'static str {
match id {
NodeId::System(_) => "system",
NodeId::Set(_) => "system set",
}
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
/// If [`ScheduleBuildSettings::hierarchy_detection`] is [`LogLevel::Ignore`] this check
/// is skipped.
fn optionally_check_hierarchy_conflicts(
&self,
transitive_edges: &[(NodeId, NodeId)],
schedule_label: &BoxedScheduleLabel,
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
) -> Result<(), ScheduleBuildError> {
if self.settings.hierarchy_detection == LogLevel::Ignore || transitive_edges.is_empty() {
return Ok(());
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
let message = self.get_hierarchy_conflicts_error_message(transitive_edges);
match self.settings.hierarchy_detection {
LogLevel::Ignore => unreachable!(),
LogLevel::Warn => {
error!(
"Schedule {schedule_label:?} has redundant edges:\n {}",
message
);
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
Ok(())
}
LogLevel::Error => Err(ScheduleBuildError::HierarchyRedundancy(message)),
}
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
fn get_hierarchy_conflicts_error_message(
&self,
transitive_edges: &[(NodeId, NodeId)],
) -> String {
let mut message = String::from("hierarchy contains redundant edge(s)");
for (parent, child) in transitive_edges {
writeln!(
message,
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
" -- {} `{}` cannot be child of set `{}`, longer path exists",
self.get_node_kind(child),
self.get_node_name(child),
self.get_node_name(parent),
)
.unwrap();
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
message
}
/// Tries to topologically sort `graph`.
///
/// If the graph is acyclic, returns [`Ok`] with the list of [`NodeId`] in a valid
/// topological order. If the graph contains cycles, returns [`Err`] with the list of
/// strongly-connected components that contain cycles (also in a valid topological order).
///
/// # Errors
///
/// If the graph contain cycles, then an error is returned.
fn topsort_graph(
&self,
graph: &DiGraphMap<NodeId, ()>,
report: ReportCycles,
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
) -> Result<Vec<NodeId>, ScheduleBuildError> {
// Tarjan's SCC algorithm returns elements in *reverse* topological order.
let mut tarjan_scc = TarjanScc::new();
let mut top_sorted_nodes = Vec::with_capacity(graph.node_count());
let mut sccs_with_cycles = Vec::new();
tarjan_scc.run(graph, |scc| {
// A strongly-connected component is a group of nodes who can all reach each other
// through one or more paths. If an SCC contains more than one node, there must be
// at least one cycle within them.
if scc.len() > 1 {
sccs_with_cycles.push(scc.to_vec());
}
top_sorted_nodes.extend_from_slice(scc);
});
if sccs_with_cycles.is_empty() {
// reverse to get topological order
top_sorted_nodes.reverse();
Ok(top_sorted_nodes)
} else {
let mut cycles = Vec::new();
for scc in &sccs_with_cycles {
cycles.append(&mut simple_cycles_in_component(graph, scc));
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
let error = match report {
ReportCycles::Hierarchy => ScheduleBuildError::HierarchyCycle(
self.get_hierarchy_cycles_error_message(&cycles),
),
ReportCycles::Dependency => ScheduleBuildError::DependencyCycle(
self.get_dependency_cycles_error_message(&cycles),
),
};
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
Err(error)
}
}
/// Logs details of cycles in the hierarchy graph.
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
fn get_hierarchy_cycles_error_message(&self, cycles: &[Vec<NodeId>]) -> String {
let mut message = format!("schedule has {} in_set cycle(s):\n", cycles.len());
for (i, cycle) in cycles.iter().enumerate() {
let mut names = cycle.iter().map(|id| self.get_node_name(id));
let first_name = names.next().unwrap();
writeln!(
message,
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
"cycle {}: set `{first_name}` contains itself",
i + 1,
)
.unwrap();
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
writeln!(message, "set `{first_name}`").unwrap();
for name in names.chain(std::iter::once(first_name)) {
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
writeln!(message, " ... which contains set `{name}`").unwrap();
}
writeln!(message).unwrap();
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
message
}
/// Logs details of cycles in the dependency graph.
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
fn get_dependency_cycles_error_message(&self, cycles: &[Vec<NodeId>]) -> String {
let mut message = format!("schedule has {} before/after cycle(s):\n", cycles.len());
for (i, cycle) in cycles.iter().enumerate() {
let mut names = cycle
.iter()
.map(|id| (self.get_node_kind(id), self.get_node_name(id)));
let (first_kind, first_name) = names.next().unwrap();
writeln!(
message,
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
"cycle {}: {first_kind} `{first_name}` must run before itself",
i + 1,
)
.unwrap();
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
writeln!(message, "{first_kind} `{first_name}`").unwrap();
for (kind, name) in names.chain(std::iter::once((first_kind, first_name))) {
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
writeln!(message, " ... which must run before {kind} `{name}`").unwrap();
}
writeln!(message).unwrap();
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
message
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
fn check_for_cross_dependencies(
&self,
dep_results: &CheckGraphResults<NodeId>,
hier_results_connected: &HashSet<(NodeId, NodeId)>,
) -> Result<(), ScheduleBuildError> {
for &(a, b) in dep_results.connected.iter() {
if hier_results_connected.contains(&(a, b)) || hier_results_connected.contains(&(b, a))
{
let name_a = self.get_node_name(&a);
let name_b = self.get_node_name(&b);
return Err(ScheduleBuildError::CrossDependency(name_a, name_b));
}
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
Ok(())
}
fn check_order_but_intersect(
&self,
dep_results_connected: &HashSet<(NodeId, NodeId)>,
set_system_bitsets: &HashMap<NodeId, FixedBitSet>,
) -> Result<(), ScheduleBuildError> {
// check that there is no ordering between system sets that intersect
for (a, b) in dep_results_connected.iter() {
if !(a.is_set() && b.is_set()) {
continue;
}
let a_systems = set_system_bitsets.get(a).unwrap();
let b_systems = set_system_bitsets.get(b).unwrap();
if !(a_systems.is_disjoint(b_systems)) {
return Err(ScheduleBuildError::SetsHaveOrderButIntersect(
self.get_node_name(a),
self.get_node_name(b),
));
}
}
Ok(())
}
fn check_system_type_set_ambiguity(
&self,
set_systems: &HashMap<NodeId, Vec<NodeId>>,
) -> Result<(), ScheduleBuildError> {
for (&id, systems) in set_systems.iter() {
let set = &self.system_sets[id.index()];
if set.is_system_type() {
let instances = systems.len();
let ambiguous_with = self.ambiguous_with.edges(id);
let before = self
.dependency
.graph
.edges_directed(id, Direction::Incoming);
let after = self
.dependency
.graph
.edges_directed(id, Direction::Outgoing);
let relations = before.count() + after.count() + ambiguous_with.count();
if instances > 1 && relations > 0 {
return Err(ScheduleBuildError::SystemTypeSetAmbiguity(
self.get_node_name(&id),
));
}
}
}
Ok(())
}
/// if [`ScheduleBuildSettings::ambiguity_detection`] is [`LogLevel::Ignore`], this check is skipped
fn optionally_check_conflicts(
&self,
conflicts: &[(NodeId, NodeId, Vec<ComponentId>)],
components: &Components,
schedule_label: &BoxedScheduleLabel,
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
) -> Result<(), ScheduleBuildError> {
if self.settings.ambiguity_detection == LogLevel::Ignore || conflicts.is_empty() {
return Ok(());
}
let message = self.get_conflicts_error_message(conflicts, components);
match self.settings.ambiguity_detection {
LogLevel::Ignore => Ok(()),
LogLevel::Warn => {
warn!("Schedule {schedule_label:?} has ambiguities.\n{}", message);
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
Ok(())
}
LogLevel::Error => Err(ScheduleBuildError::Ambiguity(message)),
}
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
fn get_conflicts_error_message(
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
&self,
ambiguities: &[(NodeId, NodeId, Vec<ComponentId>)],
components: &Components,
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
) -> String {
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
let n_ambiguities = ambiguities.len();
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
let mut message = format!(
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
"{n_ambiguities} pairs of systems with conflicting data access have indeterminate execution order. \
Consider adding `before`, `after`, or `ambiguous_with` relationships between these:\n",
);
for (system_a, system_b, conflicts) in ambiguities {
let name_a = self.get_node_name(system_a);
let name_b = self.get_node_name(system_b);
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
debug_assert!(system_a.is_system(), "{name_a} is not a system.");
debug_assert!(system_b.is_system(), "{name_b} is not a system.");
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
writeln!(message, " -- {name_a} and {name_b}").unwrap();
if !conflicts.is_empty() {
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
let conflict_names: Vec<_> = conflicts
.iter()
.map(|id| components.get_name(*id).unwrap())
.collect();
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
writeln!(message, " conflict on: {conflict_names:?}").unwrap();
} else {
// one or both systems must be exclusive
let world = std::any::type_name::<World>();
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
writeln!(message, " conflict on: {world}").unwrap();
}
}
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
message
}
Add `report_sets` option to `ScheduleBuildSettings` (#7756) # Objective - Fixes #7442. ## Solution - Added `report_sets` option to `ScheduleBuildSettings` like described in the linked issue. The output of the `3d_scene` example when reporting ambiguities with `report_sets` and `use_shortnames` set to `true` (and with #7755 applied) now looks like this: ``` 82 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- filesystem_watcher_system (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<DynamicScene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Scene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Shader> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Mesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<SkinnedMeshInverseBindposes> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Image> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<TextureAtlas> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<ColorMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Font> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<FontAtlasSet> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<StandardMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Gltf> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfNode> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfPrimitive> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfMesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSource> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSink> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AnimationClip> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- scene_spawner_system (Update) and close_when_requested (Update) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- calculate_bounds (CalculateBounds, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and visibility_propagate_system (PostUpdate, VisibilityPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_text2d_layout (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and ui_stack_system (PostUpdate, Stack) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and text_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_image_calculated_size_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and flex_node_system (Flex, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and add_clusters (AddClusters, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- visibility_propagate_system (PostUpdate, VisibilityPropagate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_text2d_layout (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- ui_stack_system (PostUpdate, Stack) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- text_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_image_calculated_size_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and animation_player (PostUpdate) conflict on: ["bevy_transform::components::transform::Transform"] -- apply_system_buffers (AddClustersFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and check_visibility (CheckVisibility, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_frusta (PostUpdate, UpdateLightFrusta) conflict on: bevy_ecs::world::World -- Assets<Scene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Shader>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Mesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<SkinnedMeshInverseBindposes>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Image>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<TextureAtlas>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<ColorMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Font>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<FontAtlasSet>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<StandardMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Gltf>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfNode>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfPrimitive>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfMesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSource>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSink>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AnimationClip>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<DynamicScene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World ``` Co-authored-by: Edgar Geier <geieredgar@gmail.com>
2023-02-20 15:31:10 +00:00
fn traverse_sets_containing_node(&self, id: NodeId, f: &mut impl FnMut(NodeId) -> bool) {
for (set_id, _, _) in self.hierarchy.graph.edges_directed(id, Direction::Incoming) {
if f(set_id) {
self.traverse_sets_containing_node(set_id, f);
}
}
}
fn names_of_sets_containing_node(&self, id: &NodeId) -> Vec<String> {
let mut sets = HashSet::new();
self.traverse_sets_containing_node(*id, &mut |set_id| {
!self.system_sets[set_id.index()].is_system_type() && sets.insert(set_id)
});
let mut sets: Vec<_> = sets
.into_iter()
.map(|set_id| self.get_node_name(&set_id))
.collect();
sets.sort();
sets
}
}
/// Category of errors encountered during schedule construction.
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum ScheduleBuildError {
/// A system set contains itself.
clean up configure_set(s) erroring (#9577) # Objective - have errors in configure_set and configure_sets show the line number of the user calling location rather than pointing to schedule.rs - use display formatting for the errors ## Example Error Text ```text // dependency loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DependencyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:39 // after thread 'main' panicked at 'System set `A` depends on itself.', examples/stress_tests/bevymark.rs:16:9 // hierarchy loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: HierarchyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:3 // after thread 'main' panicked at 'System set `A` contains itself.', examples/stress_tests/bevymark.rs:16:9 // configuring a system type set // before thread 'main' panicked at 'configuring system type sets is not allowed', crates\bevy_ecs\src\schedule\config.rs:394:9 //after thread 'main' panicked at 'configuring system type sets is not allowed', examples/stress_tests/bevymark.rs:16:9 ``` Code to produce errors: ```rust use bevy::prelude::*; #[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)] enum TestSet { A, } fn main() { fn foo() {} let mut app = App::empty(); // Hierarchy Loop app.configure_set(Main, TestSet::A.in_set(TestSet::A)); // Dependency Loop app.configure_set(Main, TestSet::A.after(TestSet::A)); // Configure System Type Set app.configure_set(Main, foo.into_system_set()); } ```
2023-08-28 17:44:52 +00:00
#[error("System set `{0}` contains itself.")]
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
HierarchyLoop(String),
/// The hierarchy of system sets contains a cycle.
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
#[error("System set hierarchy contains cycle(s).\n{0}")]
HierarchyCycle(String),
/// The hierarchy of system sets contains redundant edges.
///
/// This error is disabled by default, but can be opted-in using [`ScheduleBuildSettings`].
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
#[error("System set hierarchy contains redundant edges.\n{0}")]
HierarchyRedundancy(String),
/// A system (set) has been told to run before itself.
clean up configure_set(s) erroring (#9577) # Objective - have errors in configure_set and configure_sets show the line number of the user calling location rather than pointing to schedule.rs - use display formatting for the errors ## Example Error Text ```text // dependency loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DependencyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:39 // after thread 'main' panicked at 'System set `A` depends on itself.', examples/stress_tests/bevymark.rs:16:9 // hierarchy loop // before thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: HierarchyLoop("A")', crates\bevy_ecs\src\schedule\schedule.rs:682:3 // after thread 'main' panicked at 'System set `A` contains itself.', examples/stress_tests/bevymark.rs:16:9 // configuring a system type set // before thread 'main' panicked at 'configuring system type sets is not allowed', crates\bevy_ecs\src\schedule\config.rs:394:9 //after thread 'main' panicked at 'configuring system type sets is not allowed', examples/stress_tests/bevymark.rs:16:9 ``` Code to produce errors: ```rust use bevy::prelude::*; #[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)] enum TestSet { A, } fn main() { fn foo() {} let mut app = App::empty(); // Hierarchy Loop app.configure_set(Main, TestSet::A.in_set(TestSet::A)); // Dependency Loop app.configure_set(Main, TestSet::A.after(TestSet::A)); // Configure System Type Set app.configure_set(Main, foo.into_system_set()); } ```
2023-08-28 17:44:52 +00:00
#[error("System set `{0}` depends on itself.")]
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
DependencyLoop(String),
/// The dependency graph contains a cycle.
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
#[error("System dependencies contain cycle(s).\n{0}")]
DependencyCycle(String),
/// Tried to order a system (set) relative to a system set it belongs to.
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
#[error("`{0}` and `{1}` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.")]
CrossDependency(String, String),
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
/// Tried to order system sets that share systems.
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
#[error("`{0}` and `{1}` have a `before`-`after` relationship (which may be transitive) but share systems.")]
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
SetsHaveOrderButIntersect(String, String),
/// Tried to order a system (set) relative to all instances of some system function.
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
#[error("Tried to order against `{0}` in a schedule that has more than one `{0}` instance. `{0}` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.")]
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
SystemTypeSetAmbiguity(String),
/// Systems with conflicting access have indeterminate run order.
///
/// This error is disabled by default, but can be opted-in using [`ScheduleBuildSettings`].
Refactor build_schedule and related errors (#9579) # Objective - break up large build_schedule system to make it easier to read - Clean up related error messages. - I have a follow up PR that adds the schedule name to the error messages, but wanted to break this up from that. ## Changelog - refactor `build_schedule` to be easier to read ## Sample Error Messages Dependency Cycle ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system set 'A' must run before itself system set 'A' ... which must run before system set 'B' ... which must run before system set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` ```text thread 'main' panicked at 'System dependencies contain cycle(s). schedule has 1 before/after cycle(s): cycle 1: system 'foo' must run before itself system 'foo' ... which must run before system 'bar' ... which must run before system 'foo' ', crates\bevy_ecs\src\schedule\schedule.rs:228:13 ``` Hierarchy Cycle ```text thread 'main' panicked at 'System set hierarchy contains cycle(s). schedule has 1 in_set cycle(s): cycle 1: set 'A' contains itself set 'A' ... which contains set 'B' ... which contains set 'A' ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` System Type Set ```text thread 'main' panicked at 'Tried to order against `SystemTypeSet(fn foo())` in a schedule that has more than one `SystemTypeSet(fn foo())` instance. `SystemTypeSet(fn foo())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Hierarchy Redundancy ```text thread 'main' panicked at 'System set hierarchy contains redundant edges. hierarchy contains redundant edge(s) -- system set 'X' cannot be child of set 'A', longer path exists ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Systems have ordering but interset ```text thread 'main' panicked at '`A` and `C` have a `before`-`after` relationship (which may be transitive) but share systems.', crates\bevy_ecs\src\schedule\schedule.rs:227:51 ``` Cross Dependency ```text thread 'main' panicked at '`A` and `B` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ``` Ambiguity ```text thread 'main' panicked at 'Systems with conflicting access have indeterminate run order. 1 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- res_mut and res_ref conflict on: ["bevymark::ambiguity::X"] ', crates\bevy_ecs\src\schedule\schedule.rs:230:13 ```
2023-08-27 17:54:59 +00:00
#[error("Systems with conflicting access have indeterminate run order.\n{0}")]
Ambiguity(String),
/// Tried to run a schedule before all of its systems have been initialized.
#[error("Systems in schedule have not been initialized.")]
Uninitialized,
}
/// Specifies how schedule construction should respond to detecting a certain kind of issue.
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
#[derive(Debug, Clone, PartialEq)]
pub enum LogLevel {
/// Occurrences are completely ignored.
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
Ignore,
/// Occurrences are logged only.
Warn,
/// Occurrences are logged and result in errors.
Error,
}
/// Specifies miscellaneous settings for schedule construction.
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
#[derive(Clone, Debug)]
pub struct ScheduleBuildSettings {
/// Determines whether the presence of ambiguities (systems with conflicting access but indeterminate order)
/// is only logged or also results in an [`Ambiguity`](ScheduleBuildError::Ambiguity) error.
Add `report_sets` option to `ScheduleBuildSettings` (#7756) # Objective - Fixes #7442. ## Solution - Added `report_sets` option to `ScheduleBuildSettings` like described in the linked issue. The output of the `3d_scene` example when reporting ambiguities with `report_sets` and `use_shortnames` set to `true` (and with #7755 applied) now looks like this: ``` 82 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- filesystem_watcher_system (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<DynamicScene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Scene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Shader> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Mesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<SkinnedMeshInverseBindposes> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Image> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<TextureAtlas> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<ColorMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Font> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<FontAtlasSet> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<StandardMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Gltf> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfNode> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfPrimitive> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfMesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSource> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSink> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AnimationClip> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- scene_spawner_system (Update) and close_when_requested (Update) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- calculate_bounds (CalculateBounds, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and visibility_propagate_system (PostUpdate, VisibilityPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_text2d_layout (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and ui_stack_system (PostUpdate, Stack) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and text_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_image_calculated_size_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and flex_node_system (Flex, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and add_clusters (AddClusters, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- visibility_propagate_system (PostUpdate, VisibilityPropagate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_text2d_layout (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- ui_stack_system (PostUpdate, Stack) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- text_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_image_calculated_size_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and animation_player (PostUpdate) conflict on: ["bevy_transform::components::transform::Transform"] -- apply_system_buffers (AddClustersFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and check_visibility (CheckVisibility, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_frusta (PostUpdate, UpdateLightFrusta) conflict on: bevy_ecs::world::World -- Assets<Scene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Shader>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Mesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<SkinnedMeshInverseBindposes>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Image>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<TextureAtlas>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<ColorMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Font>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<FontAtlasSet>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<StandardMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Gltf>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfNode>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfPrimitive>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfMesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSource>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSink>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AnimationClip>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<DynamicScene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World ``` Co-authored-by: Edgar Geier <geieredgar@gmail.com>
2023-02-20 15:31:10 +00:00
///
/// Defaults to [`LogLevel::Ignore`].
pub ambiguity_detection: LogLevel,
/// Determines whether the presence of redundant edges in the hierarchy of system sets is only
/// logged or also results in a [`HierarchyRedundancy`](ScheduleBuildError::HierarchyRedundancy)
/// error.
Add `report_sets` option to `ScheduleBuildSettings` (#7756) # Objective - Fixes #7442. ## Solution - Added `report_sets` option to `ScheduleBuildSettings` like described in the linked issue. The output of the `3d_scene` example when reporting ambiguities with `report_sets` and `use_shortnames` set to `true` (and with #7755 applied) now looks like this: ``` 82 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- filesystem_watcher_system (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<DynamicScene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Scene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Shader> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Mesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<SkinnedMeshInverseBindposes> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Image> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<TextureAtlas> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<ColorMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Font> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<FontAtlasSet> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<StandardMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Gltf> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfNode> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfPrimitive> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfMesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSource> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSink> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AnimationClip> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- scene_spawner_system (Update) and close_when_requested (Update) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- calculate_bounds (CalculateBounds, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and visibility_propagate_system (PostUpdate, VisibilityPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_text2d_layout (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and ui_stack_system (PostUpdate, Stack) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and text_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_image_calculated_size_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and flex_node_system (Flex, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and add_clusters (AddClusters, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- visibility_propagate_system (PostUpdate, VisibilityPropagate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_text2d_layout (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- ui_stack_system (PostUpdate, Stack) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- text_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_image_calculated_size_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and animation_player (PostUpdate) conflict on: ["bevy_transform::components::transform::Transform"] -- apply_system_buffers (AddClustersFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and check_visibility (CheckVisibility, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_frusta (PostUpdate, UpdateLightFrusta) conflict on: bevy_ecs::world::World -- Assets<Scene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Shader>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Mesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<SkinnedMeshInverseBindposes>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Image>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<TextureAtlas>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<ColorMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Font>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<FontAtlasSet>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<StandardMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Gltf>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfNode>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfPrimitive>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfMesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSource>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSink>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AnimationClip>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<DynamicScene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World ``` Co-authored-by: Edgar Geier <geieredgar@gmail.com>
2023-02-20 15:31:10 +00:00
///
/// Defaults to [`LogLevel::Warn`].
pub hierarchy_detection: LogLevel,
/// If set to true, node names will be shortened instead of the fully qualified type path.
Add `report_sets` option to `ScheduleBuildSettings` (#7756) # Objective - Fixes #7442. ## Solution - Added `report_sets` option to `ScheduleBuildSettings` like described in the linked issue. The output of the `3d_scene` example when reporting ambiguities with `report_sets` and `use_shortnames` set to `true` (and with #7755 applied) now looks like this: ``` 82 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- filesystem_watcher_system (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<DynamicScene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Scene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Shader> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Mesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<SkinnedMeshInverseBindposes> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Image> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<TextureAtlas> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<ColorMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Font> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<FontAtlasSet> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<StandardMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Gltf> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfNode> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfPrimitive> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfMesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSource> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSink> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AnimationClip> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- scene_spawner_system (Update) and close_when_requested (Update) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- calculate_bounds (CalculateBounds, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and visibility_propagate_system (PostUpdate, VisibilityPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_text2d_layout (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and ui_stack_system (PostUpdate, Stack) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and text_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_image_calculated_size_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and flex_node_system (Flex, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and add_clusters (AddClusters, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- visibility_propagate_system (PostUpdate, VisibilityPropagate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_text2d_layout (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- ui_stack_system (PostUpdate, Stack) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- text_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_image_calculated_size_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and animation_player (PostUpdate) conflict on: ["bevy_transform::components::transform::Transform"] -- apply_system_buffers (AddClustersFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and check_visibility (CheckVisibility, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_frusta (PostUpdate, UpdateLightFrusta) conflict on: bevy_ecs::world::World -- Assets<Scene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Shader>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Mesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<SkinnedMeshInverseBindposes>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Image>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<TextureAtlas>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<ColorMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Font>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<FontAtlasSet>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<StandardMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Gltf>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfNode>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfPrimitive>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfMesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSource>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSink>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AnimationClip>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<DynamicScene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World ``` Co-authored-by: Edgar Geier <geieredgar@gmail.com>
2023-02-20 15:31:10 +00:00
///
/// Defaults to `true`.
pub use_shortnames: bool,
Add `report_sets` option to `ScheduleBuildSettings` (#7756) # Objective - Fixes #7442. ## Solution - Added `report_sets` option to `ScheduleBuildSettings` like described in the linked issue. The output of the `3d_scene` example when reporting ambiguities with `report_sets` and `use_shortnames` set to `true` (and with #7755 applied) now looks like this: ``` 82 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- filesystem_watcher_system (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<DynamicScene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Scene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Shader> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Mesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<SkinnedMeshInverseBindposes> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Image> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<TextureAtlas> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<ColorMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Font> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<FontAtlasSet> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<StandardMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Gltf> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfNode> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfPrimitive> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfMesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSource> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSink> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AnimationClip> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- scene_spawner_system (Update) and close_when_requested (Update) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- calculate_bounds (CalculateBounds, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and visibility_propagate_system (PostUpdate, VisibilityPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_text2d_layout (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and ui_stack_system (PostUpdate, Stack) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and text_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_image_calculated_size_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and flex_node_system (Flex, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and add_clusters (AddClusters, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- visibility_propagate_system (PostUpdate, VisibilityPropagate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_text2d_layout (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- ui_stack_system (PostUpdate, Stack) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- text_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_image_calculated_size_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and animation_player (PostUpdate) conflict on: ["bevy_transform::components::transform::Transform"] -- apply_system_buffers (AddClustersFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and check_visibility (CheckVisibility, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_frusta (PostUpdate, UpdateLightFrusta) conflict on: bevy_ecs::world::World -- Assets<Scene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Shader>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Mesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<SkinnedMeshInverseBindposes>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Image>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<TextureAtlas>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<ColorMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Font>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<FontAtlasSet>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<StandardMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Gltf>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfNode>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfPrimitive>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfMesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSource>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSink>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AnimationClip>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<DynamicScene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World ``` Co-authored-by: Edgar Geier <geieredgar@gmail.com>
2023-02-20 15:31:10 +00:00
/// If set to true, report all system sets the conflicting systems are part of.
///
/// Defaults to `true`.
pub report_sets: bool,
}
impl Default for ScheduleBuildSettings {
fn default() -> Self {
Self::new()
}
}
impl ScheduleBuildSettings {
/// Default build settings.
/// See the field-level documentation for the default value of each field.
pub const fn new() -> Self {
Self {
Migrate engine to Schedule v3 (#7267) Huge thanks to @maniwani, @devil-ira, @hymm, @cart, @superdump and @jakobhellermann for the help with this PR. # Objective - Followup #6587. - Minimal integration for the Stageless Scheduling RFC: https://github.com/bevyengine/rfcs/pull/45 ## Solution - [x] Remove old scheduling module - [x] Migrate new methods to no longer use extension methods - [x] Fix compiler errors - [x] Fix benchmarks - [x] Fix examples - [x] Fix docs - [x] Fix tests ## Changelog ### Added - a large number of methods on `App` to work with schedules ergonomically - the `CoreSchedule` enum - `App::add_extract_system` via the `RenderingAppExtension` trait extension method - the private `prepare_view_uniforms` system now has a public system set for scheduling purposes, called `ViewSet::PrepareUniforms` ### Removed - stages, and all code that mentions stages - states have been dramatically simplified, and no longer use a stack - `RunCriteriaLabel` - `AsSystemLabel` trait - `on_hierarchy_reports_enabled` run criteria (now just uses an ad hoc resource checking run condition) - systems in `RenderSet/Stage::Extract` no longer warn when they do not read data from the main world - `RunCriteriaLabel` - `transform_propagate_system_set`: this was a nonstandard pattern that didn't actually provide enough control. The systems are already `pub`: the docs have been updated to ensure that the third-party usage is clear. ### Changed - `System::default_labels` is now `System::default_system_sets`. - `App::add_default_labels` is now `App::add_default_sets` - `CoreStage` and `StartupStage` enums are now `CoreSet` and `StartupSet` - `App::add_system_set` was renamed to `App::add_systems` - The `StartupSchedule` label is now defined as part of the `CoreSchedules` enum - `.label(SystemLabel)` is now referred to as `.in_set(SystemSet)` - `SystemLabel` trait was replaced by `SystemSet` - `SystemTypeIdLabel<T>` was replaced by `SystemSetType<T>` - The `ReportHierarchyIssue` resource now has a public constructor (`new`), and implements `PartialEq` - Fixed time steps now use a schedule (`CoreSchedule::FixedTimeStep`) rather than a run criteria. - Adding rendering extraction systems now panics rather than silently failing if no subapp with the `RenderApp` label is found. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. - `SceneSpawnerSystem` now runs under `CoreSet::Update`, rather than `CoreStage::PreUpdate.at_end()`. - `bevy_pbr::add_clusters` is no longer an exclusive system - the top level `bevy_ecs::schedule` module was replaced with `bevy_ecs::scheduling` - `tick_global_task_pools_on_main_thread` is no longer run as an exclusive system. Instead, it has been replaced by `tick_global_task_pools`, which uses a `NonSend` resource to force running on the main thread. ## Migration Guide - Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` - Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. - The `CoreStage`, `StartupStage, `RenderStage` and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. - Systems are no longer added to `CoreSet::Update` by default. Add systems manually if this behavior is needed, although you should consider adding your game logic systems to `CoreSchedule::FixedTimestep` instead for more reliable framerate-independent behavior. - Similarly, startup systems are no longer part of `StartupSet::Startup` by default. In most cases, this won't matter to you. - For example, `add_system_to_stage(CoreStage::PostUpdate, my_system)` should be replaced with - `add_system(my_system.in_set(CoreSet::PostUpdate)` - When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages - Run criteria have been renamed to run conditions. These can now be combined with each other and with states. - Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. - For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. - Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. - Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. - Adding extract systems is now typically done directly on the main app. Make sure the `RenderingAppExtension` trait is in scope, then call `app.add_extract_system(my_system)`. - the `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. - the `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity - `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. - Instead of creating `SystemSet` containers for systems that run in stages, simply use `.on_enter::<State::Variant>()` or its `on_exit` or `on_update` siblings. - `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. - `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a bool. - States have been dramatically simplified: there is no longer a "state stack". To queue a transition to the next state, call `NextState::set` ## TODO - [x] remove dead methods on App and World - [x] add `App::add_system_to_schedule` and `App::add_systems_to_schedule` - [x] avoid adding the default system set at inappropriate times - [x] remove any accidental cycles in the default plugins schedule - [x] migrate benchmarks - [x] expose explicit labels for the built-in command flush points - [x] migrate engine code - [x] remove all mentions of stages from the docs - [x] verify docs for States - [x] fix uses of exclusive systems that use .end / .at_start / .before_commands - [x] migrate RenderStage and AssetStage - [x] migrate examples - [x] ensure that transform propagation is exported in a sufficiently public way (the systems are already pub) - [x] ensure that on_enter schedules are run at least once before the main app - [x] re-enable opt-in to execution order ambiguities - [x] revert change to `update_bounds` to ensure it runs in `PostUpdate` - [x] test all examples - [x] unbreak directional lights - [x] unbreak shadows (see 3d_scene, 3d_shape, lighting, transparaency_3d examples) - [x] game menu example shows loading screen and menu simultaneously - [x] display settings menu is a blank screen - [x] `without_winit` example panics - [x] ensure all tests pass - [x] SubApp doc test fails - [x] runs_spawn_local tasks fails - [x] [Fix panic_when_hierachy_cycle test hanging](https://github.com/alice-i-cecile/bevy/pull/120) ## Points of Difficulty and Controversy **Reviewers, please give feedback on these and look closely** 1. Default sets, from the RFC, have been removed. These added a tremendous amount of implicit complexity and result in hard to debug scheduling errors. They're going to be tackled in the form of "base sets" by @cart in a followup. 2. The outer schedule controls which schedule is run when `App::update` is called. 3. I implemented `Label for `Box<dyn Label>` for our label types. This enables us to store schedule labels in concrete form, and then later run them. I ran into the same set of problems when working with one-shot systems. We've previously investigated this pattern in depth, and it does not appear to lead to extra indirection with nested boxes. 4. `SubApp::update` simply runs the default schedule once. This sucks, but this whole API is incomplete and this was the minimal changeset. 5. `time_system` and `tick_global_task_pools_on_main_thread` no longer use exclusive systems to attempt to force scheduling order 6. Implemetnation strategy for fixed timesteps 7. `AssetStage` was migrated to `AssetSet` without reintroducing command flush points. These did not appear to be used, and it's nice to remove these bottlenecks. 8. Migration of `bevy_render/lib.rs` and pipelined rendering. The logic here is unusually tricky, as we have complex scheduling requirements. ## Future Work (ideally before 0.10) - Rename schedule_v3 module to schedule or scheduling - Add a derive macro to states, and likely a `EnumIter` trait of some form - Figure out what exactly to do with the "systems added should basically work by default" problem - Improve ergonomics for working with fixed timesteps and states - Polish FixedTime API to match Time - Rebase and merge #7415 - Resolve all internal ambiguities (blocked on better tools, especially #7442) - Add "base sets" to replace the removed default sets.
2023-02-06 02:04:50 +00:00
ambiguity_detection: LogLevel::Ignore,
hierarchy_detection: LogLevel::Warn,
Add `report_sets` option to `ScheduleBuildSettings` (#7756) # Objective - Fixes #7442. ## Solution - Added `report_sets` option to `ScheduleBuildSettings` like described in the linked issue. The output of the `3d_scene` example when reporting ambiguities with `report_sets` and `use_shortnames` set to `true` (and with #7755 applied) now looks like this: ``` 82 pairs of systems with conflicting data access have indeterminate execution order. Consider adding `before`, `after`, or `ambiguous_with` relationships between these: -- filesystem_watcher_system (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<DynamicScene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Scene> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Shader> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Mesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<SkinnedMeshInverseBindposes> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Image> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<TextureAtlas> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<ColorMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Font> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<FontAtlasSet> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<StandardMaterial> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<Gltf> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfNode> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfPrimitive> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<GltfMesh> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSource> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AudioSink> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- update_asset_storage_system<AnimationClip> (LoadAssets) and apply_system_buffers (FirstFlush) conflict on: bevy_ecs::world::World -- scene_spawner_system (Update) and close_when_requested (Update) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- exit_on_all_closed (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<Projection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<OrthographicProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (CalculateBoundsFlush, PostUpdate) conflict on: bevy_ecs::world::World -- camera_system<PerspectiveProjection> (CameraUpdateSystem, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- calculate_bounds (CalculateBounds, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and visibility_propagate_system (PostUpdate, VisibilityPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_text2d_layout (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and ui_stack_system (PostUpdate, Stack) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and text_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_image_calculated_size_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and flex_node_system (Flex, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and add_clusters (AddClusters, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (CalculateBoundsFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- visibility_propagate_system (PostUpdate, VisibilityPropagate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_text2d_layout (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- ui_stack_system (PostUpdate, Stack) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- text_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- update_image_calculated_size_system (PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and apply_system_buffers (AddClustersFlush, PostUpdate) conflict on: bevy_ecs::world::World -- flex_node_system (Flex, PostUpdate) and animation_player (PostUpdate) conflict on: ["bevy_transform::components::transform::Transform"] -- apply_system_buffers (AddClustersFlush, PostUpdate) and play_queued_audio_system<AudioSource> (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and animation_player (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and propagate_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and sync_simple_transforms (PostUpdate, TransformPropagate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_cascades (PostUpdate, UpdateDirectionalLightCascades) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_clipping_system (PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<Projection> (PostUpdate, UpdateProjectionFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<PerspectiveProjection> (PostUpdate, UpdatePerspectiveFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_frusta<OrthographicProjection> (PostUpdate, UpdateOrthographicFrusta) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and check_visibility (CheckVisibility, PostUpdate) conflict on: bevy_ecs::world::World -- apply_system_buffers (AddClustersFlush, PostUpdate) and update_directional_light_frusta (PostUpdate, UpdateLightFrusta) conflict on: bevy_ecs::world::World -- Assets<Scene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Shader>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Mesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<SkinnedMeshInverseBindposes>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Image>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<TextureAtlas>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<ColorMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Font>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<FontAtlasSet>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<StandardMaterial>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<Gltf>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfNode>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfPrimitive>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<GltfMesh>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSource>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AudioSink>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<AnimationClip>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World -- Assets<DynamicScene>::asset_event_system (AssetEvents) and apply_system_buffers (PostUpdateFlush) conflict on: bevy_ecs::world::World ``` Co-authored-by: Edgar Geier <geieredgar@gmail.com>
2023-02-20 15:31:10 +00:00
use_shortnames: true,
report_sets: true,
}
}
}
#[cfg(test)]
mod tests {
use crate::{
self as bevy_ecs,
schedule::{IntoSystemConfigs, IntoSystemSetConfig, Schedule, SystemSet},
world::World,
};
// regression test for https://github.com/bevyengine/bevy/issues/9114
#[test]
fn ambiguous_with_not_breaking_run_conditions() {
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
struct Set;
let mut world = World::new();
let mut schedule = Schedule::default();
schedule.configure_set(Set.run_if(|| false));
schedule.add_systems(
(|| panic!("This system must not run"))
.ambiguous_with(|| ())
.in_set(Set),
);
schedule.run(&mut world);
}
}