Use MaybeUninit in QueryManyIter::sort methods to drop the lens items before returning.#6
Closed
Use MaybeUninit in QueryManyIter::sort methods to drop the lens items before returning.#6
Conversation
# Objective - Migrate UI bundles to required components, fixes bevyengine#15889 ## Solution - deprecate `NodeBundle` in favor of `Node` - deprecate `ImageBundle` in favor of `UiImage` - deprecate `ButtonBundle` in favor of `Button` ## Testing CI. ## Migration Guide - Replace all uses of `NodeBundle` with `Node`. e.g. ```diff commands - .spawn(NodeBundle { - style: Style { + .spawn(( + Node::default(), + Style { width: Val::Percent(100.), align_items: AlignItems::Center, justify_content: JustifyContent::Center, ..default() }, - ..default() - }) + )) ``` - Replace all uses of `ButtonBundle` with `Button`. e.g. ```diff .spawn(( - ButtonBundle { - style: Style { - width: Val::Px(w), - height: Val::Px(h), - // horizontally center child text - justify_content: JustifyContent::Center, - // vertically center child text - align_items: AlignItems::Center, - margin: UiRect::all(Val::Px(20.0)), - ..default() - }, - image: image.clone().into(), + Button, + Style { + width: Val::Px(w), + height: Val::Px(h), + // horizontally center child text + justify_content: JustifyContent::Center, + // vertically center child text + align_items: AlignItems::Center, + margin: UiRect::all(Val::Px(20.0)), ..default() }, + UiImage::from(image.clone()), ImageScaleMode::Sliced(slicer.clone()), )) ``` - Replace all uses of `ImageBundle` with `UiImage`. e.g. ```diff - commands.spawn(ImageBundle { - image: UiImage { + commands.spawn(( + UiImage { texture: metering_mask, ..default() }, - style: Style { + Style { width: Val::Percent(100.0), height: Val::Percent(100.0), ..default() }, - ..default() - }); + )); ``` --------- Co-authored-by: Carter Anderson <[email protected]>
# Objective Fixes bevyengine#15976 ## Solution I haven't been following the recent camera changes but on a whim I inverted the scale and it restored the old behavior. It seems that a similar inversion was done when migrating the `pixel_grid_snap` example in bevyengine#15976. ## Testing `cargo run --example pbr`
…rties. (bevyengine#15975) # Objective Continue improving the user experience of our UI Node API in the direction specified by [Bevy's Next Generation Scene / UI System](bevyengine#14437) ## Solution As specified in the document above, merge `Style` fields into `Node`, and move "computed Node fields" into `ComputedNode` (I chose this name over something like `ComputedNodeLayout` because it currently contains more than just layout info. If we want to break this up / rename these concepts, lets do that in a separate PR). `Style` has been removed. This accomplishes a number of goals: ## Ergonomics wins Specifying both `Node` and `Style` is now no longer required for non-default styles Before: ```rust commands.spawn(( Node::default(), Style { width: Val::Px(100.), ..default() }, )); ``` After: ```rust commands.spawn(Node { width: Val::Px(100.), ..default() }); ``` ## Conceptual clarity `Style` was never a comprehensive "style sheet". It only defined "core" style properties that all `Nodes` shared. Any "styled property" that couldn't fit that mold had to be in a separate component. A "real" style system would style properties _across_ components (`Node`, `Button`, etc). We have plans to build a true style system (see the doc linked above). By moving the `Style` fields to `Node`, we fully embrace `Node` as the driving concept and remove the "style system" confusion. ## Next Steps * Consider identifying and splitting out "style properties that aren't core to Node". This should not happen for Bevy 0.15. --- ## Migration Guide Move any fields set on `Style` into `Node` and replace all `Style` component usage with `Node`. Before: ```rust commands.spawn(( Node::default(), Style { width: Val::Px(100.), ..default() }, )); ``` After: ```rust commands.spawn(Node { width: Val::Px(100.), ..default() }); ``` For any usage of the "computed node properties" that used to live on `Node`, use `ComputedNode` instead: Before: ```rust fn system(nodes: Query<&Node>) { for node in &nodes { let computed_size = node.size(); } } ``` After: ```rust fn system(computed_nodes: Query<&ComputedNode>) { for computed_node in &computed_nodes { let computed_size = computed_node.size(); } } ```
) # Objective - Fixes bevyengine#13552 ## Solution - Thanks for the guidance from @DGriffin91, the current solution is to transmit the light_map through the emissive channel to avoid increasing the bandwidth of deferred shading. - <del>Store lightmap sample result into G-Buffer and pass them into the `Deferred Lighting Pipeline`, therefore we can get the correct indirect lighting via the `apply_pbr_lighting` function.</del> - <del>The original G-Buffer lacks storage for lightmap data, therefore a new buffer is added. We can only use Rgba16Uint here due to the 32-byte limit on the render targets.</del> ## Testing - Need to test all the examples that contains a prepass, with both the forward and deferred rendering mode. - I have tested the ones below. - `lightmaps` (adjust the code based on the issue and check the rendering result) - `transmission` (it contains a prepass) - `ssr` (it also uses the G-Bufffer) - `meshlet` (forward and deferred) - `pbr` ## Showcase By updating the `lightmaps` example to use deferred rendering, this pull request enables correct rendering result of the Cornell Box. ``` diff --git a/examples/3d/lightmaps.rs b/examples/3d/lightmaps.rs index 564a316..11a748fba 100644 --- a/examples/3d/lightmaps.rs +++ b/examples/3d/lightmaps.rs @@ -1,12 +1,14 @@ //! Rendering a scene with baked lightmaps. -use bevy::pbr::Lightmap; +use bevy::core_pipeline::prepass::DeferredPrepass; +use bevy::pbr::{DefaultOpaqueRendererMethod, Lightmap}; use bevy::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) .insert_resource(AmbientLight::NONE) + .insert_resource(DefaultOpaqueRendererMethod::deferred()) .add_systems(Startup, setup) .add_systems(Update, add_lightmaps_to_meshes) .run(); @@ -19,10 +21,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) { ..default() }); - commands.spawn(Camera3dBundle { - transform: Transform::from_xyz(-278.0, 273.0, 800.0), - ..default() - }); + commands + .spawn(Camera3dBundle { + transform: Transform::from_xyz(-278.0, 273.0, 800.0), + ..default() + }) + .insert(DeferredPrepass); } fn add_lightmaps_to_meshes( ``` <img width="1280" alt="image" src="https://github.com/user-attachments/assets/17fd3367-61cc-4c23-b956-e7cfc751af3c"> ## Emissive Issue **The emissive light object appears incorrectly rendered because the alpha channel of emission is set to 1 in deferred rendering and 0 in forward rendering, leading to different emissive light result. Could this be a bug?** ```wgsl // pbr_deferred_functions.wgsl - pbr_input_from_deferred_gbuffer let emissive = rgb9e5::rgb9e5_to_vec3_(gbuffer.g); if ((pbr.material.flags & STANDARD_MATERIAL_FLAGS_UNLIT_BIT) != 0u) { pbr.material.base_color = vec4(emissive, 1.0); pbr.material.emissive = vec4(vec3(0.0), 1.0); } else { pbr.material.base_color = vec4(pow(base_rough.rgb, vec3(2.2)), 1.0); pbr.material.emissive = vec4(emissive, 1.0); } // pbr_functions.wgsl - apply_pbr_lighting emissive_light = emissive_light * mix(1.0, view_bindings::view.exposure, emissive.a); ``` --------- Co-authored-by: JMS55 <[email protected]>
# Objective Fixes bevyengine#15995 ## Solution Corrects a mistake made during the example migration in bevyengine#15591. `AnimationControl` was meant to be on the parent, not the child. So the query in `update_ui` was no longer matching. ## Testing `cargo run --example animation_masks`
bevyengine#15865) # Objective The Custom Material GLSL shader example has an old version of the camera view uniform structure. This PR updates the example GLSL custom material shader to have the latest structure. ## Solution I was running into issues using the camera world position (it wasn't changing) and someone in discord pointed me to the source of truth. `crates/bevy_render/src/view/view.wgsl` After using this latest uniform structure in my project I'm now able to work with the camera position in my shader. ## Testing I tested this change by running the example with: ```bash cargo run --features shader_format_glsl --example shader_material_glsl ``` <img width="1392" alt="image" src="https://github.com/user-attachments/assets/39fc82ec-ff3b-4864-ad73-05f3a25db483"> --------- Co-authored-by: Carter Anderson <[email protected]>
# Objective - The depth test was only using the final depth but it should be testing each fragments - Fully transparent fragments should not be added to the list ## Solution - Test each fragment after sorting ## Testing before: TODO after: TODO
Just some very minor fixes to the OIT example.
…5946) # Objective Switch to retained render world causes the extracted cameras in render world to not be removed until camera in main world is despawned. When extracting data from main world inactive cameras are skipped. Therefore camera that was active and became inactive has a retained `ExtractedCamera` component from previous frames (when it was active) and is processed the same way as if it were active (there is no `active` field on `ExtractedCamera`). This breakes switching between cameras in `render_primitives` example. Fixes bevyengine#15822 ## Solution Fix it by removing `ExtractedCamera` and related components from inactive cameras. Note that despawning inactive camera seems to be bad option because they are spawned using `SyncToRenderWorld` component. ## Testing Switching camera in `render_primitives` example now works correctly. --------- Co-authored-by: akimakinai <[email protected]>
# Objective - Fixes bevyengine#15871 (Camera is done in bevyengine#15946) ## Solution - Do the same as bevyengine#15904 for other extraction systems - Added missing `SyncComponentPlugin` for DOF, TAA, and SSAO (According to the [documentation](https://dev-docs.bevyengine.org/bevy/render/sync_component/struct.SyncComponentPlugin.html), this plugin "needs to be added for manual extraction implementations." We may need to check this is done.) ## Testing Modified example locally to add toggles if not exist. - [x] DOF - toggling DOF component and perspective in `depth_of_field` example - [x] TAA - toggling `Camera.is_active` and TAA component - [x] clusters - not entirely sure, toggling `Camera.is_active` in `many_lights` example (no crash/glitch even without this PR) - [x] previous_view - toggling `Camera.is_active` in `skybox` (no crash/glitch even without this PR) - [x] lights - toggling `Visibility` of `DirectionalLight` in `lighting` example - [x] SSAO - toggling `Camera.is_active` and SSAO component in `ssao` example - [x] default UI camera view - toggling `Camera.is_active` (nop without bevyengine#15946 because UI defaults to some camera even if `DefaultCameraView` is not there) - [x] volumetric fog - toggling existence of volumetric light. Looks like optimization, no change in behavior/visuals
# Objective
Fixes the following warning when compiling to wasm.
```
warning: unnecessary qualification
--> crates\bevy_asset\src\io\mod.rs:733:19
|
733 | _cx: &mut core::task::Context<'_>,
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: requested on the command line with `-W unused-qualifications`
help: remove the unnecessary path segments
|
733 - _cx: &mut core::task::Context<'_>,
733 + _cx: &mut Context<'_>,
|
```
## Solution
- Removes the qualification.
# Objective - Progress towards bevyengine#15918 - Add tests for 3d ## Solution - Add tests that cover lights, bloom, gltf and animation - Removed examples `contributors` and `load_gltf` as they don't contribute additional checks to CI ## Testing - `CI_TESTING_CONFIG=.github/example-run/testbed_3d.ron cargo run --example testbed_3d --features "bevy_ci_testing"`
…` setup. (bevyengine#15989) # Objective Adding a `WinitPlugin` to a `MinimalPlugins` setup is a bit tricky and confusing due to having a terrible error message and no examples in the repo. ## Solution Document what you need to add.
# Objective Make UI rendering optional. Quite a few people have been experimenting with using Bevy UI for layout and interaction but replacing the rendering with `bevy_prototype_lyon` or whatever. It's awkward to do though as there is no way to disable the existing UI rendering requiring users to create their own custom node bundles and components. Also, you can't replace the UI's shader and a number of other things. This PR makes the setup and initialization of UI rendering for the RenderApp optional. Then you can do whatever you want by replacing `build_ui_render` with your own function. For instance, one that loads a custom shader. The UI layout and interaction components are still updated as normal. ## Solution Add a field `enable_rendering` to `UiPlugin`. Only call `build_ui_render` and initialize the `UiPipeline` if `enable_rendering` is false. I thought about implementing a "bevy_ui_render" feature but suspect everything is too tightly coupled atm and it would be very fragile. Similar to the struggles with the "bevy_text" feature but worse. --- ## Changelog `UiPlugin` * Added a bool field `enable_rendering`. * Only calls `build_ui_render` and initializes the `UiPipeline` if `enable_rendering` is true. ## Migration Guide `UiPlugin` has a new field `enable_rendering`. If set to false, the UI's rendering systems won't be added to the `RenderApp` and no UI elements will be drawn. The layout and interaction components will still be updated as normal.
# Objective Stumbled upon one of these, and set off in search of more, armed with my trusty `\b(\w+)\s+\1\b`. ## Solution Remove ~one~ one of them.
# Objective The `ui_material` recently gained a harsh red background via bevyengine#15898. I'm assuming this was added for testing and forgotten about. https://pixel-eagle.com/project/b25a040a-a980-4602-b90c-d480ab84076d/run/5268/compare/5259?screenshot=UI%20(User%20Interface)/ui_material.png ## Solution Remove the red background ## Testing `cargo run --example ui_material`
# Objective Fix a tiny mismatch between code and comment
## Objective Be able to depend on the crate for the types without bringing in `smol-hyper` and other http dependencies. ## Solution Create a new `HTTP` feature that is enabled by default.
…evyengine#16018) # Objective Built-in observers & events should be `Reflect` so that components that interact with them can be serialized in scenes. This is a similar pr to bevyengine#14259.
# Objective Making work with `Indices` struct easier. Currently when building indices in some quick-and-dirty code we need to do matches and handle enum variants. ## Solution `Indices::push` utility which works transparently with `U16` and `U32` variants. ## Testing Unit test added.
# Objective
```
cargo check -p bevy_reflect
```
outputs a lot of warnings like:
```
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
--> crates/bevy_reflect/src/impls/std.rs:223:13
|
223 | impl_type_path!($ty);
| ^-------------------
| |
| `TypePath` is not local
| move the `impl` block outside of this constant `_` and up 2 bodies
...
346 | / impl_reflect_for_atomic!(
347 | | ::core::sync::atomic::AtomicIsize,
| | --------------------------------- `AtomicIsize` is not local
348 | | ::core::sync::atomic::Ordering::SeqCst
349 | | );
| |_- in this macro invocation
|
= note: the macro `impl_type_path` defines the non-local `impl`, and may need to be changed
= note: the macro `impl_type_path` may come from an old version of the `bevy_reflect_derive` crate, try updating your dependency with `cargo update -p bevy_reflect_derive`
= note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
= note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint
= note: `#[warn(non_local_definitions)]` on by default
= note: this warning originates in the macro `impl_type_path` which comes from the expansion of the macro `impl_reflect_for_atomic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
## Solution
Move `impl_type_path!` into global scope. Warnings no longer pop up.
## Testing
CI
# Objective Make compiler output more helpful when running `cargo check -p bevy_mesh`. Currently it contains a lot of unreachable patterns/code warnings due to features disabled by default. ## Solution Mute the warnings. ## Testing CI
# Objective - Checks screenshots on Windows - Progress towards bevyengine#15918 ## Solution - Checks screenshots on Windows - Also disable the helmet gltf scene in windows ci as it doesn't work
From TheBevyFlock/bevy_new_2d#317 plus a few other changes.
# Objective Typo-check .hidden files like `.cargo/config_fast_builds.toml` and `.github/*`. Context: bevyengine#16025. ## Solution - Add `ignore-hidden = false` to `typos.toml` to override the default value of `true`. - Add an exception to keep `.git/` ignored in `typos.toml`. - Fix newly-found typos so CI passes. ## Testing Running `typos` locally finds no further typos.
Use the new `disqualified` crate in `QueryEntityError` to make the error message more readable. --- ## Showcase Old: QueryDoesNotMatch(0v1 with components my_game::main::foo::A, my_game::main::foo::B, bevy_pbr::light::point_light::PointLight, bevy_render::primitives::CubemapFrusta, bevy_pbr::bundle::CubemapVisibleEntities, bevy_transform::components::transform::Transform, bevy_transform::components::global_transform::GlobalTransform, bevy_render::view::visibility::Visibility, bevy_render::view::visibility::InheritedVisibility, bevy_render::view::visibility::ViewVisibility, bevy_render::sync_world::SyncToRenderWorld) New: QueryDoesNotMatch(0v1 with components A, B, PointLight, CubemapFrusta, CubemapVisibleEntities, Transform, GlobalTransform, Visibility, InheritedVisibility, ViewVisibility, SyncToRenderWorld) --------- Co-authored-by: Alice Cecile <[email protected]>
# Objective - Code is safer with tests ## Solution - Add a test ## Testing - Test added
# Objective - Less code - Simpler code ## Solution - Remove unnecessary division: `normalize` already does that ## Testing - Test added in bevyengine#16038
# Objective Bevy seems to want to standardize on "American English" spellings. Not sure if this is laid out anywhere in writing, but see also bevyengine#15947. While perusing the docs for `typos`, I noticed that it has a `locale` config option and tried it out. ## Solution Switch to `en-us` locale in the `typos` config and run `typos -w` ## Migration Guide The following methods or fields have been renamed from `*dependants*` to `*dependents*`. - `ProcessorAssetInfo::dependants` - `ProcessorAssetInfos::add_dependant` - `ProcessorAssetInfos::non_existent_dependants` - `AssetInfo::dependants_waiting_on_load` - `AssetInfo::dependants_waiting_on_recursive_dep_load` - `AssetInfos::loader_dependants` - `AssetInfos::remove_dependants_and_labels`
# Objective - Less code - Better iterator (implements `size_hint` for example) ## Solution - Use `either` - This change is free because `bevy_animation` depends on `bevy_asset`, which already depends on `either` ## Testing CI
# Objective - I got tired of calling `enable_state_scoped_entities`, and though it would make more sense to define that at the place where the state is defined ## Solution - add a derive attribute `#[states(scoped_entities)]` when derive `States` or `SubStates` that enables it automatically when adding the state ## Testing - Ran the examples using it, they still work
# Objective - Fixes: bevyengine#15663 ## Solution - Add an `is_forward_plane` method to `Aabb`, and a `contains_aabb` method to `Frustum`. ## Test - I have created a frustum with an offset along with three unit tests to evaluate the `contains_aabb` algorithm. ## Explanation for the Test Cases - To facilitate the code review, I will explain how the frustum is created. Initially, we create a frustum without any offset and then create a cuboid that is just contained within it. <img width="714" alt="image" src="https://github.com/user-attachments/assets/a9ac53a2-f8a3-4e09-b20b-4ee71b27a099"> - Secondly, we move the cuboid by 2 units along both the x-axis and the y-axis to make it more general. ## Reference - [Frustum Culling](https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling#) - [AABB Plane intersection](https://gdbooks.gitbooks.io/3dcollisions/content/Chapter2/static_aabb_plane.html) --------- Co-authored-by: IQuick 143 <[email protected]>
# Objective Add support for multiple box shadows on a single `Node`. ## Solution * Rename `BoxShadow` to `ShadowStyle` and remove its `Component` derive. * Create a new `BoxShadow` component that newtypes a `Vec<ShadowStyle>`. * Add a `new` constructor method to `BoxShadow` for single shadows. * Change `extract_shadows` to iterate through a list of shadows per node. Render order is determined implicitly from the order of the shadows stored in the `BoxShadow` component, back-to-front. Might be more efficient to use a `SmallVec<[ShadowStyle; 1]>` for the list of shadows but not sure if the extra friction is worth it. ## Testing Added a node with four differently coloured shadows to the `box_shadow` example. --- ## Showcase ``` cargo run --example box_shadow ``` <img width="460" alt="four-shadow" src="https://github.com/user-attachments/assets/2f728c47-33b4-42e1-96ba-28a774b94b24"> ## Migration Guide Bevy UI now supports multiple shadows per node. A new struct `ShadowStyle` is used to set the style for each shadow. And the `BoxShadow` component is changed to a tuple struct wrapping a vector containing a list of `ShadowStyle`s. To spawn a node with a single shadow you can use the `new` constructor function: ```rust commands.spawn(( Node::default(), BoxShadow::new( Color::BLACK.with_alpha(0.8), Val::Percent(offset.x), Val::Percent(offset.y), Val::Percent(spread), Val::Px(blur), ) )); ``` --------- Co-authored-by: Alice Cecile <[email protected]>
# Objective - Fix outdated link in README.md Perhaps the link name should be updated as well since the article is no longer labelled as "Contributor's Guide"? Either way better to avoid making users click twice.
# Objective - Fixes bevyengine#16495 ## Solution - Added `Commands::run_schedule`, which internally calls `World::try_run_schedule`, logging any issues. ## Testing - Added doctest - Ran CI ## Showcase Instead of writing: ```rust commands.queue(|world: &mut World| world.run_schedule(FooSchedule)); ``` You can now write: ```rust commands.run_schedule(FooSchedule); ```
…bevyengine#16620) # Objective - dont depend on wgpu if we dont have to ## Solution - works towards this, but doesnt fully accomplish it. the remaining types stopping us from doing this need to be moved upstream, i will PR this ## Testing - 3d_scene runs --------- Co-authored-by: François Mockers <[email protected]>
# Objective ~Blocked on bevyengine#13417~ Motivation is the same as in bevyengine#13417. If users can sort `QueryIter`, to only makes sense to also allow them to use this functionality on `QueryManyIter`. ## Solution Also implement the sorts on `QueryManyIter`. The implementation of the sorts themselves are mostly the same as with `QueryIter` in bevyengine#13417. They differ in that they re-use the `entity_iter` passed to the `iter_many`, and internally call `iter_many_unchecked_manual` on the lens `QueryState` with it. These methods also return a different struct, `QuerySortedManyIter`, because there is no longer a guarantee of unique entities. `QuerySortedManyIter` implements the various `Iterator` traits for read-only iteration, as `QueryManyIter` does + `DoubleEndedIterator`. For mutable iteration, there is both a `fetch_next` and a `fetch_next_back` method. However, they only become available after the user calls `collect_inner` on `QuerySortedManyIter` first. This collects the inner `entity_iter` (this is the sorted one, **not** the original the user passed) to drop all query lens items to avoid aliasing. When TAITs are available this `collect_inner` could be hidden away, until then it is unfortunately not possible to elide this without either regressing read-only iteration, or introducing a whole new type, mostly being a copy of `QuerySortedIter`. As a follow-up we could add a `entities_all_unique` method to check whether the entity list consists of only unique entities, and then return a `QuerySortedIter` from it (under opaque impl Trait if need be), *allowing mutable `Iterator` trait iteration* over what was originally an `iter_many` call. Such a method can also be added to `QueryManyIter`, albeit needing a separate, new return type. ## Testing I've switched the third example/doc test under `sort` out for one that shows the collect_inner/fetch_next_back functionality, otherwise the examples are the same as in bevyengine#13417, adjusted to use `iter_many` instead of `iter`. The `query-iter-many-sorts` test checks for equivalence to the underlying sorts. The test after shows that these sorts *do not* panic after `fetch`/`fetch_next` calls. ## Changelog Added `sort`, `sort_unstable`, `sort_by`, `sort_unstable_by`, `sort_by_key`, `sort_by_cached_key` to `QueryManyIter`. Added `QuerySortedManyIter`.
# Objective - Contributes to bevyengine#15460 ## Solution - Added two new features, `std` (default) and `alloc`, gating `std` and `alloc` behind them respectively. - Added missing `f32` functions to `std_ops` as required. These `f32` methods have been added to the `clippy.toml` deny list to aid in `no_std` development. ## Testing - CI - `cargo clippy -p bevy_math --no-default-features --features libm --target "x86_64-unknown-none"` - `cargo test -p bevy_math --no-default-features --features libm` - `cargo test -p bevy_math --no-default-features --features "libm, alloc"` - `cargo test -p bevy_math --no-default-features --features "libm, alloc, std"` - `cargo test -p bevy_math --no-default-features --features "std"` ## Notes The following items require the `alloc` feature to be enabled: - `CubicBSpline` - `CubicBezier` - `CubicCardinalSpline` - `CubicCurve` - `CubicGenerator` - `CubicHermite` - `CubicNurbs` - `CyclicCubicGenerator` - `RationalCurve` - `RationalGenerator` - `BoxedPolygon` - `BoxedPolyline2d` - `BoxedPolyline3d` - `SampleCurve` - `SampleAutoCurve` - `UnevenSampleCurve` - `UnevenSampleAutoCurve` - `EvenCore` - `UnevenCore` - `ChunkedUnevenCore` This requirement could be relaxed in certain cases, but I had erred on the side of gating rather than modifying. Since `no_std` is a new set of platforms we are adding support to, and the `alloc` feature is enabled by default, this is not a breaking change. --------- Co-authored-by: Benjamin Brienen <[email protected]> Co-authored-by: Matty <[email protected]> Co-authored-by: Joona Aalto <[email protected]>
# Objective - Keep Taffy version up to date Taffy 0.6 doesn't include a huge amount relevant to Bevy. But it does: - Add the `box_sizing` style - Expose the computed `margin` in layout - Traitifies the `Style` struct, which opens up the possibility of using Bevy's `Style` struct directly (although Bevy currently does some style resolution at conversion time which would no longer be cached if it was used directly). - Have a few bug fixes in the layout algorithms ## Solution - Upgrade Taffy to `0.6.0` ## Testing - I've run the `grid` example. All looks good. - More testing is probably warranted. We have had regressions from Taffy upgrades before - Having said that, most of the algorithm changes this cycle were driven by fixing WPT tests run through the new Servo integration. So they're possibly less likely than usual to cause regressions. ## Breaking changes The only "breaking" change is adding a field to `Style`. Probably doesn't bear mentioning? --------- Co-authored-by: Alice Cecile <[email protected]>
# Objective - Exposes raw winit events making Bevy even more modular and powerful for custom plugin developers (e.g. a custom render plugin). XRef: bevyengine#5977 It doesn't quite close the issue as sending events is not supported (or not very useful to be precise). I would think that supporting that requires some extra considerations by someone a bit more familiar with the `bevy_winit` crate. That said, this PR could be a nice step forward. ## Solution Emit `RawWinitWindowEvent` objects for each received event. ## Testing I verified that the events are emitted using a basic test app. I don't think it makes sense to solidify this behavior in one of the examples. --- ## Showcase My example usage for a custom `egui_winit` integration: ```rust for ev in winit_events.read() { if ev.window_id == window.id { let _ = egui_winit.on_window_event(&window, &ev.event); } } ``` --------- Co-authored-by: IceSentry <[email protected]>
# Objective Avoid a premature normalize operation and get better smooth normals for it. ## Inspiration @IceSentry suggested `face_normal()` could have its normalize removed based on [this article](https://iquilezles.org/articles/normals/) in PR bevyengine#16039. ## Solution I did not want to change `face_normal()` to return a vector that's not normalized. The name "normal" implies it'll be normalized. Instead I added the `face_area_normal()` function, whose result is not normalized. Its magnitude is equal two times the triangle's area. I've noted why this is the case in its doc comment. I changed `compute_smooth_normals()` from computing normals from adjacent faces with equal weight to use the area of the faces as a weight. This has the benefit of being cheaper computationally and hopefully produces better normals. The `compute_flat_normals()` is unchanged and still uses `face_normal()`. ## Testing One test was added which shows the bigger triangle having an effect on the normal, but the previous test that uses the same size triangles is unchanged. **WARNING:** No visual test has been done yet. No example exists that demonstrates the compute_smooth_normals(). Perhaps there's a good model to demonstrate what the differences are. I would love to have some input on this. I'd suggest @IceSentry and @stepancheg to review this PR. ## Further Considerations It's possible weighting normals by their area is not definitely better than unweighted. It's possible there may be aesthetic reasons to prefer one over the other. In such a case, we could offer two variants: weighted or unweighted. Or we could offer another function perhaps like this: `compute_smooth_normals_with_weights(|normal, area| 1.0)` which would restore the original unweighted sum of normals. --- ## Showcase Smooth normal calculation now weights adjacent face normals by their area. ## Migration Guide
# Objective - Fixes bevyengine#16078 ## Solution - Rename things to clarify that we _want_ unclipped depth for directional light shadow views, and need some way of disabling the GPU's builtin depth clipping - Use DEPTH_CLIP_CONTROL instead of the fragment shader emulation on supported platforms - Pass only the clip position depth instead of the whole clip position between vertex->fragment shader (no idea if this helps performance or not, compiler might optimize it anyways) - Meshlets - HW raster always uses DEPTH_CLIP_CONTROL since it targets a more limited set of platforms - SW raster was not handling DEPTH_CLAMP_ORTHO correctly, it ended up pretty much doing nothing. - This PR made me realize that SW raster technically should have depth clipping for all views that are not directional light shadows, but I decided not to bother writing it. I'm not sure that it ever matters in practice. If proven otherwise, I can add it. ## Testing - Did you test these changes? If so, how? - Lighting example. Both opaque (no fragment shader) and alpha masked geometry (fragment shader emulation) are working with depth_clip_control, and both work when it's turned off. Also tested meshlet example. - Are there any parts that need more testing? - Performance. I can't figure out a good test scene. - How can other people (reviewers) test your changes? Is there anything specific they need to know? - Toggle depth_clip_control_supported in prepass/mod.rs line 323 to turn this PR on or off. - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? - Native --- ## Migration Guide - `MeshPipelineKey::DEPTH_CLAMP_ORTHO` is now `MeshPipelineKey::UNCLIPPED_DEPTH_ORTHO` - The `DEPTH_CLAMP_ORTHO` shaderdef has been renamed to `UNCLIPPED_DEPTH_ORTHO_EMULATION` - `clip_position_unclamped: vec4<f32>` is now `unclipped_depth: f32`
## Objective Fixes bevyengine#1515 This PR implements a flexible entity cloning system. The primary use case for it is to clone dynamically-generated entities. Example: ```rs #[derive(Component, Clone)] pub struct Projectile; #[derive(Component, Clone)] pub struct Damage { value: f32, } fn player_input( mut commands: Commands, projectiles: Query<Entity, With<Projectile>>, input: Res<ButtonInput<KeyCode>>, ) { // Fire a projectile if input.just_pressed(KeyCode::KeyF) { commands.spawn((Projectile, Damage { value: 10.0 })); } // Triplicate all active projectiles if input.just_pressed(KeyCode::KeyT) { for projectile in projectiles.iter() { // To triplicate a projectile we need to create 2 more clones for _ in 0..2{ commands.clone_entity(projectile) } } } } ``` ## Solution ### Commands Add a `clone_entity` command to create a clone of an entity with all components that can be cloned. Components that can't be cloned will be ignored. ```rs commands.clone_entity(entity) ``` If there is a need to configure the cloning process (like set to clone recursively), there is a second command: ```rs commands.clone_entity_with(entity, |builder| { builder.recursive(true) }); ``` Both of these commands return `EntityCommands` of the cloned entity, so the copy can be modified afterwards. ### Builder All these commands use `EntityCloneBuilder` internally. If there is a need to clone an entity using `World` instead, it is also possible: ```rs let entity = world.spawn(Component).id(); let entity_clone = world.spawn_empty().id(); EntityCloneBuilder::new(&mut world).clone_entity(entity, entity_clone); ``` Builder has methods to `allow` or `deny` certain components during cloning if required and can be extended by implementing traits on it. This PR includes two `EntityCloneBuilder` extensions: `CloneEntityWithObserversExt` to configure adding cloned entity to observers of the original entity, and `CloneEntityRecursiveExt` to configure cloning an entity recursively. ### Clone implementations By default, all components that implement either `Clone` or `Reflect` will be cloned (with `Clone`-based implementation preferred in case component implements both). This can be overriden on a per-component basis: ```rs impl Component for SomeComponent { const STORAGE_TYPE: StorageType = StorageType::Table; fn get_component_clone_handler() -> ComponentCloneHandler { // Don't clone this component ComponentCloneHandler::Ignore } } ``` ### `ComponentCloneHandlers` Clone implementation specified in `get_component_clone_handler` will get registered in `ComponentCloneHandlers` (stored in `bevy_ecs::component::Components`) at component registration time. The clone handler implementation provided by a component can be overriden after registration like so: ```rs let component_id = world.components().component_id::<Component>().unwrap() world.get_component_clone_handlers_mut() .set_component_handler(component_id, ComponentCloneHandler::Custom(component_clone_custom)) ``` The default clone handler for all components that do not explicitly define one (or don't derive `Component`) is `component_clone_via_reflect` if `bevy_reflect` feature is enabled, and `component_clone_ignore` (noop) otherwise. Default handler can be overriden using `ComponentCloneHandlers::set_default_handler` ### Handlers Component clone handlers can be used to modify component cloning behavior. The general signature for a handler that can be used in `ComponentCloneHandler::Custom` is as follows: ```rs pub fn component_clone_custom( world: &mut DeferredWorld, entity_cloner: &EntityCloner, ) { // implementation } ``` The `EntityCloner` implementation (used internally by `EntityCloneBuilder`) assumes that after calling this custom handler, the `target` entity has the desired version of the component from the `source` entity. ### Builder handler overrides Besides component-defined and world-overriden handlers, `EntityCloneBuilder` also has a way to override handlers locally. It is mainly used to allow configuration methods like `recursive` and `add_observers`. ```rs // From observer clone handler implementation impl CloneEntityWithObserversExt for EntityCloneBuilder<'_> { fn add_observers(&mut self, add_observers: bool) -> &mut Self { if add_observers { self.override_component_clone_handler::<ObservedBy>(ComponentCloneHandler::Custom( component_clone_observed_by, )) } else { self.remove_component_clone_handler_override::<ObservedBy>() } } } ``` ## Testing Includes some basic functionality tests and doctests. Performance-wise this feature is the same as calling `clone` followed by `insert` for every entity component. There is also some inherent overhead due to every component clone handler having to access component data through `World`, but this can be reduced without breaking current public API in a later PR.
# Objective Fixes bevyengine#15941 ## Solution Created https://crates.io/crates/variadics_please and moved the code there; updating references `bevy_utils/macros` is deleted. ## Testing cargo check ## Migration Guide Use `variadics_please::{all_tuples, all_tuples_with_size}` instead of `bevy::utils::{all_tuples, all_tuples_with_size}`.
# Objective - Supersedes bevyengine#16344 ## Solution - Updated `rodio` version requirement to `0.20`. - [Changelog](https://github.com/RustAudio/rodio/blob/master/CHANGELOG.md) ## Testing - CI checks. Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This patch adds the infrastructure necessary for Bevy to support
*bindless resources*, by adding a new `#[bindless]` attribute to
`AsBindGroup`.
Classically, only a single texture (or sampler, or buffer) can be
attached to each shader binding. This means that switching materials
requires breaking a batch and issuing a new drawcall, even if the mesh
is otherwise identical. This adds significant overhead not only in the
driver but also in `wgpu`, as switching bind groups increases the amount
of validation work that `wgpu` must do.
*Bindless resources* are the typical solution to this problem. Instead
of switching bindings between each texture, the renderer instead
supplies a large *array* of all textures in the scene up front, and the
material contains an index into that array. This pattern is repeated for
buffers and samplers as well. The renderer now no longer needs to switch
binding descriptor sets while drawing the scene.
Unfortunately, as things currently stand, this approach won't quite work
for Bevy. Two aspects of `wgpu` conspire to make this ideal approach
unacceptably slow:
1. In the DX12 backend, all binding arrays (bindless resources) must
have a constant size declared in the shader, and all textures in an
array must be bound to actual textures. Changing the size requires a
recompile.
2. Changing even one texture incurs revalidation of all textures, a
process that takes time that's linear in the total size of the binding
array.
This means that declaring a large array of textures big enough to
encompass the entire scene is presently unacceptably slow. For example,
if you declare 4096 textures, then `wgpu` will have to revalidate all
4096 textures if even a single one changes. This process can take
multiple frames.
To work around this problem, this PR groups bindless resources into
small *slabs* and maintains a free list for each. The size of each slab
for the bindless arrays associated with a material is specified via the
`#[bindless(N)]` attribute. For instance, consider the following
declaration:
```rust
#[derive(AsBindGroup)]
#[bindless(16)]
struct MyMaterial {
#[buffer(0)]
color: Vec4,
#[texture(1)]
#[sampler(2)]
diffuse: Handle<Image>,
}
```
The `#[bindless(N)]` attribute specifies that, if bindless arrays are
supported on the current platform, each resource becomes a binding array
of N instances of that resource. So, for `MyMaterial` above, the `color`
attribute is exposed to the shader as `binding_array<vec4<f32>, 16>`,
the `diffuse` texture is exposed to the shader as
`binding_array<texture_2d<f32>, 16>`, and the `diffuse` sampler is
exposed to the shader as `binding_array<sampler, 16>`. Inside the
material's vertex and fragment shaders, the applicable index is
available via the `material_bind_group_slot` field of the `Mesh`
structure. So, for instance, you can access the current color like so:
```wgsl
// `uniform` binding arrays are a non-sequitur, so `uniform` is automatically promoted
// to `storage` in bindless mode.
@group(2) @binding(0) var<storage> material_color: binding_array<Color, 4>;
...
@Fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
let color = material_color[mesh[in.instance_index].material_bind_group_slot];
...
}
```
Note that portable shader code can't guarantee that the current platform
supports bindless textures. Indeed, bindless mode is only available in
Vulkan and DX12. The `BINDLESS` shader definition is available for your
use to determine whether you're on a bindless platform or not. Thus a
portable version of the shader above would look like:
```wgsl
#ifdef BINDLESS
@group(2) @binding(0) var<storage> material_color: binding_array<Color, 4>;
#else // BINDLESS
@group(2) @binding(0) var<uniform> material_color: Color;
#endif // BINDLESS
...
@Fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
#ifdef BINDLESS
let color = material_color[mesh[in.instance_index].material_bind_group_slot];
#else // BINDLESS
let color = material_color;
#endif // BINDLESS
...
}
```
Importantly, this PR *doesn't* update `StandardMaterial` to be bindless.
So, for example, `scene_viewer` will currently not run any faster. I
intend to update `StandardMaterial` to use bindless mode in a follow-up
patch.
A new example, `shaders/shader_material_bindless`, has been added to
demonstrate how to use this new feature.
Here's a Tracy profile of `submit_graph_commands` of this patch and an
additional patch (not submitted yet) that makes `StandardMaterial` use
bindless. Red is those patches; yellow is `main`. The scene was Bistro
Exterior with a hack that forces all textures to opaque. You can see a
1.47x mean speedup.

## Migration Guide
* `RenderAssets::prepare_asset` now takes an `AssetId` parameter.
* Bin keys now have Bevy-specific material bind group indices instead of
`wgpu` material bind group IDs, as part of the bindless change. Use the
new `MaterialBindGroupAllocator` to map from bind group index to bind
group ID.
…cking (bevyengine#16388) # Objective - Allow bevy_sprite_picking backend to pass through transparent sections of the sprite. - Fixes bevyengine#14929 ## Solution - After sprite picking detects the cursor is within a sprites rect, check the pixel at that location on the texture and check that it meets an optional transparency cutoff. Change originally created for mod_picking on bevy 0.14 (aevyrie/bevy_mod_picking#373) ## Testing - Ran Sprite Picking example to check it was working both with transparency enabled and disabled - ModPicking version is currently in use in my own isometric game where this has been an extremely noticeable issue ## Showcase  ## Migration Guide Sprite picking now ignores transparent regions (with an alpha value less than or equal to 0.1). To configure this, modify the `SpriteBackendSettings` resource. --------- Co-authored-by: andriyDev <[email protected]>
…aces (bevyengine#16402) # Objective This was always a bit weird; `IntoIterator` is considered more idiomatic in Rust. The reason these used `Into<Vec<..>>` in the first place was (to my knowledge) because of concerns that passing an already-owned vector would cause a redundant allocation if the iterator API was used instead. However, I have looked at simple examples for this scenario and the generated assembly is identical (i.e. `into_iter().collect()` is effectively converted to a no-op). ## Solution As described in the title. ## Testing It compiles. Ran existing tests. ## Migration Guide The cubic splines API now uses `IntoIterator` in places where it used `Into<Vec<..>>`. For most users, this will have little to no effect (it is largely more permissive). However, in case you were using some unusual input type that implements `Into<Vec<..>>` without implementing `IntoIterator`, you can migrate by converting the input to a `Vec<..>` before passing it into the interface.
…6459) # Objective Remove the `min` and `max` fields from `LayoutContext`. It doesn't seem useful to cache these values, it's simpler just to call `min_element` and `max_element` on the `physical_size` field. ## Migration Guide The `min` and `max` fields have been removed from `LayoutContext`. To retrieve these values call `min_element` and `max_element` on `LayoutContent::physical_size` instead.
# Objective `flush_and_reserve_invalid_assuming_no_entities` was made for the old rendering world (which was reset every frame) and is usused since the 0.15 retained rendering world, but wasn't removed yet. It is pub, but is undocumented apart from the safety comment. ## Solution Remove `flush_and_reserve_invalid_assuming_no_entities` and the safety invariants this method required for `EntityMeta`, `EntityLocation`, `TableId` and `TableRow`. This reduces the amount of unsafe code & safety invariants and makes bevyengine#16047 easier. ## Alternatives - Document `flush_and_reserve_invalid_assuming_no_entities` and keep it unchanged - Document `flush_and_reserve_invalid_assuming_no_entities` and change it to be based on `EntityMeta::INVALID` ## Migration Guide - exchange `Entities::flush_and_reserve_invalid_assuming_no_entities` for `reserve` and `flush_as_invalid` and notify us if that's insufficient --------- Co-authored-by: Benjamin Brienen <[email protected]>
# Objective The `UiBoxShadowSamples` resource should be renamed to `BoxShadowSamples` so it matches the `BoxShadow` component. ## Migration Guide `UiBoxShadowSamples` has been renamed to `BoxShadowSamples`
# Objective Make documentation of a component's required components more visible by moving it to the type's docs ## Solution Change `#[require]` from a derive macro helper to an attribute macro. Disadvantages: - this silences any unused code warnings on the component, as it is used by the macro! - need to import `require` if not using the ecs prelude (I have not included this in the migration guilde as Rust tooling already suggests the fix) --- ## Showcase  --------- Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: JMS55 <[email protected]>
# Objective - Fixes bevyengine#16594 ## Solution - `StateTransitionSteps` was made public ## Testing - _Did you test these changes? If so, how?_ I am now able to import it and use it. --- ## Showcase - Users can now write their own state scoped resources ```rust fn init_state_scoped_resource<R: Resource + FromWorld>( &mut self, state: impl States, ) -> &mut Self { use bevy::state::state::StateTransitionSteps; // this PR in action self.add_systems( StateTransition, ( clear_state_scoped_resource_impl::<_, R>(state.clone()) .in_set(StateTransitionSteps::ExitSchedules), // and here init_state_scoped_resource_impl::<_, R>(state) .in_set(StateTransitionSteps::EnterSchedules), // here too ), ); self } ```
# Objective - dont depend on wgpu if we dont have to ## Solution - works towards this, but doesnt fully accomplish it. bevy_mesh depends on bevy_image ## Testing - 3d_scene runs --------- Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: BD103 <[email protected]>
# Objective Fix bevyengine#16553
# Objective - Contributes to bevyengine#15460 ## Solution - Removed `petgraph` as a dependency from the `bevy_ecs` crate. - Replaced `TarjanScc` and `GraphMap` with specialised in-tree alternatives. ## Testing - Ran CI locally. - Added new unit tests to check ordering invariants. - Confirmed `petgraph` is no longer present in `cargo tree -p bevy_ecs` ## Migration Guide The `Dag::graph` method no longer returns a `petgraph` `DiGraph` and instead returns the new `DiGraph` type within `bevy_ecs`. Edge and node iteration methods are provided so conversion to the `petgraph` type should be trivial if required. ## Notes - `indexmap` was already in the dependency graph for `bevy_ecs`, so its inclusion here makes no difference to compilation time for Bevy. - The implementation for `Graph` is heavily inspired from the `petgraph` original, with specialisations added to simplify and improve the type. - `petgraph` does have public plans for `no_std` support, however there is no timeframe on if or when that functionality will be available. Moving to an in-house solution in the interim allows Bevy to continue developing its `no_std` offerings and further explore alternate graphing options. --------- Co-authored-by: Lixou <[email protected]> Co-authored-by: vero <[email protected]>
89139d5 to
45d5e2e
Compare
This allows sound mutable iteration without needing to call collect_inner().
45d5e2e to
fc66c25
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Objective
Allow sound mutable streaming iteration of
QuerySortedManyIterwithout needing to callcollect_inner().Solution
The reason we can't allow this in the current version is that the lens items used during sorting may alias with the data items from another copy of the same entity. To fix this, we need to drop the lens items early in a way that no longer requires them to be valid. So, we wrap them in
MaybeUninitand drop them early, so that rust no longer requires them to be valid after the sort method returns.Testing
Added a new unit test that fails miri with Undefined Behavior without the
MaybeUninitchange, but passes with it.