118424d64a
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
33c7a2251e
|
bevy_ecs address trivial cases of unsafe_op_in_unsafe_fn (#11861)
# Objective - Part of #11590 - Fix `unsafe_op_in_unsafe_fn` for trivial cases in bevy_ecs ## Solution Fix `unsafe_op_in_unsafe_fn` in bevy_ecs for trivial cases, i.e., add an `unsafe` block when the safety comment already exists or add a comment like "The invariants are uphold by the caller". --------- Co-authored-by: James Liu <contact@jamessliu.com> |
||
|
|
950bd2284d
|
System::type_id Consistency (#11728)
# Objective - Fixes #11679 ## Solution - Added `IntoSystem::system_type_id` which returns the equivalent of `system.into_system().type_id()` without construction. This allows for getting the `TypeId` of functions (a function is an unnamed type and therefore you cannot call `TypeId::of::<apply_deferred::System>()`) - Added default implementation of `System::type_id` to ensure consistency between implementations. Some returned `Self`, while others were returning an inner value instead. This ensures consistency with `IntoSystem::system_type_id`. ## Migration Guide If you use `System::type_id()` on function systems (exclusive or not), ensure you are comparing its value to other `System::type_id()` calls, or `IntoSystem::system_type_id()`. This code wont require any changes, because `IntoSystem`'s are directly compared to each other. ```rust fn test_system() {} let type_id = test_system.type_id(); // ... // No change required assert_eq!(test_system.type_id(), type_id); ``` Likewise, this code wont, because `System`'s are directly compared. ```rust fn test_system() {} let type_id = IntoSystem::into_system(test_system).type_id(); // ... // No change required assert_eq!(IntoSystem::into_system(test_system).type_id(), type_id); ``` The below _does_ require a change, since you're comparing a `System` type to a `IntoSystem` type. ```rust fn test_system() {} // Before assert_eq!(test_system.type_id(), IntoSystem::into_system(test_system).type_id()); // After assert_eq!(test_system.system_type_id(), IntoSystem::into_system(test_system).type_id()); ``` |
||
|
|
6b84ba97a3
|
Auto insert sync points (#9822)
# Objective - Users are often confused when their command effects are not visible in the next system. This PR auto inserts sync points if there are deferred buffers on a system and there are dependents on that system (systems with after relationships). - Manual sync points can lead to users adding more than needed and it's hard for the user to have a global understanding of their system graph to know which sync points can be merged. However we can easily calculate which sync points can be merged automatically. ## Solution 1. Add new edge types to allow opting out of new behavior 2. Insert an sync point for each edge whose initial node has deferred system params. 3. Reuse nodes if they're at the number of sync points away. * add opt outs for specific edges with `after_ignore_deferred`, `before_ignore_deferred` and `chain_ignore_deferred`. The `auto_insert_apply_deferred` boolean on `ScheduleBuildSettings` can be set to false to opt out for the whole schedule. ## Perf This has a small negative effect on schedule build times. ```text group auto-sync main-for-auto-sync ----- ----------- ------------------ build_schedule/1000_schedule 1.06 2.8±0.15s ? ?/sec 1.00 2.7±0.06s ? ?/sec build_schedule/1000_schedule_noconstraints 1.01 26.2±0.88ms ? ?/sec 1.00 25.8±0.36ms ? ?/sec build_schedule/100_schedule 1.02 13.1±0.33ms ? ?/sec 1.00 12.9±0.28ms ? ?/sec build_schedule/100_schedule_noconstraints 1.08 505.3±29.30µs ? ?/sec 1.00 469.4±12.48µs ? ?/sec build_schedule/500_schedule 1.00 485.5±6.29ms ? ?/sec 1.00 485.5±9.80ms ? ?/sec build_schedule/500_schedule_noconstraints 1.00 6.8±0.10ms ? ?/sec 1.02 6.9±0.16ms ? ?/sec ``` --- ## Changelog - Auto insert sync points and added `after_ignore_deferred`, `before_ignore_deferred`, `chain_no_deferred` and `auto_insert_apply_deferred` APIs to opt out of this behavior ## Migration Guide - `apply_deferred` points are added automatically when there is ordering relationship with a system that has deferred parameters like `Commands`. If you want to opt out of this you can switch from `after`, `before`, and `chain` to the corresponding `ignore_deferred` API, `after_ignore_deferred`, `before_ignore_deferred` or `chain_ignore_deferred` for your system/set ordering. - You can also set `ScheduleBuildSettings::auto_insert_sync_points` to `false` if you want to do it for the whole schedule. Note that in this mode you can still add `apply_deferred` points manually. - For most manual insertions of `apply_deferred` you should remove them as they cannot be merged with the automatically inserted points and might reduce parallelizability of the system graph. ## TODO - [x] remove any apply_deferred used in the engine - [x] ~~decide if we should deprecate manually using apply_deferred.~~ We'll still allow inserting manual sync points for now for whatever edge cases users might have. - [x] Update migration guide - [x] rerun schedule build benchmarks --------- Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com> |
||
|
|
b2661ea73d
|
Reorder impl to be the same as the trait (#10964)
# Objective - Make the implementation order consistent between all sources to fit the order in the trait. ## Solution - Change the implementation order. |
||
|
|
a830530be4
|
Replace all labels with interned labels (#7762)
# Objective First of all, this PR took heavy inspiration from #7760 and #5715. It intends to also fix #5569, but with a slightly different approach. This also fixes #9335 by reexporting `DynEq`. ## Solution The advantage of this API is that we can intern a value without allocating for zero-sized-types and for enum variants that have no fields. This PR does this automatically in the `SystemSet` and `ScheduleLabel` derive macros for unit structs and fieldless enum variants. So this should cover many internal and external use cases of `SystemSet` and `ScheduleLabel`. In these optimal use cases, no memory will be allocated. - The interning returns a `Interned<dyn SystemSet>`, which is just a wrapper around a `&'static dyn SystemSet`. - `Hash` and `Eq` are implemented in terms of the pointer value of the reference, similar to my first approach of anonymous system sets in #7676. - Therefore, `Interned<T>` does not implement `Borrow<T>`, only `Deref`. - The debug output of `Interned<T>` is the same as the interned value. Edit: - `AppLabel` is now also interned and the old `derive_label`/`define_label` macros were replaced with the new interning implementation. - Anonymous set ids are reused for different `Schedule`s, reducing the amount of leaked memory. ### Pros - `InternedSystemSet` and `InternedScheduleLabel` behave very similar to the current `BoxedSystemSet` and `BoxedScheduleLabel`, but can be copied without an allocation. - Many use cases don't allocate at all. - Very fast lookups and comparisons when using `InternedSystemSet` and `InternedScheduleLabel`. - The `intern` module might be usable in other areas. - `Interned{ScheduleLabel, SystemSet, AppLabel}` does implement `{ScheduleLabel, SystemSet, AppLabel}`, increasing ergonomics. ### Cons - Implementors of `SystemSet` and `ScheduleLabel` still need to implement `Hash` and `Eq` (and `Clone`) for it to work. ## Changelog ### Added - Added `intern` module to `bevy_utils`. - Added reexports of `DynEq` to `bevy_ecs` and `bevy_app`. ### Changed - Replaced `BoxedSystemSet` and `BoxedScheduleLabel` with `InternedSystemSet` and `InternedScheduleLabel`. - Replaced `impl AsRef<dyn ScheduleLabel>` with `impl ScheduleLabel`. - Replaced `AppLabelId` with `InternedAppLabel`. - Changed `AppLabel` to use `Debug` for error messages. - Changed `AppLabel` to use interning. - Changed `define_label`/`derive_label` to use interning. - Replaced `define_boxed_label`/`derive_boxed_label` with `define_label`/`derive_label`. - Changed anonymous set ids to be only unique inside a schedule, not globally. - Made interned label types implement their label trait. ### Removed - Removed `define_boxed_label` and `derive_boxed_label`. ## Migration guide - Replace `BoxedScheduleLabel` and `Box<dyn ScheduleLabel>` with `InternedScheduleLabel` or `Interned<dyn ScheduleLabel>`. - Replace `BoxedSystemSet` and `Box<dyn SystemSet>` with `InternedSystemSet` or `Interned<dyn SystemSet>`. - Replace `AppLabelId` with `InternedAppLabel` or `Interned<dyn AppLabel>`. - Types manually implementing `ScheduleLabel`, `AppLabel` or `SystemSet` need to implement: - `dyn_hash` directly instead of implementing `DynHash` - `as_dyn_eq` - Pass labels to `World::try_schedule_scope`, `World::schedule_scope`, `World::try_run_schedule`. `World::run_schedule`, `Schedules::remove`, `Schedules::remove_entry`, `Schedules::contains`, `Schedules::get` and `Schedules::get_mut` by value instead of by reference. --------- Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com> Co-authored-by: Carter Anderson <mcanders1@gmail.com> |
||
|
|
474b55a29c
|
Add system.map(...) for transforming the output of a system (#8526)
# Objective Any time we wish to transform the output of a system, we currently use system piping to do so: ```rust my_system.pipe(|In(x)| do_something(x)) ``` Unfortunately, system piping is not a zero cost abstraction. Each call to `.pipe` requires allocating two extra access sets: one for the second system and one for the combined accesses of both systems. This also adds extra work to each call to `update_archetype_component_access`, which stacks as one adds multiple layers of system piping. ## Solution Add the `AdapterSystem` abstraction: similar to `CombinatorSystem`, this allows you to implement a trait to generically control how a system is run and how its inputs and outputs are processed. Unlike `CombinatorSystem`, this does not have any overhead when computing world accesses which makes it ideal for simple operations such as inverting or ignoring the output of a system. Add the extension method `.map(...)`: this is similar to `.pipe(...)`, only it accepts a closure as an argument instead of an `In<T>` system. ```rust my_system.map(do_something) ``` This has the added benefit of making system names less messy: a system that ignores its output will just be called `my_system`, instead of `Pipe(my_system, ignore)` --- ## Changelog TODO ## Migration Guide The `system_adapter` functions have been deprecated: use `.map` instead, which is a lightweight alternative to `.pipe`. ```rust // Before: my_system.pipe(system_adapter::ignore) my_system.pipe(system_adapter::unwrap) my_system.pipe(system_adapter::new(T::from)) // After: my_system.map(std::mem::drop) my_system.map(Result::unwrap) my_system.map(T::from) // Before: my_system.pipe(system_adapter::info) my_system.pipe(system_adapter::dbg) my_system.pipe(system_adapter::warn) my_system.pipe(system_adapter::error) // After: my_system.map(bevy_utils::info) my_system.map(bevy_utils::dbg) my_system.map(bevy_utils::warn) my_system.map(bevy_utils::error) ``` --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> |