Commit graph

7698 commits

Author SHA1 Message Date
charlotte
994312ac6d
Fix TAA on camera with viewport (#14582)
# Objective

Closes #14526 

## Solution

The history texture was being created incorrectly with the viewport size
rather than target size. When viewport < target, this meant that the
render attachments would differer in size which causes a wgpu validation
error.

## Testing

Example in linked issue works.
2024-08-07 23:59:38 +00:00
Gino Valente
a0cc636ea3
bevy_reflect: Anonymous function parsing (#14641)
# Objective

### TL;DR

#14098 added the `FunctionRegistry` but had some last minute
complications due to anonymous functions. It ended up going with a
"required name" approach to ensure anonymous functions would always have
a name.

However, this approach isn't ideal for named functions since, by
definition, they will always have a name.

Therefore, this PR aims to modify function reflection such that we can
make function registration easier for named functions, while still
allowing anonymous functions to be registered as well.

### Context

Function registration (#14098) ran into a little problem: anonymous
functions.

Anonymous functions, including function pointers, have very non-unique
type names. For example, the anonymous function `|a: i32, b: i32| a + b`
has the type name of `fn(i32, i32) -> i32`. This obviously means we'd
conflict with another function like `|a: i32, b: i32| a - b`.

The solution that #14098 landed on was to always require a name during
function registration.

The downside with this is that named functions (e.g. `fn add(a: i32, b:
i32) -> i32 { a + b }`) had to redundantly provide a name. Additionally,
manually constructed `DynamicFunction`s also ran into this ergonomics
issue.

I don't entirely know how the function registry will be used, but I have
a strong suspicion that most of its registrations will either be named
functions or manually constructed `DynamicFunction`s, with anonymous
functions only being used here and there for quick prototyping or adding
small functionality.

Why then should the API prioritize the anonymous function use case by
always requiring a name during registration?

#### Telling Functions Apart

Rust doesn't provide a lot of out-of-the-box tools for reflecting
functions. One of the biggest hurdles in attempting to solve the problem
outlined above would be to somehow tell the different kinds of functions
apart.

Let's briefly recap on the categories of functions in Rust:

| Category           | Example                                   |
| ------------------ | ----------------------------------------- |
| Named function     | `fn add(a: i32, b: i32) -> i32 { a + b }` |
| Closure            | `\|a: i32\| a + captured_variable`          |
| Anonymous function | `\|a: i32, b: i32\| a + b`                  |
| Function pointer   | `fn(i32, i32) -> i32`                     |

My first thought was to try and differentiate these categories based on
their size. However, we can see that this doesn't quite work:

| Category           | `size_of` |
| ------------------ | --------- |
| Named function     | 0         |
| Closure            | 0+        |
| Anonymous function | 0         |
| Function pointer   | 8         |

Not only does this not tell anonymous functions from named ones, but it
struggles with pretty much all of them.

My second then was to differentiate based on type name:

| Category           | `type_name`             |
| ------------------ | ----------------------- |
| Named function     | `foo::bar::baz`         |
| Closure            | `foo::bar::{{closure}}` |
| Anonymous function | `fn() -> String`        |
| Function pointer   | `fn() -> String`        |

This is much better. While it can't distinguish between function
pointers and anonymous functions, this doesn't matter too much since we
only care about whether we can _name_ the function.

So why didn't we implement this in #14098?

#### Relying on `type_name`

While this solution was known about while working on #14098, it was left
out from that PR due to it being potentially controversial.

The [docs](https://doc.rust-lang.org/stable/std/any/fn.type_name.html)
for `std::any::type_name` state:

> The returned string must not be considered to be a unique identifier
of a type as multiple types may map to the same type name. Similarly,
there is no guarantee that all parts of a type will appear in the
returned string: for example, lifetime specifiers are currently not
included. In addition, the output may change between versions of the
compiler.

So that's it then? We can't use `type_name`?

Well, this statement isn't so much a rule as it is a guideline. And Bevy
is no stranger to bending the rules to make things work or to improve
ergonomics. Remember that before `TypePath`, Bevy's scene system was
entirely dependent on `type_name`. Not to mention that `type_name` is
being used as a key into both the `TypeRegistry` and the
`FunctionRegistry`.

Bevy's practices aside, can we reliably use `type_name` for this?

My answer would be "yes".

Anonymous functions are anonymous. They have no name. There's nothing
Rust could do to give them a name apart from generating a random string
of characters. But remember that this is a diagnostic tool, it doesn't
make sense to obfuscate the type by randomizing the output. So changing
it to be anything other than what it is now is very unlikely.

The only changes that I could potentially see happening are:

1. Closures replace `{{closure}}` with the name of their variable
2. Lifetimes are included in the output

I don't think the first is likely to happen, but if it does then it
actually works out in our favor: closures are now named!

The second point is probably the likeliest. However, adding lifetimes
doesn't mean we can't still rely on `type_name` to determine whether or
not a function is named. So we should be okay in this case as well.

## Solution

Parse the `type_name` of the function in the `TypedFunction` impl to
determine if the function is named or anonymous.

This once again makes `FunctionInfo::name` optional. For manual
constructions of `DynamicFunction`, `FunctionInfo::named` or
``FunctionInfo::anonymous` can be used.

The `FunctionRegistry` API has also been reworked to account for this
change.

`FunctionRegistry::register` no longer takes a name and instead takes it
from the supplied function, returning a
`FunctionRegistrationError::MissingName` error if the name is `None`.
This also doubles as a replacement for the old
`FunctionRegistry::register_dynamic` method, which has been removed.

To handle anonymous functions, a `FunctionRegistry::register_with_name`
method has been added. This works in the same way
`FunctionRegistry::register` used to work before this PR.

The overwriting methods have been updated in a similar manner, with
modifications to `FunctionRegistry::overwrite_registration`, the removal
of `FunctionRegistry::overwrite_registration_dynamic`, and the addition
of `FunctionRegistry::overwrite_registration_with_name`.

This PR also updates the methods on `App` in a similar way:
`App::register_function` no longer requires a name argument and
`App::register_function_with_name` has been added to handle anonymous
functions (and eventually closures).

## Testing

You can run the tests locally by running:

```
cargo test --package bevy_reflect --features functions
```

---

## Internal Migration Guide

> [!important]
> Function reflection was introduced as part of the 0.15 dev cycle. This
migration guide was written for developers relying on `main` during this
cycle, and is not a breaking change coming from 0.14.

> [!note]
> This list is not exhaustive. It only contains some of the most
important changes.

`FunctionRegistry::register` no longer requires a name string for named
functions. Anonymous functions, however, need to be registered using
`FunctionRegistry::register_with_name`.

```rust
// BEFORE
registry
  .register(std::any::type_name_of_val(&foo), foo)?
  .register("bar", || println!("Hello world!"));

// AFTER
registry
  .register(foo)?
  .register_with_name("bar", || println!("Hello world!"));
```

`FunctionInfo::name` is now optional. Anonymous functions and closures
will now have their name set to `None` by default. Additionally,
`FunctionInfo::new` has been renamed to `FunctionInfo::named`.
2024-08-07 03:11:08 +00:00
IceSentry
5abc32ceda
Add 2d opaque phase with depth buffer (#13069)
This PR is based on top of #12982

# Objective

- Mesh2d currently only has an alpha blended phase. Most sprites don't
need transparency though.
- For some 2d games it can be useful to have a 2d depth buffer

## Solution

- Add an opaque phase to render Mesh2d that don't need transparency
- This phase currently uses the `SortedRenderPhase` to make it easier to
implement based on the already existing transparent phase. A follow up
PR will switch this to `BinnedRenderPhase`.
- Add a 2d depth buffer
- Use that depth buffer in the transparent phase to make sure that
sprites and transparent mesh2d are displayed correctly

## Testing

I added the mesh2d_transforms example that layers many opaque and
transparent mesh2d to make sure they all get displayed correctly. I also
confirmed it works with sprites by modifying that example locally.

---

## Changelog

- Added `AlphaMode2d`
- Added `Opaque2d` render phase
- Camera2d now have a `ViewDepthTexture` component

## Migration Guide

- `ColorMaterial` now contains `AlphaMode2d`. To keep previous
behaviour, use `AlphaMode::BLEND`. If you know your sprite is opaque,
use `AlphaMode::OPAQUE`

## Follow up PRs

- See tracking issue: #13265

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
2024-08-07 00:22:09 +00:00
Paul Buehne
e7d40c9b08
Fixed typo (#14636)
The closure in the `async_task` example was referred to as a `FnOne`. I
think this should be `FnOnce`.
2024-08-06 17:35:35 +00:00
Periwink
2334638556
Fix access conflicts for resources (#14635)
# Objective

- I made a mistake when fixing the merge conflicts here:
https://github.com/bevyengine/bevy/pull/14579#discussion_r1705377452

It wasn't caught because there's no easy way to trigger access conflicts
with resources without triggering them with components first.
2024-08-06 14:35:41 +00:00
Lubba64
8e20a3e313
Fix gizmos regression (#14633)
# Objective

- Fixes #14142

## Solution

- Make sure a regression test is written on this case that fails for the
current code base but works with the suggested patch linked in the
aforementioned issue. After this is confirmed to be working, apply the
patch.

## Testing

- Run the regression test in both contexts, outputs were as expected.
2024-08-06 14:00:32 +00:00
Zhixing Zhang
5fd0661c15
Making bevy_render an optional dependency for bevy_gizmos (#14448)
# Objective

This PR makes `bevy_render` an optional dependency for `bevy_gizmos`,
thereby allowing `bevy_gizmos` to be used with alternative rendering
backend.

Previously `bevy_gizmos` assumes that one of `bevy_pbr` or `bevy_sprite`
will be enabled. Here we introduced a new feature named `bevy_render`
which disables all rendering-related code paths. An alternative renderer
will then take the `LineGizmo` assets (made public in this PR) and issue
draw calls on their own. A new field `config_ty` was added to
`LineGizmo` to help looking up the related configuration info.

---

## Migration Guide
No user-visible changes needed from the users.
2024-08-06 13:09:10 +00:00
Periwink
e85c072372
Fix soudness issue with Conflicts involving read_all and write_all (#14579)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/14575
- There is a soundness issue because we use `conflicts()` to check for
system ambiguities + soundness issues. However since the current
conflicts is a `Vec<T>`, we cannot express conflicts where there is no
specific `ComponentId` at fault. For example `q1: Query<EntityMut>, q2:
Query<EntityMut>`
There was a TODO to handle the `write_all` case but it was never
resolved


## Solution

- Introduce an `AccessConflict` enum that is either a list of specific
ids that are conflicting or `All` if all component ids are conflicting

## Testing

- Introduced a new unit test to check for the `EntityMut` case

## Migration guide

The `get_conflicts` method of `Access` now returns an `AccessConflict`
enum instead of simply a `Vec` of `ComponentId`s that are causing the
access conflict. This can be useful in cases where there are no
particular `ComponentId`s conflicting, but instead **all** of them are;
for example `fn system(q1: Query<EntityMut>, q2: Query<EntityRef>)`
2024-08-06 10:55:31 +00:00
charlotte
3360b45153
Expose winit's MonitorHandle (#13669)
# Objective

Adds a new `Monitor` component representing a winit `MonitorHandle` that
can be used to spawn new windows and check for system monitor
information.

Closes #12955.

## Solution

For every winit event, check available monitors and spawn them into the
world as components.

## Testing

TODO:
- [x] Test plugging in and unplugging monitor during app runtime
- [x] Test spawning a window on a second monitor by entity id
- [ ] Since this touches winit, test all platforms

---

## Changelog

- Adds a new `Monitor` component that can be queried for information
about available system monitors.

## Migration Guide

- `WindowMode` variants now take a `MonitorSelection`, which can be set
to `MonitorSelection::Primary` to mirror the old behavior.

---------

Co-authored-by: Pascal Hertleif <pascal@technocreatives.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Pascal Hertleif <killercup@gmail.com>
2024-08-06 10:54:37 +00:00
Lubba64
897625c899
Add Reflect to OnReplace (#14620)
# Objective

- Fixes #14337 

## Solution

- Add a `cfg_attr` that derives `Refect` for this type. 

## Testing

- I am going to make sure the tests pass on this PR before requesting
review, If more testing is necessary let me know some good action steps
to take.
2024-08-06 01:31:13 +00:00
Gino Valente
0caeaa2ca9
bevy_reflect: Update serde tests for Set (#14616)
# Objective

Support for reflecting set-like types (e.g. `HashSet`) was added in
#13014. However, we didn't add any serialization tests to verify that
serialization works as expected.

## Solution

Update the serde tests.

## Testing

You can test locally by running:

```
cargo test --package bevy_reflect
```
2024-08-06 01:29:15 +00:00
Robert Walter
70a18d26e2
Glam 0.28 update - adopted (#14613)
Basically it's https://github.com/bevyengine/bevy/pull/13792 with the
bumped versions of `encase` and `hexasphere`.

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-06 01:28:00 +00:00
Christian Hughes
039bf90817
Improve documentation on Update vs FixedUpdate schedule dichotomy (#14600)
# Objective

When looking at documentation for the `Update` schedule, its not
entirely obvious that developers should actually be using the
`FixedUpdate` schedule for most of their game logic. We should directly
cross-link between the two, and give examples of which systems to put in
which schedules.

## Solution

Do just that.
2024-08-06 01:26:37 +00:00
Periwink
3a664b052d
Separate component and resource access (#14561)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/13139
- Fixes https://github.com/bevyengine/bevy/issues/7255
- Separates component from resource access so that we can correctly
handles edge cases like the issue above
- Inspired from https://github.com/bevyengine/bevy/pull/14472

## Solution

- Update access to have `component` fields and `resource` fields

## Testing

- Added some unit tests
2024-08-06 01:19:39 +00:00
Lixou
0d0f77a7ab
Add invert_winding for triangle list meshes (#14555)
# Objective

Implements #14547 

## Solution

Add a function `invert_winding` for `Mesh` that inverts the winding for
`LineList`, `LineStrip`, `TriangleList` and `TriangleStrip`.

## Testing

Tests added

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Alix Bott <bott.alix@gmail.com>
2024-08-06 01:16:43 +00:00
barsoosayque
5f2570eb4c
Export glTF skins as a Gltf struct (#14343)
# Objective

- Make skin data of glTF meshes available for users, so it would be
possible to create skinned meshes without spawning a scene.
- I believe it contributes to
https://github.com/bevyengine/bevy/issues/13681 ?

## Solution

- Add a new `GltfSkin`, representing skin data from a glTF file, new
member `skin` to `GltfNode` and both `skins` + `named_skins` to `Gltf`
(a la meshes/nodes).
- Rewrite glTF nodes resolution as an iterator which sorts nodes by
their dependencies (nodes without dependencies first). So when we create
`GltfNodes` with their associated `GltfSkin` while iterating, their
dependencies already have been loaded.
- Make a distinction between `GltfSkin` and
`SkinnedMeshInverseBindposes` in assets: prior to this PR,
`GltfAssetLabel::Skin(n)` was responsible not for a skin, but for one of
skin's components. Now `GltfAssetLabel::InverseBindMatrices(n)` will map
to `SkinnedMeshInverseBindposes`, and `GltfAssetLabel::Skin(n)` will map
to `GltfSkin`.

## Testing

- New test `skin_node` does just that; it tests whether or not
`GltfSkin` was loaded properly.

## Migration Guide

- Change `GltfAssetLabel::Skin(..)` to
`GltfAssetLabel::InverseBindMatrices(..)`.
2024-08-06 01:14:42 +00:00
Gino Valente
df61117850
bevy_reflect: Function registry (#14098)
# Objective

#13152 added support for reflecting functions. Now, we need a way to
register those functions such that they may be accessed anywhere within
the ECS.

## Solution

Added a `FunctionRegistry` type similar to `TypeRegistry`.

This allows a function to be registered and retrieved by name.

```rust
fn foo() -> i32 {
    123
}

let mut registry = FunctionRegistry::default();
registry.register("my_function", foo);

let function = registry.get_mut("my_function").unwrap();
let value = function.call(ArgList::new()).unwrap().unwrap_owned();
assert_eq!(value.downcast_ref::<i32>(), Some(&123));
```

Additionally, I added an `AppFunctionRegistry` resource which wraps a
`FunctionRegistryArc`. Functions can be registered into this resource
using `App::register_function` or by getting a mutable reference to the
resource itself.

### Limitations

#### `Send + Sync`

In order to get this registry to work across threads, it needs to be
`Send + Sync`. This means that `DynamicFunction` needs to be `Send +
Sync`, which means that its internal function also needs to be `Send +
Sync`.

In most cases, this won't be an issue because standard Rust functions
(the type most likely to be registered) are always `Send + Sync`.
Additionally, closures tend to be `Send + Sync` as well, granted they
don't capture any `!Send` or `!Sync` variables.

This PR adds this `Send + Sync` requirement, but as mentioned above, it
hopefully shouldn't be too big of an issue.

#### Closures

Unfortunately, closures can't be registered yet. This will likely be
explored and added in a followup PR.

### Future Work

Besides addressing the limitations listed above, another thing we could
look into is improving the lookup of registered functions. One aspect is
in the performance of hashing strings. The other is in the developer
experience of having to call `std::any::type_name_of_val` to get the
name of their function (assuming they didn't give it a custom name).

## Testing

You can run the tests locally with:

```
cargo test --package bevy_reflect
```

---

## Changelog

- Added `FunctionRegistry`
- Added `AppFunctionRegistry` (a `Resource` available from `bevy_ecs`)
- Added `FunctionRegistryArc`
- Added `FunctionRegistrationError`
- Added `reflect_functions` feature to `bevy_ecs` and `bevy_app`
- `FunctionInfo` is no longer `Default`
- `DynamicFunction` now requires its wrapped function be `Send + Sync`

## Internal Migration Guide

> [!important]
> Function reflection was introduced as part of the 0.15 dev cycle. This
migration guide was written for developers relying on `main` during this
cycle, and is not a breaking change coming from 0.14.

`DynamicFunction` (both those created manually and those created with
`IntoFunction`), now require `Send + Sync`. All standard Rust functions
should meet that requirement. Closures, on the other hand, may not if
they capture any `!Send` or `!Sync` variables from its environment.
2024-08-06 01:09:48 +00:00
Periwink
ec4cf024f8
Add a ComponentIndex and update QueryState creation/update to use it (#13460)
# Objective

To implement relations we will need to add a `ComponentIndex`, which is
a map from a Component to the list of archetypes that contain this
component.
One of the reasons is that with fragmenting relations the number of
archetypes will explode, so it will become inefficient to create and
update the query caches by iterating through the list of all archetypes.

In this PR, we introduce the `ComponentIndex`, and we update the
`QueryState` to make use of it:
- if a query has at least 1 required component (i.e. something other
than `()`, `Entity` or `Option<>`, etc.): for each of the required
components we find the list of archetypes that contain it (using the
ComponentIndex). Then, we select the smallest list among these. This
gives a small subset of archetypes to iterate through compared with
iterating through all new archetypes
- if it doesn't, then we keep using the current approach of iterating
through all new archetypes


# Implementation
- This breaks query iteration order, in the sense that we are not
guaranteed anymore to return results in the order in which the
archetypes were created. I think this should be fine because this wasn't
an explicit bevy guarantee so users should not be relying on this. I
updated a bunch of unit tests that were failing because of this.

- I had an issue with the borrow checker because iterating the list of
potential archetypes requires access to `&state.component_access`, which
was conflicting with the calls to
```
  if state.new_archetype_internal(archetype) {
      state.update_archetype_component_access(archetype, access);
  }
```
which need a mutable access to the state.

The solution I chose was to introduce a `QueryStateView` which is a
temporary view into the `QueryState` which enables a "split-borrows"
kind of approach. It is described in detail in this blog post:
https://smallcultfollowing.com/babysteps/blog/2018/11/01/after-nll-interprocedural-conflicts/

# Test

The unit tests pass.

Benchmark results:
```
❯ critcmp main pr
group                                  main                                   pr
-----                                  ----                                   --
iter_fragmented/base                   1.00   342.2±25.45ns        ? ?/sec    1.02   347.5±16.24ns        ? ?/sec
iter_fragmented/foreach                1.04   165.4±11.29ns        ? ?/sec    1.00    159.5±4.27ns        ? ?/sec
iter_fragmented/foreach_wide           1.03      3.3±0.04µs        ? ?/sec    1.00      3.2±0.06µs        ? ?/sec
iter_fragmented/wide                   1.03      3.1±0.06µs        ? ?/sec    1.00      3.0±0.08µs        ? ?/sec
iter_fragmented_sparse/base            1.00      6.5±0.14ns        ? ?/sec    1.02      6.6±0.08ns        ? ?/sec
iter_fragmented_sparse/foreach         1.00      6.3±0.08ns        ? ?/sec    1.04      6.6±0.08ns        ? ?/sec
iter_fragmented_sparse/foreach_wide    1.00     43.8±0.15ns        ? ?/sec    1.02     44.6±0.53ns        ? ?/sec
iter_fragmented_sparse/wide            1.00     29.8±0.44ns        ? ?/sec    1.00     29.8±0.26ns        ? ?/sec
iter_simple/base                       1.00      8.2±0.10µs        ? ?/sec    1.00      8.2±0.09µs        ? ?/sec
iter_simple/foreach                    1.00      3.8±0.02µs        ? ?/sec    1.02      3.9±0.03µs        ? ?/sec
iter_simple/foreach_sparse_set         1.00     19.0±0.26µs        ? ?/sec    1.01     19.3±0.16µs        ? ?/sec
iter_simple/foreach_wide               1.00     17.8±0.24µs        ? ?/sec    1.00     17.9±0.31µs        ? ?/sec
iter_simple/foreach_wide_sparse_set    1.06     95.6±6.23µs        ? ?/sec    1.00     90.6±0.59µs        ? ?/sec
iter_simple/sparse_set                 1.00     19.3±1.63µs        ? ?/sec    1.01     19.5±0.29µs        ? ?/sec
iter_simple/system                     1.00      8.1±0.10µs        ? ?/sec    1.00      8.1±0.09µs        ? ?/sec
iter_simple/wide                       1.05     37.7±2.53µs        ? ?/sec    1.00     35.8±0.57µs        ? ?/sec
iter_simple/wide_sparse_set            1.00     95.7±1.62µs        ? ?/sec    1.00     95.9±0.76µs        ? ?/sec
par_iter_simple/with_0_fragment        1.04     35.0±2.51µs        ? ?/sec    1.00     33.7±0.49µs        ? ?/sec
par_iter_simple/with_1000_fragment     1.00     50.4±2.52µs        ? ?/sec    1.01     51.0±3.84µs        ? ?/sec
par_iter_simple/with_100_fragment      1.02     40.3±2.23µs        ? ?/sec    1.00     39.5±1.32µs        ? ?/sec
par_iter_simple/with_10_fragment       1.14     38.8±7.79µs        ? ?/sec    1.00     34.0±0.78µs        ? ?/sec
```
2024-08-06 00:57:15 +00:00
Giacomo Stevanato
68ec6f4f50
Make QueryState::transmute&co validate the world of the &Components used (#14631)
# Objective

- Fix #14629

## Solution

- Make `QueryState::transmute`, `QueryState::transmute_filtered`,
`QueryState::join` and `QueryState::join_filtered` take a `impl
Into<UnsafeWorldCell>` instead of a `&Components` and validate their
`WorldId`

## Migration Guide

- `QueryState::transmute`, `QueryState::transmute_filtered`,
`QueryState::join` and `QueryState::join_filtered` now take a `impl
Into<UnsafeWorldCell>` instead of a `&Components`

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-08-05 22:39:31 +00:00
dependabot[bot]
fc2f564c6f
Bump crate-ci/typos from 1.23.5 to 1.23.6 (#14626)
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.23.5 to
1.23.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/releases">crate-ci/typos's
releases</a>.</em></p>
<blockquote>
<h2>v1.23.6</h2>
<h2>[1.23.6] - 2024-07-31</h2>
<h3>Fixes</h3>
<ul>
<li>Updated the dictionary with the <a
href="https://redirect.github.com/crate-ci/typos/issues/1051">July
2024</a> changes</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's
changelog</a>.</em></p>
<blockquote>
<h2>[1.23.6] - 2024-07-31</h2>
<h3>Fixes</h3>
<ul>
<li>Updated the dictionary with the <a
href="https://redirect.github.com/crate-ci/typos/issues/1051">July
2024</a> changes</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="935271f020"><code>935271f</code></a>
chore: Release</li>
<li><a
href="7dbdf8c01c"><code>7dbdf8c</code></a>
chore: Release</li>
<li><a
href="be714bc5ef"><code>be714bc</code></a>
docs: Update changelog</li>
<li><a
href="a87cf89ab1"><code>a87cf89</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1070">#1070</a>
from epage/july</li>
<li><a
href="12a33e21f4"><code>12a33e2</code></a>
fix(dict): July updates</li>
<li><a
href="0d9c778a8c"><code>0d9c778</code></a>
chore(deps): Update Rust Stable to v1.80 (<a
href="https://redirect.github.com/crate-ci/typos/issues/1064">#1064</a>)</li>
<li><a
href="ebbe2a1b19"><code>ebbe2a1</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1066">#1066</a>
from epage/template</li>
<li><a
href="9dc8c88844"><code>9dc8c88</code></a>
chore(ci): Don't check minimal versions for bins</li>
<li><a
href="267121b5d6"><code>267121b</code></a>
style: Make clippy happy</li>
<li><a
href="063ac6d4b5"><code>063ac6d</code></a>
chore: Update from _rust/main template</li>
<li>Additional commits viewable in <a
href="https://github.com/crate-ci/typos/compare/v1.23.5...v1.23.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.23.5&new-version=1.23.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-05 07:13:22 +00:00
akimakinai
c1c003d3c7
Fix num_cascades in split_screen exmample for WebGL (#14601)
# Objective

- Fixes #14595

## Solution

- Use `num_cascades: 1` in WebGL build.
`CascadeShadowConfigBuilder::default()` gives this number in WebGL:
8235daaea0/crates/bevy_pbr/src/light/mod.rs (L241-L248)

## Testing

- Tested the modified example in WebGL with Firefox/Chrome

---------

Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
2024-08-04 13:57:22 +00:00
Rob Parrett
e164e5a873
Add link to with_children in with_child doc (#14604)
# Objective

Discourage users from using `with_child` for spawning multiple children.

## Solution

Add link to `with_children` in docs for `with_child`.
2024-08-04 13:36:52 +00:00
Ben Frankel
9b254aab1e
Explicitly order CameraUpdateSystem before UiSystem::Prepare (#14609)
# Objective

Fixes https://github.com/bevyengine/bevy/issues/14277.

May also fix https://github.com/bevyengine/bevy/issues/14255, needs
verification.

## Solution

Explicitly order `CameraUpdateSystem` before `UiSystem::Prepare`, so
that when the window resizes, `camera_system` will update the `Camera`'s
viewport size before `ui_layout_system` also reacts to the window resize
and tries to read the new `Camera` viewport size to set UI node sizes
accordingly.

## Testing

I tested that explicitly ordering `CameraUpdateSystem` _after_ triggers
the buggy behavior, and explicitly ordering it _before_ does not trigger
the buggy behavior or crash the app (which also demonstrates that the
system sets are ambiguous).

---

## Migration Guide

`CameraUpdateSystem` is now explicitly ordered before
`UiSystem::Prepare` instead of being ambiguous with it.
2024-08-04 13:34:51 +00:00
radiish
4b20d822e9
update hashbrown to 0.14.2 (#14603)
# Objective

- We previously had a dependency in `bevy_utils`, `hashbrown = 0.14`,
and used the `hashbrown::hash_table` api, which was introduced in
`0.14.2`.

## Solution

- Bump `hashbrown` to `0.14.2`

## Testing

- Now compiles with the minimum declared `hashbrown` version.

---
2024-08-04 13:23:28 +00:00
re0312
8235daaea0
Opportunistically use dense iteration for archetypal iteration (#14049)
# Objective
- currently, bevy employs sparse iteration if any of the target
components in the query are stored in a sparse set. it may lead to
increased cache misses in some cases, potentially impacting performance.
- partial fixes #12381 

## Solution

- use dense iteration when an archetype and its table have the same
entity count.
- to avoid introducing complicate unsafe noise, this pr only implement
for `for_each ` style iteration.
- added a benchmark to test performance for hybrid iteration.


## Performance


![image](https://github.com/bevyengine/bevy/assets/45868716/5cce13cf-6ff2-4861-9576-e75edc63bd46)

nearly 2x win in specific scenarios, and no performance degradation in
other test cases.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Christian Hughes <9044780+ItsDoot@users.noreply.github.com>
2024-08-02 21:18:15 +00:00
Lixou
7c80ae7313
Add depth_ndc_to_view_z for cpu-side (#14590)
# Objective

I want to get the visual depth (after view proj matrix stuff) of the
object beneath my cursor.
Even when having a write-back of the depth texture, you would still need
to convert the NDC depth to a logical value.

## Solution

This is done on shader-side by [this
function](e6261b0f5f/crates/bevy_pbr/src/render/view_transformations.wgsl (L151)),
which I ported over to the cpu-side.

I also added `world_to_viewport_with_depth` to get a `Vec3` instead of
`Vec2`.

---

If anyone knows a smarter solution to get the visual depth instead of
going `screen -> viewport ray -> screen`, please let me know :>
2024-08-02 15:37:29 +00:00
Rob Parrett
5b29402cc8
Add with_child to simplify spawning when there will only be one child (#14594)
# Objective

This idea came up in the context of a hypothetical "text sections as
entities" where text sections are children of a text bundle.

```rust
commands
    .spawn(TextBundle::default())
    .with_children(|parent} {
        parent.spawn(TextSection::from("Hello"));
    });
```

This is a bit cumbersome (but powerful and probably the way things are
headed). [`bsn!`](https://github.com/bevyengine/bevy/discussions/14437)
will eventually make this nicer, but in the mean time, this might
improve ergonomics for the common case where there is only one
`TextSection`.

## Solution

Add a `with_child` method to the `BuildChildren` trait that spawns a
single bundle and adds it as a child to the entity.

```rust
commands
    .spawn(TextBundle::default())
    .with_child(TextSection::from("Hello"));
```

## Testing

I added some tests, and modified the `button` example to use the new
method.

If any potential co-authors want to improve the tests, that would be
great.

## Alternatives

- Some sort of macro. See
https://github.com/tigregalis/bevy_spans_ent/blob/main/examples/macro.rs#L20.
I don't love this, personally, and it would probably be obsoleted by
`bsn!`.
- Wait for `bsn!`
- Add `with_children_batch` that takes an `Into<Iterator>` of bundles.
  ```rust
  with_children_batch(vec![TextSection::from("Hello")])
  ```
This is maybe not as useful as it sounds -- it only works with
homogeneous bundles, so no marker components or styles.
- If this doesn't seem valuable, doing nothing is cool with me.
2024-08-02 15:37:15 +00:00
Lixou
4c2cef2223
Reflection for DepthOfFieldSettings (#14588)
# Objective

I can't mutate the dof settings via tools like `bevy_inspector_egui`

## Solution

Add `Reflect` for `DepthOfFieldSettings` and `DepthOfFieldMode`
2024-08-02 15:36:39 +00:00
Joona Aalto
e6261b0f5f
Add Dir2::from_xy_unchecked and Dir3::from_xyz_unchecked (#14587)
# Objective

Bevy's direction types have `new` and `new_unchecked` constructors, but
no unchecked variant for the `Dir2::from_xy` and `Dir3::from_xyz`
methods.

For me, this has several times lead to constructing directions like
this, in cases where the components of the direction are already known
to be normalized:

```rust
let normal = Dir2::new_unchecked(Vec2::new(-ray.direction.x.signum(), 0.0));
```

```rust
segment.direction =
    Dir2::new_unchecked(Vec2::new(-segment.direction.x, segment.direction.y));
```

For consistency and ergonomics, it would be nice to have unchecked
variants of `Dir2::from_xy` and `Dir3::from_xyz`:

```rust
let normal = Dir2::from_xy_unchecked(-ray.direction.x.signum(), 0.0);
```

```rust
segment.direction = Dir2::from_xy_unchecked(-segment.direction.x, segment.direction.y);
```

## Solution

Add `Dir2::from_xy_unchecked` and `Dir3::from_xyz_unchecked`.
2024-08-02 13:10:13 +00:00
James O'Brien
b98d15f278
Skip batching for phase items from other pipelines (#14296)
# Objective

- Fix #14295

## Solution

- Early out when `GFBD::get_index_and_compare_data` returns None.

## Testing

- Tested on a selection of examples including `many_foxes` and
`3d_shapes`.
- Resolved the original issue in `bevy_vector_shapes`.
2024-08-02 00:15:42 +00:00
JJJimbo1
56c9d4489b
fix asymmetrical 9-slicing (#14148)
# Objective

Fixes #14147.

## Solution

Modify the slicing checks and algorithm to fully allow asymmetrical
textures to work.
Some opinionated code cleanup.

## Testing

Tested using the ui_texture_slice example and a custom asymmetrical
texture.

Before:

![asymmetrical_texture_slice_before](https://github.com/bevyengine/bevy/assets/88861660/00dafce1-904a-41ac-b5d9-faaf087b0681)

After:

![asymmetrical_texture_slice_after](https://github.com/bevyengine/bevy/assets/88861660/f3d742f3-6157-4d35-b383-aee4b8f6e7d0)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-08-01 20:03:23 +00:00
Brian Reavis
4c4a6c4506
Don’t prepare lights (and shadow map textures) for 2D cameras (#14574)
# Objective

When running the Metal debugger I noticed that 2D cameras have shadow
map textures from `bevy_pbr` built for them. For a 2560x1440 2D camera,
this PR saves about 40mb of texture memory.


![image](https://github.com/user-attachments/assets/925e9392-2721-41bb-83e9-25c84fd563cd)


![image](https://github.com/user-attachments/assets/0cc3c0a9-cbf7-431c-b444-952c28d4e9d0)


## Solution

- Added `With<Camera3d>` filter to the appropriate view queries.

## Testing

- This is a trivial fix (the examples still work)
2024-08-01 19:29:18 +00:00
Brezak
0c7df881e7
Properly handle repeated window close requests (#14573)
# Objective

Spamming the window close button on window may trigger a panic.

```
thread 'main' panicked at <Bevy repo>\crates\bevy_ecs\src\system\commands\mod.rs:1320:13:
error[B0003]: Could not insert a bundle (of type `bevy_window:🪟:ClosingWindow`) for entity 0v1#4294967296 because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/b0003
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic when applying buffers for system `bevy_window::system::close_when_requested`!
2024-08-01T15:00:29.742612Z  WARN bevy_ecs::world::command_queue: CommandQueue has un-applied commands being dropped. Did you forget to call SystemState::apply?
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
error: process didn't exit successfully: `target\debug\bevy.exe` (exit code: 101)
```

## Solution

Don't panic when trying to insert the `ClosingWindow` component into a
entity.

## Testing

Found and tested on windows. I haven't checked if this bug happens on
linux or macos.
For testing I ran this code:

```rust
use std::{thread, time::Duration};

use bevy::prelude::*;

fn lag() {
    thread::sleep(Duration::from_millis(300));
}

fn main() -> AppExit {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Update, lag)
        .run()
}
```

Then spammed the window close button. The panic no longer occurs.
2024-08-01 16:15:28 +00:00
SpecificProtagonist
0685d2da4d
B0003: Print caller (#14556)
# Objective

B0003 indicates that you tried to act upon a nonexistant entity, but
does not mention where the error occured:
```
2024-07-31T15:46:25.954840Z  WARN bevy_ecs::world: error[B0003]: Could not despawn entity Entity { index: 4294967295, generation: 1 } because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/b0003
```

## Solution

Include caller location:

```
2024-07-31T15:46:25.954840Z  WARN bevy_ecs::world: error[B0003]: src/main.rs:18:11: Could not despawn entity Entity { index: 4294967295, generation: 1 } because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/b0003
```

Open question: What should the exact message format be?

## Testing

None, this doesn't change any logic.
2024-08-01 00:14:48 +00:00
François Mockers
d5ccb096b5
remove changelog file (#14564)
# Objective

- Remove CHANGELOG.md
- it's redundant with the release blog / the git log
- it's an extra step that may be forgotten in the release process (it
was not updated for the 0.14)
- it's an extra file at the root

## Solution

- Remove it
2024-07-31 22:24:33 +00:00
Guillaume Gomez
0e86675177
Add freebsd support for sysinfo (#14553)
I'm not sure if bevy works on FreeBSD or not. But in case it does,
better allow `sysinfo` to be used as well if users want.
2024-07-31 21:41:40 +00:00
Jan Hohenheim
6f7c554daa
Fix common capitalization errors in documentation (#14562)
WASM -> Wasm
MacOS -> macOS

Nothing important, just something that annoyed me for a while :)
2024-07-31 21:16:05 +00:00
IceSentry
bfcb19a871
Add example showing how to use SpecializedMeshPipeline (#14370)
# Objective

- A lot of mid-level rendering apis are hard to figure out because they
don't have any examples
- SpecializedMeshPipeline can be really useful in some cases when you
want more flexibility than a Material without having to go to low level
apis.

## Solution

- Add an example showing how to make a custom `SpecializedMeshPipeline`.

## Testing

- Did you test these changes? If so, how?
- Are there any parts that need more testing?
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?

---

## Showcase

The examples just spawns 3 triangles in a triangle pattern.


![image](https://github.com/user-attachments/assets/c3098758-94c4-4775-95e5-1d7c7fb9eb86)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-07-31 18:24:58 +00:00
Lixou
20264d0810
Make AnimationPlayer::start and ::play work accordingly to documentation (#14546)
# Objective

While scrolling through the animation crate, I was confused by the docs
and code for the two methods. One does nothing for resetting an
animation, the other just resets the weights for whatever reason.

## Solution

Made the functions work accordingly to their documentation.
`start` now replays the animation.
And `play` doesn't reset the weight anymore. I have no clue why it
should. `play` is there to don't do anything to an already existing
animation.

## Testing

I tested the current 0.14 code with bevy playground in the Animated Fox
exampled and changed it such that on pressing space, either `play` or
`start` would be called. Neither changed anything.
I then inlined the function for start there and it restarted the
animation, so it should work.

---

## Migration Guide

`AnimationPlayer::start` now correspondingly to its docs restarts a
running animation.
`AnimationPlayer::play` doesn't reset the weight anymore.
2024-07-31 14:07:53 +00:00
Guillaume Gomez
68dc7a8b8b
Update sysinfo version to 0.31.0 (#14551)
This release will likely remove a few dependencies in bevy since you
only need the `system` feature.
2024-07-31 14:06:52 +00:00
Rich Churcher
e579622a65
time_system is ambiguous_with event_update_system (#14544)
# Objective

Resolve possible ambiguity detection panic between `time_system` and
`event_update_system`.

Fixes #14524

## Solution

Sets `.ambiguous_with(event_update_system)` on `time_system`. This is
slightly new territory for me, so please treat with scepticism.

## Testing

As described in the issue, added
```
        .configure_schedules(ScheduleBuildSettings {
            ambiguity_detection: LogLevel::Error,
            ..default()
        })
```
to the `time` example and ran it.
2024-07-31 12:13:17 +00:00
Zeenobit
023e0e5bde
Fix Entity Debug Format (#14539)
# Objective

Fixes #12139

## Solution

See this comment on original issue for my proposal:
https://github.com/bevyengine/bevy/issues/12139#issuecomment-2241915791

This PR is an implementation of this proposal.

I modified the implementation of `fmt::Debug` to instead display
`0v0#12345` to ensure entity index, generation, and raw bits are all
present in the output for debug purposes while still keeping log message
concise.

`fmt::Display` remains as is (`0v0`) to offer an even shorter output.

To me, this is the most non-intrusive fix for this issue.

## Testing

Add `fn entity_debug` test

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-07-31 01:36:41 +00:00
Rich Churcher
924f1cbc02
Fix lints in nightly (#14543)
# Objective

Similar to #14537 , this fixes a minor lint issue causing CI failures
when using nightly toolchain.

## Solution

Add `#[allow(dead_code)]` to unused sample code.

## Testing

`cargo run -p ci -- lints` using 1.82 toolchain.
2024-07-31 01:35:19 +00:00
BD103
399219a2c7
Fix rust beta lints (#14537)
# Objective

- Fixes #14517.

## Solution

- Replace two instances of `map()` with `inspect()`.
- `#[allow(dead_code)]` on `Bundle` derive macro tests.

## Testing

You need to install the beta toolchain, since these lints are not stable
yet.

```bash
cargo +beta clippy --workspace
cargo +beta test --workspace
```
2024-07-31 01:27:26 +00:00
Robin KAY
3d1c9ca87f
Change SceneInstanceReady to trigger an observer. (#13859)
# Objective

The `SceneInstanceReady` event would be more ergonomic (and potentially
efficient) if it could be delivered to listeners attached to the scene
entities becoming ready rather than into a World-global queue.

This is an evolution of @Shatur's work in #9313.

## Solution

The scene spawner is changed to trigger observers on the scene entity
when it is ready rather than enqueue an event with `EventWriter`.

This addresses the two outstanding feature requests mentioned on #2218,
that i) the events should be "scoped" in some way and ii) that the
`InstanceId` should be included in the event.

## Testing

Modified the `scene_spawner::tests::event` test to use the new
mechanism.

---

## Changelog

- Changed `SceneInstanceReady` to trigger an entity observer rather than
be written to an event queue.
- Changed `SceneInstanceReady` to carry the `InstanceId` of the scene.

## Migration Guide

If you have a system which read `SceneInstanceReady` events:

> ```fn ready_system(ready_events: EventReader<'_, '_,
SceneInstanceReady>) {```

It must be rewritten as an observer:

> ```commands.observe(|trigger: Trigger<SceneInstanceReady>| {```

Or, if you were expecting the event in relation to a specific entity or
entities, as an entity observer:

> ```commands.entity(entity).observe(|trigger:
Trigger<SceneInstanceReady>| {```
2024-07-30 21:23:48 +00:00
s-puig
ba09f35474
Fix UI texture atlas with offset (#13620)
# Objective

- Fixes #11219 

## Solution

- Scaling calculations use texture dimensions instead of layout
dimensions.

## Testing

- Did you test these changes? If so, how?

All UI examples look fine.

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

Example in #11219

## Migration Guide

```diff
let ui_node = ExtractedUiNode {
                    stack_index,
                    transform,
                    color,
                    rect,
                    image,
-                   atlas_size: Some(atlas_size * scale_factor),      
+                   atlas_scaling: Some(Vec2::splat(scale_factor)),
                    clip,
                    flip_x,
                    flip_y,
                    camera_entity,
                    border,
                    border_radius,
                    node_type,
                },
```

```diff
let computed_slices = ComputedTextureSlices {
    slices,
-    image_size,
}
```
2024-07-30 15:31:58 +00:00
BD103
d722fef23d
Remove deprecated bevy_dynamic_plugin (#14534)
# Objective

- Dynamic plugins were deprecated in #13080 due to being unsound. The
plan was to deprecate them in 0.14 and remove them in 0.15.

## Solution

- Remove all dynamic plugin functionality.
- Update documentation to reflect this change.

---

## Migration Guide

Dynamic plugins were deprecated in 0.14 for being unsound, and they have
now been fully removed. Please consider using the alternatives listed in
the `bevy_dynamic_plugin` crate documentation, or worst-case scenario
you may copy the code from 0.14.
2024-07-30 15:31:08 +00:00
Aevyrie
9575b20d31
Track source location in change detection (#14034)
# Objective

- Make it possible to know *what* changed your component or resource.
- Common need when debugging, when you want to know the last code
location that mutated a value in the ECS.
- This feature would be very useful for the editor alongside system
stepping.

## Solution

- Adds the caller location to column data.
- Mutations now `track_caller` all the way up to the public API.
- Commands that invoke these functions immediately call
`Location::caller`, and pass this into the functions, instead of the
functions themselves attempting to get the caller. This would not work
for commands which are deferred, as the commands are executed by the
scheduler, not the user's code.

## Testing

- The `component_change_detection` example now shows where the component
was mutated:

```
2024-07-28T06:57:48.946022Z  INFO component_change_detection: Entity { index: 1, generation: 1 }: New value: MyComponent(0.0)
2024-07-28T06:57:49.004371Z  INFO component_change_detection: Entity { index: 1, generation: 1 }: New value: MyComponent(1.0)
2024-07-28T06:57:49.012738Z  WARN component_change_detection: Change detected!
        -> value: Ref(MyComponent(1.0))
        -> added: false
        -> changed: true
        -> changed by: examples/ecs/component_change_detection.rs:36:23
```

- It's also possible to inspect change location from a debugger:
<img width="608" alt="image"
src="https://github.com/user-attachments/assets/c90ecc7a-0462-457a-80ae-42e7f5d346b4">


---

## Changelog

- Added source locations to ECS change detection behind the
`track_change_detection` flag.

## Migration Guide

- Added `changed_by` field to many internal ECS functions used with
change detection when the `track_change_detection` feature flag is
enabled. Use Location::caller() to provide the source of the function
call.

---------

Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-07-30 12:02:38 +00:00
Giacomo Stevanato
adb4709d08
Fix CI after #12965 (#14527)
# Objective

- In #12965 I broke CI (sorry!)
- The command was tested locally, but somehow the yaml formatting messed
it up
- I hate yaml

## Solution

- It should now use the correct formatting
  - I hope
- I wish there was a straightforward way to test github actions locally
2024-07-30 07:14:41 +00:00
Rostyslav Toch
455c1bfbe8
Optimize cloning for Access-related structs (#14502)
# Objective

Optimize the cloning process for Access-related structs in the ECS
system, specifically targeting the `clone_from` method.

Previously, profiling showed that 1% of CPU time was spent in
`FixedBitSet`'s `drop_in_place`, due to the default `clone_from`
implementation:

```rust
fn clone_from(&mut self, source: &Self) {
    *self = source.clone()
}
```

This implementation causes unnecessary allocations and deallocations.
However, [FixedBitSet provides a more optimized clone_from
method](https://github.com/petgraph/fixedbitset/blob/master/src/lib.rs#L1445-L1465)
that avoids these allocations and utilizes SIMD instructions for better
performance.

This PR aims to leverage the optimized clone_from method of FixedBitSet
and implement custom clone_from methods for Access-related structs to
take full advantage of this optimization. By doing so, we expect to
significantly reduce CPU time spent on cloning operations and improve
overall system performance.



![image](https://github.com/user-attachments/assets/7526a5c5-c75b-4a9a-b8d2-891f64fd553b)


## Solution

- Implemented custom `clone` and `clone_from` methods for `Access`,
`FilteredAccess`, `AccessFilters`, and `FilteredAccessSet` structs.
- Removed `#[derive(Clone)]` and manually implemented `Clone` trait to
use optimized `clone_from` method from `FixedBitSet`.
- Added unit tests for cloning and `clone_from` methods to ensure
correctness.

## Testing

- Conducted performance testing comparing the original and optimized
versions.
- Measured CPU time consumption for the `clone_from` method:
  - Original version: 1.34% of CPU time
  - Optimized version: 0.338% of CPU time
- Compared FPS before and after the changes (results may vary depending
on the run):

Before optimization:
```
2024-07-28T12:49:11.864019Z  INFO bevy diagnostic: fps        :  213.489463   (avg 214.502488)
2024-07-28T12:49:11.864037Z  INFO bevy diagnostic: frame_time :    4.704746ms (avg 4.682251ms)
2024-07-28T12:49:11.864042Z  INFO bevy diagnostic: frame_count: 7947.000000   (avg 7887.500000)
```


![image](https://github.com/user-attachments/assets/7865a365-0569-4b46-814a-964779d90973)

After optimization:
```
2024-07-28T12:29:42.705738Z  INFO bevy diagnostic: fps        :  220.273721   (avg 220.912227)
2024-07-28T12:29:42.705762Z  INFO bevy diagnostic: frame_time :    4.559127ms (avg 4.544905ms)
2024-07-28T12:29:42.705769Z  INFO bevy diagnostic: frame_count: 7596.000000   (avg 7536.500000)
```


![image](https://github.com/user-attachments/assets/8dd96908-86d0-4850-8e29-f80176a005d6)

---

Reviewers can test these changes by running `cargo run --release
--example ssr`
2024-07-29 23:48:21 +00:00