Commit graph

812 commits

Author SHA1 Message Date
Andrew Jakubowicz
978f7cd8bf Remove unused test resource in a bevy_ecs schedule unit test (#7551)
Small commit to remove an unused resource scoped within a single bevy_ecs unit test. Also rearranged the initialization to follow initialization conventions of surrounding tests. World/Schedule initialization followed by resource initialization.

This change was tested locally with `cargo test`, and `cargo fmt` was run.

Risk should be tiny as change is scoped to a single unit test and very tiny, and I can't see any way that this resource is being used in the test.

Thank you so much!
2023-02-07 22:59:19 +00:00
JoJoJet
5efc226290 Allow piping run conditions (#7547)
# Objective

Run conditions are a special type of system that do not modify the world, and which return a bool. Due to the way they are currently implemented, you can *only* use bare function systems as a run condition. Among other things, this prevents the use of system piping with run conditions. This make very basic constructs impossible, such as `my_system.run_if(my_condition.pipe(not))`.

Unblocks a basic solution for #7202.

## Solution

Add the trait `ReadOnlySystem`, which is implemented for any system whose parameters all implement `ReadOnlySystemParam`. Allow any `-> bool` system implementing this trait to be used as a run condition.

---

## Changelog

+ Added the trait `ReadOnlySystem`, which is implemented for any `System` type whose parameters all implement `ReadOnlySystemParam`.
+ Added the function `bevy::ecs::system::assert_is_read_only_system`.
2023-02-07 22:22:16 +00:00
Niklas Eicker
943499fcdf Remove last mentions of Stages (#7553)
# Objective

- Remove mentions of Stages, since they are gone now

## Solution

- Remove mentions of Stages
2023-02-07 18:07:57 +00:00
JoJoJet
5d2cd08165 Simplify a doc example for EventWriter (#7549)
# Objective

Use the `World::send_event` method added in #5355 to simplify a doc example for `EventWriter`.
2023-02-07 16:45:26 +00:00
SpecificProtagonist
6314f50e7b States derive macro (#7535)
# Objective
Implementing `States` manually is repetitive, so let's not.

One thing I'm unsure of is whether the macro import statement is in the right place.
2023-02-07 14:02:21 +00:00
JoJoJet
d26b63a04d Add a SystemParam primitive for deferred mutations; allow #[derive]ing more types of SystemParam (#6817)
# Objective

One pattern to increase parallelism is deferred mutation: instead of directly mutating the world (and preventing other systems from running at the same time), you queue up operations to be applied to the world at the end of the stage. The most common example of this pattern uses the `Commands` SystemParam.

In order to avoid the overhead associated with commands, some power users may want to add their own deferred mutation behavior. To do this, you must implement the unsafe trait `SystemParam`, which interfaces with engine internals in a way that we'd like users to be able to avoid.

## Solution

Add the `Deferred<T>` primitive `SystemParam`, which encapsulates the deferred mutation pattern.
This can be combined with other types of `SystemParam` to safely and ergonomically create powerful custom types.

Essentially, this is just a variant of `Local<T>` which can run code at the end of the stage.

This type is used in the engine to derive `Commands` and `ParallelCommands`, which removes a bunch of unsafe boilerplate.

### Example

```rust
use bevy_ecs::system::{Deferred, SystemBuffer};

/// Sends events with a delay, but may run in parallel with other event writers.
#[derive(SystemParam)]
pub struct BufferedEventWriter<'s, E: Event> {
    queue: Deferred<'s, EventQueue<E>>,
}

struct EventQueue<E>(Vec<E>);

impl<'s, E: Event> BufferedEventWriter<'s, E> {
    /// Queues up an event to be sent at the end of this stage.
    pub fn send(&mut self, event: E) {
        self.queue.0.push(event);
    }
}

// The `SystemBuffer` trait controls how [`Deferred`] gets applied at the end of the stage.
impl<E: Event> SystemBuffer for EventQueue<E> {
    fn apply(&mut self, world: &mut World) {
        let mut events = world.resource_mut::<Events<E>>();
        for e in self.0.drain(..) {
            events.send(e);
        }
    }
}
```

---

## Changelog

+ Added the `SystemParam` type `Deferred<T>`, which can be used to defer `World` mutations. Powered by the new trait `SystemBuffer`.
2023-02-06 21:57:57 +00:00
Mike
d95df29fc0 early return from multithreaded executor (#7521)
# Objective

- There is a small perf cost for starting the multithreaded executor.

## Solution

- We can skip that cost when there are zero systems in the schedule. Overall not a big perf boost unless there are a lot of empty schedules that are trying to run, but it is something.

Below is a tracy trace of the run_fixed_update_schedule for many_foxes which has zero systems in it. Yellow is main and red is this pr. The time difference between the peaks of the humps is around 15us.

![image](https://user-images.githubusercontent.com/2180432/216884536-f3af8f5e-6224-4d0f-8fbd-67b0beb90baf.png)
2023-02-06 20:50:08 +00:00
Boxy
5c680a38a7 Move all logic to UnsafeWorldCell (#7381)
# Objective

- Implementing logic used by system params and `UnsafeWorldCell` on `&World` is sus since `&World` generally denotes shared read only access to world but this is a lie in the above situations. Move most/all logic that uses `&World` to mean `UnsafeWorldCell` onto `UnsafeWorldCell`
-  Add a way to take a `&mut World` out of `UnsafeWorldCell` and use this in `WorldCell`'s `Drop` impl instead of a `UnsafeCell` field

---

## Changelog

- changed some `UnsafeWorldCell` methods to take `self` instead of `&self`/`&mut self` since there is literally no point to them doing that
- `UnsafeWorldCell::world` is now used to get immutable access to the whole world instead of just the metadata which can now be done via `UnsafeWorldCell::world_metadata`
- `UnsafeWorldCell::world_mut` now exists and can be used to get a `&mut World` out of `UnsafeWorldCell`
- removed `UnsafeWorldCell::storages` since that is probably unsound since storages contains the actual component/resource data not just metadata

## Migration guide

N/A none of the breaking changes here make any difference for a 0.9->0.10 transition since `UnsafeWorldCell` did not exist in 0.9
2023-02-06 19:02:52 +00:00
张林伟
aa4170d9a4 Rename schedule v3 to schedule (#7519)
# Objective

- Follow up of https://github.com/bevyengine/bevy/pull/7267

## Solution

- Rename schedule_v3 to schedule
- Suppress "module inception" lint
2023-02-06 18:44:40 +00:00
Carter Anderson
dcc03724a5 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
Alice Cecile
206c7ce219 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
Mike
e1b0bbf5ed Stageless: add a method to scope to always run a task on the scope thread (#7415)
# Objective

- Currently exclusive systems and applying buffers run outside of the multithreaded executor and just calls the funtions on the thread the schedule is running on. Stageless changes this to run these using tasks in a scope. Specifically It uses `spawn_on_scope` to run these. For the render thread this is incorrect as calling `spawn_on_scope` there runs tasks on the main thread. It should instead run these on the render thread and only run nonsend systems on the main thread.
 
## Solution

- Add another executor to `Scope` for spawning tasks on the scope. `spawn_on_scope` now always runs the task on the thread the scope is running on. `spawn_on_external` spawns onto the external executor than is optionally passed in. If None is passed `spawn_on_external` will spawn onto the scope executor.
- Eventually this new machinery will be able to be removed. This will happen once a fix for removing NonSend resources from the world lands. So this is a temporary fix to support stageless.

---

## Changelog

- add a spawn_on_external method to allow spawning on the scope's thread or an external thread

## Migration Guide

> No migration guide. The main thread executor was introduced in pipelined rendering which was merged for 0.10. spawn_on_scope now behaves the same way as on 0.9.
2023-02-05 21:44:46 +00:00
CatThingy
b30ba78e16 Add a wrapper around Entity for RemovedComponents (#7503)
# Objective

- Make the internals of `RemovedComponents` clearer


## Solution

- Add a wrapper around `Entity`, used in `RemovedComponents` as `Events<RemovedComponentsEntity>`

---

## Changelog

- `RemovedComponents` now internally uses an `Events<RemovedComponentsEntity>` instead of an `Events<Entity>`
2023-02-05 15:37:07 +00:00
ira
32023a5f6a Remove broken DoubleEndedIterator impls on event iterators (#7469)
The `DoubleEndedIterator` impls produce incorrect results on subsequent calls to `iter()` if the iterator is only partially consumed.

The following code shows what happens
```rust

fn next_back_is_bad() {
    let mut events = Events::<TestEvent>::default();
    events.send(TestEvent { i: 0 });
    events.send(TestEvent { i: 1 });
    events.send(TestEvent { i: 2 });
    let mut reader = events.get_reader();
    let mut iter = reader.iter(&events);
    assert_eq!(iter.next_back(), Some(&TestEvent { i: 2 }));
    assert_eq!(iter.next(), Some(&TestEvent { i: 0 }));
    
    let mut iter = reader.iter(&events);
    // `i: 2` event is returned twice! The `i: 1` event is missed. 
    assert_eq!(iter.next(), Some(&TestEvent { i: 2 }));
    assert_eq!(iter.next(), None);
}
```

I don't think this can be fixed without adding some very convoluted bookkeeping.

## Migration Guide
`ManualEventIterator` and `ManualEventIteratorWithId` are no longer `DoubleEndedIterator`s.



Co-authored-by: devil-ira <justthecooldude@gmail.com>
2023-02-05 15:18:19 +00:00
Aceeri
67826b21d4 Replace RemovedComponents<T> backing with Events<Entity> (#5680)
# Objective
Removal events are unwieldy and require some knowledge of when to put systems that need to catch events for them, it is very easy to end up missing one and end up with memory leak-ish issues where you don't clean up after yourself.

## Solution
Consolidate removals with the benefits of `Events<...>` (such as double buffering and per system ticks for reading the events) and reduce the special casing of it, ideally I was hoping to move the removals to a `Resource` in the world, but that seems a bit more rough to implement/maintain because of double mutable borrowing issues.

This doesn't go the full length of change detection esque removal detection a la https://github.com/bevyengine/rfcs/pull/44.
Just tries to make the current workflow a bit more user friendly so detecting removals isn't such a scheduling nightmare.

---

## Changelog
- RemovedComponents<T> is now backed by an `Events<Entity>` for the benefits of double buffering.

## Migration Guide
- Add a `mut` for `removed: RemovedComponents<T>` since we are now modifying an event reader internally.
- Iterating over removed components now requires `&mut removed_components` or `removed_components.iter()` instead of `&removed_components`.
2023-02-04 20:53:37 +00:00
JoJoJet
e0bf4311d3 Remove ExclusiveSystemParam::apply (#7489)
# Objective

The trait method `SystemParam::apply` allows a `SystemParam` type to defer world mutations, which is internally used to apply `Commands` at the end of the stage. Any operations that require `&mut World` access must be deferred in this way, since parallel systems do not have exclusive access to the world.

The `ExclusiveSystemParam` trait (added in #6083) has an `apply` method which serves the same purpose. However, deferring mutations in this way does not make sense for exclusive systems since they already have `&mut World` access: there is no need to wait until a hard sync point, as the system *is* a hard sync point. World mutations can and should be performed within the body of the system.

## Solution

Remove the method. There were no implementations of this method in the engine.

---

## Changelog

*Note for maintainers: this changelog makes more sense if it's placed above the one for #6919.*

- Removed the method `ExclusiveSystemParamState::apply`.

## Migration Guide

*Note for maintainers: this migration guide makes more sense if it's placed above the one for #6919.*

The trait method `ExclusiveSystemParamState::apply` has been removed. If you have an exclusive system with buffers that must be applied, you should apply them within the body of the exclusive system.
2023-02-04 00:25:09 +00:00
Björn Tegelund
6506ea4d83 Add unit test with system that panics (#7491)
# Objective

Fixes #7434.

This is my first time contributing to a Rust project, so please let me know if this wasn't the change intended by the linked issue.

## Solution

Adds a test with a system that panics to `bevy_ecs`.

I'm not sure if this is the intended panic message, but this is what the test currently results in:
```
thread 'system::tests::panic_inside_system' panicked at 'called `Option::unwrap()` on a `None` value', /Users/bjorn/workplace/bevy/crates/bevy_tasks/src/task_pool.rs:354:49
```
2023-02-03 21:05:47 +00:00
JoJoJet
44a572e4e6 Fix ignored lifetimes in #[derive(SystemParam)] (#7458)
# Objective

Fix #7447.

The `SystemParam` derive uses the wrong lifetimes for ignored fields.

## Solution

Use type inference instead of explicitly naming the types of ignored fields. This allows the compiler to automatically use the correct lifetime.
2023-02-03 09:17:48 +00:00
Mike
ff7d5ff444 Stageless: close the finish channel so executor doesn't deadlock (#7448)
# Objective

- Fix panic_when_hierachy_cycle test hanging
- The problem is that the scope only awaits one task at a time in get_results. In stageless this task is the multithreaded executor. That tasks hangs when a system panics and cannot make anymore progress. This wasn't a problem before because the executor was spawned after all the system tasks had been spawned. But in stageless the executor is spawned before all the system tasks are spawned.

## Solution

- We can catch unwind on each system and close the finish channel if one panics. This then causes the receiver end of the finish channel to panic too.
- this might have a small perf impact, but when running many_foxes it seems to be within the noise. So less than 40us.

## Other possible solutions

- It might be possible to fairly poll all the tasks in get_results in the scope. If we could do that then the scope could panic whenever one of tasks panics. It would require a data structure that we could both poll the futures through a shared ref and also push to it. I tried FuturesUnordered, but it requires an exclusive ref to poll it.
- The catch unwind could be moved onto when we create the tasks for scope instead. We would then need something like a oneshot async channel to inform get_results if a task panics.
2023-02-03 07:16:02 +00:00
Jakub Łabor
e1d741aa19 bevy_ecs: ReflectComponentFns without World (#7206)
# Objective

Ability to use `ReflectComponent` methods in dynamic type contexts with no access to `&World`.

This problem occurred to me when wanting to apply reflected types to an entity where the `&World` reference was already consumed by query iterator leaving only `EntityMut`.

## Solution

- Remove redundant `EntityMut` or `EntityRef` lookup from `World` and `Entity` in favor of taking `EntityMut` directly in `ReflectComponentFns`.
- Added `RefectComponent::contains` to determine without panic whether `apply` can be used.

## Changelog

- Changed function signatures of `ReflectComponent` methods, `apply`, `remove`, `contains`, and `reflect`.

## Migration Guide

- Call `World::entity` before calling into the changed `ReflectComponent` methods, most likely user already has a `EntityRef` or `EntityMut` which was being queried redundantly.
2023-02-03 05:53:58 +00:00
Mike
4f3ed196fa Stageless: move MainThreadExecutor to schedule_v3 (#7444)
# Objective

- Trying to move some of the fixes from https://github.com/bevyengine/bevy/pull/7267 to make that one easier to review
- The MainThreadExecutor is how the render world runs nonsend systems on the main thread for pipelined rendering.
- The multithread executor for stageless wasn't using the MainThreadExecutor.
- MainThreadExecutor was declared in the old executor_parallel module that is getting deleted.
- The way the MainThreadExecutor was getting passed to the scope was actually unsound as the resource could be dropped from the World while the schedule was running

## Solution

- Move MainThreadExecutor to the new multithreaded_executor's file.
- Make the multithreaded executor use the MainThreadExecutor
- Clone the MainThreadExecutor onto the stack and pass that ref in

## Changelog

- Move MainThreadExecutor for stageless migration.
2023-02-03 03:19:41 +00:00
Mike
27e20df6de Stageless: move final apply outside of spawned executor (#7445)
# Objective

- After the multithreaded executor finishes running all the systems, we apply the buffers for any system that hasn't applied it's buffers. This is a courtesy apply for users who forget to order their systems before a apply_system_buffers. When checking stageless, it was found that this apply_system_buffers was running on the executor thread instead of the world's thread. This is a problem because anything with world access should be able to access nonsend resources.

## Solution

- Move the final apply_system_buffers outside of the executor and outside of the scope, so it runs on the same thread that schedule.run is called on.
2023-02-03 02:35:20 +00:00
Mike
3ff68b6ddb Stageless: fix unapplied systems (#7446)
# Objective

- The stageless executor keeps track of systems that have run, but have not applied their system buffers. The bitset for that was being cloned into apply_system_buffers and cleared in that function, but we need to clear the original version instead of the cloned version

## Solution

- move the clear out of the apply_system_buffers function.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2023-02-03 01:20:11 +00:00
ira
9481a2c8a7 Optimise EventReader::clear() and improve documentation (#7471)
# Objective

Clearing the reader doesn't require iterating the events. Updating the `last_event_count` of the reader is enough.

I rewrote part of the documentation as some of it was incorrect or harder to understand than necessary.

## Changelog

Added `ManualEventReader::clear()`

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2023-02-03 01:03:56 +00:00
JoJoJet
209f6f8e83 Fix unsoundness in EntityMut::world_scope (#7387)
# Objective

Found while working on #7385.

The struct `EntityMut` has the safety invariant that it's cached `EntityLocation` must always accurately specify where the entity is stored. Thus, any time its location might be invalidated (such as by calling `EntityMut::world_mut` and moving archetypes), the cached location *must* be updated by calling `EntityMut::update_location`.

The method `world_scope` encapsulates this pattern in safe API by requiring world mutations to be done in a closure, after which `update_location` will automatically be called. However, this method has a soundness hole: if a panic occurs within the closure, then `update_location` will never get called. If the panic is caught in an outer scope, then the `EntityMut` will be left with an outdated location, which is undefined behavior.

An example of this can be seen in the unit test `entity_mut_world_scope_panic`, which has been added to this PR as a regression test. Without the other changes in this PR, that test will invoke undefined behavior in safe code.

## Solution

Call `EntityMut::update_location()` from within a `Drop` impl, which ensures that it will get executed even if `EntityMut::world_scope` unwinds.
2023-01-29 00:10:45 +00:00
JoJoJet
299bd37752 Add Ref to the prelude (#7392)
# Objective

Add the change-detection wrapper type `Ref<T>` (originally added in #7097) to `bevy_ecs::prelude`.
2023-01-28 09:28:47 +00:00
JoJoJet
5d912a2f35 Speed up CommandQueue by storing commands more densely (#6391)
# Objective

* Speed up inserting and applying commands. 
* Halve the stack size of `CommandQueue` to 24 bytes.
* Require fewer allocations.

## Solution

Store commands and metadata densely within the same buffer. Each command takes up 1 `usize` of metadata, plus the bytes to store the command itself. Zero-sized types take up no space except for the metadata.

# Benchmarks

All of the benchmarks related to commands.

| Bench                                  | Time      |  % Change         |    p-value |
|----------------------------------------|-----------|--------------|-----------------|
| empty_commands/0_entities              | 4.7780 ns | -18.381% | 0.00  |
| spawn_commands/2000_entities           | 233.11 us | -0.9961%     | 0.00  |
| spawn_commands/4000_entities           | 448.38 us | -3.1466%     | 0.00  |
| spawn_commands/6000_entities           | 693.12 us | -0.3978%     | _0.52_ |
| spawn_commands/8000_entities           | 889.48 us | -2.8802%     | 0.00  |
| insert_commands/insert                 | 609.95 us | -4.8604%     | 0.00  |
| insert_commands/insert_batch           | 355.54 us | -2.8165%     |  0.00 |
| fake_commands/2000_commands            | 4.8018 us | **-17.802%** | 0.00  |
| fake_commands/4000_commands            | 9.5969 us | **-17.337%** | 0.00  |
| fake_commands/6000_commands            | 14.421 us | **-18.454%** | 0.00  |
| fake_commands/8000_commands            | 19.192 us | **-18.261%** | 0.00 |
| sized_commands_0_bytes/2000_commands   | 4.0593 us | -4.7145%     |  0.00 |
| sized_commands_0_bytes/4000_commands   | 8.1541 us | -4.9470%     |  0.00  |
| sized_commands_0_bytes/6000_commands   | 12.806 us | -12.017%     | 0.00 |
| sized_commands_0_bytes/8000_commands   | 17.096 us | -14.070% |  0.00 |
| sized_commands_12_bytes/2000_commands  | 5.3425 us | **-27.632%** | 0.00 |
| sized_commands_12_bytes/4000_commands  | 10.283 us | **-31.158%** |  0.00  |
| sized_commands_12_bytes/6000_commands  | 15.339 us | **-31.418%** |  0.00 |
| sized_commands_12_bytes/8000_commands  | 20.206 us | **-33.133%** |  0.00 |
| sized_commands_512_bytes/2000_commands | 99.118 us | -9.9655%     |  0.00  |
| sized_commands_512_bytes/4000_commands | 201.96 us | -8.8235%     |  0.00 |
| sized_commands_512_bytes/6000_commands | 300.95 us | -9.2344%     |  0.00  |
| sized_commands_512_bytes/8000_commands | 404.69 us | -8.4578%     |  0.00  |
2023-01-28 01:15:51 +00:00
JoJoJet
9ffba9bb1a Allow returning a value from EntityMut::world_scope (#7385)
# Objective

The function `EntityMut::world_scope` is a safe abstraction that allows you to temporarily get mutable access to the underlying `World` of an `EntityMut`. This function is purely stateful, meaning it is not easily possible to return a value from it.

## Solution

Allow returning a computed value from the closure. This is similar to how `World::resource_scope` works.

---

## Changelog

- The function `EntityMut::world_scope` now allows returning a value from the immediately-computed closure.
2023-01-27 19:42:10 +00:00
Chris Ohk
3281aea5c2 Fix minor typos in code and docs (#7378)
# Objective

I found several words in code and docs are incorrect. This should be fixed.

## Solution

- Fix several minor typos

Co-authored-by: Chris Ohk <utilforever@gmail.com>
2023-01-27 12:12:53 +00:00
Jakob Hellermann
0cb0d8b55d add UnsafeWorldCell abstraction (#6404)
alternative to #5922, implements #5956 
builds on top of https://github.com/bevyengine/bevy/pull/6402

# Objective

https://github.com/bevyengine/bevy/issues/5956 goes into more detail, but the TLDR is:
- bevy systems ensure disjoint accesses to resources and components, and for that to work there are methods `World::get_resource_unchecked_mut(&self)`, ..., `EntityRef::get_mut_unchecked(&self)` etc.
- we don't have these unchecked methods for `by_id` variants, so third-party crate authors cannot build their own safe disjoint-access abstractions with these
- having `_unchecked_mut` methods is not great, because in their presence safe code can accidentally violate subtle invariants. Having to go through `world.as_unsafe_world_cell().unsafe_method()` forces you to stop and think about what you want to write in your `// SAFETY` comment.

The alternative is to keep exposing `_unchecked_mut` variants for every operation that we want third-party crates to build upon, but we'd prefer to avoid using these methods alltogether: https://github.com/bevyengine/bevy/pull/5922#issuecomment-1241954543

Also, this is something that **cannot be implemented outside of bevy**, so having either this PR or #5922 as an escape hatch with lots of discouraging comments would be great.

## Solution

- add `UnsafeWorldCell` with `unsafe fn get_resource(&self)`, `unsafe fn get_resource_mut(&self)`
- add `fn World::as_unsafe_world_cell(&mut self) -> UnsafeWorldCell<'_>` (and `as_unsafe_world_cell_readonly(&self)`)
- add `UnsafeWorldCellEntityRef` with `unsafe fn get`, `unsafe fn get_mut` and the other utilities on `EntityRef` (no methods for spawning, despawning, insertion)
- use the `UnsafeWorldCell` abstraction in `ReflectComponent`, `ReflectResource` and `ReflectAsset`, so these APIs are easier to reason about
- remove `World::get_resource_mut_unchecked`, `EntityRef::get_mut_unchecked` and use `unsafe { world.as_unsafe_world_cell().get_mut() }` and `unsafe { world.as_unsafe_world_cell().get_entity(entity)?.get_mut() }` instead

This PR does **not** make use of `UnsafeWorldCell` for anywhere else in `bevy_ecs` such as `SystemParam` or `Query`. That is a much larger change, and I am convinced that having `UnsafeWorldCell` is already useful for third-party crates.

Implemented API:

```rust
struct World { .. }
impl World {
  fn as_unsafe_world_cell(&self) -> UnsafeWorldCell<'_>;
}

struct UnsafeWorldCell<'w>(&'w World);
impl<'w> UnsafeWorldCell {
  unsafe fn world(&self) -> &World;

  fn get_entity(&self) -> UnsafeWorldCellEntityRef<'w>; // returns 'w which is `'self` of the `World::as_unsafe_world_cell(&'w self)`

  unsafe fn get_resource<T>(&self) -> Option<&'w T>;
  unsafe fn get_resource_by_id(&self, ComponentId) -> Option<&'w T>;
  unsafe fn get_resource_mut<T>(&self) -> Option<Mut<'w, T>>;
  unsafe fn get_resource_mut_by_id(&self) -> Option<MutUntyped<'w>>;
  unsafe fn get_non_send_resource<T>(&self) -> Option<&'w T>;
  unsafe fn get_non_send_resource_mut<T>(&self) -> Option<Mut<'w, T>>>;

  // not included: remove, remove_resource, despawn, anything that might change archetypes
}

struct UnsafeWorldCellEntityRef<'w> { .. }
impl UnsafeWorldCellEntityRef<'w> {
  unsafe fn get<T>(&self, Entity) -> Option<&'w T>;
  unsafe fn get_by_id(&self, Entity, ComponentId) -> Option<Ptr<'w>>;
  unsafe fn get_mut<T>(&self, Entity) -> Option<Mut<'w, T>>;
  unsafe fn get_mut_by_id(&self, Entity, ComponentId) -> Option<MutUntyped<'w>>;
  unsafe fn get_change_ticks<T>(&self, Entity) -> Option<Mut<'w, T>>;
  // fn id, archetype, contains, contains_id, containts_type_id
}
```

<details>
<summary>UnsafeWorldCell docs</summary>

Variant of the [`World`] where resource and component accesses takes a `&World`, and the responsibility to avoid
aliasing violations are given to the caller instead of being checked at compile-time by rust's unique XOR shared rule.

### Rationale
In rust, having a `&mut World` means that there are absolutely no other references to the safe world alive at the same time,
without exceptions. Not even unsafe code can change this.

But there are situations where careful shared mutable access through a type is possible and safe. For this, rust provides the [`UnsafeCell`](std::cell::UnsafeCell)
escape hatch, which allows you to get a `*mut T` from a `&UnsafeCell<T>` and around which safe abstractions can be built.

Access to resources and components can be done uniquely using [`World::resource_mut`] and [`World::entity_mut`], and shared using [`World::resource`] and [`World::entity`].
These methods use lifetimes to check at compile time that no aliasing rules are being broken.

This alone is not enough to implement bevy systems where multiple systems can access *disjoint* parts of the world concurrently. For this, bevy stores all values of
resources and components (and [`ComponentTicks`](crate::component::ComponentTicks)) in [`UnsafeCell`](std::cell::UnsafeCell)s, and carefully validates disjoint access patterns using
APIs like [`System::component_access`](crate::system::System::component_access).

A system then can be executed using [`System::run_unsafe`](crate::system::System::run_unsafe) with a `&World` and use methods with interior mutability to access resource values.
access resource values.

### Example Usage

[`UnsafeWorldCell`] can be used as a building block for writing APIs that safely allow disjoint access into the world.
In the following example, the world is split into a resource access half and a component access half, where each one can
safely hand out mutable references.

```rust
use bevy_ecs::world::World;
use bevy_ecs::change_detection::Mut;
use bevy_ecs::system::Resource;
use bevy_ecs::world::unsafe_world_cell_world::UnsafeWorldCell;

// INVARIANT: existance of this struct means that users of it are the only ones being able to access resources in the world
struct OnlyResourceAccessWorld<'w>(UnsafeWorldCell<'w>);
// INVARIANT: existance of this struct means that users of it are the only ones being able to access components in the world
struct OnlyComponentAccessWorld<'w>(UnsafeWorldCell<'w>);

impl<'w> OnlyResourceAccessWorld<'w> {
    fn get_resource_mut<T: Resource>(&mut self) -> Option<Mut<'w, T>> {
        // SAFETY: resource access is allowed through this UnsafeWorldCell
        unsafe { self.0.get_resource_mut::<T>() }
    }
}
// impl<'w> OnlyComponentAccessWorld<'w> {
//     ...
// }

// the two interior mutable worlds borrow from the `&mut World`, so it cannot be accessed while they are live
fn split_world_access(world: &mut World) -> (OnlyResourceAccessWorld<'_>, OnlyComponentAccessWorld<'_>) {
    let resource_access = OnlyResourceAccessWorld(unsafe { world.as_unsafe_world_cell() });
    let component_access = OnlyComponentAccessWorld(unsafe { world.as_unsafe_world_cell() });
    (resource_access, component_access)
}
```


</details>
2023-01-27 00:12:13 +00:00
Jakob Hellermann
671e7a0de8 schedule_v3: fix default set for systems not being applied (#7350)
# Objective

`add_system(system)` without any `.in_set` configuration should land in `CoreSet::Update`.
We check that the sets are empty, but for systems there is always the `SystemTypeset`.

## Solution

- instead of `is_empty()`, check that the only set it the `SystemTypeSet`
2023-01-24 14:44:46 +00:00
JoJoJet
e84907fc55 Add context to compile tests (#7342)
# Objective

`bevy_ecs/system_param.rs` contains many seemingly-arbitrary struct definitions which serve as compile tests.

## Solution

Add a comment to each one, linking the issue or PR that motivated its addition.
2023-01-23 22:34:32 +00:00
Jonah Henriksson
eda3ffb0af Added resource_id and changed init_resource and init_non_send_resource to return ComponentId (#7284)
# Objective

- `Components::resource_id` doesn't exist. Like `Components::component_id` but for resources.

## Solution

- Created `Components::resource_id` and added some docs.

---

## Changelog

- Added `Components::resource_id`.
- Changed `World::init_resource` to return the generated `ComponentId`.
- Changed `World::init_non_send_resource` to return the generated `ComponentId`.
2023-01-20 19:08:04 +00:00
JoJoJet
5d5a504685 Revise SystemParam docs (#7274)
# Objective

Increase clarity in a few places for the `SystemParam` docs.
2023-01-20 13:39:23 +00:00
James Liu
dfea88c64d Basic adaptive batching for parallel query iteration (#4777)
# Objective
Fixes #3184. Fixes #6640. Fixes #4798. Using `Query::par_for_each(_mut)` currently requires a `batch_size` parameter, which affects how it chunks up large archetypes and tables into smaller chunks to run in parallel. Tuning this value is difficult, as the performance characteristics entirely depends on the state of the `World` it's being run on. Typically, users will just use a flat constant and just tune it by hand until it performs well in some benchmarks. However, this is both error prone and risks overfitting the tuning on that benchmark.

This PR proposes a naive automatic batch-size computation based on the current state of the `World`.

## Background
`Query::par_for_each(_mut)` schedules a new Task for every archetype or table that it matches. Archetypes/tables larger than the batch size are chunked into smaller tasks. Assuming every entity matched by the query has an identical workload, this makes the worst case scenario involve using a batch size equal to the size of the largest matched archetype or table. Conversely, a batch size of `max {archetype, table} size / thread count * COUNT_PER_THREAD` is likely the sweetspot where the overhead of scheduling tasks is minimized, at least not without grouping small archetypes/tables together.

There is also likely a strict minimum batch size below which the overhead of scheduling these tasks is heavier than running the entire thing single-threaded.

## Solution

- [x] Remove the `batch_size` from `Query(State)::par_for_each`  and friends.
- [x] Add a check to compute `batch_size = max {archeytpe/table} size / thread count  * COUNT_PER_THREAD`
- [x] ~~Panic if thread count is 0.~~ Defer to `for_each` if the thread count is 1 or less.
- [x] Early return if there is no matched table/archetype. 
- [x] Add override option for users have queries that strongly violate the initial assumption that all iterated entities have an equal workload.

---

## Changelog
Changed: `Query::par_for_each(_mut)` has been changed to `Query::par_iter(_mut)` and will now automatically try to produce a batch size for callers based on the current `World` state.

## Migration Guide
The `batch_size` parameter for `Query(State)::par_for_each(_mut)` has been removed. These calls will automatically compute a batch size for you. Remove these parameters from all calls to these functions.

Before:
```rust
fn parallel_system(query: Query<&MyComponent>) {
   query.par_for_each(32, |comp| {
        ...
   });
}
```

After:

```rust
fn parallel_system(query: Query<&MyComponent>) {
   query.par_iter().for_each(|comp| {
        ...
   });
}
```

Co-authored-by: Arnav Choubey <56453634+x-52@users.noreply.github.com>
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Corey Farwell <coreyf@rwell.org>
Co-authored-by: Aevyrie <aevyrie@gmail.com>
2023-01-20 08:47:20 +00:00
Mike
2027af4c54 Pipelined Rendering (#6503)
# Objective

- Implement pipelined rendering
- Fixes #5082
- Fixes #4718

## User Facing Description

Bevy now implements piplelined rendering! Pipelined rendering allows the app logic and rendering logic to run on different threads leading to large gains in performance.

![image](https://user-images.githubusercontent.com/2180432/202049871-3c00b801-58ab-448f-93fd-471e30aba55f.png)
*tracy capture of many_foxes example*

To use pipelined rendering, you just need to add the `PipelinedRenderingPlugin`. If you're using `DefaultPlugins` then it will automatically be added for you on all platforms except wasm. Bevy does not currently support multithreading on wasm which is needed for this feature to work. If you aren't using `DefaultPlugins` you can add the plugin manually.

```rust
use bevy::prelude::*;
use bevy::render::pipelined_rendering::PipelinedRenderingPlugin;

fn main() {
    App::new()
        // whatever other plugins you need
        .add_plugin(RenderPlugin)
        // needs to be added after RenderPlugin
        .add_plugin(PipelinedRenderingPlugin)
        .run();
}
```

If for some reason pipelined rendering needs to be removed. You can also disable the plugin the normal way.

```rust
use bevy::prelude::*;
use bevy::render::pipelined_rendering::PipelinedRenderingPlugin;

fn main() {
    App::new.add_plugins(DefaultPlugins.build().disable::<PipelinedRenderingPlugin>());
}
```

### A setup function was added to plugins

A optional plugin lifecycle function was added to the `Plugin trait`. This function is called after all plugins have been built, but before the app runner is called. This allows for some final setup to be done. In the case of pipelined rendering, the function removes the sub app from the main app and sends it to the render thread.

```rust
struct MyPlugin;
impl Plugin for MyPlugin {
    fn build(&self, app: &mut App) {
        
    }
    
    // optional function
    fn setup(&self, app: &mut App) {
        // do some final setup before runner is called
    }
}
```

### A Stage for Frame Pacing

In the `RenderExtractApp` there is a stage labelled `BeforeIoAfterRenderStart` that systems can be added to.  The specific use case for this stage is for a frame pacing system that can delay the start of main app processing in render bound apps to reduce input latency i.e. "frame pacing". This is not currently built into bevy, but exists as `bevy`

```text
|-------------------------------------------------------------------|
|         | BeforeIoAfterRenderStart | winit events | main schedule |
| extract |---------------------------------------------------------|
|         | extract commands | rendering schedule                   |
|-------------------------------------------------------------------|
```

### Small API additions

* `Schedule::remove_stage`
* `App::insert_sub_app`
* `App::remove_sub_app` 
* `TaskPool::scope_with_executor`

## Problems and Solutions

### Moving render app to another thread

Most of the hard bits for this were done with the render redo. This PR just sends the render app back and forth through channels which seems to work ok. I originally experimented with using a scope to run the render task. It was cuter, but that approach didn't allow render to start before i/o processing. So I switched to using channels. There is much complexity in the coordination that needs to be done, but it's worth it. By moving rendering during i/o processing the frame times should be much more consistent in render bound apps. See https://github.com/bevyengine/bevy/issues/4691.

### Unsoundness with Sending World with NonSend resources

Dropping !Send things on threads other than the thread they were spawned on is considered unsound. The render world doesn't have any nonsend resources. So if we tell the users to "pretty please don't spawn nonsend resource on the render world", we can avoid this problem.

More seriously there is this https://github.com/bevyengine/bevy/pull/6534 pr, which patches the unsoundness by aborting the app if a nonsend resource is dropped on the wrong thread. ~~That PR should probably be merged before this one.~~ For a longer term solution we have this discussion going https://github.com/bevyengine/bevy/discussions/6552.

### NonSend Systems in render world

The render world doesn't have any !Send resources, but it does have a non send system. While Window is Send, winit does have some API's that can only be accessed on the main thread. `prepare_windows` in the render schedule thus needs to be scheduled on the main thread. Currently we run nonsend systems by running them on the thread the TaskPool::scope runs on. When we move render to another thread this no longer works.

To fix this, a new `scope_with_executor` method was added that takes a optional `TheadExecutor` that can only be ticked on the thread it was initialized on. The render world then holds a `MainThreadExecutor` resource which can be passed to the scope in the parallel executor that it uses to spawn it's non send systems on. 

### Scopes executors between render and main should not share tasks

Since the render world and the app world share the `ComputeTaskPool`. Because `scope` has executors for the ComputeTaskPool a system from the main world could run on the render thread or a render system could run on the main thread. This can cause performance problems because it can delay a stage from finishing. See https://github.com/bevyengine/bevy/pull/6503#issuecomment-1309791442 for more details.

To avoid this problem, `TaskPool::scope` has been changed to not tick the ComputeTaskPool when it's used by the parallel executor. In the future when we move closer to the 1 thread to 1 logical core model we may want to overprovide threads, because the render and main app threads don't do much when executing the schedule.

## Performance

My machine is Windows 11, AMD Ryzen 5600x, RX 6600

### Examples

#### This PR with pipelining vs Main

> Note that these were run on an older version of main and the performance profile has probably changed due to optimizations

Seeing a perf gain from 29% on many lights to 7% on many sprites.

<html>
<body>
<!--StartFragment--><google-sheets-html-origin>

  | percent |   |   | Diff |   |   | Main |   |   | PR |   |  
-- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | --
tracy frame time | mean | median | sigma | mean | median | sigma | mean | median | sigma | mean | median | sigma
many foxes | 27.01% | 27.34% | -47.09% | 1.58 | 1.55 | -1.78 | 5.85 | 5.67 | 3.78 | 4.27 | 4.12 | 5.56
many lights | 29.35% | 29.94% | -10.84% | 3.02 | 3.03 | -0.57 | 10.29 | 10.12 | 5.26 | 7.27 | 7.09 | 5.83
many animated sprites | 13.97% | 15.69% | 14.20% | 3.79 | 4.17 | 1.41 | 27.12 | 26.57 | 9.93 | 23.33 | 22.4 | 8.52
3d scene | 25.79% | 26.78% | 7.46% | 0.49 | 0.49 | 0.15 | 1.9 | 1.83 | 2.01 | 1.41 | 1.34 | 1.86
many cubes | 11.97% | 11.28% | 14.51% | 1.93 | 1.78 | 1.31 | 16.13 | 15.78 | 9.03 | 14.2 | 14 | 7.72
many sprites | 7.14% | 9.42% | -85.42% | 1.72 | 2.23 | -6.15 | 24.09 | 23.68 | 7.2 | 22.37 | 21.45 | 13.35

<!--EndFragment-->
</body>
</html>

#### This PR with pipelining disabled vs Main

Mostly regressions here. I don't think this should be a problem as users that are disabling pipelined rendering are probably running single threaded and not using the parallel executor. The regression is probably mostly due to the switch to use `async_executor::run` instead of `try_tick` and also having one less thread to run systems on. I'll do a writeup on why switching to `run` causes regressions, so we can try to eventually fix it. Using try_tick causes issues when pipeline rendering is enable as seen [here](https://github.com/bevyengine/bevy/pull/6503#issuecomment-1380803518)

<html>
<body>
<!--StartFragment--><google-sheets-html-origin>

  | percent |   |   | Diff |   |   | Main |   |   | PR no pipelining |   |  
-- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | --
tracy frame time | mean | median | sigma | mean | median | sigma | mean | median | sigma | mean | median | sigma
many foxes | -3.72% | -4.42% | -1.07% | -0.21 | -0.24 | -0.04 | 5.64 | 5.43 | 3.74 | 5.85 | 5.67 | 3.78
many lights | 0.29% | -0.30% | 4.75% | 0.03 | -0.03 | 0.25 | 10.29 | 10.12 | 5.26 | 10.26 | 10.15 | 5.01
many animated sprites | 0.22% | 1.81% | -2.72% | 0.06 | 0.48 | -0.27 | 27.12 | 26.57 | 9.93 | 27.06 | 26.09 | 10.2
3d scene | -15.79% | -14.75% | -31.34% | -0.3 | -0.27 | -0.63 | 1.9 | 1.83 | 2.01 | 2.2 | 2.1 | 2.64
many cubes | -2.85% | -3.30% | 0.00% | -0.46 | -0.52 | 0 | 16.13 | 15.78 | 9.03 | 16.59 | 16.3 | 9.03
many sprites | 2.49% | 2.41% | 0.69% | 0.6 | 0.57 | 0.05 | 24.09 | 23.68 | 7.2 | 23.49 | 23.11 | 7.15

<!--EndFragment-->
</body>
</html>

### Benchmarks

Mostly the same except empty_systems has got a touch slower. The maybe_pipelining+1 column has the compute task pool with an extra thread over default added. This is because pipelining loses one thread over main to execute systems on, since the main thread no longer runs normal systems.

<details>
<summary>Click Me</summary>

```text
group                                                             main                                         maybe-pipelining+1
-----                                                             -------------------------                ------------------
busy_systems/01x_entities_03_systems                              1.07     30.7±1.32µs        ? ?/sec      1.00     28.6±1.35µs        ? ?/sec
busy_systems/01x_entities_06_systems                              1.10     52.1±1.10µs        ? ?/sec      1.00     47.2±1.08µs        ? ?/sec
busy_systems/01x_entities_09_systems                              1.00     74.6±1.36µs        ? ?/sec      1.00     75.0±1.93µs        ? ?/sec
busy_systems/01x_entities_12_systems                              1.03    100.6±6.68µs        ? ?/sec      1.00     98.0±1.46µs        ? ?/sec
busy_systems/01x_entities_15_systems                              1.11    128.5±3.53µs        ? ?/sec      1.00    115.5±1.02µs        ? ?/sec
busy_systems/02x_entities_03_systems                              1.16     50.4±2.56µs        ? ?/sec      1.00     43.5±3.00µs        ? ?/sec
busy_systems/02x_entities_06_systems                              1.00     87.1±1.27µs        ? ?/sec      1.05     91.5±7.15µs        ? ?/sec
busy_systems/02x_entities_09_systems                              1.04    139.9±6.37µs        ? ?/sec      1.00    134.0±1.06µs        ? ?/sec
busy_systems/02x_entities_12_systems                              1.05    179.2±3.47µs        ? ?/sec      1.00    170.1±3.17µs        ? ?/sec
busy_systems/02x_entities_15_systems                              1.01    219.6±3.75µs        ? ?/sec      1.00    218.1±2.55µs        ? ?/sec
busy_systems/03x_entities_03_systems                              1.10     70.6±2.33µs        ? ?/sec      1.00     64.3±0.69µs        ? ?/sec
busy_systems/03x_entities_06_systems                              1.02    130.2±3.11µs        ? ?/sec      1.00    128.0±1.34µs        ? ?/sec
busy_systems/03x_entities_09_systems                              1.00   195.0±10.11µs        ? ?/sec      1.00    194.8±1.41µs        ? ?/sec
busy_systems/03x_entities_12_systems                              1.01    261.7±4.05µs        ? ?/sec      1.00    259.8±4.11µs        ? ?/sec
busy_systems/03x_entities_15_systems                              1.00    318.0±3.04µs        ? ?/sec      1.06   338.3±20.25µs        ? ?/sec
busy_systems/04x_entities_03_systems                              1.00     82.9±0.63µs        ? ?/sec      1.02     84.3±0.63µs        ? ?/sec
busy_systems/04x_entities_06_systems                              1.01    181.7±3.65µs        ? ?/sec      1.00    179.8±1.76µs        ? ?/sec
busy_systems/04x_entities_09_systems                              1.04    265.0±4.68µs        ? ?/sec      1.00    255.3±1.98µs        ? ?/sec
busy_systems/04x_entities_12_systems                              1.00    335.9±3.00µs        ? ?/sec      1.05   352.6±15.84µs        ? ?/sec
busy_systems/04x_entities_15_systems                              1.00   418.6±10.26µs        ? ?/sec      1.08   450.2±39.58µs        ? ?/sec
busy_systems/05x_entities_03_systems                              1.07    114.3±0.95µs        ? ?/sec      1.00    106.9±1.52µs        ? ?/sec
busy_systems/05x_entities_06_systems                              1.08    229.8±2.90µs        ? ?/sec      1.00    212.3±4.18µs        ? ?/sec
busy_systems/05x_entities_09_systems                              1.03    329.3±1.99µs        ? ?/sec      1.00    319.2±2.43µs        ? ?/sec
busy_systems/05x_entities_12_systems                              1.06    454.7±6.77µs        ? ?/sec      1.00    430.1±3.58µs        ? ?/sec
busy_systems/05x_entities_15_systems                              1.03    554.6±6.15µs        ? ?/sec      1.00   538.4±23.87µs        ? ?/sec
contrived/01x_entities_03_systems                                 1.00     14.0±0.15µs        ? ?/sec      1.08     15.1±0.21µs        ? ?/sec
contrived/01x_entities_06_systems                                 1.04     28.5±0.37µs        ? ?/sec      1.00     27.4±0.44µs        ? ?/sec
contrived/01x_entities_09_systems                                 1.00     41.5±4.38µs        ? ?/sec      1.02     42.2±2.24µs        ? ?/sec
contrived/01x_entities_12_systems                                 1.06     55.9±1.49µs        ? ?/sec      1.00     52.6±1.36µs        ? ?/sec
contrived/01x_entities_15_systems                                 1.02     68.0±2.00µs        ? ?/sec      1.00     66.5±0.78µs        ? ?/sec
contrived/02x_entities_03_systems                                 1.03     25.2±0.38µs        ? ?/sec      1.00     24.6±0.52µs        ? ?/sec
contrived/02x_entities_06_systems                                 1.00     46.3±0.49µs        ? ?/sec      1.04     48.1±4.13µs        ? ?/sec
contrived/02x_entities_09_systems                                 1.02     70.4±0.99µs        ? ?/sec      1.00     68.8±1.04µs        ? ?/sec
contrived/02x_entities_12_systems                                 1.06     96.8±1.49µs        ? ?/sec      1.00     91.5±0.93µs        ? ?/sec
contrived/02x_entities_15_systems                                 1.02    116.2±0.95µs        ? ?/sec      1.00    114.2±1.42µs        ? ?/sec
contrived/03x_entities_03_systems                                 1.00     33.2±0.38µs        ? ?/sec      1.01     33.6±0.45µs        ? ?/sec
contrived/03x_entities_06_systems                                 1.00     62.4±0.73µs        ? ?/sec      1.01     63.3±1.05µs        ? ?/sec
contrived/03x_entities_09_systems                                 1.02     96.4±0.85µs        ? ?/sec      1.00     94.8±3.02µs        ? ?/sec
contrived/03x_entities_12_systems                                 1.01    126.3±4.67µs        ? ?/sec      1.00    125.6±2.27µs        ? ?/sec
contrived/03x_entities_15_systems                                 1.03    160.2±9.37µs        ? ?/sec      1.00    156.0±1.53µs        ? ?/sec
contrived/04x_entities_03_systems                                 1.02     41.4±3.39µs        ? ?/sec      1.00     40.5±0.52µs        ? ?/sec
contrived/04x_entities_06_systems                                 1.00     78.9±1.61µs        ? ?/sec      1.02     80.3±1.06µs        ? ?/sec
contrived/04x_entities_09_systems                                 1.02    121.8±3.97µs        ? ?/sec      1.00    119.2±1.46µs        ? ?/sec
contrived/04x_entities_12_systems                                 1.00    157.8±1.48µs        ? ?/sec      1.01    160.1±1.72µs        ? ?/sec
contrived/04x_entities_15_systems                                 1.00    197.9±1.47µs        ? ?/sec      1.08   214.2±34.61µs        ? ?/sec
contrived/05x_entities_03_systems                                 1.00     49.1±0.33µs        ? ?/sec      1.01     49.7±0.75µs        ? ?/sec
contrived/05x_entities_06_systems                                 1.00     95.0±0.93µs        ? ?/sec      1.00     94.6±0.94µs        ? ?/sec
contrived/05x_entities_09_systems                                 1.01    143.2±1.68µs        ? ?/sec      1.00    142.2±2.00µs        ? ?/sec
contrived/05x_entities_12_systems                                 1.00    191.8±2.03µs        ? ?/sec      1.01    192.7±7.88µs        ? ?/sec
contrived/05x_entities_15_systems                                 1.02    239.7±3.71µs        ? ?/sec      1.00    235.8±4.11µs        ? ?/sec
empty_systems/000_systems                                         1.01     47.8±0.67ns        ? ?/sec      1.00     47.5±2.02ns        ? ?/sec
empty_systems/001_systems                                         1.00  1743.2±126.14ns        ? ?/sec     1.01  1761.1±70.10ns        ? ?/sec
empty_systems/002_systems                                         1.01      2.2±0.04µs        ? ?/sec      1.00      2.2±0.02µs        ? ?/sec
empty_systems/003_systems                                         1.02      2.7±0.09µs        ? ?/sec      1.00      2.7±0.16µs        ? ?/sec
empty_systems/004_systems                                         1.00      3.1±0.11µs        ? ?/sec      1.00      3.1±0.24µs        ? ?/sec
empty_systems/005_systems                                         1.00      3.5±0.05µs        ? ?/sec      1.11      3.9±0.70µs        ? ?/sec
empty_systems/010_systems                                         1.00      5.5±0.12µs        ? ?/sec      1.03      5.7±0.17µs        ? ?/sec
empty_systems/015_systems                                         1.00      7.9±0.19µs        ? ?/sec      1.06      8.4±0.16µs        ? ?/sec
empty_systems/020_systems                                         1.00     10.4±1.25µs        ? ?/sec      1.02     10.6±0.18µs        ? ?/sec
empty_systems/025_systems                                         1.00     12.4±0.39µs        ? ?/sec      1.14     14.1±1.07µs        ? ?/sec
empty_systems/030_systems                                         1.00     15.1±0.39µs        ? ?/sec      1.05     15.8±0.62µs        ? ?/sec
empty_systems/035_systems                                         1.00     16.9±0.47µs        ? ?/sec      1.07     18.0±0.37µs        ? ?/sec
empty_systems/040_systems                                         1.00     19.3±0.41µs        ? ?/sec      1.05     20.3±0.39µs        ? ?/sec
empty_systems/045_systems                                         1.00     22.4±1.67µs        ? ?/sec      1.02     22.9±0.51µs        ? ?/sec
empty_systems/050_systems                                         1.00     24.4±1.67µs        ? ?/sec      1.01     24.7±0.40µs        ? ?/sec
empty_systems/055_systems                                         1.05     28.6±5.27µs        ? ?/sec      1.00     27.2±0.70µs        ? ?/sec
empty_systems/060_systems                                         1.02     29.9±1.64µs        ? ?/sec      1.00     29.3±0.66µs        ? ?/sec
empty_systems/065_systems                                         1.02     32.7±3.15µs        ? ?/sec      1.00     32.1±0.98µs        ? ?/sec
empty_systems/070_systems                                         1.00     33.0±1.42µs        ? ?/sec      1.03     34.1±1.44µs        ? ?/sec
empty_systems/075_systems                                         1.00     34.8±0.89µs        ? ?/sec      1.04     36.2±0.70µs        ? ?/sec
empty_systems/080_systems                                         1.00     37.0±1.82µs        ? ?/sec      1.05     38.7±1.37µs        ? ?/sec
empty_systems/085_systems                                         1.00     38.7±0.76µs        ? ?/sec      1.05     40.8±0.83µs        ? ?/sec
empty_systems/090_systems                                         1.00     41.5±1.09µs        ? ?/sec      1.04     43.2±0.82µs        ? ?/sec
empty_systems/095_systems                                         1.00     43.6±1.10µs        ? ?/sec      1.04     45.2±0.99µs        ? ?/sec
empty_systems/100_systems                                         1.00     46.7±2.27µs        ? ?/sec      1.03     48.1±1.25µs        ? ?/sec
```
</details>

## Migration Guide

### App `runner` and SubApp `extract` functions are now required to be Send 

This was changed to enable pipelined rendering. If this breaks your use case please report it as these new bounds might be able to be relaxed.

## ToDo

* [x] redo benchmarking
* [x] reinvestigate the perf of the try_tick -> run change for task pool scope
2023-01-19 23:45:46 +00:00
Mike
884ebbf4b7 min version of fixedbitset was changed (#7275)
# Objective

- schedule v3 is using is_clear which was added in 0.4.2, so bump the version
2023-01-19 05:08:55 +00:00
JoJoJet
629cfab135 Improve safety for CommandQueue internals (#7039)
# Objective

- Safety comments for the `CommandQueue` type are quite sparse and very imprecise. Sometimes, they are right for the wrong reasons or use circular reasoning.

## Solution

- Document previously-implicit safety invariants.
- Rewrite safety comments to actually reflect the specific invariants of each operation.
- Use `OwningPtr` instead of raw pointers, to encode an invariant in the type system instead of via comments.
- Use typed pointer methods when possible to increase reliability.

---

## Changelog

+ Added the function `OwningPtr::read_unaligned`.
2023-01-19 03:04:39 +00:00
targrub
f8feec6ef1 Fix tiny clippy issue for upcoming Rust version (#7266)
Co-authored-by: targrub <62773321+targrub@users.noreply.github.com>
2023-01-18 17:20:27 +00:00
Rob Parrett
46293ce1e4 Fix init_non_send_resource overwriting previous values (#7261)
# Objective

Repeated calls to `init_non_send_resource` currently overwrite the old value because the wrong storage is being checked.

## Solution

Use the correct storage. Add some tests.

## Notes

Without the fix, the new test fails with
```
thread 'world::tests::init_non_send_resource_does_not_overwrite' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `0`', crates/bevy_ecs/src/world/mod.rs:2267:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test world::tests::init_non_send_resource_does_not_overwrite ... FAILED
```

This was introduced by #7174 and it seems like a fairly straightforward oopsie.
2023-01-18 17:06:08 +00:00
Charles Bournhonesque
d6bfd44f8f update doc comment for new_archetype in query-state (#7241)
# Objective

I was reading through the bevy_ecs code, trying to understand how everything works.
I was getting a bit confused when reading the doc comment for the `new_archetype` function; it looks like it doesn't create a new archetype but instead updates some internal state in the SystemParam to facility QueryIteration.

(I still couldn't find where a new archetype was actually created)


## Solution

- Adding a doc comment with a more correct explanation.

If it's deemed correct, I can also update the doc-comment for the other `new_archetype` calls
2023-01-18 14:26:07 +00:00
James Liu
88b353c4b1 Reduce the use of atomics in the render phase (#7084)
# Objective
Speed up the render phase of rendering. An extension of #6885.

`SystemState::get` increments the `World`'s change tick atomically every time it's called. This is notably more expensive than a unsynchronized increment, even without contention. It also updates the archetypes, even when there has been nothing to update when it's called repeatedly.

## Solution
Piggyback off of #6885. Split `SystemState::validate_world_and_update_archetypes` into `SystemState::validate_world` and `SystemState::update_archetypes`, and make the later `pub`. Then create safe variants of `SystemState::get_unchecked_manual` that still validate the `World` but do not update archetypes and do not increment the change tick using `World::read_change_tick` and `World::change_tick`. Update `RenderCommandState` to call `SystemState::update_archetypes` in `Draw::prepare` and `SystemState::get_manual` in `Draw::draw`.

## Performance
There's a slight perf benefit (~2%) for `main_opaque_pass_3d` on `many_foxes` (340.39 us -> 333.32 us)

![image](https://user-images.githubusercontent.com/3137680/210643746-25320b98-3e2b-4a95-8084-892c23bb8b4e.png)

## Alternatives
We can change `SystemState::get` to not increment the `World`'s change tick. Though this would still put updating the archetypes and an atomic read on the hot-path.

---

## Changelog
Added: `SystemState::get_manual`
Added: `SystemState::get_manual_mut`
Added: `SystemState::update_archetypes`
2023-01-18 02:19:19 +00:00
Mike
63a291c6a8 add tests for change detection and conditions for stageless (#7249)
# Objective

- add some tests for how change detection and run criteria interact in stageless
2023-01-17 17:54:53 +00:00
2ne1ugly
16ff05acdf Add World::clear_resources & World::clear_all (#3212)
# Objective

- Fixes #3158

## Solution

- clear columns

My implementation of `clear_resources` do not remove the components itself but it clears the columns that keeps the resource data. I'm not sure if the issue meant to clear all resources, even the components and component ids (which I'm not sure if it's possible)

Co-authored-by: 2ne1ugly <47616772+2ne1ugly@users.noreply.github.com>
2023-01-17 04:20:42 +00:00
JoJoJet
b5893e570d Add a missing impl of ReadOnlySystemParam for Option<NonSend<>> (#7245)
# Objective

The trait `ReadOnlySystemParam` is not implemented for `Option<NonSend<>>`, even though it should be.

Follow-up to #7243. This fixes another mistake made in #6919.

## Solution

Add the missing impl.
2023-01-17 03:29:08 +00:00
JoJoJet
0efe66b081 Remove an incorrect impl of ReadOnlySystemParam for NonSendMut (#7243)
# Objective

The trait `ReadOnlySystemParam` is implemented for `NonSendMut`, when it should not be. This mistake was made in #6919.

## Solution

Remove the incorrect impl.
2023-01-17 01:39:19 +00:00
Cameron
684f07595f Add bevy_ecs::schedule_v3 module (#6587)
# Objective

Complete the first part of the migration detailed in bevyengine/rfcs#45.

## Solution

Add all the new stuff.

### TODO

- [x] Impl tuple methods.
- [x] Impl chaining.
- [x] Port ambiguity detection.
- [x] Write docs.
- [x] ~~Write more tests.~~(will do later)
- [ ] Write changelog and examples here?
- [x] ~~Replace `petgraph`.~~ (will do later)



Co-authored-by: james7132 <contact@jamessliu.com>
Co-authored-by: Michael Hsu <mike.hsu@gmail.com>
Co-authored-by: Mike Hsu <mike.hsu@gmail.com>
2023-01-17 01:39:17 +00:00
Alice Cecile
39e14a4a40 Make EntityRef::new unsafe (#7222)
# Objective

- We rely on the construction of `EntityRef` to be valid elsewhere in unsafe code. This construction is not checked (for performance reasons), and thus this private method must be unsafe.
- Fixes #7218.

## Solution

- Make the method unsafe.
- Add safety docs.
- Improve safety docs slightly for the sibling `EntityMut::new`.
- Add debug asserts to start to verify these assumptions in debug mode.


## Context for reviewers

I attempted to verify the `EntityLocation` more thoroughly, but this turned out to be more work than expected. I've spun that off into #7221 as a result.
2023-01-16 22:10:51 +00:00
JoJoJet
addc36fe29 Add safety comments to usages of byte_add (Ptr, PtrMut, OwningPtr) (#7214)
# Objective

The usages of the unsafe function `byte_add` are not properly documented.

Follow-up to #7151.

## Solution

Add safety comments to each call-site.
2023-01-16 20:35:15 +00:00
JoJoJet
4b326fb4ca Improve safety for BlobVec::replace_unchecked (#7181)
# Objective

- The function `BlobVec::replace_unchecked` has informal use of safety comments.
- This function does strange things with `OwningPtr` in order to get around the borrow checker.

## Solution

- Put safety comments in front of each unsafe operation. Describe the specific invariants of each operation and how they apply here.
- Added a guard type `OnDrop`, which is used to simplify ownership transfer in case of a panic.

---

## Changelog

+ Added the guard type `bevy_utils::OnDrop`.
+ Added conversions from `Ptr`, `PtrMut`, and `OwningPtr` to `NonNull<u8>`.
2023-01-16 15:41:12 +00:00
JoJoJet
38005b0702 Support piping exclusive systems (#7023)
# Objective

Fix #5248.

## Solution

Support `In<T>` parameters and allow returning arbitrary types in exclusive systems.

---

## Changelog

- Exclusive systems may now be used with system piping.

## Migration Guide

Exclusive systems (systems that access `&mut World`) now support system piping, so the `ExclusiveSystemParamFunction` trait now has generics for the `In`put and `Out`put types.

```rust
// Before
fn my_generic_system<T, Param>(system_function: T)
where T: ExclusiveSystemParamFunction<Param>
{ ... }

// After
fn my_generic_system<T, In, Out, Param>(system_function: T)
where T: ExclusiveSystemParamFunction<In, Out, Param>
{ ... }
```
2023-01-16 15:22:38 +00:00
Jakob Hellermann
008c156991 refactor: move internals from entity_ref to World, add SAFETY comments (#6402)
# Objective

There are some utility functions for actually working with `Storages` inside `entity_ref.rs` that are used both for `EntityRef/EntityMut` and `World`, with a `// TODO: move to Storages`.
This PR moves them to private methods on `World`, because that's the safest API boundary. On `Storages` you would need to ensure that you pass `Components` from the same world.

## Solution

- move get_component[_with_type], get_ticks[_with_type], get_component_and_ticks[_with_type] to `World` (still pub(crate))
- replace `pub use entity_ref::*;` with `pub use entity_ref::{EntityRef, EntityMut}` and qualified `entity_ref::get_mut[_by_id]` in `world.rs`
- add safety comments to a bunch of methods
2023-01-13 16:50:26 +00:00
JoJoJet
feac2c206c Remove duplicate lookups from Resource initialization (#7174)
# Objective

* `World::init_resource` and `World::get_resource_or_insert_with` are implemented naively, and as such they perform duplicate `TypeId -> ComponentId` lookups.
* `World::get_resource_or_insert_with` contains an additional duplicate `ComponentId -> ResourceData` lookup.
    * This function also contains an unnecessary panic branch, which we rely on the optimizer to be able to remove.

## Solution

Implement the functions using engine-internal code, instead of combining high-level functions. This allows computed variables to persist across different branches, instead of being recomputed.
2023-01-12 23:25:11 +00:00
James Liu
f4920bbd6d Mark TableRow and TableId as repr(transparent) (#7166)
# Objective
Following #6681, both `TableRow` and `TableId` are now part of `EntityLocation`. However, the safety invariant on `EntityLocation` requires that all of the constituent fields are `repr(transprent)` or `repr(C)` and the bit pattern of all 1s must be valid. This is not true for `TableRow` and `TableId` currently.

## Solution
Mark `TableRow` and `TableId` to satisfy the safety requirement. Add safety comments on `ArchetypeId`, `ArchetypeRow`, `TableId` and `TableRow`.
2023-01-11 23:31:22 +00:00
James Liu
dfc4f05c87 Ensure Ptr/PtrMut/OwningPtr are aligned when casting in debug builds (#7117)
# Objective
Improve safety testing when using `bevy_ptr` types. This is a follow-up to #7113.

## Solution
Add a debug-only assertion that pointers are aligned when casting to a concrete type. This should very quickly catch any unsoundness from unaligned pointers, even without miri. However, this can have a large negative perf impact on debug builds.

---

## Changelog
Added: `Ptr::deref` will now panic in debug builds if the pointer is not aligned.
Added: `PtrMut::deref_mut` will now panic in debug builds if the pointer is not aligned.
Added: `OwningPtr::read` will now panic in debug builds if the pointer is not aligned.
Added: `OwningPtr::drop_as` will now panic in debug builds if the pointer is not aligned.
2023-01-11 23:12:20 +00:00
JoJoJet
59751d6e33 Add a method for converting MutUntyped -> Mut<T> (#7113)
# Objective

`MutUntyped` is a struct that stores a `PtrMut` alongside change tick metadata. Working with this type is cumbersome, and has few benefits over storing the pointer and change ticks separately.

Related: #6430 (title is out of date)

## Solution

Add a convenience method for transforming an untyped change detection pointer into its typed counterpart.

---

## Changelog

- Added the method `MutUntyped::with_type`.
2023-01-11 17:47:54 +00:00
Joshua Chapman
9dd8fbc570 Added Ref to allow immutable access with change detection (#7097)
# Objective

- Fixes #7066 

## Solution

- Split the ChangeDetection trait into ChangeDetection and ChangeDetectionMut
- Added Ref as equivalent to &T with change detection

---

## Changelog

- Support for Ref which allow inspecting change detection flags in an immutable way

## Migration Guide

- While bevy prelude includes both ChangeDetection and ChangeDetectionMut any code explicitly referencing ChangeDetection might need to be updated to ChangeDetectionMut or both. Specifically any reading logic requires ChangeDetection while writes requires ChangeDetectionMut.

use bevy_ecs::change_detection::DetectChanges -> use bevy_ecs::change_detection::{DetectChanges, DetectChangesMut}

- Previously Res had methods to access change detection `is_changed` and `is_added` those methods have been moved to the `DetectChanges` trait. If you are including bevy prelude you will have access to these types otherwise you will need to `use bevy_ecs::change_detection::DetectChanges` to continue using them.
2023-01-11 15:41:54 +00:00
张林伟
0d2cdb450d Fix beta clippy lints (#7154)
# Objective

- When I run `cargo run -p ci` for my pr locally using latest beta toolchain, the ci failed due to [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) and [needless_lifetimes](https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes) lints

## Solution

- Fix lints according to clippy suggestions.
2023-01-11 09:51:22 +00:00
Boxy
d4babafe81 Make Query fields private (#7149)
`Query`'s fields being `pub(crate)` means that the struct can be constructed via safe code from anywhere in `bevy_ecs` . This is Not Good since it is intended that all construction of this type goes through `Query::new` which is an `unsafe fn` letting various `Query` methods rely on those invariants holding even though they can be trivially bypassed.

This has no user facing impact
2023-01-10 18:55:23 +00:00
JoJoJet
fa40e2badb Fix a miscompilation with #[derive(SystemParam)] (#7105)
# Objective

- Fix #7103.
- The issue is caused because I forgot to add a where clause to a generated struct in #7056.

## Solution

- Add the where clause.
2023-01-10 18:41:50 +00:00
Tirth Patel
a207178344 Add wrapping_add to change_tick (#7146)
# Objective

Fixes #7140


## Solution

As discussed in the issue, added wrapping_add

---
2023-01-10 17:48:34 +00:00
Boxy
d03c1a0687 Ensure Query does not use the wrong World (#7150)
`Query` relies on the `World` it stores being the same as the world used for creating the `QueryState` it stores. If they are not the same then everything is very unsound. This was not actually being checked anywhere, `Query::new` did not have a safety invariant or even an assertion that the `WorldId`'s are the same.

This shouldn't have any user facing impact unless we have really messed up in bevy and have unsoundness elsewhere (in which case we would now get a panic instead of being unsound).
2023-01-10 17:25:45 +00:00
zeroacez
aaaf357dbb Added docs for `.apply()in basic usage of systemState` (#7138)
# Objective

Fixes #5940 

## Solution

Added the suggested comment.

Co-authored-by: zeroacez <43633834+zeroacez@users.noreply.github.com>
2023-01-10 17:25:44 +00:00
JoJoJet
9adc8cdaf6 Add Mut::reborrow (#7114)
# Objective

- In some cases, you need a `Mut<T>` pointer, but you only have a mutable reference to one. There is no easy way of converting `&'a mut Mut<'_, T>` -> `Mut<'a, T>` outside of the engine.

### Example (Before)

```rust
fn do_with_mut<T>(val: Mut<T>) { ... }

for x: Mut<T> in &mut query {
    // The function expects a `Mut<T>`, so `x` gets moved here.
    do_with_mut(x);
    // Error: use of moved value.
    do_a_thing(&x);
}
```

## Solution

- Add the function `reborrow`, which performs the mapping. This is analogous to `PtrMut::reborrow`.

### Example (After)

```rust
fn do_with_mut<T>(val: Mut<T>) { ... }

for x: Mut<T> in &mut query {
    // We reborrow `x`, so the original does not get moved.
    do_with_mut(x.reborrow());
    // Works fine.
    do_a_thing(&x);
}
```

---

## Changelog

- Added the method `reborrow` to `Mut`, `ResMut`, `NonSendMut`, and `MutUntyped`.
2023-01-09 22:20:10 +00:00
2ne1ugly
0e9f80e00b Implement SparseSetIndex for WorldId (#7125)
# Objective

- Fixes #7124

## Solution

- Add Hash Derive on `WorldId`
- Add `SparseSetIndex` impl
2023-01-09 21:43:27 +00:00
JoJoJet
afe0a0650b Relax Sync bound on Local<T> as ExclusiveSystemParam (#7040)
# Objective

The type `Local<T>` unnecessarily has the bound `T: Sync` when the local is used in an exclusive system.

## Solution

Lift the bound.

---

## Changelog

Removed the bound `T: Sync` from `Local<T>` when used as an `ExclusiveSystemParam`.
2023-01-09 20:56:06 +00:00
James Liu
aaf384ae58 Panic on dropping NonSend in non-origin thread. (#6534)
# Objective

Fixes #3310. Fixes #6282. Fixes #6278. Fixes #3666.

## Solution
Split out `!Send` resources into `NonSendResources`. Add a `origin_thread_id` to all `!Send` Resources, check it on dropping `NonSendResourceData`, if there's a mismatch, panic. Moved all of the checks that `MainThreadValidator` would do into `NonSendResources` instead.

All `!Send` resources now individually track which thread they were inserted from. This is validated against for every access, mutation, and drop that could be done against the value. 

A regression test using an altered version of the example from #3310 has been added.

This is a stopgap solution for the current status quo. A full solution may involve fully removing `!Send` resources/components from `World`, which will likely require a much more thorough design on how to handle the existing in-engine and ecosystem use cases.

This PR also introduces another breaking change:

```rust
    use bevy_ecs::prelude::*;

    #[derive(Resource)]
    struct Resource(u32);

    fn main() {
        let mut world = World::new();
        world.insert_resource(Resource(1));
        world.insert_non_send_resource(Resource(2));
        let res = world.get_resource_mut::<Resource>().unwrap();
        assert_eq!(res.0, 2);
    }
```

This code will run correctly on 0.9.1 but not with this PR, since NonSend resources and normal resources have become actual distinct concepts storage wise.

## Changelog
Changed: Fix soundness bug with `World: Send`. Dropping a `World` that contains a `!Send` resource on the wrong thread will now panic.

## Migration Guide
Normal resources and `NonSend` resources no longer share the same backing storage. If `R: Resource`, then `NonSend<R>` and `Res<R>` will return different instances from each other. If you are using both `Res<T>` and `NonSend<T>` (or their mutable variants), to fetch the same resources, it's strongly advised to use `Res<T>`.
2023-01-09 20:40:34 +00:00
Mike
d76b53bf4d Separate Extract from Sub App Schedule (#7046)
# Objective

- This pulls out some of the changes to Plugin setup and sub apps from #6503 to make that PR easier to review.
- Separate the extract stage from running the sub app's schedule to allow for them to be run on separate threads in the future
- Fixes #6990

## Solution

- add a run method to `SubApp` that runs the schedule
- change the name of `sub_app_runner` to extract to make it clear that this function is only for extracting data between the main app and the sub app
- remove the extract stage from the sub app schedule so it can be run separately. This is done by adding a `setup` method to the `Plugin` trait that runs after all plugin build methods run. This is required to allow the extract stage to be removed from the schedule after all the plugins have added their systems to the stage. We will also need the setup method for pipelined rendering to setup the render thread. See e3267965e1/crates/bevy_render/src/pipelined_rendering.rs (L57-L98)

## Changelog

- Separate SubApp Extract stage from running the sub app schedule.

## Migration Guide

### SubApp `runner` has conceptually been changed to an `extract` function.

The `runner` no longer is in charge of running the sub app schedule. It's only concern is now moving data between the main world and the sub app. The `sub_app.app.schedule` is now run for you after the provided function is called.

```rust
// before
fn main() {
    let sub_app = App::empty();
    sub_app.add_stage(MyStage, SystemStage::parallel());
    
    App::new().add_sub_app(MySubApp, sub_app, move |main_world, sub_app| {
        extract(app_world, render_app);
        render_app.app.schedule.run();
    });
}

// after
fn main() {
        let sub_app = App::empty();
    sub_app.add_stage(MyStage, SystemStage::parallel());
    
    App::new().add_sub_app(MySubApp, sub_app, move |main_world, sub_app| {
        extract(app_world, render_app);
        // schedule is automatically called for you after extract is run
    });
}
```
2023-01-09 19:24:54 +00:00
JoJoJet
1efdbb7e3e Remove the SystemParamState trait and remove types like ResState (#6919)
Spiritual successor to #5205.
Actual successor to #6865.

# Objective

Currently, system params are defined using three traits: `SystemParam`, `ReadOnlySystemParam`, `SystemParamState`. The behavior for each param is specified by the `SystemParamState` trait, while `SystemParam` simply defers to the state.

Splitting the traits in this way makes it easier to implement within macros, but it increases the cognitive load. Worst of all, this approach requires each `MySystemParam` to have a public `MySystemParamState` type associated with it.

## Solution

* Merge the trait `SystemParamState` into `SystemParam`.
* Remove all trivial `SystemParam` state types. 
  * `OptionNonSendMutState<T>`: you will not be missed.

---

- [x] Fix/resolve the remaining test failure.

## Changelog

* Removed the trait `SystemParamState`, merging its functionality into `SystemParam`.

## Migration Guide

**Note**: this should replace the migration guide for #6865.
This is relative to Bevy 0.9, not main.

The traits `SystemParamState` and `SystemParamFetch` have been removed, and their functionality has been transferred to `SystemParam`.


```rust
// Before (0.9)
impl SystemParam for MyParam<'_, '_> {
    type State = MyParamState;
}
unsafe impl SystemParamState for MyParamState {
    fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
}
unsafe impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState {
    type Item = MyParam<'w, 's>;
    fn get_param(&mut self, ...) -> Self::Item;
}
unsafe impl ReadOnlySystemParamFetch for MyParamState { }

// After (0.10)
unsafe impl SystemParam for MyParam<'_, '_> {
    type State = MyParamState;
    type Item<'w, 's> = MyParam<'w, 's>;
    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { ... }
    fn get_param<'w, 's>(state: &mut Self::State, ...) -> Self::Item<'w, 's>;
}
unsafe impl ReadOnlySystemParam for MyParam<'_, '_> { }
```

The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`.

```rust
// Before
unsafe impl ReadOnlySystemParamFetch for MyParamState {}

// After
unsafe impl ReadOnlySystemParam for MyParam<'_, '_> {}
```
2023-01-07 23:20:32 +00:00
JoJoJet
076e6f780c Update an outdated example for Mut::map_unchanged (#7115)
# Objective

- The doctest for `Mut::map_unchanged` uses a fake function `set_if_not_equal` to demonstrate usage.
- Now that #6853 has been merged, we can use `Mut::set_if_neq` directly instead of mocking it.
2023-01-06 23:24:25 +00:00
iiYese
653c062ba3 Added missing details to SystemParam Local documentation. (#7106)
# Objective

`SystemParam` `Local`s documentation currently leaves out information that should be documented.
- What happens when multiple `SystemParam`s within the same system have the same `Local` type.
- What lifetime parameter is expected by `Local`.
 
## Solution

- Added sentences to documentation to communicate this information.
- Renamed `Local` lifetimes in code to `'s` where they previously were not. Users can get complicated incorrect suggested fixes if they pass the wrong lifetime. Some instance of the code had `'w` indicating the expected lifetime might not have been known to those that wrote the code either.

Co-authored-by: iiYese <83026177+iiYese@users.noreply.github.com>
2023-01-06 15:40:10 +00:00
Rob Parrett
3dd8b42f72 Fix various typos (#7096)
I stumbled across a typo in some docs. Fixed some more while I was in there.
2023-01-06 00:43:30 +00:00
JoJoJet
8ca3d0462c Allow SystemParams with private fields (#7056)
# Objective

- Fix #4200

Currently, `#[derive(SystemParam)]` publicly exposes each field type, which makes it impossible to encapsulate private fields.

## Solution

Previously, the fields were leaked because they were used as an input generic type to the macro-generated `SystemParam::State` struct. That type has been changed to store its state in a field with a specific type, instead of a generic type.

---

## Changelog

- Fixed a bug that caused `#[derive(SystemParam)]` to leak the types of private fields.
2023-01-04 23:25:36 +00:00
James Liu
a5b1c46d5b Extend EntityLocation with TableId and TableRow (#6681)
# Objective
`Query::get` and other random access methods require looking up `EntityLocation` for every provided entity, then always looking up the `Archetype` to get the table ID and table row. This requires 4 total random fetches from memory: the `Entities` lookup, the `Archetype` lookup, the table row lookup, and the final fetch from table/sparse sets. If `EntityLocation` contains the table ID and table row, only the `Entities` lookup and the final storage fetch are required.

## Solution
Add `TableId` and table row to `EntityLocation`. Ensure it's updated whenever entities are moved around. To ensure `EntityMeta` does not grow bigger, both `TableId` and `ArchetypeId` have been shrunk to u32, and the archetype index and table row are stored as u32s instead of as usizes. This should shrink `EntityMeta` by 4 bytes, from 24 to 20 bytes, as there is no padding anymore due to the change in alignment.

This idea was partially concocted by @BoxyUwU. 

## Performance
This should restore the `Query::get` "gains" lost to #6625 that were introduced in #4800 without being unsound, and also incorporates some of the memory usage reductions seen in #3678.

This also removes the same lookups during add/remove/spawn commands, so there may be a bit of a speedup in commands and `Entity{Ref,Mut}`.

---

## Changelog
Added: `EntityLocation::table_id`
Added: `EntityLocation::table_row`.
Changed: `World`s can now only hold a maximum of 2<sup>32</sup>- 1 archetypes.
Changed: `World`s can now only hold a maximum of 2<sup>32</sup> - 1 tables.

## Migration Guide

A `World` can only hold a maximum of 2<sup>32</sup> - 1 archetypes and tables now. If your use case requires more than this, please file an issue explaining your use case.
2023-01-02 21:25:04 +00:00
Nile
0ddaa7e83a Round out the untyped api s (#7009)
# Objective

Bevy uses custom `Ptr` types so the rust borrow checker can help ensure lifetimes are correct, even when types aren't known. However, these types don't benefit from the automatic lifetime coercion regular rust references enjoy

## Solution

Add a couple methods to Ptr, PtrMut, and MutUntyped to allow for easy usage of these types in more complex scenarios.

## Changelog

- Added `as_mut` and `as_ref` methods to `MutUntyped`.
- Added `shrink` and `as_ref` methods to `PtrMut`.

## Migration Guide

- `MutUntyped::into_inner` now marks things as changed.
2022-12-27 16:05:16 +00:00
JoJoJet
48b4a45d82 Add a const PipeSystem constructor (#7019)
# Objective

Fix #5914.

`PipeSystem` cannot be constructed in `const` contexts.

## Solution

Add a const `PipeSystem::new` function.
2022-12-25 00:51:19 +00:00
JoJoJet
a91f89db73 Add a basic example for system ordering (#7017)
# Objective

Fix #5653.

## Solution

- Add an example of how systems can be ordered from within a stage.
- Update some docs from before #4224
2022-12-25 00:51:17 +00:00
JoJoJet
65d390163f Add a trait for commands that run for a given Entity (#7015)
# Objective

Resolve #6156.

The most common type of command is one that runs for a single entity. Built-in commands like this can be ergonomically added to the command queue using the `EntityCommands` struct. However, adding custom entity commands to the queue is quite cumbersome. You must first spawn an entity, store its ID in a local, then construct a command using that ID and add it to the queue. This prevents method chaining, which is the main benefit of using `EntityCommands`.

### Example (before)

```rust
struct MyCustomCommand(Entity);

impl Command for MyCustomCommand { ... }

let id = commands.spawn((...)).id();
commmands.add(MyCustomCommand(id));
```

## Solution

Add the `EntityCommand` trait, which allows directly adding per-entity commands to the `EntityCommands` struct.

### Example (after)

```rust
struct MyCustomCommand;

impl EntityCommand for MyCustomCommand { ... }

commands.spawn((...)).add(MyCustomCommand);
```
---

## Changelog

- Added the trait `EntityCommand`. This is a counterpart of `Command` for types that execute code for a single entity.

## Future Work

If we feel its necessary, we can simplify built-in commands (such as `Despawn`) to use this trait.
2022-12-25 00:51:16 +00:00
JoJoJet
83b602a77c Relax Sync bound on anonymous Commands (#7014)
# Objective

Any closure with the signature `FnOnce(&mut World)` implicitly implements the trait `Command` due to a blanket implementation. However, this implementation unnecessarily has the `Sync` bound, which limits the types that can be used.

## Solution

Remove the bound.

---

## Changelog

- `Command` closures no longer need to implement the marker trait `std::marker::Sync`.
2022-12-25 00:51:14 +00:00
Aceeri
9717204aef Rework manual event iterator so we can actually name the type (#5735)
# Objective
- Be able to name the type that `ManualEventReader::iter/iter_with_id` returns and `EventReader::iter/iter_with_id` by proxy.
  Currently for the purpose of https://github.com/bevyengine/bevy/pull/5719

## Solution
- Create a custom `Iterator` type.
2022-12-25 00:39:27 +00:00
JoJoJet
0d98327ce7 Support SystemParam types with const generics (#7001)
# Objective

* Currently, the `SystemParam` derive does not support types with const generic parameters.
  * If you try to use const generics, the error message is cryptic and unhelpful.
* Continuation of the work started in #6867 and #6957.

## Solution

Allow const generic parameters to be used with `#[derive(SystemParam)]`.
2022-12-25 00:06:23 +00:00
JoJoJet
fa2b5f2b36 Add documentation to ParamSet (#6998)
# Objective

Fixes #4729.
Continuation of #4854.

## Solution

Add documentation to `ParamSet` and its methods. Includes examples suggested by community members in the original PR.


Co-authored-by: Nanox19435 <50684926+Nanox19435@users.noreply.github.com>
Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
2022-12-25 00:06:22 +00:00
JoJoJet
025996b18c Lift the 16-field limit from the SystemParam derive (#6867)
# Objective

* The `SystemParam` derive internally uses tuples, which means it is constrained by the 16-field limit on `all_tuples`.
    * The error message if you exceed this limit is abysmal.
* Supercedes #5965 -- this does the same thing, but is simpler.

## Solution

If any tuples have more than 16 fields, they are folded into tuples of tuples until they are under the 16-field limit.
2022-12-21 01:54:10 +00:00
JoJoJet
0363e0b32a Support tuple structs with #[derive(SystemParam)] (#6957)
# Objective

Currently, only named structs can be used with the `SystemParam` derive macro.

## Solution

Remove the restriction. Tuple structs and unit structs are now supported.

---

## Changelog

+ Added support for tuple structs and unit structs to the `SystemParam` derive macro.
2022-12-20 23:45:44 +00:00
ira
0761594dd8 Use World helper methods for sending HierarchyEvents (#6921)
A code-quality PR

Also cleans up the helper methods by just importing the `Event` type

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-12-20 16:17:07 +00:00
Zeenobit
f8e4b755ff Add EntityMap::iter() (#6935)
# Objective

There is currently no way to iterate over key/value pairs inside an `EntityMap`, which makes the usage of this struct very awkward. I couldn't think of a good reason why the `iter()` function should not be exposed, considering the interface already exposes `keys()` and `values()`, so I made this PR.

## Solution

Implement `iter()` for `EntityMap` in terms of its inner map type.
2022-12-16 20:14:13 +00:00
Rob Parrett
ec0478d100 Fix clippy lints and failed test with Rust 1.66 (#6945)
# Objective

[Rust 1.66](https://blog.rust-lang.org/inside-rust/2022/12/12/1.66.0-prerelease.html) is coming in a few days, and bevy doesn't build with it.

Fix that.

## Solution

Replace output from a trybuild test, and fix a few new instances of `needless_borrow` and `unnecessary_cast` that are now caught.

## Note

Due to the trybuild test, this can't be merged until 1.66 is released.
2022-12-15 18:05:15 +00:00
James Liu
79b9231b74 Move system_commands spans into apply_buffers (#6900)
# Objective
A separate `tracing` span for running a system's commands is created, even if the system doesn't have commands. This is adding extra measuring overhead (see #4892) where it's not needed.

## Solution
Move the span into `ParallelCommandState` and `CommandQueue`'s `SystemParamState::apply`. To get the right metadata for the span, a additional `&SystemMeta` parameter was added to `SystemParamState::apply`.

---

## Changelog
Added: `SystemMeta::name`
Changed: Systems without `Commands` and  `ParallelCommands` will no longer show a "system_commands" span when profiling.
Changed: `SystemParamState::apply` now takes a `&SystemMeta` parameter in addition to the provided `&mut World`.
2022-12-11 23:04:04 +00:00
Zoey
4820917af6 Add set_if_neq method to DetectChanges trait (Rebased) (#6853)
# Objective

Change detection can be spuriously triggered by setting a field to the same value as before. As a result, a common pattern is to write:

```rust
if *foo != value {
  *foo = value;
}
```

This is confusing to read, and heavy on boilerplate.

Adopted from #5373, but untangled and rebased to current `bevy/main`.

## Solution

    1. Add a method to the `DetectChanges` trait that implements this boilerplate when the appropriate trait bounds are met.

    2. Document this minor footgun, and point users to it.


## Changelog

    * added the `set_if_neq` method to avoid triggering change detection when the new and previous values are equal. This will work on both components and resources.


## Migration Guide

If you are manually checking if a component or resource's value is equal to its new value before setting it to avoid triggering change detection, migrate to the clearer and more convenient `set_if_neq` method.
## Context

Related to #2363 as it avoids triggering change detection, but not a complete solution (as it still requires triggering it when real changes are made).



Co-authored-by: Zoey <Dessix@Dessix.net>
2022-12-11 19:24:19 +00:00
James Liu
87bf0e2664 Remove unnecessary branching from bundle insertion (#6902)
# Objective
Speed up bundle insertion and spawning from a bundle.

## Solution
Use the same technique used in #6800 to remove the branch on storage type when writing components from a `Bundle` into storage.

 - Add a `StorageType` argument to the closure on `Bundle::get_components`.
 - Pass `C::Storage::STORAGE_TYPE` into that argument.
 - Match on that argument instead of reading from a `Vec<StorageType>` in `BundleInfo`.
 - Marked all implementations of `Bundle::get_components` as inline to encourage dead code elimination.

The `Vec<StorageType>` in `BundleInfo` was also removed as it's no longer needed. If users were reliant on this, they can either use the compile time constants or fetch the information from `Components`. Should save a rather negligible amount of memory.

## Performance
Microbenchmarks show a slight improvement to inserting components into existing entities, as well as spawning from a bundle. Ranging about 8-16% faster depending on the benchmark.

```
group                                          main                                    soft-constant-write-components
-----                                          ----                                    ------------------------------
add_remove/sparse_set                          1.08  1019.0±80.10µs        ? ?/sec     1.00   944.6±66.86µs        ? ?/sec
add_remove/table                               1.07  1343.3±20.37µs        ? ?/sec     1.00  1257.3±18.13µs        ? ?/sec
add_remove_big/sparse_set                      1.08  1132.4±263.10µs        ? ?/sec    1.00  1050.8±240.74µs        ? ?/sec
add_remove_big/table                           1.02      2.6±0.05ms        ? ?/sec     1.00      2.5±0.08ms        ? ?/sec
get_or_spawn/batched                           1.15   401.4±17.76µs        ? ?/sec     1.00   349.3±11.26µs        ? ?/sec
get_or_spawn/individual                        1.13   732.1±43.35µs        ? ?/sec     1.00   645.6±41.44µs        ? ?/sec
insert_commands/insert                         1.12   623.9±37.48µs        ? ?/sec     1.00   557.4±34.99µs        ? ?/sec
insert_commands/insert_batch                   1.16   401.4±17.00µs        ? ?/sec     1.00   347.4±12.87µs        ? ?/sec
insert_simple/base                             1.08    416.9±5.60µs        ? ?/sec     1.00    385.2±4.14µs        ? ?/sec
insert_simple/unbatched                        1.06   934.5±44.58µs        ? ?/sec     1.00   881.3±47.86µs        ? ?/sec
spawn_commands/2000_entities                   1.09   190.7±11.41µs        ? ?/sec     1.00    174.7±9.15µs        ? ?/sec
spawn_commands/4000_entities                   1.10   386.5±25.33µs        ? ?/sec     1.00   352.3±18.81µs        ? ?/sec
spawn_commands/6000_entities                   1.10   586.2±34.42µs        ? ?/sec     1.00   535.3±27.25µs        ? ?/sec
spawn_commands/8000_entities                   1.08   778.5±45.15µs        ? ?/sec     1.00   718.0±33.66µs        ? ?/sec
spawn_world/10000_entities                     1.04  1026.4±195.46µs        ? ?/sec    1.00  985.8±253.37µs        ? ?/sec
spawn_world/1000_entities                      1.06   103.8±20.23µs        ? ?/sec     1.00    97.6±18.22µs        ? ?/sec
spawn_world/100_entities                       1.15     11.4±4.25µs        ? ?/sec     1.00      9.9±1.87µs        ? ?/sec
spawn_world/10_entities                        1.05  1030.8±229.78ns        ? ?/sec    1.00  986.2±231.12ns        ? ?/sec
spawn_world/1_entities                         1.01   105.1±23.33ns        ? ?/sec     1.00   104.6±31.84ns        ? ?/sec
```

---

## Changelog
Changed: `Bundle::get_components` now takes a `FnMut(StorageType, OwningPtr)`. The provided storage type must be correct for the component being fetched.
2022-12-11 18:46:43 +00:00
Mike
75880a0b17 run clear trackers on render world (#6878)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/6417

## Solution

- clear_trackers was not being called on the render world. This causes the removed components vecs to continuously grow. This PR adds clear trackers to the end of RenderStage::Cleanup

## Migration Guide

The call to `clear_trackers` in `App` has been moved from the schedule to App::update for the main world and calls to `clear_trackers` have been added for sub_apps in the same function. This was due to needing stronger guarantees. If clear_trackers isn't called on a world it can lead to memory leaks in `RemovedComponents`.
2022-12-11 18:34:15 +00:00
JoJoJet
1af73624fa Simplify trait hierarchy for SystemParam (#6865)
# Objective

* Implementing a custom `SystemParam` by hand requires implementing three traits -- four if it is read-only.
* The trait `SystemParamFetch<'w, 's>` is a workaround from before we had generic associated types, and is no longer necessary.

## Solution

* Combine the trait `SystemParamFetch` with `SystemParamState`.
    * I decided to remove the `Fetch` name and keep the `State` name, since the former was consistently conflated with the latter.
* Replace the trait `ReadOnlySystemParamFetch` with `ReadOnlySystemParam`, which simplifies trait bounds in generic code.

---

## Changelog

- Removed the trait `SystemParamFetch`, moving its functionality to `SystemParamState`.
- Replaced the trait `ReadOnlySystemParamFetch` with `ReadOnlySystemParam`.

## Migration Guide

The trait `SystemParamFetch` has been removed, and its functionality has been transferred to `SystemParamState`.

```rust
// Before
impl SystemParamState for MyParamState {
    fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
}
impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState {
    type Item = MyParam<'w, 's>;
    fn get_param(...) -> Self::Item;
}

// After
impl SystemParamState for MyParamState {
    type Item<'w, 's> = MyParam<'w, 's>; // Generic associated types!
    fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
    fn get_param<'w, 's>(...) -> Self::Item<'w, 's>;
}
```

The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`.

```rust
// Before
unsafe impl ReadOnlySystemParamFetch for MyParamState {}

// After
unsafe impl<'w, 's> ReadOnlySystemParam for MyParam<'w, 's> {}
```
2022-12-11 18:34:14 +00:00
James Liu
c16791ce67 Document options for !Sync types for Component and Resources (#6864)
# Objective
It's not clear to users how to handle `!Sync` types as components and resources in the absence of engine level support for them. 

## Solution
Added a section to `Component`'s and `Resource`'s type level docs on available options for making a type `Sync` when it holds `!Sync` fields, linking `bevy_utils::synccell::SyncCell` and the currently unstable `std::sync::Exclusive`.

Also added a compile_fail doctest that illustrates how to apply `SyncCell`. These will break when/if #6572 gets merged, at which point these docs should be updated.
2022-12-11 18:34:13 +00:00
Edvin Kjell
aea4c5b1a4 [Fixes #6224] Add logging variants of system piping (#6751)
# Objective

Fixes #6224, add ``dbg``, ``info``, ``warn`` and ``error`` system piping adapter variants to expand #5776, which call the corresponding re-exported [bevy_log macros](https://docs.rs/bevy/latest/bevy/log/macro.info.html) when the result is an error.

## Solution

* Added ``dbg``, ``info``, ``warn`` and ``error`` system piping adapter variants to ``system_piping.rs``. 
* Modified and added tests for these under examples in ``system_piping.rs``.
2022-12-11 18:10:03 +00:00
Jerome Humbert
07e7fa5a4d Document World::clear_trackers() (#6520)
# Objective

Document `World::clear_trackers()`.

## Solution

Document the `World::clear_trackers()` method, and briefly how it's related to change detection and `RemovedComponents`.

This is a follow-up from [this discussion](https://discord.com/channels/691052431525675048/749335865876021248/1039628807025479700) on Discord.
2022-12-11 18:10:01 +00:00
James Liu
6308041772 Fix Sparse Change Detection (#6896)
# Objective
#6547 accidentally broke change detection for SparseSet components by using `Ticks::from_tick_cells` with the wrong argument order.

## Solution
Use the right argument order. Add a regression test.
2022-12-10 09:25:53 +00:00
Boxy
bac0d89059 remove a doc(hidden) on read only version of derive(WorldQuery) (#6877)
having `doc(hidden)` on the read only version of a generated mutable world query leads to docs on the readonly item having a dead link. It also makes it annoying to have nice docs for libraries attempting to expose derived `WorldQuery` structs as re-exporting the read only item does not cause it to appear in docs even though it would be intended for users to know about the read only world query and use it.
2022-12-07 23:10:26 +00:00
James Liu
530be10e72 Newtype ArchetypeRow and TableRow (#4878)
# Objective
Prevent future unsoundness that was seen in #6623.

## Solution
Newtype both indexes in `Archetype` and `Table` as `ArchetypeRow` and `TableRow`. This avoids weird numerical manipulation on the indices, and can be stored and treated opaquely. Also enforces the source and destination of where these indices at a type level.

---

## Changelog
Changed: `Archetype` indices and `Table` rows have been newtyped as `ArchetypeRow` and `TableRow`.
2022-12-06 01:38:21 +00:00
James Liu
a3f203b504 Use T::Storage::STORAGE_TYPE to optimize out unused branches (#6800)
# Objective
`EntityRef::get` and friends all type erase calls to fetch the target components by using passing in the `TypeId` instead of using generics. This is forcing a lookup to `Components` to fetch the storage type. This adds an extra memory lookup and forces a runtime branch instead of allowing the compiler to optimize out the unused branch.

## Solution
Leverage `Component::Storage::STORAGE_TYPE` as a constant instead of fetching the metadata from `Components`.

## Performance
This has a near 2x speedup for all calls to `World::get`. Microbenchmark results from my local machine. `Query::get_component`, which uses `EntityRef::get` internally also show a slight speed up. This has closed the gap between `World::get` and `Query::get` for the same use case.

```
group                                                             entity-ref-generics                     main
-----                                                             -------------------                     ----
query_get_component/50000_entities_sparse                         1.00   890.6±40.42µs        ? ?/sec     1.10   980.6±28.22µs        ? ?/sec
query_get_component/50000_entities_table                          1.00   968.5±73.73µs        ? ?/sec     1.08  1048.8±31.76µs        ? ?/sec
query_get_component_simple/system                                 1.00    703.2±4.37µs        ? ?/sec     1.00    702.1±6.13µs        ? ?/sec
query_get_component_simple/unchecked                              1.02    855.8±8.98µs        ? ?/sec     1.00    843.1±8.19µs        ? ?/sec
world_get/50000_entities_sparse                                   1.00    202.3±3.15µs        ? ?/sec     1.85   374.0±20.96µs        ? ?/sec
world_get/50000_entities_table                                    1.00    193.0±1.78µs        ? ?/sec     2.02   389.2±26.55µs        ? ?/sec
world_query_get/50000_entities_sparse                             1.01    162.4±2.23µs        ? ?/sec     1.00    161.3±0.95µs        ? ?/sec
world_query_get/50000_entities_table                              1.00    199.9±0.63µs        ? ?/sec     1.00    200.2±0.74µs        ? ?/sec
```

This should also, by proxy, speed up the `ReflectComponent` APIs as most of those use `World::get` variants internally.
2022-12-05 23:56:33 +00:00
JoJoJet
83e8224694 Add missing docs to World::change_tick and World::read_change_tick (#6765)
# Objective

The methods `World::change_tick` and `World::read_change_tick` lack documentation and have confusingly similar behavior.

## Solution

Add documentation and clarify the distinction between the two functions.
2022-12-05 23:23:14 +00:00