# Objective
Refactor `bevy_gltf`, the criteria for the split is kind of arbitrary
but at least it is not a 2.6k line file.
## Solution
Move methods and structs found in `bevy_gltf/loader.rs` into multiple
new modules.
## Testing
`cargo run -p ci`
# Objective
- Systems that use the task pool, either explicitly or implicitly using
parallel queries, will often end up executing tasks from different
systems.
- This can cause random tasks to block the main or render schedule at
random, adding frame variance and increasing frame times when CPU bound.
- This profile is a common occurrence on `main`.
`propagate_parent_transforms` takes more than twice as long as it
should, blocking the main schedule for that time, because it uses `task
pool.scope`, which has decided to execute tasks from the render schedule
on the main schedule.

## Solution
- In task pool scope execution, prefer to check if the current task is
complete instead of ticking the executor to find new work.
## Testing
- Ran the scene viewer with tracy to look for images like the one in the
objective section.
- Things look much, much better, and I could not find any occurrences:


# Objective
- Fixes#16416
## Solution
- Add a intermediate temporary mutable `RequiredComponents` to get avoid
of the borrowing issues.
## Testing
- I have run `cargo test --package bevy_ecs -- --exact --show-output`
and past all the tests.
# Objective
- Attempts to fix#17876.
## Solution
- Reverted some changes that added a glob pattern to match all
`compile_fail` crates. This should enable Dependabot to create PRs
again.
- Added a TODO comment to not forget that this glob matching failure
should also be fixed in the Dependabot repo.
## Objective
The closure argument for
`EntityClonerBuilder::without_required_components` has `Send + Sync +
'static` bounds, but the closure immediately gets called and never needs
to be sent anywhere. (This was my fault :P )
## Solution
Remove the bounds so that users aren't unnecessarily restricted.
I also took the opportunity to expand the tests a little.
# Objective
- next step for #15918
## Solution
- Move jobs for macOS, Linux and Windows to their own workflow
- Remove running on push to `main` from workflows CI and validation
# Objective
This prevents overflowing the `last_trigger_id` property that leads to a
panic in debug mode.
```bash
panicked at C:\XXX\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.15.2\src\world\unsafe_world_cell.rs:630:18:
attempt to add with overflow
Encountered a panic when applying buffers for system `bevy_sprite::calculate_bounds_2d`!
Encountered a panic in system `bevy_ecs::schedule::executor::apply_deferred`!
```
## Solution
As this value is only used for detecting a change, we can wrap when it
reaches max value.
## Testing
This can be verified by running `cargo run --example observers`
# Objective
Closes#17572
## Solution
Add the `add_one_related` methods to `EntityCommands` and
`EntityWorldMut`.
## Testing
Clippy
---
## Showcase
The `EntityWorldMut` and `FilteredResourcesMut` now include the
`add_one_related` method if you just want to relate 2 entities.
# Objective
It's not always obvious when the issue created by the weekly CI run is
safe to close.
## Solution
Automatically close it when a weekly CI run succeeds so it doesn't get
forgotten.
## Testing
Hope.
Currently, we reload a glTF skin each time we encounter a node that
references it. By checking for duplicates, PR #18013 turned this into a
fatal error. But this was always wasteful. This commit fixes the issue
by caching each skin by its index as we load it.
The Maya babylon.js export plugin likes to emit glTFs with multiple
nodes that reference the same skin, so this effectively unbreaks Maya
rigs.
# Objective
* Fixes https://github.com/bevyengine/bevy/issues/14074
* Applies CI fixes for #16326
It is currently not possible to issues a trigger that targets a specific
list of components AND a specific list of entities
## Solution
We can now use `((A, B), (entity_1, entity_2))` as a trigger target, as
well as the reverse
## Testing
Added a unit test.
The triggering rules for observers are quite confusing:
Triggers once per entity target
For each entity target, an observer system triggers if any of its
components matches the trigger target components (but it triggers at
most once, since we use an internal counter to make sure that an
observer can run at most once per entity target)
(copied from #14563)
(copied from #16326)
## Notes
All credit to @BenjaminBrienen and @cBournhonesque! Just applying a
small fix to this PR so it can be merged.
---------
Co-authored-by: Benjamin Brienen <Benjamin.Brienen@outlook.com>
Co-authored-by: Christian Hughes <xdotdash@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
- Makes #18010 more easily debuggable. This doesn't solve that issue,
but protects us from it in the future.
## Solution
- Make `LoadContext::add_labeled_asset` and friends return an error if
it finds a duplicate asset.
## Testing
- Added a test - it fails before the fix.
---
## Migration Guide
- `AssetLoader`s must now handle the case of a duplicate subasset label
when using `LoadContext::add_labeled_asset` and its variants. If you
know your subasset labels are unique by construction (e.g., they include
an index number), you can simply unwrap this result.
Even though opaque deferred entities aren't placed into the `Opaque3d`
bin, we still want to cache them as though they were, so that we don't
have to re-queue them every frame. This commit implements that logic,
reducing the time of `queue_material_meshes` to near-zero on Caldera.
Currently, the structure-level `#[uniform]` attribute of `AsBindGroup`
creates a binding array of individual buffers, each of which contains
data for a single material. A more efficient approach would be to
provide a single buffer with an array containing all of the data for all
materials in the bind group. Because `StandardMaterial` uses
`#[uniform]`, this can be notably inefficient with large numbers of
materials.
This patch introduces a new attribute on `AsBindGroup`, `#[data]`, which
works identically to `#[uniform]` except that it concatenates all the
data into a single buffer that the material bind group allocator itself
manages. It also converts `StandardMaterial` to use this new
functionality. This effectively provides the "material data in arrays"
feature.
# Objective
Continuation of #17589 and #16547.
`get_many` is last of the `many` methods with a missing `unique`
counterpart.
It both takes and returns arrays, thus necessitates a matching
`UniqueEntityArray` type!
Plus, some slice methods involve returning arrays, which are currently
missing from `UniqueEntitySlice`.
## Solution
Add the type, the related methods and trait impls.
Note that for this PR, we abstain from some methods/trait impls that
create `&mut UniqueEntityArray`, because it can be successfully
mem-swapped. This can potentially invalidate a larger slice, which is
the same reason we punted on some mutable slice methods in #17589. We
can follow-up on all of these together in a following PR.
The new `unique_array` module is not glob-exported, because the trait
alias `unique_array::IntoIter` would conflict with
`unique_vec::IntoIter`.
The solution for this is to make the various `unique_*` modules public,
which I intend to do in yet another PR.
# Objective
Fixes#17945
## Solution
Check if the view being extracted has OIT enabled and incorporate the
associated bit into the mesh pipeline key.
I basically have no idea what's going on in the renderer, so let me know
if I missed something, which is extraordinarily possible.
## Testing
I modified the `order_independent_transparency` example to put
everything on the default render layer and render a gizmo at the origin.
Previously, this would cause the application to panic.
# Objective
- Fixes#17897.
## Solution
- When removing components, we filter the list of components in the
removed bundle based on whether they are actually in the archetype.
## Testing
- Added a test.
# Objective
Allow prepass to run without ATTRIBUTE_NORMAL.
This is needed for custom materials with non-standard vertex attributes.
For example a voxel material with manually packed vertex data.
Fixes#13054.
This PR covers the first part of the **stale** PR #13569 to only focus
on fixing #13054.
## Solution
- Only push normals `vertex_attributes` when the layout contains
`Mesh::ATTRIBUTE_NORMAL`
## Testing
- Did you test these changes? If so, how?
**Tested the fix on my own project with a mesh without normal
attribute.**
- Are there any parts that need more testing?
**I don't think so.**
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
**Prepass should not be blocked on a mesh without normal attributes
(with or without custom material).**
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
**Probably irrelevant, but Windows/Vulkan.**
# Objective
Implements and closes#17515
## Solution
Add `uv_transform` to `ColorMaterial`
## Testing
Create a example similar to `repeated_texture` but for `Mesh2d` and
`MeshMaterial2d<ColorMaterial>`
## Showcase

## Migration Guide
Add `uv_transform` field to constructors of `ColorMaterial`
# Objective
I noticed when I was looking at the embedded assets example that there
wasn't any comments on it to indicate what an embedded asset is and why
anyone would want to make one.
## Solution
I added some more comments to the example that gives more detail about
embedded assets and how they work. Feel free to be aggressive with
rewriting these comments however, I just think the example could use
something haha.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fix https://github.com/bevyengine/bevy/issues/17108
See
https://github.com/bevyengine/bevy/issues/17108#issuecomment-2653020889
## Solution
- Make the query match `&Pickable` instead `Option<&Pickable>`
## Testing
- Run the `sprite_picking` example and everything still work
## Migration Guide
- Sprite picking are now opt-in, make sure you insert `Pickable`
component when using sprite picking.
```diff
-commands.spawn(Sprite { .. } );
+commands.spawn((Sprite { .. }, Pickable::default());
```
# Objective
Fixes#17761
## Solution
- Added core error to InvalidDirectionError
## Testing
- Did you test these changes? If so, how?
- An added test that pulls in anyhow as a dev dependency to ensure the
conversion is accounted for in creation via From
- Are there any parts that need more testing?
- I'm unsure but probably not due to being a trivial change
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- I did not try a fully built version of Bevy. Relied purely on tests.
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
- Only windows
---------
Co-authored-by: Chanceler Shaffer <cshaffer2@lululemon.com>
Co-authored-by: Chanceler Shaffer <chancelershaffer@lululemon.com>
# Objective
A `TransparentUI` phase's items all target the same camera so there is
no need to store the current camera entity in `UiBatch` and ending the
current `UiBatch` on camera changes is pointless as the camera doesn't
change.
## Solution
Remove the `camera` fields from `UiBatch`, `UiShadowsBatch` and
`UiTextureSliceBatch`.
Remove the camera changed check from `prepare_uinodes`.
## Testing
The `multiple_windows` and `split_screen` examples both render UI
elements to multiple cameras and can be used to test these changes.
The UI material plugin already didn't store the camera entity per batch
and worked fine without it.
# Objective
- Contributes to #15460
- Reduce quantity and complexity of feature gates across Bevy
## Solution
- Used `target_has_atomic` configuration variable to automatically
detect impartial atomic support and automatically switch to
`portable-atomic` over the standard library on an as-required basis.
## Testing
- CI
## Notes
To explain the technique employed here, consider getting `Arc` either
from `alloc::sync` _or_ `portable-atomic-util`. First, we can inspect
the `alloc` crate to see that you only have access to `Arc` _if_
`target_has_atomic = "ptr"`. We add a target dependency for this
particular configuration _inverted_:
```toml
[target.'cfg(not(target_has_atomic = "ptr"))'.dependencies]
portable-atomic-util = { version = "0.2.4", default-features = false }
```
This ensures we only have the dependency when it is needed, and it is
entirely excluded from the dependency graph when it is not. Next, we
adjust our configuration flags to instead of checking for `feature =
"portable-atomic"` to instead check for `target_has_atomic = "ptr"`:
```rust
// `alloc` feature flag hidden for brevity
#[cfg(not(target_has_atomic = "ptr"))]
use portable_atomic_util as arc;
#[cfg(target_has_atomic = "ptr")]
use alloc::sync as arc;
pub use arc::{Arc, Weak};
```
The benefits of this technique are three-fold:
1. For platforms without full atomic support, the functionality is
enabled automatically.
2. For platforms with atomic support, the dependency is never included,
even if a feature was enabled using `--all-features` (for example)
3. The `portable-atomic` feature no longer needs to virally spread to
all user-facing crates, it's instead something handled within
`bevy_platform_support` (with some extras where other dependencies also
need their features enabled).
# Objective
- The previous implementation of automatically inserting sync points did
not consider explicitly added sync points. This created additional sync
points. For example:
```
A-B
C-D-E
```
If `A` and `B` needed a sync point, and `D` was an `ApplyDeferred`, an
additional sync point would be generated between `A` and `B`.
```
A-D2-B
C-D -E
```
This can result in the following system ordering:
```
A-D2-(B-C)-D-E
```
Where only `B` and `C` run in parallel. If we could reuse `D` as the
sync point, we would get the following ordering:
```
(A-C)-D-(B-E)
```
Now we have two more opportunities for parallelism!
## Solution
- In the first pass, we:
- Compute the number of sync points before each node
- This was already happening but now we consider `ApplyDeferred` nodes
as creating a sync point.
- Pick an arbitrary explicit `ApplyDeferred` node for each "sync point
index" that we can (some required sync points may be missing!)
- In the second pass, we:
- For each edge, if two nodes have a different number of sync points
before them then there must be a sync point between them.
- Look for an explicit `ApplyDeferred`. If one exists, use it as the
sync point.
- Otherwise, generate a new sync point.
I believe this should also gracefully handle changes to the
`ScheduleGraph`. Since automatically inserted sync points are inserted
as systems, they won't look any different to explicit sync points, so
they are also candidates for "reusing" sync points.
One thing this solution does not handle is "deduping" sync points. If
you add 10 sync points explicitly, there will be at least 10 sync
points. You could keep track of all the sync points at the same
"distance" and then hack apart the graph to dedup those, but that could
be a follow-up step (and it's more complicated since you have to worry
about transferring edges between nodes).
## Testing
- Added a test to test the feature.
- The existing tests from all our crates still pass.
## Showcase
- Automatically inserted sync points can now reuse explicitly inserted
`ApplyDeferred` systems! Previously, Bevy would add new sync points
between systems, ignoring the explicitly added sync points. This would
reduce parallelism of systems in some situations. Now, the parallelism
has been improved!
# Objective
- Closes#12944.
## Solution
- Load `R8G8B8` textures by transcoding to an rgba format since `wgpu`
does not support texture formats with 3 channels.
- Switch to erroring out instead of panicking on an invalid dds file.
---
## Changelog
### Added
- DDS Textures with the `R8G8B8` format are now supported. They require
an additional conversion step, so using `R8G8B8A8` or a similar format
is preferable for texture loading performance.
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.29.7 to
1.29.9.
<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.29.9</h2>
<h2>[1.29.9] - 2025-02-20</h2>
<h3>Fixes</h3>
<ul>
<li><em>(action)</em> Correctly get binary for some aarch64 systems</li>
</ul>
<h2>v1.29.8</h2>
<h2>[1.29.8] - 2025-02-19</h2>
<h3>Features</h3>
<ul>
<li>Attempt to build Linux aarch64 binaries</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.29.9] - 2025-02-20</h2>
<h3>Fixes</h3>
<ul>
<li><em>(action)</em> Correctly get binary for some aarch64 systems</li>
</ul>
<h2>[1.29.8] - 2025-02-19</h2>
<h3>Features</h3>
<ul>
<li>Attempt to build Linux aarch64 binaries</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="212923e4ff"><code>212923e</code></a>
chore: Release</li>
<li><a
href="659bf55253"><code>659bf55</code></a>
docs: Update changelog</li>
<li><a
href="092b7056bb"><code>092b705</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1239">#1239</a>
from codingskynet/fix/support-aarch64</li>
<li><a
href="298a143ed0"><code>298a143</code></a>
chore(gh): Fix links</li>
<li><a
href="d7059d7796"><code>d7059d7</code></a>
chore(gh): Fix links</li>
<li><a
href="636d59beef"><code>636d59b</code></a>
chore(gh): Encourage people to check for dupes</li>
<li><a
href="51cd88f328"><code>51cd88f</code></a>
chore(gh): Add a data template</li>
<li><a
href="c11cf6c0e1"><code>c11cf6c</code></a>
chore(gh): Try to clarify template</li>
<li><a
href="3bcb919148"><code>3bcb919</code></a>
fix: add aarch64 on arm64 cond</li>
<li><a
href="1ea66fdf4d"><code>1ea66fd</code></a>
docs(readme): Call out that the readme is not exhaustive</li>
<li>Additional commits viewable in <a
href="https://github.com/crate-ci/typos/compare/v1.29.7...v1.29.9">compare
view</a></li>
</ul>
</details>
<br />
[](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>
# Objective
- Fixes#17960
## Solution
- Followed the [edition upgrade
guide](https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html)
## Testing
- CI
---
## Summary of Changes
### Documentation Indentation
When using lists in documentation, proper indentation is now linted for.
This means subsequent lines within the same list item must start at the
same indentation level as the item.
```rust
/* Valid */
/// - Item 1
/// Run-on sentence.
/// - Item 2
struct Foo;
/* Invalid */
/// - Item 1
/// Run-on sentence.
/// - Item 2
struct Foo;
```
### Implicit `!` to `()` Conversion
`!` (the never return type, returned by `panic!`, etc.) no longer
implicitly converts to `()`. This is particularly painful for systems
with `todo!` or `panic!` statements, as they will no longer be functions
returning `()` (or `Result<()>`), making them invalid systems for
functions like `add_systems`. The ideal fix would be to accept functions
returning `!` (or rather, _not_ returning), but this is blocked on the
[stabilisation of the `!` type
itself](https://doc.rust-lang.org/std/primitive.never.html), which is
not done.
The "simple" fix would be to add an explicit `-> ()` to system
signatures (e.g., `|| { todo!() }` becomes `|| -> () { todo!() }`).
However, this is _also_ banned, as there is an existing lint which (IMO,
incorrectly) marks this as an unnecessary annotation.
So, the "fix" (read: workaround) is to put these kinds of `|| -> ! { ...
}` closuers into variables and give the variable an explicit type (e.g.,
`fn()`).
```rust
// Valid
let system: fn() = || todo!("Not implemented yet!");
app.add_systems(..., system);
// Invalid
app.add_systems(..., || todo!("Not implemented yet!"));
```
### Temporary Variable Lifetimes
The order in which temporary variables are dropped has changed. The
simple fix here is _usually_ to just assign temporaries to a named
variable before use.
### `gen` is a keyword
We can no longer use the name `gen` as it is reserved for a future
generator syntax. This involved replacing uses of the name `gen` with
`r#gen` (the raw-identifier syntax).
### Formatting has changed
Use statements have had the order of imports changed, causing a
substantial +/-3,000 diff when applied. For now, I have opted-out of
this change by amending `rustfmt.toml`
```toml
style_edition = "2021"
```
This preserves the original formatting for now, reducing the size of
this PR. It would be a simple followup to update this to 2024 and run
`cargo fmt`.
### New `use<>` Opt-Out Syntax
Lifetimes are now implicitly included in RPIT types. There was a handful
of instances where it needed to be added to satisfy the borrow checker,
but there may be more cases where it _should_ be added to avoid
breakages in user code.
### `MyUnitStruct { .. }` is an invalid pattern
Previously, you could match against unit structs (and unit enum
variants) with a `{ .. }` destructuring. This is no longer valid.
### Pretty much every use of `ref` and `mut` are gone
Pattern binding has changed to the point where these terms are largely
unused now. They still serve a purpose, but it is far more niche now.
### `iter::repeat(...).take(...)` is bad
New lint recommends using the more explicit `iter::repeat_n(..., ...)`
instead.
## Migration Guide
The lifetimes of functions using return-position impl-trait (RPIT) are
likely _more_ conservative than they had been previously. If you
encounter lifetime issues with such a function, please create an issue
to investigate the addition of `+ use<...>`.
## Notes
- Check the individual commits for a clearer breakdown for what
_actually_ changed.
---------
Co-authored-by: François Mockers <francois.mockers@vleue.com>
# Objective
`Eq`/`PartialEq` are currently implemented for `MeshMaterial{2|3}d` only
through the derive macro. Since we don't have perfect derive yet, the
impls are only present for `M: Eq` and `M: PartialEq`. On the other
hand, I want to be able to compare material components for my toy
reactivity project.
## Solution
Switch to manual `Eq`/`PartialEq` impl.
## Testing
Boy I hope this didn't break anything!
# Objective
Fixes#17488
## Solution
The world update logic happened in the the `about_to_wait` winit window
callback, but this is is not correct as (1) the winit documentation
states that the callback should not be used for that purpose and (2) the
callback is not fired when the window is resized or being dragged.
However, that callback was used in #11245 to fix an iOS bug (which
caused the regression). The solution presented here is a workaround
until the event loop code can be re-written.
## Testing
I confirmed that the `eased_motion` example continued to be animated
when dragging or resizing the window.
https://github.com/user-attachments/assets/ffaf0abf-4cd7-479b-83e9-e1850aaf3513
- Remove references to the short-lived `CommandError` type.
- Add a sentence to the explanation of error handlers.
- Clean up spacing/linebreaks.
- Use `where` notation for command-related trait `impl`s to make the big
ones easier to parse.
Fixes#17856.
## Migration Guide
- `EventWriter::send` has been renamed to `EventWriter::write`.
- `EventWriter::send_batch` has been renamed to
`EventWriter::write_batch`.
- `EventWriter::send_default` has been renamed to
`EventWriter::write_default`.
---------
Co-authored-by: François Mockers <mockersf@gmail.com>
# Objective
- Make transform propagation faster.
## Solution
- Work sharing worker threads
- Parallel tree traversal excluding leaves
- Second cache friendly wide pass over all leaves
- 3-10x faster than main
## Testing
- Tracy
- Caldera hotel is showing 3-7x faster on my M4 Max. Timing for bevy's
existing transform system shifts wildly run to run, so I don't know that
I would advertise a particular number. But this implementation is faster
in a... statistically significant way.

---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
PR #17898 regressed this, causing much of #17970. This commit fixes the
issue by freeing and reallocating materials in the
`MaterialBindGroupAllocator` on change. Note that more efficiency is
possible, but I opted for the simple approach because (1) we should fix
this bug ASAP; (2) I'd like #17965 to land first, because that unlocks
the biggest potential optimization, which is not recreating the bind
group if it isn't necessary to do so.
We might not be able to prepare a material on the first frame we
encounter a mesh using it for various reasons, including that the
material hasn't been loaded yet or that preparing the material is
exceeding the per-frame cap on number of bytes to load. When this
happens, we currently try to find the material in the
`MaterialBindGroupAllocator`, fail, and then fall back to group 0, slot
0, the default `MaterialBindGroupId`, which is obviously incorrect.
Worse, we then fail to dirty the mesh and reextract it when we *do*
finish preparing the material, so the mesh will continue to be rendered
with an incorrect material.
This patch fixes both problems. In `collect_meshes_for_gpu_building`, if
we fail to find a mesh's material in the `MeshBindGroupAllocator`, then
we detect that case, bail out, and add it to a list,
`MeshesToReextractNextFrame`. On subsequent frames, we process all the
meshes in `MeshesToReextractNextFrame` as though they were changed. This
ensures both that we don't render a mesh if its material hasn't been
loaded and that we start rendering the mesh once its material does load.
This was first noticed in the intermittent Pixel Eagle failures in the
`testbed_3d` patch in #17898, although the problem has actually existed
for some time. I believe it just so happened that the changes to the
allocator in that PR caused the problem to appear more commonly than it
did before.
This patch fixes two bugs in the new non-bindless material allocator
that landed in PR #17898:
1. A debug assertion to prevent double frees had been flipped: we
checked to see whether the slot was empty before freeing, while we
should have checked to see whether the slot was full.
2. The non-bindless allocator returned `None` when querying a slab that
hadn't been prepared yet instead of returning a handle to that slab.
This resulted in a 1-frame delay when modifying materials. In the
`animated_material` example, this resulted in the meshes never showing
up at all, because that example changes every material every frame.
Together with #17979, this patch locally fixes the problems with
`animated_material` on macOS that were reported in #17970.
# Objective
Fixes#8615
## Solution
Bevy currently interprets 1x1 dds textures as 1-dimensional. I think it
might be more common for game engines to assume two dimensions in this
ambiguous case. [citation needed]
I reworked the dimension choosing logic to only use 1d if there's a
dimension > 1, and assume 2d otherwise. I kept the assumption that
compressed textures are probably 2d.
## Testing
Modified `sprite.rs` to use `Tex_0012_0.dds` from the linked issue.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
# Objective
Fix#17924
## Solution
Use fully qualified syntax (`usize::from` rather than `.into()`).
## Testing
Ran a build for the platform specified in the issue.
---------
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
# Objective
-
[`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces)
is a Clippy lint that enforces what braces certain known macros are
allowed to use.
- For instance, requiring `println!()` instead of `println!{}`.
- I started working on this after seeing
https://github.com/TheBevyFlock/bevy_cli/issues/277.
## Solution
- Enable `nonstandard_macro_braces` in the workspace.
- Configure Clippy so it enforces `[]` braces for `children!`.
## Testing
1. Create `examples/clippy_test.rs`.
2. Paste the following code:
```rust
//! Some docs woooooooo
use bevy::prelude::*;
fn main() {
let _ = children!(Name::new("Foo"));
}
```
3. Run `cargo clippy --example clippy_test`.
4. Ensure the following warning is emitted:
```sh
warning: use of irregular braces for `children!` macro
--> examples/clippy_test.rs:6:13
|
6 | let _ = children!(Name::new("Foo"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `children![Name::new("Foo")]`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
= note: requested on the command line with `-W clippy::nonstandard-macro-braces`
warning: `bevy` (example "clippy_test") generated 1 warning (run `cargo clippy --fix --example "clippy_test"` to apply 1 suggestion)
```
Fixes#17883
# Objective + Solution
When doing normal scene root entity despawns (which are notably now
recursive), do not despawn instanced entities that are no longer in the
hierarchy.
(I would not classify this as a bug, but rather a behavior change)
## Migration Guide
If you previously relied on scene entities no longer in the hierarchy
being despawned when the scene root is despawned , use
`SceneSpawner::despawn_instance()` instead.
# Objective
Calling `define_label!` in a `no_std` 3rd party crate currently requires
the user to import `Box` themselves due to a non-fully-specified
reference to `Box`.
## Solution
Add a fully specified path for `Box` in the one location necessary, to
match all of the other cases.
Two-phase occlusion culling can be helpful for shadow maps just as it
can for a prepass, in order to reduce vertex and alpha mask fragment
shading overhead. This patch implements occlusion culling for shadow
maps from directional lights, when the `OcclusionCulling` component is
present on the entities containing the lights. Shadow maps from point
lights are deferred to a follow-up patch. Much of this patch involves
expanding the hierarchical Z-buffer to cover shadow maps in addition to
standard view depth buffers.
The `scene_viewer` example has been updated to add `OcclusionCulling` to
the directional light that it creates.
This improved the performance of the rend3 sci-fi test scene when
enabling shadows.
Currently, Bevy's implementation of bindless resources is rather
unusual: every binding in an object that implements `AsBindGroup` (most
commonly, a material) becomes its own separate binding array in the
shader. This is inefficient for two reasons:
1. If multiple materials reference the same texture or other resource,
the reference to that resource will be duplicated many times. This
increases `wgpu` validation overhead.
2. It creates many unused binding array slots. This increases `wgpu` and
driver overhead and makes it easier to hit limits on APIs that `wgpu`
currently imposes tight resource limits on, like Metal.
This PR fixes these issues by switching Bevy to use the standard
approach in GPU-driven renderers, in which resources are de-duplicated
and passed as global arrays, one for each type of resource.
Along the way, this patch introduces per-platform resource limits and
bumps them from 16 resources per binding array to 64 resources per bind
group on Metal and 2048 resources per bind group on other platforms.
(Note that the number of resources per *binding array* isn't the same as
the number of resources per *bind group*; as it currently stands, if all
the PBR features are turned on, Bevy could pack as many as 496 resources
into a single slab.) The limits have been increased because `wgpu` now
has universal support for partially-bound binding arrays, which mean
that we no longer need to fill the binding arrays with fallback
resources on Direct3D 12. The `#[bindless(LIMIT)]` declaration when
deriving `AsBindGroup` can now simply be written `#[bindless]` in order
to have Bevy choose a default limit size for the current platform.
Custom limits are still available with the new
`#[bindless(limit(LIMIT))]` syntax: e.g. `#[bindless(limit(8))]`.
The material bind group allocator has been completely rewritten. Now
there are two allocators: one for bindless materials and one for
non-bindless materials. The new non-bindless material allocator simply
maintains a 1:1 mapping from material to bind group. The new bindless
material allocator maintains a list of slabs and allocates materials
into slabs on a first-fit basis. This unfortunately makes its
performance O(number of resources per object * number of slabs), but the
number of slabs is likely to be low, and it's planned to become even
lower in the future with `wgpu` improvements. Resources are
de-duplicated with in a slab and reference counted. So, for instance, if
multiple materials refer to the same texture, that texture will exist
only once in the appropriate binding array.
To support these new features, this patch adds the concept of a
*bindless descriptor* to the `AsBindGroup` trait. The bindless
descriptor allows the material bind group allocator to probe the layout
of the material, now that an array of `BindGroupLayoutEntry` records is
insufficient to describe the group. The `#[derive(AsBindGroup)]` has
been heavily modified to support the new features. The most important
user-facing change to that macro is that the struct-level `uniform`
attribute, `#[uniform(BINDING_NUMBER, StandardMaterial)]`, now reads
`#[uniform(BINDLESS_INDEX, MATERIAL_UNIFORM_TYPE,
binding_array(BINDING_NUMBER)]`, allowing the material to specify the
binding number for the binding array that holds the uniform data.
To make this patch simpler, I removed support for bindless
`ExtendedMaterial`s, as well as field-level bindless uniform and storage
buffers. I intend to add back support for these as a follow-up. Because
they aren't in any released Bevy version yet, I figured this was OK.
Finally, this patch updates `StandardMaterial` for the new bindless
changes. Generally, code throughout the PBR shaders that looked like
`base_color_texture[slot]` now looks like
`bindless_2d_textures[material_indices[slot].base_color_texture]`.
This patch fixes a system hang that I experienced on the [Caldera test]
when running with `caldera --random-materials --texture-count 100`. The
time per frame is around 19.75 ms, down from 154.2 ms in Bevy 0.14: a
7.8× speedup.
[Caldera test]: https://github.com/DGriffin91/bevy_caldera_scene
Deferred rendering currently doesn't support occlusion culling. This PR
implements it in a straightforward way, mirroring what we already do for
the non-deferred pipeline.
On the rend3 sci-fi base test scene, this resulted in roughly a 2×
speedup when applied on top of my other patches. For that scene, it was
useful to add another option, `--add-light`, which forces the addition
of a shadow-casting light, to the scene viewer, which I included in this
patch.
This commit restructures the multidrawable batch set builder for better
performance in various ways:
* The bin traversal is optimized to make the best use of the CPU cache.
* The inner loop that iterates over the bins, which is the hottest part
of `batch_and_prepare_binned_render_phase`, has been shrunk as small as
possible.
* Where possible, multiple elements are added to or reserved from GPU
buffers as a batch instead of one at a time.
* Methods that LLVM wasn't inlining have been marked `#[inline]` where
doing so would unlock optimizations.
This code has also been refactored to avoid duplication between the
logic for indexed and non-indexed meshes via the introduction of a
`MultidrawableBatchSetPreparer` object.
Together, this improved the `batch_and_prepare_binned_render_phase` time
on Caldera by approximately 2×.
Eventually, we should optimize the batchable-but-not-multidrawable and
unbatchable logic as well, but these meshes are much rarer, so in the
interests of keeping this patch relatively small I opted to leave those
to a follow-up.