Commit graph

1567 commits

Author SHA1 Message Date
Alice Cecile
b33dae31ec Rename get_multiple APIs to get_many (#4384)
# Objective

-  std's new APIs do the same thing as `Query::get_multiple_mut`, but are called `get_many`: https://github.com/rust-lang/rust/pull/83608

## Solution

- Find and replace `get_multiple` with `get_many`
2022-03-31 20:59:26 +00:00
devil ira
48ac955afd Fix loading non-TriangleList meshes without normals in gltf loader (#4376)
# Objective
Make it so that loading in a mesh without normals that is not a `TriangleList` succeeds.

## Solution
Flat normals can only be calculated on a mesh made of triangles.
Check whether the mesh is a `TriangleList` before trying to compute missing normals.

## Additional changes
The panic condition in `duplicate_vertices` did not make sense to me. I moved it to `compute_flat_normals` where the algorithm would produce incorrect results if the mesh is not a `TriangleList`.

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-03-31 20:43:01 +00:00
Daniel McNab
aca7fc1854 Remove outdated perf comments (#4374)
# Objective

- The perf comments, added (by me) in https://github.com/bevyengine/bevy/pull/1349, became outdated once the initialisation call started to take an exclusive reference, (presumably in https://github.com/bevyengine/bevy/pull/1525).
- They have been naïvely transferred along ever since

## Solution

- Remove them
2022-03-31 20:43:00 +00:00
SecretPocketCat
3af90b67a6 Update RemovedComponents doc comment (#4373)
# Objective

- Clarify `RemovedComponents` are flushed in `CoreStage::Last` and systems relying on that should run before that stage

## Solution

- Update `RemovedComponents` doc comment
2022-03-31 20:24:32 +00:00
Boxy
637a149910 unsafeify World::entities_mut (#4093)
# Objective
make bevy ecs a lil bit less unsound

## Solution
make unsound API unsafe so that there is an unsafe block to blame:

```rust
use bevy_ecs::prelude::*;

#[derive(Debug, Component)]
struct Foo(u8);

fn main() {
    let mut world = World::new();
    let e1 = world.spawn().id();
    let e2 = world.spawn().insert(Foo(2)).id();
    world.entities_mut().meta[0] = world.entities_mut().meta[1].clone();
    let foo = world.entity(e1).get::<Foo>().unwrap();
    // whoo i love having components i dont have
    dbg!(foo);
}
```

This is not _strictly_ speaking UB, however: 
- `Query::get_multiple` cannot work if this is allowed
- bevy_ecs is a pile of unsafe code whose soundness generally depends on the world being in a "correct" state with "no funny business" so it seems best to disallow this
- it is trivial to get bevy to panic inside of functions with safety invariants that have been violated (the entity location is not valid)
- it seems to violate what the safety invariant on `Entities::flush` is trying to ensure
2022-03-30 23:52:45 +00:00
Chris Russell
2b35dbabfd impl Reflect and Debug for Mesh2dHandle (#4368)
# Objective

An entity spawned with `MaterialMesh2dBundle<M>` cannot be saved and spawned using `DynamicScene` because the `Mesh2dHandle` component does not `impl Reflect`.  

## Solution

Add `#[derive(Reflect)]` and `#[reflect(Component)]` to `Mesh2dHandle`, and call `register_type` in `SpritePlugin`.  Also add `#[derive(Debug)]` since I'm touching the `derive`s anyway.
2022-03-30 19:56:17 +00:00
François
3537c6ae2d Fix animation: shadow and wireframe support (#4367)
# Objective

Animation with shadows crashes with:
```
thread 'main' panicked at 'wgpu error: Validation Error

Caused by:
    In Device::create_render_pipeline
      note: label = `shadow_pipeline`
    error matching VERTEX shader requirements against the pipeline
    shader global ResourceBinding { group: 1, binding: 1 } is not available in the layout pipeline layout
    visibility flags don't include the shader stage
```


Animation with wireframe crashes with:
```
thread 'main' panicked at 'wgpu error: Validation Error

Caused by:
    In Device::create_render_pipeline
      note: label = `opaque_mesh_pipeline`
    error matching VERTEX shader requirements against the pipeline
    shader global ResourceBinding { group: 2, binding: 0 } is not available in the layout pipeline layout
    binding is missing from the pipeline layout
```

## Solution

- Fix the bindings
2022-03-30 19:56:16 +00:00
François
f6bc9a022d Sprites - keep color as 4 f32 (#4361)
# Objective

- Fix #4356

## Solution

- Do not reduce the color of sprites to 4 u8
2022-03-30 19:38:24 +00:00
Alice Cecile
509548190b Add get_multiple and get_multiple_mut APIs for Query and QueryState (#4298)
# Objective

- The inability to have multiple active mutable borrows into a query is a common source of borrow-checker pain for users.
- This is a pointless restriction if and only if we can guarantee that the entities they are accessing are unique.
- This could already by bypassed with get_unchecked, but that is an extremely unsafe API.
- Closes https://github.com/bevyengine/bevy/issues/2042.

## Solution

- Add `get_multiple`, `get_multiple_mut` and their unchecked equivalents (`multiple` and `multiple_mut`) to `Query` and `QueryState`.
- Improve the `QueryEntityError` type to provide more useful error information.

## Changelog

- Added `get_multiple`, `get_multiple_mut` and their unchecked equivalents (`multiple` and `multiple_mut`) to Query and QueryState.

## Migration Guide

- The `QueryEntityError` enum now has a `AliasedMutability variant, and returns the offending entity.

## Context

This is a fresh attempt at #3333; rebasing was behaving very badly and it was important to rebase on top of the recent query soundness fixes. Many thanks to all the reviewers in that thread, especially @BoxyUwU for the help with lifetimes.

## To-do

- [x] Add compile fail tests
- [x] Successfully deduplicate code
- [x] Decide what to do about failing doc tests
- [x] Get some reviews for lifetime soundness
2022-03-30 19:16:48 +00:00
bilsen
63fee2572b ParamSet for conflicting SystemParam:s (#2765)
# Objective
Add a system parameter `ParamSet` to be used as container for conflicting parameters.

## Solution
Added two methods to the SystemParamState trait, which gives the access used by the parameter. Did the implementation. Added some convenience methods to FilteredAccessSet. Changed `get_conflicts` to return every conflicting component instead of breaking on the first conflicting `FilteredAccess`.


Co-authored-by: bilsen <40690317+bilsen@users.noreply.github.com>
2022-03-29 23:39:38 +00:00
Rob Parrett
7ff3d876fa Clean up duplicated color conversion code (#4360)
# Objective

Cleans up some duplicated color -> u32 conversion code in `bevy_sprite` and `bevy_ui`

## Solution

Use `as_linear_rgba_u32` which was added recently by #4088
2022-03-29 23:03:22 +00:00
Yutao Yuan
954022c799 Add text wrapping support to Text2d (#4347)
# Objective

Fixes #4344.

## Solution

Add a new component `Text2dBounds` to `Text2dBundle` that specifies the maximum width and height of text. Text will wrap according to this size.
2022-03-29 23:03:20 +00:00
KDecay
c7c08f95cb Fix gamepad connection system ordering (#4313)
# Objective

- Part of the splitting process of #3692.

## Solution

- Change the `gamepad_connection_system` to run after the `InputSystem` label.

## Reasons

I changed the `gamepad_connection_system` to run after the `InputSystem` instead of in parallel, because this system checks the `GamepadEvent`s which get send inside of the `gamepad_event_system`. This means that the `gamepad_connection_system` could respond to the events one frame later, instead of instantly resulting in one frame lag.

Old possible case:
1. `gamepad_connection_system` (reacts to the `GamepadEvent`s too early)
2. `gamepad_event_system` (sends the `GamepadEvent`s)

New fixed ordering:
1. `gamepad_event_system` (sends the `GamepadEvent`s)
2. `gamepad_connection_system` (reacts to the `GamepadEvent`s)
2022-03-29 22:39:21 +00:00
KDecay
f3a61327a4 Remove margins.rs (#4284)
# Objective

- Closes #335.
- Part of the splitting process of #3503.

## Solution

- Remove the `margins.rs` file containing the `Margins` type.

## Reasons

- It is unused inside of `bevy`.
- The `Rect`/`UiRect` is identical to the `Margins` type and is also used for margins inside of `bevy` (rename of `Rect` happens in #4276)
- Discussion in #3503.

## Changelog

### Removed

- The `Margins` type got removed.

## Migration Guide

- The `Margins` type got removed. To migrate you just have to change every occurrence of `Margins` to `UiRect`.
2022-03-29 22:39:18 +00:00
KDecay
f5e53ba6f5 Only insert or remove input if needed (#4273)
# Objective

We are currently inserting an `input` into `pressed` even if it is already pressed. This also applies to releasing an input. This is not a big deal, but since we are already checking if the `input` is pressed or not we might as well remove the cost of the value update caused by the `pressed.insert` method.

Related to #4209

## Solution

Only insert or remove input if needed.
2022-03-29 22:39:16 +00:00
Jakob Hellermann
551d9f6cd7 use error scope to handle errors on shader module creation (#3675)
related: https://github.com/bevyengine/bevy/pull/3289

In addition to validating shaders early when debug assertions are enabled, use the new [error scopes](https://gpuweb.github.io/gpuweb/#error-scopes) API when creating a shader module.

I chose to keep the early validation (and thereby parsing twice) when debug assertions are enabled in, because it lets as handle errors ourselves and display them with pretty colors, while the error scopes API just gives us a string we can display.



This change pulls in `futures-util` as a new dependency for `future.now_or_never()`. I can inline that part of futures-lite into `bevy_render` to keep the compilation time lower if that's preferred.
2022-03-29 22:39:14 +00:00
Mika
6844a6f4fd Introduce SystemLabel's for RenderAssetPlugin, and change Image preparation system to run before others (#3917)
# Objective

Fixes `StandardMaterial` texture update (see sample code below).

Most probably fixes #3674 (did not test)

## Solution

Material updates, such as PBR update, reference the underlying `GpuImage`. Like here: 9a7852db0f/crates/bevy_pbr/src/pbr_material.rs (L177)

However, currently the `GpuImage` update may actually happen *after* the material update fetches the gpu image. Resulting in the material actually not being updated for the correct gpu image.

In this pull req, I introduce new systemlabels for the renderassetplugin. Also assigned the RenderAssetPlugin::<Image> to the `PreAssetExtract` stage, so that it is executed before any material updates.

Code to test.

Expected behavior:
* should update to red texture

Unexpected behavior (before this merge):
* texture stays randomly as green one (depending on the execution order of systems)

```rust
use bevy::{
    prelude::*,
    render::render_resource::{Extent3d, TextureDimension, TextureFormat},
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_startup_system(setup)
        .add_system(changes)
        .run();
}

struct Iteration(usize);

#[derive(Component)]
struct MyComponent;

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
    mut images: ResMut<Assets<Image>>,
) {
    commands.spawn_bundle(PointLightBundle {
        point_light: PointLight {
            ..Default::default()
        },
        transform: Transform::from_xyz(4.0, 8.0, 4.0),
        ..Default::default()
    });

    commands.spawn_bundle(PerspectiveCameraBundle {
        transform: Transform::from_xyz(-2.0, 0.0, 5.0)
            .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
        ..Default::default()
    });

    commands.insert_resource(Iteration(0));

    commands
        .spawn_bundle(PbrBundle {
            mesh: meshes.add(Mesh::from(shape::Quad::new(Vec2::new(3., 2.)))),
            material: materials.add(StandardMaterial {
                base_color_texture: Some(images.add(Image::new(
                    Extent3d {
                        width: 600,
                        height: 400,
                        depth_or_array_layers: 1,
                    },
                    TextureDimension::D2,
                    [0, 255, 0, 128].repeat(600 * 400), // GREEN
                    TextureFormat::Rgba8Unorm,
                ))),
                ..Default::default()
            }),
            ..Default::default()
        })
        .insert(MyComponent);
}

fn changes(
    mut materials: ResMut<Assets<StandardMaterial>>,
    mut images: ResMut<Assets<Image>>,
    mut iteration: ResMut<Iteration>,
    webview_query: Query<&Handle<StandardMaterial>, With<MyComponent>>,
) {
    if iteration.0 == 2 {
        let material = materials.get_mut(webview_query.single()).unwrap();

        let image = images
            .get_mut(material.base_color_texture.as_ref().unwrap())
            .unwrap();

        image
            .data
            .copy_from_slice(&[255, 0, 0, 255].repeat(600 * 400));
    }

    iteration.0 += 1;
}
```

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-29 19:44:45 +00:00
James Liu
31bd4ecbbc Mesh Skinning. Attempt #3 (#4238)
# Objective
Load skeletal weights and indices from GLTF files. Animate meshes.

## Solution
 - Load skeletal weights and indices from GLTF files.
 - Added `SkinnedMesh` component and ` SkinnedMeshInverseBindPose` asset
 - Added `extract_skinned_meshes` to extract joint matrices.
 - Added queue phase systems for enqueuing the buffer writes.

Some notes:

 -  This ports part of # #2359 to the current main.
 -  This generates new `BufferVec`s and bind groups every frame. The expectation here is that the number of `Query::get` calls during extract is probably going to be the stronger bottleneck, with up to 256 calls per skinned mesh. Until that is optimized, caching buffers and bind groups is probably a non-concern.
 - Unfortunately, due to the uniform size requirements, this means a 16KB buffer is allocated for every skinned mesh every frame. There's probably a few ways to get around this, but most of them require either compute shaders or storage buffers, which are both incompatible with WebGL2.

Co-authored-by: james7132 <contact@jamessliu.com>
Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
2022-03-29 18:31:13 +00:00
Robert Swain
54d2e86afc bevy_transform: Use Changed in the query for much faster transform_propagate_system (#4180)
# Objective

- Improve transform propagation performance

## Solution

- Use `Changed<Transform>` as part of the `root_query` and `transform_query` to avoid the indirection of having to look up the `Entity` in the `changed_transform_query`
- Get rid of the `changed_transform_query` entirely
- `transform_propagate_system` execution time for `many_cubes -- sphere` dropped from 1.07ms to 0.159ms, an 85% reduction for this system. Frame rate increased from ~42fps to ~44fps
2022-03-29 03:05:01 +00:00
MrGVSV
f16768d868 bevy_derive: Add derives for Deref and DerefMut (#4328)
# Objective

A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like:

```rust
#[derive(Component)]
struct Items(Vec<String>);

fn give_sword(query: Query<&mut Items>) { 
  query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom"));
}
```

> We could then define another struct that wraps `Vec<String>` without anything clashing in the query.

However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this.

Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations.


## Solution

Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field:

```rust
#[derive(Deref)]
struct Foo(String);

#[derive(Deref, DerefMut)]
struct Bar {
  name: String,
}
```

This allows us to then remove that pesky `.0`:

```rust
#[derive(Component, Deref, DerefMut)]
struct Items(Vec<String>);

fn give_sword(query: Query<&mut Items>) { 
  query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom"));
}
```

### Alternatives

There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now).

### Considerations

One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree.

### Additional Context

Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630))

---

## Changelog

- Add `Deref` derive macro (exported to prelude)
- Add `DerefMut` derive macro (exported to prelude)
- Updated most newtypes in examples to use one or both derives

Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
Boxy
28ba87e6c8 CI runs cargo miri test -p bevy_ecs (#4310)
# Objective

Fixes #1529
Run bevy_ecs in miri

## Solution

- Don't set thread names when running in miri rust-lang/miri/issues/1717
- Update `event-listener` to `2.5.2` as previous versions have UB that is detected by miri: [event-listener commit](1fa31c553e)
- Ignore memory leaks when running in miri as they are impossible to track down rust-lang/miri/issues/1481
- Make `table_add_remove_many` test less "many" because miri is really quite slow :)
- Make CI run `RUSTFLAGS="-Zrandomize-layout" MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-tag-raw-pointers -Zmiri-disable-isolation" cargo +nightly miri test -p bevy_ecs`
2022-03-25 00:26:07 +00:00
Carter Anderson
207ebde020 Always update clusters and remove per-frame allocations (#4169)
* Refactor assign_lights_to_clusters to always clear + update clusters, even if the screen size isn't available yet / is zero. This fixes #4167. We still avoid the "expensive" per-light work when the screen size isn't available yet. I also consolidated some logic to eliminate some redundancies.
* Removed _a ton_ of (potentially very large) per-frame reallocations
  * Removed `Res<VisiblePointLights>` (a vec) in favor of  `Res<GlobalVisiblePointLights>` (a hashmap). We were allocating a new hashmap every frame, the collecting it into a vec every frame, then in another system _re-generating the hashmap_. It is always used like a hashmap, might as well embrace that. We now reuse the same hashmap every frame and dont use any intermediate collections.
  * We were re-allocating Clusters aabb and light vectors every frame by re-constructing Clusters every frame. We now re-use the existing collections.
  * Reuse per-camera VisiblePointLight vecs when possible instead of allocating them every frame. We now only insert VisiblePointLights if the component doesn't exist yet.
2022-03-24 00:20:27 +00:00
Carter Anderson
b1c3e9862d Auto-label function systems with SystemTypeIdLabel (#4224)
This adds the concept of "default labels" for systems (currently scoped to "parallel systems", but this could just as easily be implemented for "exclusive systems"). Function systems now include their function's `SystemTypeIdLabel` by default.

This enables the following patterns:

```rust
// ordering two systems without manually defining labels
app
  .add_system(update_velocity)
  .add_system(movement.after(update_velocity))

// ordering sets of systems without manually defining labels
app
  .add_system(foo)
  .add_system_set(
    SystemSet::new()
      .after(foo)
      .with_system(bar)
      .with_system(baz)
  )
```

Fixes: #4219
Related to: #4220 

Credit to @aevyrie @alice-i-cecile @DJMcNab (and probably others) for proposing (and supporting) this idea about a year ago. I was a big dummy that both shut down this (very good) idea and then forgot I did that. Sorry. You all were right!
2022-03-23 22:53:56 +00:00
Kurt Kühnert
9e450f2827 Compute Pipeline Specialization (#3979)
# Objective

- Fixes #3970
- To support Bevy's shader abstraction(shader defs, shader imports and hot shader reloading) for compute shaders, I have followed carts advice and change the `PipelinenCache` to accommodate both compute and render pipelines.

## Solution

- renamed `RenderPipelineCache` to `PipelineCache`
- Cached Pipelines are now represented by an enum (render, compute)
- split the `SpecializedPipelines` into `SpecializedRenderPipelines` and `SpecializedComputePipelines`
- updated the game of life example

## Open Questions

- should `SpecializedRenderPipelines` and `SpecializedComputePipelines` be merged and how would we do that?
- should the `get_render_pipeline` and `get_compute_pipeline` methods be merged?
- is pipeline specialization for different entry points a good pattern




Co-authored-by: Kurt Kühnert <51823519+Ku95@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-23 00:27:26 +00:00
Robert Swain
0a4136d266 Add a helper for storage buffers similar to UniformVec (#4079)
# Objective

- Add a helper for storage buffers similar to `UniformVec`

## Solution

- Add a `StorageBuffer<T, U>` where `T` is the main body of the shader struct without any final variable-sized array member, and `U` is the type of the items in a variable-sized array.
- Use `()` as the type for unwanted parts, e.g. `StorageBuffer<(), Vec4>::default()` would construct a binding that would work with `struct MyType { data: array<vec4<f32>>; }` in WGSL and `StorageBuffer<MyType, ()>::default()` would work with `struct MyType { ... }` in WGSL as long as there are no variable-sized arrays.
- Std430 requires that there is at most one variable-sized array in a storage buffer, that if there is one it is the last member of the binding, and that it has at least one item. `StorageBuffer` handles all of these constraints.
2022-03-22 21:23:50 +00:00
Boxy
024d98457c yeet unsound lifetime annotations on Query methods (#4243)
# Objective
Continuation of #2964 (I really should have checked other methods when I made that PR)

yeet unsound lifetime annotations on `Query` methods.
Example unsoundness:
```rust
use bevy::prelude::*;

fn main() {
    App::new().add_startup_system(bar).add_system(foo).run();
}

pub fn bar(mut cmds: Commands) {
    let e = cmds.spawn().insert(Foo { a: 10 }).id();
    cmds.insert_resource(e);
}

#[derive(Component, Debug, PartialEq, Eq)]
pub struct Foo {
    a: u32,
}
pub fn foo(mut query: Query<&mut Foo>, e: Res<Entity>) {
    dbg!("hi");
    {
        let data: &Foo = query.get(*e).unwrap();
        let data2: Mut<Foo> = query.get_mut(*e).unwrap();
        assert_eq!(data, &*data2); // oops UB
    }

    {
        let data: &Foo = query.single();
        let data2: Mut<Foo> = query.single_mut();
        assert_eq!(data, &*data2); // oops UB
    }

    {
        let data: &Foo = query.get_single().unwrap();
        let data2: Mut<Foo> = query.get_single_mut().unwrap();
        assert_eq!(data, &*data2); // oops UB
    }

    {
        let data: &Foo = query.iter().next().unwrap();
        let data2: Mut<Foo> = query.iter_mut().next().unwrap();
        assert_eq!(data, &*data2); // oops UB
    }

    {
        let mut opt_data: Option<&Foo> = None;
        let mut opt_data_2: Option<Mut<Foo>> = None;
        query.for_each(|data| opt_data = Some(data));
        query.for_each_mut(|data| opt_data_2 = Some(data));
        assert_eq!(opt_data.unwrap(), &*opt_data_2.unwrap()); // oops UB
    }
    dbg!("bye");
}

```

## Solution
yeet unsound lifetime annotations on `Query` methods

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-22 02:49:41 +00:00
François
fbe7a49d5b Gltf animations (#3751)
# Objective

- Load informations for animations from GLTF
- Make experimenting on animations easier

# Non Objective

- Implement a solutions for all animations in Bevy. This would need a discussion / RFC. The goal here is only to have the information available to try different APIs

## Solution

- Load animations with a representation close to the GLTF spec
- Add an example to display animations. There is an animation driver in the example, not in Bevy code, to show how it can be used. The example is cycling between examples from the official gltf sample ([AnimatedTriangle](https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/AnimatedTriangle), [BoxAnimated](https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/BoxAnimated)), and one from me with some cases not present in the official examples.


https://user-images.githubusercontent.com/8672791/150696656-073403f0-d921-43b6-beaf-099c7aee16ed.mp4




Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-22 02:26:34 +00:00
Robert Swain
6c085cba47 bevy_render: Support removal of nodes, edges, subgraphs (#3048)
Add support for removing nodes, edges, and subgraphs. This enables live re-wiring of the render graph.

This was something I did to support the MSAA implementation, but it turned out to be unnecessary there. However, it is still useful so here it is in its own PR.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-21 23:58:37 +00:00
Boxy
050d2b7f00 yeet World::components_mut >:( (#4092)
# Objective
make bevy ecs a lil bit less unsound
## Solution
yeet unsound API `World::components_mut`:
```rust
use bevy_ecs::prelude::*;

#[derive(Component)]
struct Foo(u8);

#[derive(Debug, Component)]
struct Bar([u8; 100]);

fn main() {
    let mut world = World::new();
    let e = world.spawn().insert(Foo(0)).id();
    *world.components_mut() = Default::default();
    let bar = world.entity_mut(e).remove::<Bar>().unwrap();
    // oopsies reading memory copied from outside allocation
    dbg!(bar);
}
```
2022-03-21 23:43:08 +00:00
James Liu
4c1678c78d Hide docs for concrete impls of Fetch, FetchState, and SystemParamState (#4250)
# Objective
 The following pages in the docs are rather noisy, and the types they point to are not particularly useful by themselves:

 - http://dev-docs.bevyengine.org/bevy/ecs/query/index.html
 - http://dev-docs.bevyengine.org/bevy/ecs/system/index.html

## Solution
 
- Replace docs on these types with `#[doc(hidden)]`.
- Hide `InputMarker`  too.
2022-03-21 05:23:36 +00:00
Jakob Hellermann
685b6e59be register Camera{2,3}d components for reflection (#4269)
# Objective

When loading a gltf scene with a camera, bevy will panic at ``thread 'main' panicked at 'scene contains the unregistered type `bevy_render:📷:bundle::Camera3d`. consider registering the type using `app.register_type::<T>()`', /home/jakob/dev/rust/contrib/bevy/bevy/crates/bevy_scene/src/scene_spawner.rs:332:35``.

## Solution

Register the camera types to fix the panic.
2022-03-20 21:54:11 +00:00
Mathis
cd694c0d08 Prevent event from getting registered twice (#4258)
# Objective

As described in  #4257, registering an Event twice would cause some systems to miss events on some starts, since the event buffer is cleared + swapped multiple times.

Fixes #4257

## Solution

A simple check whether the event is already registered is added, making adding an Event a second time a no-op.
2022-03-20 21:54:10 +00:00
Chris Foster
b0ddce36bd Check an Input's pressed set before adding to just_released. (#4209)
# Objective

- Fixes #4208

## Solution

- Adds a check before inserting into an `Input`'s `just_released` set, in the same way that one exists for adding into the `just_pressed` set.
2022-03-20 21:54:09 +00:00
Jakob Hellermann
3e631e6234 gltf-loader: disable backface culling if material is double-sided (#4270)
# Objective

The  [glTF spec](8e798b02d2/specification/2.0/Specification.adoc (395-double-sided)) the `doubleSided` has the following to say about the `doubleSided` boolean:

> When this value is false, back-face culling is enabled, i.e., only front-facing triangles are rendered.
> When this value is true, back-face culling is disabled and double sided lighting is enabled. The back-face MUST have its normals reversed before the lighting equation is evaluated.

## Solution
Disable backface culling when `doubleSided: true`.
2022-03-20 21:32:38 +00:00
Robert Swain
fee7a26137 Tracy spans around main 3D passes (#4182)
# Objective

- Make visible how much time is spent building the Opaque3d, AlphaMask3d, and Transparent3d passes

## Solution

- Add a `trace` feature to `bevy_core_pipeline`
- Add tracy spans around the three passes
- I didn't do this for shadows, sprites, etc as they are only one pass in the node. Perhaps it should be split into 3 nodes to allow insertion of other nodes between...?
2022-03-19 12:57:47 +00:00
Robert Swain
ac8bbafc5c Faster view frustum culling (#4181)
# Objective

- Reduce time spent in the `check_visibility` system

## Solution

- Use `Vec3A` for all bounding volume types to leverage SIMD optimisations and to avoid repeated runtime conversions from `Vec3` to `Vec3A`
- Inline all bounding volume intersection methods
- Add on-the-fly calculated `Aabb` -> `Sphere` and do `Sphere`-`Frustum` intersection tests before `Aabb`-`Frustum` tests. This is faster for `many_cubes` but could be slower in other cases where the sphere test gives a false-positive that the `Aabb` test discards. Also, I tested precalculating the `Sphere`s and inserting them alongside the `Aabb` but this was slower. 
- Do not test meshes against the far plane. Apparently games don't do this anymore with infinite projections, and it's one fewer plane to test against. I made it optional and still do the test for culling lights but that is up for discussion.
- These collectively reduce `check_visibility` execution time in `many_cubes -- sphere` from 2.76ms to 1.48ms and increase frame rate from ~42fps to ~44fps
2022-03-19 04:41:28 +00:00
Boxy
e7a9420443 Change Cow<[ComponentId]> to Box<[ComponentId]> (#4185)
`Cow::Borrowed` was never used
2022-03-19 04:14:27 +00:00
Alice Cecile
7ce3ae43e3 Bump Bevy to 0.7.0-dev (#4230)
# Objective

- The [dev docs](https://dev-docs.bevyengine.org/bevy/index.html#) show version 0.6.0, which is actively misleading.

[Image of the problem](https://cdn.discordapp.com/attachments/695741366520512563/953513612943704114/Screenshot_20220316-154100_Firefox-01.jpeg)

Noticed by @ickk, fix proposed by @mockersf.

## Solution

- Bump the version across all Bevy crates to 0.7.0 dev.
- Set a reminder in the Release Checklist to remember to do this each release.
2022-03-19 03:54:15 +00:00
Carter Anderson
de677dbfc9 Use more ergonomic span syntax (#4246)
Tracing added support for "inline span entering", which cuts down on a lot of complexity:

```rust
let span = info_span!("my_span").entered();
```

This adapts our code to use this pattern where possible, and updates our docs to recommend it.

This produces equivalent tracing behavior. Here is a side by side profile of "before" and "after" these changes.
![image](https://user-images.githubusercontent.com/2694663/158912137-b0aa6dc8-c603-425f-880f-6ccf5ad1b7ef.png)
2022-03-18 04:19:21 +00:00
Robert Swain
0529f633f9 KTX2/DDS/.basis compressed texture support (#3884)
# Objective

- Support compressed textures including 'universal' formats (ETC1S, UASTC) and transcoding of them to 
- Support `.dds`, `.ktx2`, and `.basis` files

## Solution

- Fixes https://github.com/bevyengine/bevy/issues/3608 Look there for more details.
- Note that the functionality is all enabled through non-default features. If it is desirable to enable some by default, I can do that.
- The `basis-universal` crate, used for `.basis` file support and for transcoding, is built on bindings against a C++ library. It's not feasible to rewrite in Rust in a short amount of time. There are no Rust alternatives of which I am aware and it's specialised code. In its current state it doesn't support the wasm target, but I don't know for sure. However, it is possible to build the upstream C++ library with emscripten, so there is perhaps a way to add support for web too with some shenanigans.
- There's no support for transcoding from BasisLZ/ETC1S in KTX2 files as it was quite non-trivial to implement and didn't feel important given people could use `.basis` files for ETC1S.
2022-03-15 22:26:46 +00:00
Daniel McNab
6e61fef67d Obviate the need for RunSystem, and remove it (#3817)
# Objective

- Fixes #3300
- `RunSystem` is messy

## Solution

- Adds the trick theorised in https://github.com/bevyengine/bevy/issues/3300#issuecomment-991791234

P.S. I also want this for an experimental refactoring of `Assets`, to remove the duplication of `Events<AssetEvent<T>>`


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-15 02:16:55 +00:00
Alice Cecile
a304fd9a99 Split bevy_hierarchy out from bevy_transform (#4168)
# Objective

- Hierarchy tools are not just used for `Transform`: they are also used for scenes.
- In the future there's interest in using them for other features, such as visiibility inheritance.
- The fact that these tools are found in `bevy_transform` causes a great deal of user and developer confusion
- Fixes #2758.

## Solution

- Split `bevy_transform` into two!
- Make everything work again.

Note that this is a very tightly scoped PR: I *know* there are code quality and docs issues that existed in bevy_transform that I've just moved around. We should fix those in a seperate PR and try to merge this ASAP to reduce the bitrot involved in splitting an entire crate.

## Frustrations

The API around `GlobalTransform` is a mess: we have massive code and docs duplication, no link between the two types and no clear way to extend this to other forms of inheritance.

In the medium-term, I feel pretty strongly that `GlobalTransform` should be replaced by something like `Inherited<Transform>`, which lives in `bevy_hierarchy`:

- avoids code duplication
- makes the inheritance pattern extensible
- links the types at the type-level
- allows us to remove all references to inheritance from `bevy_transform`, making it more useful as a standalone crate and cleaning up its docs

## Additional context

- double-blessed by @cart in https://github.com/bevyengine/bevy/issues/4141#issuecomment-1063592414 and https://github.com/bevyengine/bevy/issues/2758#issuecomment-913810963
- preparation for more advanced / cleaner hierarchy tools: go read https://github.com/bevyengine/rfcs/pull/53 !
- originally attempted by @finegeometer in #2789. It was a great idea, just needed more discussion!

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-15 01:54:05 +00:00
Jakob Hellermann
bf6de89622 use marker components for cameras instead of name strings (#3635)
**Problem**
- whenever you want more than one of the builtin cameras (for example multiple windows, split screen, portals), you need to add a render graph node that executes the correct sub graph, extract the camera into the render world and add the correct `RenderPhase<T>` components
- querying for the 3d camera is annoying because you need to compare the camera's name to e.g. `CameraPlugin::CAMERA_3d`

**Solution**
- Introduce the marker types `Camera3d`, `Camera2d` and `CameraUi`
-> `Query<&mut Transform, With<Camera3d>>` works
- `PerspectiveCameraBundle::new_3d()` and `PerspectiveCameraBundle::<Camera3d>::default()` contain the `Camera3d` marker
- `OrthographicCameraBundle::new_3d()` has `Camera3d`, `OrthographicCameraBundle::new_2d()` has `Camera2d`
- remove `ActiveCameras`, `ExtractedCameraNames`
- run 2d, 3d and ui passes for every camera of their respective marker
-> no custom setup for multiple windows example needed

**Open questions**
- do we need a replacement for `ActiveCameras`? What about a component `ActiveCamera { is_active: bool }` similar to `Visibility`?

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-12 00:41:06 +00:00
Robert Swain
0e821da704 bevy_render: Batch insertion for prepare_uniform_components (#4179)
# Objective

- Make insertion of uniform components faster

## Solution

- Use batch insertion in the prepare_uniform_components system
- Improves `many_cubes -- sphere` from ~42fps to ~43fps


Co-authored-by: François <mockersf@gmail.com>
2022-03-11 23:20:18 +00:00
robtfm
5af746457e fix cluster tiling calculations (#4148)
# Objective

fix cluster tilesize and tilecount calculations.
Fixes https://github.com/bevyengine/bevy/issues/4127 & https://github.com/bevyengine/bevy/issues/3596

## Solution

- calculate tilesize as smallest integers such that dimensions.xy() tiles will cover the screen
- calculate final dimensions as smallest integers such that final dimensions * tilesize will cover the screen

there is more cleanup that could be done in these functions. a future PR will likely remove the tilesize completely, so this is just a minimal change set to fix the current bug at small screen sizes

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-10 01:14:21 +00:00
Roman
2b11202614 fix mul_vec3 tranformation order: should be scale -> rotate -> translate (#3811)
# Objective

Lets say we need to rotate stretched object for this purpose we can created stretched `Child` and add as child to `Parent`, later we can rotate `Parent`, `Child` in this situation should rotate keeping it form, it is not the case with `SpriteBundle` currently. If you try to do it with `SpriteBundle` it will deform.

## Solution

My pull request fixes order of transformations to scale -> rotate -> translate, with this fix `SpriteBundle` behaves as expected in described rotation, without deformation. Here is quote from "Essential Mathematics for Games":

> Generally, the desired order we wish to use for these transforms is to scale first, then rotate, then translate. Scaling first gives us the scaling along the axes we expect. We can then rotate around the origin of the frame, and then translate it into place.

I'm must say when I was using `MaterialMesh2dBundle` it behaves correctly in both cases with `bevy main` and with my fix, don't know why, was not able to figure it out why there is difference.

here is code I was using for testing:
```rust
use bevy::{
    prelude::*,
    render::render_resource::{Extent3d, TextureDimension, TextureFormat},
    sprite::{MaterialMesh2dBundle, Mesh2dHandle},
};

fn main() {
    let mut app = App::new();
    app.insert_resource(ClearColor(Color::rgb(0.1, 0.2, 0.3)))
        .add_plugins(DefaultPlugins)
        .add_startup_system(setup);
    app.run();
}

fn setup(
    mut commands: Commands,
    mut images: ResMut<Assets<Image>>,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    let mut c = OrthographicCameraBundle::new_2d();
    c.orthographic_projection.scale = 1.0 / 10.0;
    commands.spawn_bundle(c);
    // note: mesh somehow works for both variants
    // let quad: Mesh2dHandle = meshes.add(Mesh::from(shape::Quad::default())).into();
    // let child = commands
    //     .spawn_bundle(MaterialMesh2dBundle {
    //         mesh: quad.clone(),
    //         transform: Transform::from_translation(Vec3::new(0.0, 0.0, -1.0))
    //             .with_scale(Vec3::new(10.0, 1.0, 1.0)),
    //         material: materials.add(ColorMaterial::from(Color::BLACK)),
    //         ..Default::default()
    //     })
    //     .id();
    // commands
    //     .spawn_bundle(MaterialMesh2dBundle {
    //         mesh: quad,
    //         transform: Transform::from_rotation(Quat::from_rotation_z(0.78))
    //             .with_translation(Vec3::new(0.0, 0.0, 10.0)),
    //         material: materials.add(ColorMaterial::from(Color::WHITE)),
    //         ..Default::default()
    //     })
    //     .push_children(&[child]);

    let white = images.add(get_image(Color::rgb(1.0, 1.0, 1.0)));
    let black = images.add(get_image(Color::rgb(0.0, 0.0, 0.0)));
    let child = commands
        .spawn_bundle(SpriteBundle {
            texture: black,
            transform: Transform::from_translation(Vec3::new(0.0, 0.0, -1.0))
                .with_scale(Vec3::new(10.0, 1.0, 1.0)),
            ..Default::default()
        })
        .id();
    commands
        .spawn_bundle(SpriteBundle {
            texture: white,
            transform: Transform::from_rotation(Quat::from_rotation_z(0.78))
                .with_translation(Vec3::new(0.0, 0.0, 10.0)),
            ..Default::default()
        })
        .push_children(&[child]);
}

fn get_image(color: Color) -> Image {
    let mut bytes = Vec::with_capacity((1 * 1 * 4 * 4) as usize);
    let color = color.as_rgba_f32();
    bytes.extend(color[0].to_le_bytes());
    bytes.extend(color[1].to_le_bytes());
    bytes.extend(color[2].to_le_bytes());
    bytes.extend(1.0_f32.to_le_bytes());
    Image::new(
        Extent3d {
            width: 1,
            height: 1,
            depth_or_array_layers: 1,
        },
        TextureDimension::D2,
        bytes,
        TextureFormat::Rgba32Float,
    )
}

```

here is screenshot with `bevy main` and my fix:
![examples](https://user-images.githubusercontent.com/816292/151708304-c07c891e-da70-43f4-9c41-f85fa166a96d.png)
2022-03-08 05:47:36 +00:00
robtfm
244687a0bb Dynamic light clusters (#3968)
# Objective

provide some customisation for default cluster setup
avoid "cluster index lists is full" in all cases (using a strategy outlined by @superdump)

## Solution

Add ClusterConfig enum (which can be inserted into a view at any time) to allow specifying cluster setup with variants:
- None (do not do any light assignment - for views which do not require light info, e.g. minimaps etc)
- Single (one cluster)
- XYZ (explicit cluster counts in each dimension)
- FixedZ (most similar to current - specify Z-slices and total, then x and y counts are dynamically determined to give approximately square clusters based on current aspect ratio)
Defaults to FixedZ { total: 4096, z: 24 } which is similar to the current setup.

Per frame, estimate the number of indices that would be required for the current config and decrease the cluster counts / increase the cluster sizes in the x and y dimensions if the index list would be too small.

notes:

- I didn't put ClusterConfig in the camera bundles to avoid introducing a dependency from bevy_render to bevy_pbr. the ClusterConfig enum comes with a pbr-centric impl block so i didn't want to move that into bevy_render either.
- ~Might want to add None variant to cluster config for views that don't care about lights?~
- Not well tested for orthographic
- ~there's a cluster_muck branch on my repo which includes some diagnostics / a modified lighting example which may be useful for tyre-kicking~ (outdated, i will bring it up to date if required)

anecdotal timings:

FPS on the lighting demo is negligibly better (~5%), maybe due to a small optimisation constraining the light aabb to be in front of the camera
FPS on the lighting demo with 100 extra lights added is ~33% faster, and also renders correctly as the cluster index count is no longer exceeded
2022-03-08 04:56:42 +00:00
François
4add96b1be Cleanup doc / comments about changed defaults (#4144)
# Objective

- Update comment about default audio format
- remove doc about msaa in wasm
2022-03-08 02:11:59 +00:00
François
de2a47c2ba export TaskPoolThreadAssignmentPolicy (#4145)
# Objective

- Fix #2163
- Allow configuration of thread pools through `DefaultTaskPoolOptions`

## Solution

- `TaskPoolThreadAssignmentPolicy` was already public but not exported. Export it.
2022-03-08 01:54:36 +00:00
Gabriel Bourgeois
e41c5c212c Fix UI node Transform change detection (#4138)
# Objective

Fixes #4133 

## Solution

Add comparisons to make sure we don't dereference `Mut<>` in the two places where `Transform` is being mutated. `GlobalTransform` implementation already works properly so fixing Transform automatically fixed that as well.
2022-03-08 01:00:23 +00:00