Commit graph

6065 commits

Author SHA1 Message Date
Hexorg
7a9a459a40
Fixed crash when transcoding one- or two-channel KTX2 textures (#12629)
# Objective

Fixes a crash when transcoding one- or two-channel KTX2 textures

## Solution

transcoded array has been pre-allocated up to levels.len using a macros.
Rgb8 transcoding already uses that and addresses transcoded array by an
index. R8UnormSrgb and Rg8UnormSrgb were pushing on top of the
transcoded vec, resulting in first levels.len() vectors to stay empty,
and second levels.len() levels actually being transcoded, which then
resulted in out of bounds read when copying levels to gpu
2024-04-14 14:40:10 +00:00
BD103
a362c278bb
Fix crates not building individually (#12948)
# Objective

- `cargo check --workspace` appears to merge features and dependencies
together, so it does not catch some issues where dependencies are not
properly feature-gated.
- The issues **are** caught, though, by running `cd $crate && cargo
check`.

## Solution

- Manually check each crate for issues.

```shell
# Script used
for i in crates/bevy_* do
    pushd $i
    cargo check
    popd
done
```

- `bevy_color` had an issue where it used `#[derive(Pod, Zeroable)]`
without using `bytemuck`'s `derive` feature.
- The `FpsOverlayPlugin` in `bevy_dev_tools` uses `bevy_ui`'s
`bevy_text` integration without properly enabling `bevy_text` as a
feature.
- `bevy_gizmos`'s `light` module was not properly feature-gated behind
`bevy_pbr`.
- ~~Lights appear to only be implemented in `bevy_pbr` and not
`bevy_sprite`, so I think this is the right call. Can I get a
confirmation by a gizmos person?~~ Confirmed :)
- `bevy_gltf` imported `SmallVec`, but only used it if `bevy_animation`
was enabled.
- There was another issue, but it was more challenging to solve than the
`smallvec` one. Run `cargo check -p bevy_gltf` and it will raise an
issue about `animation_roots`.

<details>
  <summary><code>bevy_gltf</code> errors</summary>

```shell
error[E0425]: cannot find value `animation_roots` in this scope
   --> crates/bevy_gltf/src/loader.rs:608:26
    |
608 |                         &animation_roots,
    |                          ^^^^^^^^^^^^^^^ not found in this scope

warning: variable does not need to be mutable
    --> crates/bevy_gltf/src/loader.rs:1015:5
     |
1015 |     mut animation_context: Option<AnimationContext>,
     |     ----^^^^^^^^^^^^^^^^^
     |     |
     |     help: remove this `mut`
     |
     = note: `#[warn(unused_mut)]` on by default

For more information about this error, try `rustc --explain E0425`.
warning: `bevy_gltf` (lib) generated 1 warning
error: could not compile `bevy_gltf` (lib) due to 1 previous error; 1 warning emitted
```

</details> 

---

## Changelog

- Fixed `bevy_color`, `bevy_dev_tools`, and `bevy_gizmos` so they can
now compile by themselves.
2024-04-14 00:06:03 +00:00
BD103
380b35cee6
Create custom action for installing Linux dependencies (#12850)
# Objective

- There are several occurrences where different actions install alsa,
udev, and various other libraries for Linux.
- This is repetitive and can be an issue if the dependencies required by
Bevy ever change.

## Solution

- Create a custom action for installing Linux dependencies.
- It can be used by adding `- uses:
./.github/actions/install-linux-deps`.
- It supports configuring which libraries are installed using the `with`
property.
- It does nothing if not run on Linux, so workflows don't need to worry
about adding `if: ${{ runner.os == 'linux' }}`.

## Discussion

- The only instance where this action is not used cleanly is for the
`run-examples-linux-vulkan` verification job. I need to investigate
further the flags and dependencies that it installs.
2024-04-13 22:34:48 +00:00
blukai
9622557093
fix find_current_keyframe panic (#12931)
# Objective

i downloaded a random model from sketchfab
(https://sketchfab.com/3d-models/dragon-glass-fe00cb0ecaca4e4595874b70de7e116b)
to fiddle with bevy and encountered a panic when attempted to play
animations:
```
thread 'Compute Task Pool (3)' panicked at /home/username/code/bevy/crates/bevy_animation/src/lib.rs:848:58:
index out of bounds: the len is 40 but the index is 40
```

"Animation / Animated Fox"
(5caf085dac/examples/animation/animated_fox.rs)
example can be used for reproduction. to reproduce download a model from
sketchfab (link above) and load it instead of loading fox.glb, keep only
`dragon_glass.glb#Animation0` and remove `1` and `2` -> run and wait 1-2
seconds for crash to happen.

## Solution

correct keyframe indexing, i guess
2024-04-13 22:32:21 +00:00
Patrick Walton
363210f8fe
Don't examine every entity when extracting SpriteSources. (#12957)
`ExtractComponentPlugin` doesn't check to make sure the component is
actually present unless it's in the `QueryFilter`. This meant we placed
it everywhere. This regressed performance on many examples, such as
`many_cubes`.

Fixes #12956.
2024-04-13 22:25:37 +00:00
James Liu
60e400b22f
Remove the system task span (#12950)
# Objective
The system task span is pretty consistent in how much time it uses, so
all it adds is overhead/additional bandwidth when profiling.

## Solution
Remove it.
2024-04-13 19:27:11 +00:00
Patrick Walton
8577a448f7
Fix rendering of sprites, text, and meshlets after #12582. (#12945)
`Sprite`, `Text`, and `Handle<MeshletMesh>` were types of renderable
entities that the new segregated visible entity system didn't handle, so
they didn't appear.

Because `bevy_text` depends on `bevy_sprite`, and the visibility
computation of text happens in the latter crate, I had to introduce a
new marker component, `SpriteSource`. `SpriteSource` marks entities that
aren't themselves sprites but become sprites during rendering. I added
this component to `Text2dBundle`. Unfortunately, this is technically a
breaking change, although I suspect it won't break anybody in practice
except perhaps editors.

Fixes #12935.

## Changelog

### Changed

* `Text2dBundle` now includes a new marker component, `SpriteSource`.
Bevy uses this internally to optimize visibility calculation.

## Migration Guide

* `Text` now requires a `SpriteSource` marker component in order to
appear. This component has been added to `Text2dBundle`.
2024-04-13 14:15:00 +00:00
James Liu
ae9775c83b
Optimize Event Updates (#12936)
# Objective
Improve performance scalability when adding new event types to a Bevy
app. Currently, just using Bevy in the default configuration, all apps
spend upwards of 100+us in the `First` schedule, every app tick,
evaluating if it should update events or not, even if events are not
being used for that particular frame, and this scales with the number of
Events registered in the app.

## Solution
As `Events::update` is guaranteed `O(1)` by just checking if a
resource's value, swapping two Vecs, and then clearing one of them, the
actual cost of running `event_update_system` is *very* cheap. The
overhead of doing system dependency injection, task scheduling ,and the
multithreaded executor outweighs the cost of running the system by a
large margin.

Create an `EventRegistry` resource that keeps a number of function
pointers that update each event. Replace the per-event type
`event_update_system` with a singular exclusive system uses the
`EventRegistry` to update all events instead. Update `SubApp::add_event`
to use `EventRegistry` instead.

## Performance
This speeds reduces the cost of the `First` schedule in both many_foxes
and many_cubes by over 80%. Note this is with system spans on. The
majority of this is now context-switching costs from launching
`time_system`, which should be mostly eliminated with #12869.

![image](https://github.com/bevyengine/bevy/assets/3137680/037624be-21a2-4dc2-a42f-9d0bfa3e9b4a)

The actual `event_update_system` is usually *very* short, using only a
few microseconds on average.

![image](https://github.com/bevyengine/bevy/assets/3137680/01ff1689-3595-49b6-8f09-5c44bcf903e8)

---

## Changelog
TODO

## Migration Guide
TODO

---------

Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-04-13 14:11:28 +00:00
NiseVoid
57719fc998
Add archetypal to Access Debug impl (#12947)
# Objective

- The `archetypal` field in `Access` doesn't get printed in debug output

## Solution

- Add the field to the impl
2024-04-13 06:06:48 +00:00
Ycy
70ce6f110b
fix bevy_hierarchy crate optional feature bevy_app (#12943)
fix bevy_hierarchy crate optional feature `bevy_app`
2024-04-13 04:46:00 +00:00
BD103
aa2ebbb43f
Fix some nightly Clippy lints (#12927)
# Objective

- I daily drive nightly Rust when developing Bevy, so I notice when new
warnings are raised by `cargo check` and Clippy.
- `cargo +nightly clippy` raises a few of these new warnings.

## Solution

- Fix most warnings from `cargo +nightly clippy`
- I skipped the docs-related warnings because some were covered by
#12692.
- Use `Clone::clone_from` in applicable scenarios, which can sometimes
avoid an extra allocation.
- Implement `Default` for structs that have a `pub const fn new() ->
Self` method.
- Fix an occurrence where generic constraints were defined in both `<C:
Trait>` and `where C: Trait`.
  - Removed generic constraints that were implied by the `Bundle` trait.

---

## Changelog

- `BatchingStrategy`, `NonGenericTypeCell`, and `GenericTypeCell` now
implement `Default`.
2024-04-13 02:05:38 +00:00
Gino Valente
78345a2f7a
tools: Refactor CI to use argh (#12923)
# Objective

The CI tool currently parses input manually. This has worked fine, but
makes it just a bit more difficult to maintain and extend. Additionally,
it provides no usage help for devs wanting to run the tool locally.

It would be better if parsing was handled by a dedicated CLI library
like [`clap`](https://github.com/clap-rs/clap) or
[`argh`](https://github.com/google/argh).

## Solution

Use `argh` to parse command line input for CI.

`argh` was chosen over `clap` and other tools due to being more
lightweight and already existing in our dependency tree.

Using `argh`, the usage notes are generated automatically:

```
$ cargo run -p ci --quiet -- --help
Usage: ci [--keep-going] [<command>] [<args>]

The CI command line tool for Bevy.

Options:
  --keep-going      continue running commands even if one fails
  --help            display usage information

Commands:
  lints             Alias for running the `format` and `clippy` subcommands.
  doc               Alias for running the `doc-test` and `doc-check`
                    subcommands.
  compile           Alias for running the `compile-fail`, `bench-check`,
                    `example-check`, `compile-check`, and `test-check`
                    subcommands.
  format            Check code formatting.
  clippy            Check for clippy warnings and errors.
  test              Runs all tests (except for doc tests).
  test-check        Checks that all tests compile.
  doc-check         Checks that all docs compile.
  doc-test          Runs all doc tests.
  compile-check     Checks that the project compiles.
  cfg-check         Checks that the project compiles using the nightly compiler
                    with cfg checks enabled.
  compile-fail      Runs the compile-fail tests.
  bench-check       Checks that the benches compile.
  example-check     Checks that the examples compile.
```

This PR makes each subcommand more modular, allowing them to be called
from other subcommands. This also makes it much easier to extract them
out of `main.rs` and into their own dedicated modules.

Additionally, this PR improves failure output:

```
$ cargo run -p ci -- lints
...
One or more CI commands failed:
format: Please run 'cargo fmt --all' to format your code.
```

Including when run with the `--keep-going` flag:

```
$ cargo run -p ci -- --keep-going lints
...
One or more CI commands failed:
- format: Please run 'cargo fmt --all' to format your code.
- clippy: Please fix clippy errors in output above.
```

### Future Work

There are a lot of other things we could possibly clean up. I chose to
try and keep the API surface as unchanged as I could (for this PR at
least).

For example, now that each subcommand is an actual command, we can
specify custom arguments for each.

The `format` subcommand could include a `--check` (making the default
fun `cargo fmt` as normal). Or the `compile-fail` subcommand could
include `--ecs`, `--reflect`, and `--macros` flags for specifying which
set of compile fail tests to run.

The `--keep-going` flag could be split so that it doesn't do double-duty
where it also enables `--no-fail-fast` for certain commands. Or at least
make it more explicit via renaming or using alternative flags.

---

## Changelog

- Improved the CI CLI tool
  - Now includes usage info with the `--help` option!
- [Internal] Cleaned up and refactored the `tools/ci` crate using the
`argh` crate

## Migration Guide

The CI tool no longer supports running multiple subcommands in a single
call. Users who are currently doing so will need to split them across
multiple commands:

```bash
# BEFORE
cargo run -p ci -- lints doc compile

# AFTER
cargo run -p ci -- lints && cargo run -p ci -- doc && cargo run -p ci -- compile
# or
cargo run -p ci -- lints; cargo run -p ci -- doc; cargo run -p ci -- compile
# or
cargo run -p ci -- lints
cargo run -p ci -- doc
cargo run -p ci -- compile
```
2024-04-13 01:48:37 +00:00
Patrick Walton
5caf085dac
Divide the single VisibleEntities list into separate lists for 2D meshes, 3D meshes, lights, and UI elements, for performance. (#12582)
This commit splits `VisibleEntities::entities` into four separate lists:
one for lights, one for 2D meshes, one for 3D meshes, and one for UI
elements. This allows `queue_material_meshes` and similar methods to
avoid examining entities that are obviously irrelevant. In particular,
this separation helps scenes with many skinned meshes, as the individual
bones are considered visible entities but have no rendered appearance.

Internally, `VisibleEntities::entities` is a `HashMap` from the `TypeId`
representing a `QueryFilter` to the appropriate `Entity` list. I had to
do this because `VisibleEntities` is located within an upstream crate
from the crates that provide lights (`bevy_pbr`) and 2D meshes
(`bevy_sprite`). As an added benefit, this setup allows apps to provide
their own types of renderable components, by simply adding a specialized
`check_visibility` to the schedule.

This provides a 16.23% end-to-end speedup on `many_foxes` with 10,000
foxes (24.06 ms/frame to 20.70 ms/frame).

## Migration guide

* `check_visibility` and `VisibleEntities` now store the four types of
renderable entities--2D meshes, 3D meshes, lights, and UI
elements--separately. If your custom rendering code examines
`VisibleEntities`, it will now need to specify which type of entity it's
interested in using the `WithMesh2d`, `WithMesh`, `WithLight`, and
`WithNode` types respectively. If your app introduces a new type of
renderable entity, you'll need to add an explicit call to
`check_visibility` to the schedule to accommodate your new component or
components.

## Analysis

`many_foxes`, 10,000 foxes: `main`:
![Screenshot 2024-03-31
114444](https://github.com/bevyengine/bevy/assets/157897/16ecb2ff-6e04-46c0-a4b0-b2fde2084bad)

`many_foxes`, 10,000 foxes, this branch:
![Screenshot 2024-03-31
114256](https://github.com/bevyengine/bevy/assets/157897/94dedae4-bd00-45b2-9aaf-dfc237004ddb)

`queue_material_meshes` (yellow = this branch, red = `main`):
![Screenshot 2024-03-31
114637](https://github.com/bevyengine/bevy/assets/157897/f90912bd-45bd-42c4-bd74-57d98a0f036e)

`queue_shadows` (yellow = this branch, red = `main`):
![Screenshot 2024-03-31
114607](https://github.com/bevyengine/bevy/assets/157897/6ce693e3-20c0-4234-8ec9-a6f191299e2d)
2024-04-11 20:33:20 +00:00
BD103
5c3ae32ab1
Enable clippy::ref_as_ptr (#12918)
# Objective

-
[`clippy::ref_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#/ref_as_ptr)
prevents you from directly casting references to pointers, requiring you
to use `std::ptr::from_ref` instead. This prevents you from accidentally
converting an immutable reference into a mutable pointer (`&x as *mut
T`).
- Follow up to #11818, now that our [`rust-version` is
1.77](11817f4ba4/Cargo.toml (L14)).

## Solution

- Enable lint and fix all warnings.
2024-04-10 20:16:48 +00:00
Patrick Walton
d59b1e71ef
Implement percentage-closer filtering (PCF) for point lights. (#12910)
I ported the two existing PCF techniques to the cubemap domain as best I
could. Generally, the technique is to create a 2D orthonormal basis
using Gram-Schmidt normalization, then apply the technique over that
basis. The results look fine, though the shadow bias often needs
adjusting.

For comparison, Unity uses a 4-tap pattern for PCF on point lights of
(1, 1, 1), (-1, -1, 1), (-1, 1, -1), (1, -1, -1). I tried this but
didn't like the look, so I went with the design above, which ports the
2D techniques to the 3D domain. There's surprisingly little material on
point light PCF.

I've gone through every example using point lights and verified that the
shadow maps look fine, adjusting biases as necessary.

Fixes #3628.

---

## Changelog

### Added
* Shadows from point lights now support percentage-closer filtering
(PCF), and as a result look less aliased.

### Changed
* `ShadowFilteringMethod::Castano13` and
`ShadowFilteringMethod::Jimenez14` have been renamed to
`ShadowFilteringMethod::Gaussian` and `ShadowFilteringMethod::Temporal`
respectively.

## Migration Guide

* `ShadowFilteringMethod::Castano13` and
`ShadowFilteringMethod::Jimenez14` have been renamed to
`ShadowFilteringMethod::Gaussian` and `ShadowFilteringMethod::Temporal`
respectively.
2024-04-10 20:16:08 +00:00
Vitaliy Sapronenko
ddcbb3cc80
flipping texture coords methods has been added to the StandardMaterial (#12917)
# Objective

Fixes #11996 
The deprecated shape Quad's flip field role migrated to
StandardMaterial's flip/flipped methods

## Solution

flip/flipping methods of StandardMaterial is applicable to any mesh

---

## Changelog

- Added flip and flipped methods to the StandardMaterial implementation
- Added FLIP_HORIZONTAL, FLIP_VERTICAL, FLIP_X, FLIP_Y, FLIP_Z constants

## Migration Guide

Instead of using `Quad::flip` field, call `flipped(true, false)` method
on the StandardMaterial instance when adding the mesh.

---------

Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
2024-04-10 18:23:55 +00:00
Lynn
597799a979
Add tetrahedron gizmos (#12914)
# Objective

- Adds tetrahedron gizmos, suggestion of #9400

## Solution

- Implement tetrahedron gizmos as a `gizmos.primitive_3d`

## Additional info

Here is a short video of the default tetrahedron :)


https://github.com/bevyengine/bevy/assets/62256001/a6f31b6f-78bc-4dc2-8f46-2ebd04ed8a0e

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-04-10 17:59:58 +00:00
BD103
78c922509b
Small CI tool improvements (#12841)
# Objective

- The CI tool is slowly getting more difficult to maintain and could use
a bit of refactoring.

## Solution

- Do a first pass of small improvements.

## For Reviewers

This PR is best reviewed commit-by-commit, because I separate it into a
collection of small changes. :)
2024-04-10 14:29:05 +00:00
Patrick Walton
11817f4ba4
Generate MeshUniforms on the GPU via compute shader where available. (#12773)
Currently, `MeshUniform`s are rather large: 160 bytes. They're also
somewhat expensive to compute, because they involve taking the inverse
of a 3x4 matrix. Finally, if a mesh is present in multiple views, that
mesh will have a separate `MeshUniform` for each and every view, which
is wasteful.

This commit fixes these issues by introducing the concept of a *mesh
input uniform* and adding a *mesh uniform building* compute shader pass.
The `MeshInputUniform` is simply the minimum amount of data needed for
the GPU to compute the full `MeshUniform`. Most of this data is just the
transform and is therefore only 64 bytes. `MeshInputUniform`s are
computed during the *extraction* phase, much like skins are today, in
order to avoid needlessly copying transforms around on CPU. (In fact,
the render app has been changed to only store the translation of each
mesh; it no longer cares about any other part of the transform, which is
stored only on the GPU and the main world.) Before rendering, the
`build_mesh_uniforms` pass runs to expand the `MeshInputUniform`s to the
full `MeshUniform`.

The mesh uniform building pass does the following, all on GPU:

1. Copy the appropriate fields of the `MeshInputUniform` to the
`MeshUniform` slot. If a single mesh is present in multiple views, this
effectively duplicates it into each view.

2. Compute the inverse transpose of the model transform, used for
transforming normals.

3. If applicable, copy the mesh's transform from the previous frame for
TAA. To support this, we double-buffer the `MeshInputUniform`s over two
frames and swap the buffers each frame. The `MeshInputUniform`s for the
current frame contain the index of that mesh's `MeshInputUniform` for
the previous frame.

This commit produces wins in virtually every CPU part of the pipeline:
`extract_meshes`, `queue_material_meshes`,
`batch_and_prepare_render_phase`, and especially
`write_batched_instance_buffer` are all faster. Shrinking the amount of
CPU data that has to be shuffled around speeds up the entire rendering
process.

| Benchmark              | This branch | `main`  | Speedup |
|------------------------|-------------|---------|---------|
| `many_cubes -nfc`      |      17.259 |  24.529 |  42.12% |
| `many_cubes -nfc -vpi` |     302.116 | 312.123 |   3.31% |
| `many_foxes`           |       3.227 |   3.515 |   8.92% |

Because mesh uniform building requires compute shader, and WebGL 2 has
no compute shader, the existing CPU mesh uniform building code has been
left as-is. Many types now have both CPU mesh uniform building and GPU
mesh uniform building modes. Developers can opt into the old CPU mesh
uniform building by setting the `use_gpu_uniform_builder` option on
`PbrPlugin` to `false`.

Below are graphs of the CPU portions of `many-cubes
--no-frustum-culling`. Yellow is this branch, red is `main`.

`extract_meshes`:
![Screenshot 2024-04-02
124842](https://github.com/bevyengine/bevy/assets/157897/a6748ea4-dd05-47b6-9254-45d07d33cb10)
It's notable that we get a small win even though we're now writing to a
GPU buffer.

`queue_material_meshes`:
![Screenshot 2024-04-02
124911](https://github.com/bevyengine/bevy/assets/157897/ecb44d78-65dc-448d-ba85-2de91aa2ad94)
There's a bit of a regression here; not sure what's causing it. In any
case it's very outweighed by the other gains.

`batch_and_prepare_render_phase`:
![Screenshot 2024-04-02
125123](https://github.com/bevyengine/bevy/assets/157897/4e20fc86-f9dd-4e5c-8623-837e4258f435)
There's a huge win here, enough to make batching basically drop off the
profile.

`write_batched_instance_buffer`:
![Screenshot 2024-04-02
125237](https://github.com/bevyengine/bevy/assets/157897/401a5c32-9dc1-4991-996d-eb1cac6014b2)
There's a massive improvement here, as expected. Note that a lot of it
simply comes from the fact that `MeshInputUniform` is `Pod`. (This isn't
a maintainability problem in my view because `MeshInputUniform` is so
simple: just 16 tightly-packed words.)

## Changelog

### Added

* Per-mesh instance data is now generated on GPU with a compute shader
instead of CPU, resulting in rendering performance improvements on
platforms where compute shaders are supported.

## Migration guide

* Custom render phases now need multiple systems beyond just
`batch_and_prepare_render_phase`. Code that was previously creating
custom render phases should now add a `BinnedRenderPhasePlugin` or
`SortedRenderPhasePlugin` as appropriate instead of directly adding
`batch_and_prepare_render_phase`.
2024-04-10 05:33:32 +00:00
BD103
a9943e8d2c
Fix beta CI (#12913)
# Objective

- Fixes #12905.

## Solution

- Use proper code `` tags for `TaskPoolBuilder::thread_name`.
- Remove leftover documentation in `TaskPool` referencing the deleted
`TaskPoolInner` struct.
- It may be possible to rephrase this, but I do not know enough about
the task pool to write something. (cc @james7132 who made the change
removing `TaskPoolInner`.)
- Ignore a buggy rustdoc lint that thinks `App` is already in scope for
`UpdateMode` doc. (Extracted from #12692.)
2024-04-09 17:33:59 +00:00
Lynn
2f0b5b9c5a
Use impl Into<Color> for gizmos.primitive_3d(...) (#12915)
# Objective

- All gizmos APIs besides `gizmos.primitive_3d` use `impl Into<Color>`
as their type for `color`.

## Solution

- This PR changes `primitive_3d()` to use `impl Into<Color>` aswell.
2024-04-09 17:33:34 +00:00
Robert Swain
ab7cbfa8fc
Consolidate Render(Ui)Materials(2d) into RenderAssets (#12827)
# Objective

- Replace `RenderMaterials` / `RenderMaterials2d` / `RenderUiMaterials`
with `RenderAssets` to enable implementing changes to one thing,
`RenderAssets`, that applies to all use cases rather than duplicating
changes everywhere for multiple things that should be one thing.
- Adopts #8149 

## Solution

- Make RenderAsset generic over the destination type rather than the
source type as in #8149
- Use `RenderAssets<PreparedMaterial<M>>` etc for render materials

---

## Changelog

- Changed:
- The `RenderAsset` trait is now implemented on the destination type.
Its `SourceAsset` associated type refers to the type of the source
asset.
- `RenderMaterials`, `RenderMaterials2d`, and `RenderUiMaterials` have
been replaced by `RenderAssets<PreparedMaterial<M>>` and similar.

## Migration Guide

- `RenderAsset` is now implemented for the destination type rather that
the source asset type. The source asset type is now the `RenderAsset`
trait's `SourceAsset` associated type.
2024-04-09 13:26:34 +00:00
Remi Godin
10af274d4e
Created loading screen example (#12863)
Allows the user to select a scene to load, then a loading screen is
shown until all assets are loaded, and pipelines compiled.

# Objective
- Fixes #12654 

## Solution
- Add desired assets to be monitored to a list.
- While there are assets that are not fully loaded, show a loading
screen.
- Once all assets are loaded, and pipelines compiled, show the scene
that was loaded.
2024-04-09 12:50:19 +00:00
Matty
956604e4c7
Meshing for Triangle3d primitive (#12686)
# Objective

- Ongoing work for #10572 
- Implement the `Meshable` trait for `Triangle3d`, allowing 3d triangle
primitives to produce meshes.

## Solution

The `Meshable` trait for `Triangle3d` directly produces a `Mesh`, much
like that of `Triangle2d`. The mesh consists only of a single triangle
(the triangle itself), and its vertex data consists of:
- Vertex positions, which are the triangle's vertices themselves (i.e.
the triangle provides its own coordinates in mesh space directly)
- Normals, which are all the normal of the triangle itself
- Indices, which are directly inferred from the vertex order (note that
this is slightly different than `Triangle2d` which, because of its lower
dimension, has an orientation which can be corrected for so that it
always faces "the right way")
- UV coordinates, which are produced as follows:
1. The first coordinate is coincident with the `ab` direction of the
triangle.
2. The second coordinate maps to be perpendicular to the first in mesh
space, so that the UV-mapping is skew-free.
3. The UV-coordinates map to the smallest rectangle possible containing
the triangle, given the preceding constraints.

Here is a visual demonstration; here, the `ab` direction of the triangle
is horizontal, left to right — the point `c` moves, expanding the
bounding rectangle of the triangle when it pushes past `a` or `b`:

<img width="1440" alt="Screenshot 2024-03-23 at 5 36 01 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/bef4d786-7b82-4207-abd4-ac4557d0f8b8">

<img width="1440" alt="Screenshot 2024-03-23 at 5 38 12 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/c0f72b8f-8e70-46fa-a750-2041ba6dfb78">

<img width="1440" alt="Screenshot 2024-03-23 at 5 37 15 PM"
src="https://github.com/bevyengine/bevy/assets/2975848/db287e4f-2b0b-4fd4-8d71-88f4e7a03b7c">

The UV-mapping of `Triangle2d` has also been changed to use the same
logic.

---

## Changelog

- Implemented `Meshable` for `Triangle3d`.
- Changed UV-mapping of `Triangle2d` to match that of `Triangle3d`.

## Migration Guide

The UV-mapping of `Triangle2d` has changed with this PR; the main
difference is that the UVs are no longer dependent on the triangle's
absolute coordinates, but instead follow translations of the triangle
itself in its definition. If you depended on the old UV-coordinates for
`Triangle2d`, then you will have to update affected areas to use the new
ones which, briefly, can be described as follows:
- The first coordinate is parallel to the line between the first two
vertices of the triangle.
- The second coordinate is orthogonal to this, pointing in the direction
of the third point.

Generally speaking, this means that the first two points will have
coordinates `[_, 0.]`, while the third coordinate will be `[_, 1.]`,
with the exact values depending on the position of the third point
relative to the first two. For acute triangles, the first two vertices
always have UV-coordinates `[0., 0.]` and `[1., 0.]` respectively. For
obtuse triangles, the third point will have coordinate `[0., 1.]` or
`[1., 1.]`, with the coordinate of one of the two other points shifting
to maintain proportionality.

For example: 
- The default `Triangle2d` has UV-coordinates `[0., 0.]`, `[0., 1.]`,
[`0.5, 1.]`.
- The triangle with vertices `vec2(0., 0.)`, `vec2(1., 0.)`, `vec2(2.,
1.)` has UV-coordinates `[0., 0.]`, `[0.5, 0.]`, `[1., 1.]`.
- The triangle with vertices `vec2(0., 0.)`, `vec2(1., 0.)`, `vec2(-2.,
1.)` has UV-coordinates `[2./3., 0.]`, `[1., 0.]`, `[0., 1.]`.

## Discussion

### Design considerations

1. There are a number of ways to UV-map a triangle (at least two of
which are fairly natural); for instance, we could instead declare the
second axis to be essentially `bc` so that the vertices are always `[0.,
0.]`, `[0., 1.]`, and `[1., 0.]`. I chose this method instead because it
is skew-free, so that the sampling from textures has only bilinear
scaling. I think this is better for cases where a relatively "uniform"
texture is mapped to the triangle, but it's possible that we might want
to support the other thing in the future. Thankfully, we already have
the capability of easily expanding to do that with Builders if the need
arises. This could also allow us to provide things like barycentric
subdivision.
2. Presently, the mesh-creation code for `Triangle3d` is set up to never
fail, even in the case that the triangle is degenerate. I have mixed
feelings about this, but none of our other primitive meshes fail, so I
decided to take the same approach. Maybe this is something that could be
worth revisiting in the future across the board.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jakub Marcowski <37378746+Chubercik@users.noreply.github.com>
2024-04-08 23:00:04 +00:00
James Liu
934f2cfadf
Clean up some low level dependencies (#12858)
# Objective
Minimize the number of dependencies low in the tree.

## Solution

* Remove the dependency on rustc-hash in bevy_ecs (not used) and
bevy_macro_utils (only used in one spot).
* Deduplicate the dependency on `sha1_smol` with the existing blake3
dependency already being used for bevy_asset.
 * Remove the unused `ron` dependency on `bevy_app`
* Make the `serde` dependency for `bevy_ecs` optional. It's only used
for serializing Entity.
* Change the `wgpu` dependency to `wgpu-types`, and make it optional for
`bevy_color`.
 * Remove the unused `thread-local` dependency on `bevy_render`.
* Make multiple dependencies for `bevy_tasks` optional and enabled only
when running with the `multi-threaded` feature. Preferably they'd be
disabled all the time on wasm, but I couldn't find a clean way to do
this.

---

## Changelog
TODO 

## Migration Guide
TODO
2024-04-08 19:45:42 +00:00
Brezak
627ad6d2cc
Fix strings not interpolating in weely ci run (#12906)
# Objective

Fix invalid links in weekly CI workflow.

## Solution

Replace env vars with direct evaluation.
2024-04-08 17:21:35 +00:00
François Mockers
de3ec47f3f
Fix example game of life (#12897)
# Objective

- Example `compute_shader_game_of_life` is random and not following the
rules of the game of life: at each steps, it randomly reads some pixel
of the current step and some of the previous step instead of only from
the previous step
- Fixes #9353 

## Solution

- Adopted from #9678 
- Added a switch of the texture displayed every frame otherwise the game
of life looks wrong
- Added a way to display the texture bigger so that I could manually
check everything was right

---------

Co-authored-by: Sludge <96552222+SludgePhD@users.noreply.github.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
2024-04-08 17:19:07 +00:00
Hexorg
b9a232966b
Fixed a bug where skybox ddsfile would crash from wgpu (#12894)
Fixed a bug where skybox ddsfile would crash from wgpu while trying to
read past the file buffer.
Added a unit-test to prevent regression.
Bumped ddsfile dependency version to 0.5.2

# Objective

Prevents a crash when loading dds skybox.

## Solution

ddsfile already automatically sets array layers to be 6 for skyboxes.
Removed bevy's extra *= 6 multiplication.

---

This is a copy of
[#12598](https://github.com/bevyengine/bevy/pull/12598) ... I made that
one off of main and wasn't able to make more pull requests without
making a new branch.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-04-08 17:16:25 +00:00
orzogc
5570315baf
Document the lifetime requirement of byte_offset and byte_add (#12893)
# Objective

`byte_offset` and `byte_add` of `Ptr`, `PtrMut` and `OwningPtr` are
missing the lifetime requirement.

## Solution

Add documents.
2024-04-08 17:13:35 +00:00
Noah Emke
c0aa5170bc
Add example for using .meta files (#12882)
# Objective

- Fixes #12411 
- Add an example demonstrating the usage of asset meta files.

## Solution

- Add a new example displaying a basic scene of three pixelated images
- Apply a .meta file to one of the assets setting Nearest filtering
- Use AssetServer::load_with_settings on the last one as another way to
achieve the same effect
- The result is one blurry image and two crisp images demonstrating a
common scenario in which changing settings are useful.
2024-04-08 17:10:56 +00:00
IceSentry
08b41878d7
Add gpu readback example (#12877)
# Objective

- It's pretty common for users to want to read data back from the gpu
and into the main world

## Solution

- Add a simple example that shows how to read data back from the gpu and
send it to the main world using a channel.
- The example is largely based on this wgpu example but adapted to bevy
-
fb305b85f6/examples/src/repeated_compute/mod.rs

---------

Co-authored-by: stormy <120167078+stowmyy@users.noreply.github.com>
Co-authored-by: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com>
2024-04-08 17:08:20 +00:00
UkoeHB
2ee69807b1
Fix potential out-of-bounds access in pbr_functions.wgsl (#12585)
# Objective

- Fix a potential out-of-bounds access in the `pbr_functions.wgsl`
shader.

## Solution

- Correctly compute the `GpuLights::directional_lights` array length.

## Comments

I think this solves this comment in the code, but need someone to test
it:
```rust
//NOTE: When running bevy on Adreno GPU chipsets in WebGL, any value above 1 will result in a crash
// when loading the wgsl "pbr_functions.wgsl" in the function apply_fog.
```
2024-04-08 17:00:09 +00:00
Martín Maita
0c78bf3bb0
Moves intern and label modules into bevy_ecs (#12772)
# Objective

- Attempts to solve two items from
https://github.com/bevyengine/bevy/issues/11478.

## Solution

- Moved `intern` module from `bevy_utils` into `bevy_ecs` crate and
updated all relevant imports.
- Moved `label` module from `bevy_utils` into `bevy_ecs` crate and
updated all relevant imports.

---

## Migration Guide

- Replace `bevy_utils::define_label` imports with
`bevy_ecs::define_label` imports.
- Replace `bevy_utils:🏷️:DynEq` imports with
`bevy_ecs:🏷️:DynEq` imports.
- Replace `bevy_utils:🏷️:DynHash` imports with
`bevy_ecs:🏷️:DynHash` imports.
- Replace `bevy_utils::intern::Interned` imports with
`bevy_ecs::intern::Interned` imports.
- Replace `bevy_utils::intern::Internable` imports with
`bevy_ecs::intern::Internable` imports.
- Replace `bevy_utils::intern::Interner` imports with
`bevy_ecs::intern::Interner` imports.

---------

Co-authored-by: James Liu <contact@jamessliu.com>
2024-04-08 15:34:11 +00:00
Martín Maita
3fc0c6869d
Bump crate-ci/typos from 1.19.0 to 1.20.4 (#12907)
# Objective

- Adopting https://github.com/bevyengine/bevy/pull/12903.

## Solution

- Bump crate-ci/typos from 1.19.0 to 1.20.4.
- Fixed a typo in `crates/bevy_pbr/src/render/pbr_functions.wgsl` file.
- Added "PNG", "iy" and "SME" as exceptions to prevent false positives.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 15:31:11 +00:00
Giacomo Stevanato
74f52076a3
Make some ReflectComponent/ReflectBundle methods work with EntityMut too (#12895)
# Objective

- Make `ReflectComponent::apply`, `ReflectComponent::reflect_mut` and
`ReflectBundle::apply` work with `EntityMut` too (currently they only
work with the more restricting `EntityWorldMut`);
- Note: support for the `Filtered*` variants has been left out since the
conversion in that case is more expensive. Let me know if I should add
support for them too.

## Solution

- Make `ReflectComponent::apply`, `ReflectComponent::reflect_mut` and
`ReflectBundle::apply` take an `impl Into<EntityMut<'a>>`;
- Make the corresponding `*Fns` function pointers take a `EntityMut`.

---

## Changelog

- `ReflectComponent::apply`, `ReflectComponent::reflect_mut` and
`ReflectBundle::apply` now accept `EntityMut` as well

## Migration Guide

- `ReflectComponentFns`'s `apply` and `reflect_mut` fields now take
`EntityMut` instead of `&mut EntityWorldMut`
- `ReflectBundleFns`'s `apply` field now takes `EntityMut` instead of
`&mut EntityWorldMut`
2024-04-08 01:46:07 +00:00
JMS55
31b5943ad4
Add previous_view_uniforms.inverse_view (#12902)
# Objective
- Upload previous frame's inverse_view matrix to the GPU for use with
https://github.com/bevyengine/bevy/pull/12898.

---

## Changelog
- Added `prepass_bindings::previous_view_uniforms.inverse_view`.
- Renamed `prepass_bindings::previous_view_proj` to
`prepass_bindings::previous_view_uniforms.view_proj`.
- Renamed `PreviousViewProjectionUniformOffset` to
`PreviousViewUniformOffset`.
- Renamed `PreviousViewProjection` to `PreviousViewData`.

## Migration Guide
- Renamed `prepass_bindings::previous_view_proj` to
`prepass_bindings::previous_view_uniforms.view_proj`.
- Renamed `PreviousViewProjectionUniformOffset` to
`PreviousViewUniformOffset`.
- Renamed `PreviousViewProjection` to `PreviousViewData`.
2024-04-07 18:59:16 +00:00
robtfm
452821dd52
more robust gpu image use (#12606)
# Objective

make morph targets and tonemapping more tolerant of delayed image
loading.

neither of these actually fail currently unless using a bespoke loader
(and even then it would be rare), but i am working on adding throttling
for asset gpu uploads (as a stopgap until we can do proper asset
streaming) and they break with that.

## Solution

when a mesh with morph targets is uploaded to the gpu, the prepare
function uploads the morph target texture if it's available, otherwise
it uploads without morph targets. this is generally fine as long as
morph targets are typically loaded from bytes (in gltf loader), but may
fail for a custom loader if the asset server async-loads the target
texture and the texture is not available yet. the mesh fails to render
and doesn't update when the image is loaded
-> if morph targets are specified but not ready yet, retry mesh upload
next frame

tonemapping `unwrap`s on the lookup table image. this is never a problem
since the image is added via `include_bytes!`, but could be a problem in
future with asset gpu throttling/streaming.
-> if the lookup texture is not yet available, use a fallback
-> in the node, check if the fallback was used before caching the bind
group
2024-04-07 17:18:58 +00:00
Giacomo Stevanato
4227781e8c
Implement From<&'w mut EntityMut> for EntityMut<'w> (#12896)
# Objective

- Implement `From<&'w mut EntityMut>` for `EntityMut<'w>`;
- Make it possible to pass `&mut EntityMut` where `impl Into<EntityMut>`
is required;
- Helps with #12895.

## Solution

- Implement `From<&'w mut EntityMut>` for `EntityMut<'w>`

---

## Changelog

- `EntityMut<'w>` now implements `From<&'w mut EntityMut>`
2024-04-07 13:24:10 +00:00
Rob Parrett
6c485c80e0
Fix example showcase wasm window settings patch (#12608)
# Objective

FIx this failed workflow:
<https://github.com/bevyengine/bevy/actions/runs/8367408952/job/22909715870#step:7:11>

## Solution

Make the required changes on fresh Bevy code and save a new patch
2024-04-06 22:07:49 +00:00
JMS55
9264850a1c
Fix skybox wrong alpha (#12888)
Fix https://github.com/bevyengine/bevy/issues/12740
2024-04-06 08:08:55 +00:00
Luís Figueiredo
ac91b19118
Fixes #12000: When viewport is set to camera and switched to SizedFul… (#12861)
# Objective

- When viewport is set to the same size as the window on creation, when
adjusting to SizedFullscreen, the window may be smaller than the
viewport for a moment, which caused the arguments to be invalid and
panic.
- Fixes #12000.

## Solution

- The fix consists of matching the size of the viewport to the lower
size of the window ( if the x value of the window is lower, I update
only the x value of the viewport, same for the y value). Also added a
test to show that it does not panic anymore.

---
2024-04-06 02:22:50 +00:00
Multirious
a27ce270d0
Fix broken link in mesh docs (#12872)
# Objective

Fixes #12813

## Solution

Update the link to
`https://github.com/bevyengine/bevy/tree/main/crates/bevy_render/src/mesh/primitives`
2024-04-05 18:22:52 +00:00
François Mockers
a9964f442d
fix msaa shift with irradiance volumes in mesh pipeline key (#12845)
# Objective

- #12791 broke example `irradiance_volumes`
- Fixes #12876 

```
wgpu error: Validation Error

Caused by:
    In Device::create_render_pipeline
      note: label = `pbr_opaque_mesh_pipeline`
    Color state [0] is invalid
    Sample count 8 is not supported by format Rgba8UnormSrgb on this device. The WebGPU spec guarentees [1, 4] samples are supported by this format. With the TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES feature your device supports [1, 2, 4].
```

## Solution

- Shift bits a bit more
2024-04-05 17:50:23 +00:00
Remi Godin
c233d6e0d0
Added method to get waiting pipelines IDs from pipeline cache. (#12874)
# Objective
- Add a way to easily get currently waiting pipelines IDs.

## Solution
- Added a method to get waiting pipelines `CachedPipelineId`.

---------

Co-authored-by: James Liu <contact@jamessliu.com>
2024-04-05 03:46:15 +00:00
James Liu
a4ed1b88b8
Relax BufferVec's type constraints (#12866)
# Objective
Since BufferVec was first introduced, `bytemuck` has added additional
traits with fewer restrictions than `Pod`. Within BufferVec, we only
rely on the constraints of `bytemuck::cast_slice` to a `u8` slice, which
now only requires `T: NoUninit` which is a strict superset of `Pod`
types.

## Solution
Change out the `Pod` generic type constraint with `NoUninit`. Also
taking the opportunity to substitute `cast_slice` with
`must_cast_slice`, which avoids a runtime panic in place of a compile
time failure if `T` cannot be used.

---

## Changelog
Changed: `BufferVec` now supports working with types containing
`NoUninit` but not `Pod` members.
Changed: `BufferVec` will now fail to compile if used with a type that
cannot be safely read from. Most notably, this includes ZSTs, which
would previously always panic at runtime.
2024-04-05 02:11:41 +00:00
Matty
3a7923ea92
Random sampling of directions and quaternions (#12857)
# Objective

Augment Bevy's random sampling capabilities by providing good tools for
producing random directions and rotations.

## Solution

The `rand` crate has a natural tool for providing `Distribution`s whose
output is a type that doesn't require any additional data to sample
values — namely,
[`Standard`](https://docs.rs/rand/latest/rand/distributions/struct.Standard.html).

Here, our existing `ShapeSample` implementations have been put to good
use in providing these, resulting in patterns like the following:
```rust
// Using thread-local rng
let random_direction1: Dir3 = random();

// Using an explicit rng
let random_direction2: Dir3 = rng.gen();

// Using an explicit rng coupled explicitly with Standard
let random_directions: Vec<Dir3> = rng.sample_iter(Standard).take(5).collect();
```

Furthermore, we have introduced a trait `FromRng` which provides sugar
for `rng.gen()` that is more namespace-friendly (in this author's
opinion):
```rust
let random_direction = Dir3::from_rng(rng);
```

The types this has been implemented for are `Dir2`, `Dir3`, `Dir3A`, and
`Quat`. Notably, `Quat` uses `glam`'s implementation rather than an
in-house one, and as a result, `bevy_math`'s "rand" feature now enables
that of `glam`.

---

## Changelog

- Created `standard` submodule in `sampling` to hold implementations and
other items related to the `Standard` distribution.
- "rand" feature of `bevy_math` now enables that of `glam`.

---

## Discussion

From a quick glance at `Quat`'s distribution implementation in `glam`, I
am a bit suspicious, since it is simple and doesn't match any algorithm
that I came across in my research. I will do a little more digging as a
follow-up to this and see if it's actually uniform (maybe even using
those tools I wrote — what a thrill).

As an aside, I'd also like to say that I think
[`Distribution`](https://docs.rs/rand/latest/rand/distributions/trait.Distribution.html)
is really, really good. It integrates with distributions provided
externally (e.g. in `rand` itself and its extensions) along with doing a
good job of isolating the source of randomness, so that output can be
reliably reproduced if need be. Finally, `Distribution::sample_iter` is
quite good for ergonomically acquiring lots of random values. At one
point I found myself writing traits to describe random sampling and
essentially reinvented this one. I just think it's good, and I think
it's worth centralizing around to a significant extent.
2024-04-04 23:13:00 +00:00
François Mockers
4a649d5030
document how to publish patches (#12879)
# Objective

- Ensure patches can be released by anyone (with the appropriate
permissions)

## Solution

- Document the process
2024-04-04 21:18:00 +00:00
Carter Anderson
b27896f875
Disable RAY_QUERY and RAY_TRACING_ACCELERATION_STRUCTURE by default (#12862)
# Objective

See https://github.com/gfx-rs/wgpu/issues/5488 for context and
rationale.

## Solution

- Disables `wgpu::Features::RAY_QUERY` and
`wgpu::Features::RAY_TRACING_ACCELERATION_STRUCTURE` by default. They
must be explicitly opted into now.

---

## Changelog

- Disables `wgpu::Features::RAY_QUERY` and
`wgpu::Features::RAY_TRACING_ACCELERATION_STRUCTURE` by default. They
must be explicitly opted into now.

## Migration Guide

- If you need `wgpu::Features::RAY_QUERY` or
`wgpu::Features::RAY_TRACING_ACCELERATION_STRUCTURE`, enable them
explicitly using `WgpuSettings::features`
2024-04-04 19:20:19 +00:00
Vitaliy Sapronenko
4da4493449
Error info has been added to LoadState::Failed (#12709)
# Objective

Fixes #12667.

## Solution

- Stored
[AssetLoadError](https://docs.rs/bevy/latest/bevy/asset/enum.AssetLoadError.html)
inside of
[LoadState::Failed](https://docs.rs/bevy/latest/bevy/asset/enum.LoadState.html)
as a Box<AssetLoadError> to avoid bloating the size of all variants of
LoadState.
- Fixed dependent code

## Migration guide

Added
[AssetLoadError](https://docs.rs/bevy/latest/bevy/asset/enum.AssetLoadError.html)
to
[LoadState::Failed](https://docs.rs/bevy/latest/bevy/asset/enum.LoadState.html)
option
Removed `Copy`, `Ord` and `PartialOrd` implementations for
[LoadState](https://docs.rs/bevy/latest/bevy/asset/enum.LoadState.html)
enum
Added `Eq` and `PartialEq` implementations for
[MissingAssetSourceError](https://docs.rs/bevy/latest/bevy/asset/io/struct.MissingAssetSourceError.html),
[MissingProcessedAssetReaderError](https://docs.rs/bevy/latest/bevy/asset/io/struct.MissingProcessedAssetReaderError.html),
[DeserializeMetaError](https://docs.rs/bevy/latest/bevy/asset/enum.DeserializeMetaError.html),
[LoadState](https://docs.rs/bevy/latest/bevy/asset/enum.LoadState.html),
[AssetLoadError](https://docs.rs/bevy/latest/bevy/asset/enum.AssetLoadError.html),
[MissingAssetLoaderForTypeNameError](https://docs.rs/bevy/latest/bevy/asset/struct.MissingAssetLoaderForTypeNameError.html)
and
[MissingAssetLoaderForTypeIdError](https://docs.rs/bevy/latest/bevy/asset/struct.MissingAssetLoaderForTypeIdError.html)
2024-04-04 14:04:27 +00:00
re0312
4ca8cf5d66
Cluster small table/archetype into single Task in parallel iteration (#12846)
# Objective

- Fix #7303
- bevy would spawn a lot of tasks in parallel iteration when it matchs a
large storage and many small storage ,it significantly increase the
overhead of schedule.

## Solution

- collect small storage into one task
2024-04-04 07:09:26 +00:00