Commit graph

292 commits

Author SHA1 Message Date
James Liu
2d727afaf7 Flatten render commands (#6885)
# Objective
Speed up the render phase of rendering. Simplify the trait structure for render commands.

## Solution

 - Merge `EntityPhaseItem` into `PhaseItem` (`EntityPhaseItem::entity` -> `PhaseItem::entity`)
 - Merge `EntityRenderCommand` into `RenderCommand`.
 - Add two associated types to `RenderCommand`: `RenderCommand::ViewWorldQuery` and `RenderCommand::WorldQuery`.
 - Use the new associated types to construct two `QueryStates`s for `RenderCommandState`.
 - Hoist any `SQuery<T>` fetches in `EntityRenderCommand`s into the aformentioned two queries. Batch fetch them all at once.

## Performance
`main_opaque_pass_3d` is slightly faster on `many_foxes` (427.52us -> 401.15us)

![image](https://user-images.githubusercontent.com/3137680/206359804-9928b20a-7d92-41f8-bf7d-6e8c5cc802f0.png)

The shadow pass node is also slightly faster (344.52 -> 338.24us)

![image](https://user-images.githubusercontent.com/3137680/206359977-1212198d-f933-49a0-80f1-62ff88eb5727.png)

## Future Work

 - Can we hoist the view level queries out of the core loop?

---

## Changelog
Added: `PhaseItem::entity`
Added: `RenderCommand::ViewWorldQuery` associated type.
Added: `RenderCommand::ItemorldQuery` associated type.
Added: `Draw<T>::prepare` optional trait function.
Removed: `EntityPhaseItem` trait

## Migration Guide
TODO
2023-01-04 01:13:30 +00:00
Aceeri
8ad9a7c7c4 Rename camera "priority" to "order" (#6908)
# Objective
The documentation for camera priority is very confusing at the moment, it requires a bit of "double negative" kind of thinking.

# Solution
Flipping the wording on the documentation to reflect more common usecases like having an overlay camera and also renaming it to "order", since priority implies that it will override the other camera rather than have both run.
2022-12-25 00:39:30 +00:00
ickk
a0448eca2f enum Visibility component (#6320)
Consolidation of all the feedback about #6271 as well as the addition of an "unconditionally visible" mode.

# Objective

The current implementation of the `Visibility` struct simply wraps a boolean.. which seems like an odd pattern when rust has such nice enums that allow for more expression using pattern-matching. 

Additionally as it stands Bevy only has two settings for visibility of an entity: 
- "unconditionally hidden" `Visibility { is_visible: false }`, 
- "inherit visibility from parent" `Visibility { is_visible: true }`
   where a root level entity set to "inherit" is visible. 

Note that given the behaviour, the current naming of the inner field is a little deceptive or unclear.

Using an enum for `Visibility` opens the door for adding an extra behaviour mode. This PR adds a new "unconditionally visible" mode, which causes an entity to be visible even if its Parent entity is hidden. There should not really be any performance cost to the addition of this new mode.

--
The recently added `toggle` method is removed in this PR, as its semantics could be confusing with 3 variants.

## Solution

Change the Visibility component into
```rust
enum Visibility {
  Hidden,    // unconditionally hidden
  Visible,   // unconditionally visible
  Inherited, // inherit visibility from parent
}
```

---

## Changelog

### Changed

`Visibility` is now an enum

## Migration Guide

- evaluation of the `visibility.is_visible` field should now check for `visibility == Visibility::Inherited`.
- setting the `visibility.is_visible` field should now directly set the value: `*visibility = Visibility::Inherited`.
- usage of `Visibility::VISIBLE` or `Visibility::INVISIBLE` should now use `Visibility::Inherited` or `Visibility::Hidden` respectively.
- `ComputedVisibility::INVISIBLE` and `SpatialBundle::VISIBLE_IDENTITY` have been renamed to `ComputedVisibility::HIDDEN` and `SpatialBundle::INHERITED_IDENTITY` respectively.






Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-12-25 00:39:29 +00:00
IceSentry
f119d9df8e Add DrawFunctionsInternals::id() (#6745)
# Objective

- Every usage of `DrawFunctionsInternals::get_id()` was followed by a `.unwrap()`. which just adds boilerplate.

## Solution

- Introduce a fallible version of `DrawFunctionsInternals::get_id()` and use it where possible.
- I also took the opportunity to improve the error message a little in the case where it fails.

---

## Changelog

- Added `DrawFunctionsInternals::id()`
2022-11-28 13:54:13 +00:00
François
d44e86507f Shader defs can now have a value (#5900)
# Objective

- shaders defs can now have a `bool` or `int` value
- `#if SHADER_DEF <operator> 3`
  - ok if `SHADER_DEF` is defined, has the correct type and pass the comparison
  - `==`, `!=`, `>=`, `>`, `<`, `<=` supported
- `#SHADER_DEF` or `#{SHADER_DEF}`
  - will be replaced by the value in the shader code
---

## Migration Guide

- replace `shader_defs.push(String::from("NAME"));` by `shader_defs.push("NAME".into());`
- if you used shader def `NO_STORAGE_BUFFERS_SUPPORT`, check how `AVAILABLE_STORAGE_BUFFER_BINDINGS` is now used in Bevy default shaders
2022-11-21 22:38:29 +00:00
Torstein Grindvik
daa57fe489 Add try_* to add_slot_edge, add_node_edge (#6720)
# Objective

`add_node_edge` and `add_slot_edge` are fallible methods, but are always used with `.unwrap()`.
`input_node` is often unwrapped as well.
This points to having an infallible behaviour as default, with an alternative fallible variant if needed.

Improves readability and ergonomics.

## Solution

- Change `add_node_edge` and `add_slot_edge` to panic on error.
- Change `input_node` to panic on `None`.
- Add `try_add_node_edge` and `try_add_slot_edge` in case fallible methods are needed.
- Add `get_input_node` to still be able to get an `Option`.
---

## Changelog

### Added

- `try_add_node_edge`
- `try_add_slot_edge`
- `get_input_node`

### Changed

- `add_node_edge` is now infallible (panics on error)
- `add_slot_edge` is now infallible (panics on error)
- `input_node` now panics on `None`

## Migration Guide

Remove `.unwrap()` from `add_node_edge` and `add_slot_edge`.
For cases where the error was handled, use `try_add_node_edge` and `try_add_slot_edge` instead.

Remove `.unwrap()` from `input_node`.
For cases where the option was handled, use `get_input_node` instead.


Co-authored-by: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com>
2022-11-21 21:58:39 +00:00
Torstein Grindvik
174819be83 ExtractComponent output optional associated type (#6699)
# Objective

Allow more use cases where the user may benefit from both `ExtractComponentPlugin` _and_ `UniformComponentPlugin`.

## Solution

Add an associated type to `ExtractComponent` in order to allow specifying the output component (or bundle).

Make `extract_component` return an `Option<_>` such that components can be extracted only when needed.

What problem does this solve?

`ExtractComponentPlugin` allows extracting components, but currently the output type is the same as the input.
This means that use cases such as having a settings struct which turns into a uniform is awkward.

For example we might have:

```rust
struct MyStruct {
    enabled: bool,
    val: f32
}

struct MyStructUniform {
    val: f32
}
```

With the new approach, we can extract `MyStruct` only when it is enabled, and turn it into its related uniform.

This chains well with `UniformComponentPlugin`.

The user may then:

```rust
app.add_plugin(ExtractComponentPlugin::<MyStruct>::default());
app.add_plugin(UniformComponentPlugin::<MyStructUniform>::default());
```

This then saves the user a fair amount of boilerplate.


## Changelog

### Changed

- `ExtractComponent` can specify output type, and outputting is optional.



Co-authored-by: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com>
2022-11-21 13:19:44 +00:00
Jakub Arnold
4de4e54755 Update post_processing example to not render UI with first pass camera (#6469)
# Objective

Make sure the post processing example won't render UI twice.

## Solution

Disable UI on the first pass camera with `UiCameraConfig`
2022-11-14 22:34:26 +00:00
Aevyrie
c3c4088317 Fix instancing example for hdr (#6554)
# Objective

- Using the instancing example as reference, I found it was breaking when enabling HDR on the camera. I found that this was because, unlike in internal code, this was not updating the specialization key with `view.hdr`.

## Solution

- Add the missing HDR bit.
2022-11-12 09:31:03 +00:00
Boxy
30e35764a1 Replace WorldQueryGats trait with actual gats (#6319)
# Objective

Replace `WorldQueryGats` trait with actual gats

## Solution

Replace `WorldQueryGats` trait with actual gats

---

## Changelog

- Replaced `WorldQueryGats` trait with actual gats

## Migration Guide

- Replace usage of `WorldQueryGats` assoc types with the actual gats on `WorldQuery` trait
2022-11-03 16:33:05 +00:00
Carter Anderson
1bb751cb8d Plugins own their settings. Rework PluginGroup trait. (#6336)
# Objective

Fixes #5884 #2879
Alternative to #2988 #5885 #2886

"Immutable" Plugin settings are currently represented as normal ECS resources, which are read as part of plugin init. This presents a number of problems:

1. If a user inserts the plugin settings resource after the plugin is initialized, it will be silently ignored (and use the defaults instead)
2. Users can modify the plugin settings resource after the plugin has been initialized. This creates a false sense of control over settings that can no longer be changed.

(1) and (2) are especially problematic and confusing for the `WindowDescriptor` resource, but this is a general problem.

## Solution

Immutable Plugin settings now live on each Plugin struct (ex: `WindowPlugin`). PluginGroups have been reworked to support overriding plugin values. This also removes the need for the `add_plugins_with` api, as the `add_plugins` api can use the builder pattern directly. Settings that can be used at runtime continue to be represented as ECS resources.

Plugins are now configured like this:

```rust
app.add_plugin(AssetPlugin {
  watch_for_changes: true,
  ..default()
})
```

PluginGroups are now configured like this:

```rust
app.add_plugins(DefaultPlugins
  .set(AssetPlugin {
    watch_for_changes: true,
    ..default()
  })
)
```

This is an alternative to #2988, which is similar. But I personally prefer this solution for a couple of reasons:
* ~~#2988 doesn't solve (1)~~ #2988 does solve (1) and will panic in that case. I was wrong!
* This PR directly ties plugin settings to Plugin types in a 1:1 relationship, rather than a loose "setup resource" <-> plugin coupling (where the setup resource is consumed by the first plugin that uses it).
* I'm not a huge fan of overloading the ECS resource concept and implementation for something that has very different use cases and constraints.

## Changelog

- PluginGroups can now be configured directly using the builder pattern. Individual plugin values can be overridden by using `plugin_group.set(SomePlugin {})`, which enables overriding default plugin values.  
- `WindowDescriptor` plugin settings have been moved to `WindowPlugin` and `AssetServerSettings` have been moved to `AssetPlugin`
- `app.add_plugins_with` has been replaced by using `add_plugins` with the builder pattern.

## Migration Guide

The `WindowDescriptor` settings have been moved from a resource to `WindowPlugin::window`:

```rust
// Old (Bevy 0.8)
app
  .insert_resource(WindowDescriptor {
    width: 400.0,
    ..default()
  })
  .add_plugins(DefaultPlugins)

// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(WindowPlugin {
  window: WindowDescriptor {
    width: 400.0,
    ..default()
  },
  ..default()
}))
```


The `AssetServerSettings` resource has been removed in favor of direct `AssetPlugin` configuration:

```rust
// Old (Bevy 0.8)
app
  .insert_resource(AssetServerSettings {
    watch_for_changes: true,
    ..default()
  })
  .add_plugins(DefaultPlugins)

// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(AssetPlugin {
  watch_for_changes: true,
  ..default()
}))
```

`add_plugins_with` has been replaced by `add_plugins` in combination with the builder pattern:

```rust
// Old (Bevy 0.8)
app.add_plugins_with(DefaultPlugins, |group| group.disable::<AssetPlugin>());

// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.build().disable::<AssetPlugin>());
```
2022-10-24 21:20:33 +00:00
ira
92ba6224b9 Use SpatialBundle/TransformBundle in examples (#6002)
Does what it do

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-10-13 12:53:18 +00:00
ira
3aaf746675 Example cleanup (#6131)
Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-09-30 13:25:27 +00:00
Charles
8073362039 add globals to mesh view bind group (#5409)
# Objective

- It's often really useful to have access to the time when writing shaders.

## Solution

- Add a UnifformBuffer in the mesh view bind group
- This buffer contains the time, delta time and a wrapping frame count

https://user-images.githubusercontent.com/8348954/180130314-97948c2a-2d11-423d-a9c4-fb5c9d1892c7.mp4

---

## Changelog

- Added a `GlobalsUniform` at position 9 of the mesh view bind group

## Notes

The implementation is currently split between bevy_render and bevy_pbr because I was basing my implementation on the `ViewPlugin`. I'm not sure if that's the right way to structure it.

I named this `globals` instead of just time because we could potentially add more things to it.

## References in other engines

- Godot: <https://docs.godotengine.org/en/stable/tutorials/shaders/shader_reference/canvas_item_shader.html#global-built-ins>
    - Global time since startup, in seconds, by default resets to 0 after 3600 seconds
    - Doesn't seem to have anything else
- Unreal: <https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Materials/ExpressionReference/Constant/>
    - Generic time value that updates every frame. Can be paused or scaled.
    - Frame count node, doesn't seem to be an equivalent for shaders: <https://docs.unrealengine.com/4.26/en-US/BlueprintAPI/Utilities/GetFrameCount/>
- Unity: <https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html>
    - time since startup in seconds. No mention of time wrapping. Stored as a `vec4(t/20, t, t*2, t*3)` where `t` is the value in seconds
    - Also has delta time, sin time and cos time
- ShaderToy: <https://www.shadertoy.com/howto>
    - iTime is the time since startup in seconds.
    - iFrameRate
    - iTimeDelta
    - iFrame frame counter

Co-authored-by: Charles <IceSentry@users.noreply.github.com>
2022-09-28 04:20:27 +00:00
Carter Anderson
01aedc8431 Spawn now takes a Bundle (#6054)
# Objective

Now that we can consolidate Bundles and Components under a single insert (thanks to #2975 and #6039), almost 100% of world spawns now look like `world.spawn().insert((Some, Tuple, Here))`. Spawning an entity without any components is an extremely uncommon pattern, so it makes sense to give spawn the "first class" ergonomic api. This consolidated api should be made consistent across all spawn apis (such as World and Commands).

## Solution

All `spawn` apis (`World::spawn`, `Commands:;spawn`, `ChildBuilder::spawn`, and `WorldChildBuilder::spawn`) now accept a bundle as input:

```rust
// before:
commands
  .spawn()
  .insert((A, B, C));
world
  .spawn()
  .insert((A, B, C);

// after
commands.spawn((A, B, C));
world.spawn((A, B, C));
```

All existing instances of `spawn_bundle` have been deprecated in favor of the new `spawn` api. A new `spawn_empty` has been added, replacing the old `spawn` api.  

By allowing `world.spawn(some_bundle)` to replace `world.spawn().insert(some_bundle)`, this opened the door to removing the initial entity allocation in the "empty" archetype / table done in `spawn()` (and subsequent move to the actual archetype in `.insert(some_bundle)`).

This improves spawn performance by over 10%:
![image](https://user-images.githubusercontent.com/2694663/191627587-4ab2f949-4ccd-4231-80eb-80dd4d9ad6b9.png)

To take this measurement, I added a new `world_spawn` benchmark.

Unfortunately, optimizing `Commands::spawn` is slightly less trivial, as Commands expose the Entity id of spawned entities prior to actually spawning. Doing the optimization would (naively) require assurances that the `spawn(some_bundle)` command is applied before all other commands involving the entity (which would not necessarily be true, if memory serves). Optimizing `Commands::spawn` this way does feel possible, but it will require careful thought (and maybe some additional checks), which deserves its own PR. For now, it has the same performance characteristics of the current `Commands::spawn_bundle` on main.

**Note that 99% of this PR is simple renames and refactors. The only code that needs careful scrutiny is the new `World::spawn()` impl, which is relatively straightforward, but it has some new unsafe code (which re-uses battle tested BundlerSpawner code path).** 

---

## Changelog

- All `spawn` apis (`World::spawn`, `Commands:;spawn`, `ChildBuilder::spawn`, and `WorldChildBuilder::spawn`) now accept a bundle as input
- All instances of `spawn_bundle` have been deprecated in favor of the new `spawn` api
- World and Commands now have `spawn_empty()`, which is equivalent to the old `spawn()` behavior.  

## Migration Guide

```rust
// Old (0.8):
commands
  .spawn()
  .insert_bundle((A, B, C));
// New (0.9)
commands.spawn((A, B, C));

// Old (0.8):
commands.spawn_bundle((A, B, C));
// New (0.9)
commands.spawn((A, B, C));

// Old (0.8):
let entity = commands.spawn().id();
// New (0.9)
let entity = commands.spawn_empty().id();

// Old (0.8)
let entity = world.spawn().id();
// New (0.9)
let entity = world.spawn_empty();
```
2022-09-23 19:55:54 +00:00
Carter Anderson
cd15f0f5be Accept Bundles for insert and remove. Deprecate insert/remove_bundle (#6039)
# Objective

Take advantage of the "impl Bundle for Component" changes in #2975 / add the follow up changes discussed there.

## Solution

- Change `insert` and `remove` to accept a Bundle instead of a Component (for both Commands and World)
- Deprecate `insert_bundle`, `remove_bundle`, and `remove_bundle_intersection`
- Add `remove_intersection`

---

## Changelog

- Change `insert` and `remove` now accept a Bundle instead of a Component (for both Commands and World)
- `insert_bundle` and `remove_bundle` are deprecated
 

## Migration Guide

Replace `insert_bundle` with `insert`:
```rust
// Old (0.8)
commands.spawn().insert_bundle(SomeBundle::default());
// New (0.9)
commands.spawn().insert(SomeBundle::default());
```

Replace `remove_bundle` with `remove`:
```rust
// Old (0.8)
commands.entity(some_entity).remove_bundle::<SomeBundle>();
// New (0.9)
commands.entity(some_entity).remove::<SomeBundle>();
```

Replace `remove_bundle_intersection` with `remove_intersection`:
```rust
// Old (0.8)
world.entity_mut(some_entity).remove_bundle_intersection::<SomeBundle>();
// New (0.9)
world.entity_mut(some_entity).remove_intersection::<SomeBundle>();
```

Consider consolidating as many operations as possible to improve ergonomics and cut down on archetype moves:
```rust
// Old (0.8)
commands.spawn()
  .insert_bundle(SomeBundle::default())
  .insert(SomeComponent);

// New (0.9) - Option 1
commands.spawn().insert((
  SomeBundle::default(),
  SomeComponent,
))

// New (0.9) - Option 2
commands.spawn_bundle((
  SomeBundle::default(),
  SomeComponent,
))
```

## Next Steps

Consider changing `spawn` to accept a bundle and deprecate `spawn_bundle`.
2022-09-21 21:47:53 +00:00
ira
28205fd3f4 Remove AssetServer::watch_for_changes() (#5968)
# Objective
`AssetServer::watch_for_changes()` is racy and redundant with `AssetServerSettings`.
Closes #5964.

## Changelog

* Remove `AssetServer::watch_for_changes()`
* Add `AssetServerSettings` to the prelude.
* Minor cleanup.

## Migration Guide
`AssetServer::watch_for_changes()` was removed.
Instead, use the `AssetServerSettings` resource.
```rust
app // AssetServerSettings must be inserted before adding the AssetPlugin or DefaultPlugins.
	.insert_resource(AssetServerSettings {
		watch_for_changes: true,
		..default()
	})
```


Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-09-19 16:36:38 +00:00
ira
76ae6f4c6e Miscellaneous code-quality improvements. (#5860)
Does what it do.

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-09-05 00:30:21 +00:00
Péter Leéh
21dacbf137 fix typos in examples (#5711)
## Objective
Fixed some typos I came across while reading examples.
2022-08-16 20:28:31 +00:00
ira
992681b59b Make Resource trait opt-in, requiring #[derive(Resource)] V2 (#5577)
*This PR description is an edited copy of #5007, written by @alice-i-cecile.*
# Objective
Follow-up to https://github.com/bevyengine/bevy/pull/2254. The `Resource` trait currently has a blanket implementation for all types that meet its bounds.

While ergonomic, this results in several drawbacks:

* it is possible to make confusing, silent mistakes such as inserting a function pointer (Foo) rather than a value (Foo::Bar) as a resource
* it is challenging to discover if a type is intended to be used as a resource
* we cannot later add customization options (see the [RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/27-derive-component.md) for the equivalent choice for Component).
* dependencies can use the same Rust type as a resource in invisibly conflicting ways
* raw Rust types used as resources cannot preserve privacy appropriately, as anyone able to access that type can read and write to internal values
* we cannot capture a definitive list of possible resources to display to users in an editor
## Notes to reviewers
 * Review this commit-by-commit; there's effectively no back-tracking and there's a lot of churn in some of these commits.
   *ira: My commits are not as well organized :')*
 * I've relaxed the bound on Local to Send + Sync + 'static: I don't think these concerns apply there, so this can keep things simple. Storing e.g. a u32 in a Local is fine, because there's a variable name attached explaining what it does.
 * I think this is a bad place for the Resource trait to live, but I've left it in place to make reviewing easier. IMO that's best tackled with https://github.com/bevyengine/bevy/issues/4981.

## Changelog
`Resource` is no longer automatically implemented for all matching types. Instead, use the new `#[derive(Resource)]` macro.

## Migration Guide
Add `#[derive(Resource)]` to all types you are using as a resource.

If you are using a third party type as a resource, wrap it in a tuple struct to bypass orphan rules. Consider deriving `Deref` and `DerefMut` to improve ergonomics.

`ClearColor` no longer implements `Component`. Using `ClearColor` as a component in 0.8 did nothing.
Use the `ClearColorConfig` in the `Camera3d` and `Camera2d` components instead.


Co-authored-by: Alice <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: devil-ira <justthecooldude@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-08-08 21:36:35 +00:00
Charlie Hills
cd19d2757b use bevy_default() for texture format in post_processing (#5601)
# Objective

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

## Solution

Use bevy_default() for texture format in example to get proper texture format for wasm.
2022-08-07 20:26:13 +00:00
Matthew Taylor
50a44417ba Derive AsBindGroup Improvements: Better errors, more options, update examples (#5364)
# Objective

- Provide better compile-time errors and diagnostics.
- Add more options to allow more textures types and sampler types.
- Update array_texture example to use upgraded AsBindGroup derive macro.

## Solution

Split out the parsing of the inner struct/field attributes (the inside part of a `#[foo(...)]` attribute) for better clarity

Parse the binding index for all inner attributes, as it is part of all attributes (`#[foo(0, ...)`), then allow each attribute implementer to parse the rest of the attribute metadata as needed. This should make it very trivial to extend/change if needed in the future.

Replaced invocations of `panic!` with the `syn::Error` type, providing fine-grained errors that retains span information. This provides much nicer compile-time errors, and even better IDE errors.

![image](https://user-images.githubusercontent.com/7478134/179452241-6d85d440-4b67-44da-80a7-9d47e8c88b8a.png)

Updated the array_texture example to demonstrate the new changes.

## New AsBindGroup attribute options


### `#[texture(u32, ...)]`
Where `...` is an optional list of arguments.
| Arguments    	| Values                                                         	| Default |
|--------------	|----------------------------------------------------------------	| ----------- |
| dimension = "..."    	| `"1d"`, `"2d"`, `"2d_array"`, `"3d"`, `"cube"`, `"cube_array"` 	|    `"2d"`    |
| sample_type = "..."  	| `"float"`, `"depth"`, `"s_int"` or `"u_int"`                   	|    `"float"`    |
| filterable = ...   	| `true`, `false`                                                	|    `true`     |
| multisampled = ... 	| `true`, `false`                                                	|    `false` |
| visibility(...) 	| `all`, `none`, or a list-combination of `vertex`, `fragment`, `compute` |   `vertex`, `fragment`   |

Example: `#[texture(0, dimension = "2d_array", visibility(vertex, fragment))]`


### `#[sampler(u32, ...)]`
Where `...` is an optional list of arguments.
| Arguments 	| Values                                            	| Default |
|-----------	|---------------------------------------------------	| ----------- |
| sampler_type = "..."   	| `"filtering"`, `"non_filtering"`, `"comparison"`. 	|  `"filtering"`  |
| visibility(...) 	| `all`, `none`, or a list-combination of `vertex`, `fragment`, `compute` |   `vertex`, `fragment`   |

Example: `#[sampler(0, sampler_type = "filtering", visibility(vertex, fragment)]`

## Changelog

- Added more options to `#[texture(...)]` and `#[sampler(...)]` attributes, supporting more kinds of materials. See above for details.
- Upgraded IDE and compile-time error messages.
- Updated array_texture example using the new options.
2022-07-19 22:05:43 +00:00
Johan Klokkhammer Helsing
8810a73e87 Support AsBindGroup for 2d materials as well (#5312)
Port changes made to Material in #5053 to Material2d as well.

This is more or less an exact copy of the implementation in bevy_pbr; I
simply pretended the API existed, then copied stuff over until it
started building and the shapes example was working again.

# Objective

The changes in #5053 makes it possible to add custom materials with a lot less boiler plate. However, the implementation isn't shared with Material 2d as it's a kind of fork of the bevy_pbr version. It should be possible to use AsBindGroup on the 2d version as well.

## Solution

This makes the same kind of changes in Material2d in bevy_sprite.

This makes the following work:

```rust
//! Draws a circular purple bevy in the middle of the screen using a custom shader

use bevy::{
    prelude::*,
    reflect::TypeUuid,
    render::render_resource::{AsBindGroup, ShaderRef},
    sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle},
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugin(Material2dPlugin::<CustomMaterial>::default())
        .add_startup_system(setup)
        .run();
}

/// set up a simple 2D scene
fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<CustomMaterial>>,
    asset_server: Res<AssetServer>,
) {
    commands.spawn_bundle(MaterialMesh2dBundle {
        mesh: meshes.add(shape::Circle::new(50.).into()).into(),
        material: materials.add(CustomMaterial {
            color: Color::PURPLE,
            color_texture: Some(asset_server.load("branding/icon.png")),
        }),
        transform: Transform::from_translation(Vec3::new(-100., 0., 0.)),
        ..default()
    });

    commands.spawn_bundle(Camera2dBundle::default());
}

/// The Material2d trait is very configurable, but comes with sensible defaults for all methods.
/// You only need to implement functions for features that need non-default behavior. See the Material api docs for details!
impl Material2d for CustomMaterial {
    fn fragment_shader() -> ShaderRef {
        "shaders/custom_material.wgsl".into()
    }
}

// This is the struct that will be passed to your shader
#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
pub struct CustomMaterial {
    #[uniform(0)]
    color: Color,
    #[texture(1)]
    #[sampler(2)]
    color_texture: Option<Handle<Image>>,
}
```
2022-07-16 00:20:04 +00:00
François
814f8d1635 update wgpu to 0.13 (#5168)
# Objective

- Update wgpu to 0.13
- ~~Wait, is wgpu 0.13 released? No, but I had most of the changes already ready since playing with webgpu~~ well it has been released now
- Also update parking_lot to 0.12 and naga to 0.9

## Solution

- Update syntax for wgsl shaders https://github.com/gfx-rs/wgpu/blob/master/CHANGELOG.md#wgsl-syntax
- Add a few options, remove some references: https://github.com/gfx-rs/wgpu/blob/master/CHANGELOG.md#other-breaking-changes
- fragment inputs should now exactly match vertex outputs for locations, so I added exports for those to be able to reuse them https://github.com/gfx-rs/wgpu/pull/2704
2022-07-14 21:17:16 +00:00
ira
4847f7e3ad Update codebase to use IntoIterator where possible. (#5269)
Remove unnecessary calls to `iter()`/`iter_mut()`.
Mainly updates the use of queries in our code, docs, and examples.

```rust
// From
for _ in list.iter() {
for _ in list.iter_mut() {

// To
for _ in &list {
for _ in &mut list {
```

We already enable the pedantic lint [clippy::explicit_iter_loop](https://rust-lang.github.io/rust-clippy/stable/) inside of Bevy. However, this only warns for a few known types from the standard library.

## Note for reviewers
As you can see the additions and deletions are exactly equal.
Maybe give it a quick skim to check I didn't sneak in a crypto miner, but you don't have to torture yourself by reading every line.
I already experienced enough pain making this PR :) 


Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-07-11 15:28:50 +00:00
Daniel McNab
7b2cf98896 Make RenderStage::Extract run on the render world (#4402)
# Objective

- Currently, the `Extract` `RenderStage` is executed on the main world, with the render world available as a resource.
- However, when needing access to resources in the render world (e.g. to mutate them), the only way to do so was to get exclusive access to the whole `RenderWorld` resource.
- This meant that effectively only one extract which wrote to resources could run at a time.
- We didn't previously make `Extract`ing writing to the world a non-happy path, even though we want to discourage that.

## Solution

- Move the extract stage to run on the render world.
- Add the main world as a `MainWorld` resource.
- Add an `Extract` `SystemParam` as a convenience to access a (read only) `SystemParam` in the main world during `Extract`.

## Future work

It should be possible to avoid needing to use `get_or_spawn` for the render commands, since now the `Commands`' `Entities` matches up with the world being executed on.
We need to determine how this interacts with https://github.com/bevyengine/bevy/pull/3519
It's theoretically possible to remove the need for the `value` method on `Extract`. However, that requires slightly changing the `SystemParam` interface, which would make it more complicated. That would probably mess up the `SystemState` api too.

## Todo
I still need to add doc comments to `Extract`.

---

## Changelog

### Changed
- The `Extract` `RenderStage` now runs on the render world (instead of the main world as before).
   You must use the `Extract` `SystemParam` to access the main world during the extract phase.
   Resources on the render world can now be accessed using `ResMut` during extract.

### Removed
- `Commands::spawn_and_forget`. Use `Commands::get_or_spawn(e).insert_bundle(bundle)` instead

## Migration Guide

The `Extract` `RenderStage` now runs on the render world (instead of the main world as before).
You must use the `Extract` `SystemParam` to access the main world during the extract phase. `Extract` takes a single type parameter, which is any system parameter (such as `Res`, `Query` etc.). It will extract this from the main world, and returns the result of this extraction when `value` is called on it.

For example, if previously your extract system looked like:
```rust
fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) {
    for cloud in clouds.iter() {
        commands.get_or_spawn(cloud).insert(Cloud);
    }
}
```
the new version would be:
```rust
fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) {
    for cloud in clouds.value().iter() {
        commands.get_or_spawn(cloud).insert(Cloud);
    }
}
```
The diff is:
```diff
--- a/src/clouds.rs
+++ b/src/clouds.rs
@@ -1,5 +1,5 @@
-fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) {
-    for cloud in clouds.iter() {
+fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) {
+    for cloud in clouds.value().iter() {
         commands.get_or_spawn(cloud).insert(Cloud);
     }
 }
```
You can now also access resources from the render world using the normal system parameters during `Extract`:
```rust
fn extract_assets(mut render_assets: ResMut<MyAssets>, source_assets: Extract<Res<MyAssets>>) {
     *render_assets = source_assets.clone();
}
```
Please note that all existing extract systems need to be updated to match this new style; even if they currently compile they will not run as expected. A warning will be emitted on a best-effort basis if this is not met.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-08 23:56:33 +00:00
Boutillier
6b073ee412 Update shader_material_glsl example to include texture sampling (#5215)
# Objective

Add texture sampling to the GLSL shader example, as naga does not support the commonly used sampler2d type.
Fixes #5059

## Solution

- Align the shader_material_glsl example behaviour with the shader_material example,  as the later includes texture sampling.
- Update the GLSL shader to do texture sampling the way naga supports it, and document the way naga does not support it.

## Changelog

- The shader_material_glsl example has been updated to demonstrate texture sampling using the GLSL shading language.


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-08 01:14:22 +00:00
Robin KAY
5b5013d540 Add ViewRangefinder3d to reduce boilerplate when enqueuing standard 3D PhaseItems. (#5014)
# Objective

Reduce the boilerplate code needed to make draw order sorting work correctly when queuing items through new common functionality. Also fix several instances in the bevy code-base (mostly examples) where this boilerplate appears to be incorrect.

## Solution

- Moved the logic for handling back-to-front vs front-to-back draw ordering into the PhaseItems by inverting the sort key ordering of Opaque3d and AlphaMask3d. The means that all the standard 3d rendering phases measure distance in the same way. Clients of these structs no longer need to know to negate the distance.
- Added a new utility struct, ViewRangefinder3d, which encapsulates the maths needed to calculate a "distance" from an ExtractedView and a mesh's transform matrix.
- Converted all the occurrences of the distance calculations in Bevy and its examples to use ViewRangefinder3d. Several of these occurrences appear to be buggy because they don't invert the view matrix or don't negate the distance where appropriate. This leads me to the view that Bevy should expose a facility to correctly perform this calculation.

## Migration Guide

Code which creates Opaque3d, AlphaMask3d, or Transparent3d phase items _should_ use ViewRangefinder3d to calculate the distance value.

Code which manually calculated the distance for Opaque3d or AlphaMask3d phase items and correctly negated the z value will no longer depth sort correctly. However, incorrect depth sorting for these types will not impact the rendered output as sorting is only a performance optimisation when drawing with depth-testing enabled. Code which manually calculated the distance for Transparent3d phase items will continue to work as before.
2022-07-05 06:13:39 +00:00
SarthakSingh31
cdbabb7053 Removed world cell from places where split multable access is not needed (#5167)
Fixes #5109.
2022-07-01 17:03:32 +00:00
ira
ea13f0bddf Add helper methods for rotating Transforms (#5151)
# Objective
Users often ask for help with rotations as they struggle with `Quat`s.
`Quat` is rather complex and has a ton of verbose methods.

## Solution
Add rotation helper methods to `Transform`.


Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-07-01 03:58:54 +00:00
Carter Anderson
747b0c69b0 Better Materials: AsBindGroup trait and derive, simpler Material trait (#5053)
# Objective

This PR reworks Bevy's Material system, making the user experience of defining Materials _much_ nicer. Bevy's previous material system leaves a lot to be desired:
* Materials require manually implementing the `RenderAsset` trait, which involves manually generating the bind group, handling gpu buffer data transfer, looking up image textures, etc. Even the simplest single-texture material involves writing ~80 unnecessary lines of code. This was never the long term plan.
* There are two material traits, which is confusing, hard to document, and often redundant: `Material` and `SpecializedMaterial`. `Material` implicitly implements `SpecializedMaterial`, and `SpecializedMaterial` is used in most high level apis to support both use cases. Most users shouldn't need to think about specialization at all (I consider it a "power-user tool"), so the fact that `SpecializedMaterial` is front-and-center in our apis is a miss.
* Implementing either material trait involves a lot of "type soup". The "prepared asset" parameter is particularly heinous: `&<Self as RenderAsset>::PreparedAsset`. Defining vertex and fragment shaders is also more verbose than it needs to be. 

## Solution

Say hello to the new `Material` system:

```rust
#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
pub struct CoolMaterial {
    #[uniform(0)]
    color: Color,
    #[texture(1)]
    #[sampler(2)]
    color_texture: Handle<Image>,
}
impl Material for CoolMaterial {
    fn fragment_shader() -> ShaderRef {
        "cool_material.wgsl".into()
    }
}
```

Thats it! This same material would have required [~80 lines of complicated "type heavy" code](https://github.com/bevyengine/bevy/blob/v0.7.0/examples/shader/shader_material.rs) in the old Material system. Now it is just 14 lines of simple, readable code.

This is thanks to a new consolidated `Material` trait and the new `AsBindGroup` trait / derive.

### The new `Material` trait

The old "split" `Material` and `SpecializedMaterial` traits have been removed in favor of a new consolidated `Material` trait. All of the functions on the trait are optional.

The difficulty of implementing `Material` has been reduced by simplifying dataflow and removing type complexity:

```rust
// Old
impl Material for CustomMaterial {
    fn fragment_shader(asset_server: &AssetServer) -> Option<Handle<Shader>> {
        Some(asset_server.load("custom_material.wgsl"))
    }

    fn alpha_mode(render_asset: &<Self as RenderAsset>::PreparedAsset) -> AlphaMode {
        render_asset.alpha_mode
    }
}

// New
impl Material for CustomMaterial {
    fn fragment_shader() -> ShaderRef {
        "custom_material.wgsl".into()
    }

    fn alpha_mode(&self) -> AlphaMode {
        self.alpha_mode
    }
}
```

Specialization is still supported, but it is hidden by default under the `specialize()` function (more on this later).

### The `AsBindGroup` trait / derive

The `Material` trait now requires the `AsBindGroup` derive. This can be implemented manually relatively easily, but deriving it will almost always be preferable. 

Field attributes like `uniform` and `texture` are used to define which fields should be bindings,
what their binding type is, and what index they should be bound at:

```rust
#[derive(AsBindGroup)]
struct CoolMaterial {
    #[uniform(0)]
    color: Color,
    #[texture(1)]
    #[sampler(2)]
    color_texture: Handle<Image>,
}
```

In WGSL shaders, the binding looks like this:

```wgsl
struct CoolMaterial {
    color: vec4<f32>;
};

[[group(1), binding(0)]]
var<uniform> material: CoolMaterial;
[[group(1), binding(1)]]
var color_texture: texture_2d<f32>;
[[group(1), binding(2)]]
var color_sampler: sampler;
```

Note that the "group" index is determined by the usage context. It is not defined in `AsBindGroup`. Bevy material bind groups are bound to group 1.

The following field-level attributes are supported:
* `uniform(BINDING_INDEX)`
    * The field will be converted to a shader-compatible type using the `ShaderType` trait, written to a `Buffer`, and bound as a uniform. It can also be derived for custom structs.
* `texture(BINDING_INDEX)`
    * This field's `Handle<Image>` will be used to look up the matching `Texture` gpu resource, which will be bound as a texture in shaders. The field will be assumed to implement `Into<Option<Handle<Image>>>`. In practice, most fields should be a `Handle<Image>` or `Option<Handle<Image>>`. If the value of an `Option<Handle<Image>>` is `None`, the new `FallbackImage` resource will be used instead. This attribute can be used in conjunction with a `sampler` binding attribute (with a different binding index).
* `sampler(BINDING_INDEX)`
    * Behaves exactly like the `texture` attribute, but sets the Image's sampler binding instead of the texture. 

Note that fields without field-level binding attributes will be ignored.
```rust
#[derive(AsBindGroup)]
struct CoolMaterial {
    #[uniform(0)]
    color: Color,
    this_field_is_ignored: String,
}
```

As mentioned above, `Option<Handle<Image>>` is also supported:
```rust
#[derive(AsBindGroup)]
struct CoolMaterial {
    #[uniform(0)]
    color: Color,
    #[texture(1)]
    #[sampler(2)]
    color_texture: Option<Handle<Image>>,
}
```
This is useful if you want a texture to be optional. When the value is `None`, the `FallbackImage` will be used for the binding instead, which defaults to "pure white".

Field uniforms with the same binding index will be combined into a single binding:
```rust
#[derive(AsBindGroup)]
struct CoolMaterial {
    #[uniform(0)]
    color: Color,
    #[uniform(0)]
    roughness: f32,
}
```

In WGSL shaders, the binding would look like this:
```wgsl
struct CoolMaterial {
    color: vec4<f32>;
    roughness: f32;
};

[[group(1), binding(0)]]
var<uniform> material: CoolMaterial;
```

Some less common scenarios will require "struct-level" attributes. These are the currently supported struct-level attributes:
* `uniform(BINDING_INDEX, ConvertedShaderType)`
    * Similar to the field-level `uniform` attribute, but instead the entire `AsBindGroup` value is converted to `ConvertedShaderType`, which must implement `ShaderType`. This is useful if more complicated conversion logic is required.
* `bind_group_data(DataType)`
    * The `AsBindGroup` type will be converted to some `DataType` using `Into<DataType>` and stored as `AsBindGroup::Data` as part of the `AsBindGroup::as_bind_group` call. This is useful if data needs to be stored alongside the generated bind group, such as a unique identifier for a material's bind group. The most common use case for this attribute is "shader pipeline specialization".

The previous `CoolMaterial` example illustrating "combining multiple field-level uniform attributes with the same binding index" can
also be equivalently represented with a single struct-level uniform attribute:
```rust
#[derive(AsBindGroup)]
#[uniform(0, CoolMaterialUniform)]
struct CoolMaterial {
    color: Color,
    roughness: f32,
}

#[derive(ShaderType)]
struct CoolMaterialUniform {
    color: Color,
    roughness: f32,
}

impl From<&CoolMaterial> for CoolMaterialUniform {
    fn from(material: &CoolMaterial) -> CoolMaterialUniform {
        CoolMaterialUniform {
            color: material.color,
            roughness: material.roughness,
        }
    }
}
```

### Material Specialization

Material shader specialization is now _much_ simpler:

```rust
#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
#[bind_group_data(CoolMaterialKey)]
struct CoolMaterial {
    #[uniform(0)]
    color: Color,
    is_red: bool,
}

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
struct CoolMaterialKey {
    is_red: bool,
}

impl From<&CoolMaterial> for CoolMaterialKey {
    fn from(material: &CoolMaterial) -> CoolMaterialKey {
        CoolMaterialKey {
            is_red: material.is_red,
        }
    }
}

impl Material for CoolMaterial {
    fn fragment_shader() -> ShaderRef {
        "cool_material.wgsl".into()
    }

    fn specialize(
        pipeline: &MaterialPipeline<Self>,
        descriptor: &mut RenderPipelineDescriptor,
        layout: &MeshVertexBufferLayout,
        key: MaterialPipelineKey<Self>,
    ) -> Result<(), SpecializedMeshPipelineError> {
        if key.bind_group_data.is_red {
            let fragment = descriptor.fragment.as_mut().unwrap();
            fragment.shader_defs.push("IS_RED".to_string());
        }
        Ok(())
    }
}
```

Setting `bind_group_data` is not required for specialization (it defaults to `()`). Scenarios like "custom vertex attributes" also benefit from this system:
```rust
impl Material for CustomMaterial {
    fn vertex_shader() -> ShaderRef {
        "custom_material.wgsl".into()
    }

    fn fragment_shader() -> ShaderRef {
        "custom_material.wgsl".into()
    }

    fn specialize(
        pipeline: &MaterialPipeline<Self>,
        descriptor: &mut RenderPipelineDescriptor,
        layout: &MeshVertexBufferLayout,
        key: MaterialPipelineKey<Self>,
    ) -> Result<(), SpecializedMeshPipelineError> {
        let vertex_layout = layout.get_layout(&[
            Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
            ATTRIBUTE_BLEND_COLOR.at_shader_location(1),
        ])?;
        descriptor.vertex.buffers = vec![vertex_layout];
        Ok(())
    }
}
```

### Ported `StandardMaterial` to the new `Material` system

Bevy's built-in PBR material uses the new Material system (including the AsBindGroup derive):

```rust
#[derive(AsBindGroup, Debug, Clone, TypeUuid)]
#[uuid = "7494888b-c082-457b-aacf-517228cc0c22"]
#[bind_group_data(StandardMaterialKey)]
#[uniform(0, StandardMaterialUniform)]
pub struct StandardMaterial {
    pub base_color: Color,
    #[texture(1)]
    #[sampler(2)]
    pub base_color_texture: Option<Handle<Image>>,
    /* other fields omitted for brevity */
```

### Ported Bevy examples to the new `Material` system

The overall complexity of Bevy's "custom shader examples" has gone down significantly. Take a look at the diffs if you want a dopamine spike.

Please note that while this PR has a net increase in "lines of code", most of those extra lines come from added documentation. There is a significant reduction
in the overall complexity of the code (even accounting for the new derive logic).

---

## Changelog

### Added

* `AsBindGroup` trait and derive, which make it much easier to transfer data to the gpu and generate bind groups for a given type.

### Changed

* The old `Material` and `SpecializedMaterial` traits have been replaced by a consolidated (much simpler) `Material` trait. Materials no longer implement `RenderAsset`.
* `StandardMaterial` was ported to the new material system. There are no user-facing api changes to the `StandardMaterial` struct api, but it now implements `AsBindGroup` and `Material` instead of `RenderAsset` and `SpecializedMaterial`.

## Migration Guide
The Material system has been reworked to be much simpler. We've removed a lot of boilerplate with the new `AsBindGroup` derive and the `Material` trait is simpler as well!

### Bevy 0.7 (old)

```rust
#[derive(Debug, Clone, TypeUuid)]
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
pub struct CustomMaterial {
    color: Color,
    color_texture: Handle<Image>,
}

#[derive(Clone)]
pub struct GpuCustomMaterial {
    _buffer: Buffer,
    bind_group: BindGroup,
}

impl RenderAsset for CustomMaterial {
    type ExtractedAsset = CustomMaterial;
    type PreparedAsset = GpuCustomMaterial;
    type Param = (SRes<RenderDevice>, SRes<MaterialPipeline<Self>>);
    fn extract_asset(&self) -> Self::ExtractedAsset {
        self.clone()
    }

    fn prepare_asset(
        extracted_asset: Self::ExtractedAsset,
        (render_device, material_pipeline): &mut SystemParamItem<Self::Param>,
    ) -> Result<Self::PreparedAsset, PrepareAssetError<Self::ExtractedAsset>> {
        let color = Vec4::from_slice(&extracted_asset.color.as_linear_rgba_f32());

        let byte_buffer = [0u8; Vec4::SIZE.get() as usize];
        let mut buffer = encase::UniformBuffer::new(byte_buffer);
        buffer.write(&color).unwrap();

        let buffer = render_device.create_buffer_with_data(&BufferInitDescriptor {
            contents: buffer.as_ref(),
            label: None,
            usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
        });

        let (texture_view, texture_sampler) = if let Some(result) = material_pipeline
            .mesh_pipeline
            .get_image_texture(gpu_images, &Some(extracted_asset.color_texture.clone()))
        {
            result
        } else {
            return Err(PrepareAssetError::RetryNextUpdate(extracted_asset));
        };
        let bind_group = render_device.create_bind_group(&BindGroupDescriptor {
            entries: &[
                BindGroupEntry {
                    binding: 0,
                    resource: buffer.as_entire_binding(),
                },
                BindGroupEntry {
                    binding: 0,
                    resource: BindingResource::TextureView(texture_view),
                },
                BindGroupEntry {
                    binding: 1,
                    resource: BindingResource::Sampler(texture_sampler),
                },
            ],
            label: None,
            layout: &material_pipeline.material_layout,
        });

        Ok(GpuCustomMaterial {
            _buffer: buffer,
            bind_group,
        })
    }
}

impl Material for CustomMaterial {
    fn fragment_shader(asset_server: &AssetServer) -> Option<Handle<Shader>> {
        Some(asset_server.load("custom_material.wgsl"))
    }

    fn bind_group(render_asset: &<Self as RenderAsset>::PreparedAsset) -> &BindGroup {
        &render_asset.bind_group
    }

    fn bind_group_layout(render_device: &RenderDevice) -> BindGroupLayout {
        render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
            entries: &[
                BindGroupLayoutEntry {
                    binding: 0,
                    visibility: ShaderStages::FRAGMENT,
                    ty: BindingType::Buffer {
                        ty: BufferBindingType::Uniform,
                        has_dynamic_offset: false,
                        min_binding_size: Some(Vec4::min_size()),
                    },
                    count: None,
                },
                BindGroupLayoutEntry {
                    binding: 1,
                    visibility: ShaderStages::FRAGMENT,
                    ty: BindingType::Texture {
                        multisampled: false,
                        sample_type: TextureSampleType::Float { filterable: true },
                        view_dimension: TextureViewDimension::D2Array,
                    },
                    count: None,
                },
                BindGroupLayoutEntry {
                    binding: 2,
                    visibility: ShaderStages::FRAGMENT,
                    ty: BindingType::Sampler(SamplerBindingType::Filtering),
                    count: None,
                },
            ],
            label: None,
        })
    }
}
```

### Bevy 0.8 (new)

```rust
impl Material for CustomMaterial {
    fn fragment_shader() -> ShaderRef {
        "custom_material.wgsl".into()
    }
}

#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
pub struct CustomMaterial {
    #[uniform(0)]
    color: Color,
    #[texture(1)]
    #[sampler(2)]
    color_texture: Handle<Image>,
}
```

## Future Work

* Add support for more binding types (cubemaps, buffers, etc). This PR intentionally includes a bare minimum number of binding types to keep "reviewability" in check.
* Consider optionally eliding binding indices using binding names. `AsBindGroup` could pass in (optional?) reflection info as a "hint".
    * This would make it possible for the derive to do this:
        ```rust
        #[derive(AsBindGroup)]
        pub struct CustomMaterial {
            #[uniform]
            color: Color,
            #[texture]
            #[sampler]
            color_texture: Option<Handle<Image>>,
            alpha_mode: AlphaMode,
        }
        ```
    * Or this
        ```rust
        #[derive(AsBindGroup)]
        pub struct CustomMaterial {
            #[binding]
            color: Color,
            #[binding]
            color_texture: Option<Handle<Image>>,
            alpha_mode: AlphaMode,
        }
        ```
    * Or even this (if we flip to "include bindings by default")
        ```rust
        #[derive(AsBindGroup)]
        pub struct CustomMaterial {
            color: Color,
            color_texture: Option<Handle<Image>>,
            #[binding(ignore)]
            alpha_mode: AlphaMode,
        }
        ```
* If we add the option to define custom draw functions for materials (which could be done in a type-erased way), I think that would be enough to support extra non-material bindings. Worth considering!
2022-06-30 23:48:46 +00:00
Robert Swain
84991d34f3 Array texture example (#5077)
# Objective

- Make the reusable PBR shading functionality a little more reusable
  - Add constructor functions for `StandardMaterial` and `PbrInput` structs to populate them with default values
  - Document unclear `PbrInput` members
- Demonstrate how to reuse the bevy PBR shading functionality
- The final important piece from #3969 as the initial shot at making the PBR shader code reusable in custom materials

## Solution

- Add back and rework the 'old' `array_texture` example from pre-0.6.
- Create a custom shader material
  - Use a single array texture binding and sampler for the material bind group
  - Use a shader that calls `pbr()` from the `bevy_pbr::pbr_functions` import
- Spawn a row of cubes using the custom material
- In the shader, select the array texture layer to sample by using the world position x coordinate modulo the number of array texture layers

<img width="1392" alt="Screenshot 2022-06-23 at 12 28 05" src="https://user-images.githubusercontent.com/302146/175278593-2296f519-f577-4ece-81c0-d842283784a1.png">

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-06-28 00:58:50 +00:00
Carter Anderson
f28b921209 Add "depth_load_op" configuration to 3d Cameras (#4904)
# Objective

Users should be able to configure depth load operations on cameras. Currently every camera clears depth when it is rendered. But sometimes later passes need to rely on depth from previous passes.

## Solution

This adds the `Camera3d::depth_load_op` field with a new `Camera3dDepthLoadOp` value. This is a custom type because Camera3d uses "reverse-z depth" and this helps us record and document that in a discoverable way. It also gives us more control over reflection + other trait impls, whereas `LoadOp` is owned by the `wgpu` crate.

```rust
commands.spawn_bundle(Camera3dBundle {
    camera_3d: Camera3d {
        depth_load_op: Camera3dDepthLoadOp::Load,
        ..default()
    },
    ..default()
});
```

### two_passes example with the "second pass" camera configured to the default (clear depth to 0.0)

![image](https://user-images.githubusercontent.com/2694663/171743172-46d4fdd5-5090-46ea-abe4-1fbc519f6ee8.png)


### two_passes example with the "second pass" camera configured to "load" the depth
![image](https://user-images.githubusercontent.com/2694663/171743323-74dd9a1d-9c25-4883-98dd-38ca0bed8c17.png)

---

## Changelog

### Added

* `Camera3d` now has a `depth_load_op` field, which can configure the Camera's main 3d pass depth loading behavior.
2022-06-07 22:22:10 +00:00
Yoshiera
2f5a1c6e16 remove redundant query parameters (#4945)
# Objective

In the `queue_custom` system in `shader_instancing` example, the query of `material_meshes`  has a redundant `With<Handle<Mesh>>` query filter because `Handle<Mesh>` is included in the component access.

## Solution

Remove the `With<Handle<Mesh>>` filter
2022-06-06 14:24:41 +00:00
Thierry Berger
765bd46c2e add a post-processing example (#4797)
# Objective

- Add an example showing a custom post processing effect, done after the first rendering pass.

## Solution

- A simple post processing "chromatic aberration" effect. I mixed together examples `3d/render_to_texture`, and `shader/shader_material_screenspace_texture`
- Reading a bit how https://github.com/bevyengine/bevy/pull/3430 was done gave me pointers to apply the main pass to the 2d render rather than using a 3d quad.

This work might be or not be relevant to https://github.com/bevyengine/bevy/issues/2724

<details>

<summary> ⚠️ Click for a video of the render ⚠️ I’ve been told it might hurt the eyes 👀 , maybe we should choose another effect just in case ?</summary>

https://user-images.githubusercontent.com/2290685/169138830-a6dc8a9f-8798-44b9-8d9e-449e60614916.mp4

</details>

# Request for feedbacks

- [ ] Is chromatic aberration effect ok ? (Correct term, not a danger for the eyes ?) I'm open to suggestion to make something different.
- [ ] Is the code idiomatic ? I preferred a "main camera -> **new camera with post processing applied to a quad**" approach to emulate minimum modification to existing code wanting to add global post processing.

---

## Changelog

- Add a full screen post processing shader example
2022-06-06 00:06:49 +00:00
Henry Sloan
8e08e26c25 Update commented vsync code in example to use present_mode (#4926)
# Objective

- To fix the broken commented code in `examples/shader/compute_shader_game_of_life.rs` for disabling frame throttling

## Solution

- Change the commented code from using the old `WindowDescriptor::vsync` to the new `WindowDescriptor::present_mode`

### Note
I chose to use the fully qualified scope `bevy:🪟:PresentWindow::Immediate` rather than explicitly including `PresentWindow` to avoid an unused import when the code is commented.
2022-06-04 20:00:01 +00:00
Carter Anderson
f487407e07 Camera Driven Rendering (#4745)
This adds "high level camera driven rendering" to Bevy. The goal is to give users more control over what gets rendered (and where) without needing to deal with render logic. This will make scenarios like "render to texture", "multiple windows", "split screen", "2d on 3d", "3d on 2d", "pass layering", and more significantly easier. 

Here is an [example of a 2d render sandwiched between two 3d renders (each from a different perspective)](https://gist.github.com/cart/4fe56874b2e53bc5594a182fc76f4915):
![image](https://user-images.githubusercontent.com/2694663/168411086-af13dec8-0093-4a84-bdd4-d4362d850ffa.png)

Users can now spawn a camera, point it at a RenderTarget (a texture or a window), and it will "just work". 

Rendering to a second window is as simple as spawning a second camera and assigning it to a specific window id:
```rust
// main camera (main window)
commands.spawn_bundle(Camera2dBundle::default());

// second camera (other window)
commands.spawn_bundle(Camera2dBundle {
    camera: Camera {
        target: RenderTarget::Window(window_id),
        ..default()
    },
    ..default()
});
```

Rendering to a texture is as simple as pointing the camera at a texture:

```rust
commands.spawn_bundle(Camera2dBundle {
    camera: Camera {
        target: RenderTarget::Texture(image_handle),
        ..default()
    },
    ..default()
});
```

Cameras now have a "render priority", which controls the order they are drawn in. If you want to use a camera's output texture as a texture in the main pass, just set the priority to a number lower than the main pass camera (which defaults to `0`).

```rust
// main pass camera with a default priority of 0
commands.spawn_bundle(Camera2dBundle::default());

commands.spawn_bundle(Camera2dBundle {
    camera: Camera {
        target: RenderTarget::Texture(image_handle.clone()),
        priority: -1,
        ..default()
    },
    ..default()
});

commands.spawn_bundle(SpriteBundle {
    texture: image_handle,
    ..default()
})
```

Priority can also be used to layer to cameras on top of each other for the same RenderTarget. This is what "2d on top of 3d" looks like in the new system:

```rust
commands.spawn_bundle(Camera3dBundle::default());

commands.spawn_bundle(Camera2dBundle {
    camera: Camera {
        // this will render 2d entities "on top" of the default 3d camera's render
        priority: 1,
        ..default()
    },
    ..default()
});
```

There is no longer the concept of a global "active camera". Resources like `ActiveCamera<Camera2d>` and `ActiveCamera<Camera3d>` have been replaced with the camera-specific `Camera::is_active` field. This does put the onus on users to manage which cameras should be active.

Cameras are now assigned a single render graph as an "entry point", which is configured on each camera entity using the new `CameraRenderGraph` component. The old `PerspectiveCameraBundle` and `OrthographicCameraBundle` (generic on camera marker components like Camera2d and Camera3d) have been replaced by `Camera3dBundle` and `Camera2dBundle`, which set 3d and 2d default values for the `CameraRenderGraph` and projections.

```rust
// old 3d perspective camera
commands.spawn_bundle(PerspectiveCameraBundle::default())

// new 3d perspective camera
commands.spawn_bundle(Camera3dBundle::default())
```

```rust
// old 2d orthographic camera
commands.spawn_bundle(OrthographicCameraBundle::new_2d())

// new 2d orthographic camera
commands.spawn_bundle(Camera2dBundle::default())
```

```rust
// old 3d orthographic camera
commands.spawn_bundle(OrthographicCameraBundle::new_3d())

// new 3d orthographic camera
commands.spawn_bundle(Camera3dBundle {
    projection: OrthographicProjection {
        scale: 3.0,
        scaling_mode: ScalingMode::FixedVertical,
        ..default()
    }.into(),
    ..default()
})
```

Note that `Camera3dBundle` now uses a new `Projection` enum instead of hard coding the projection into the type. There are a number of motivators for this change: the render graph is now a part of the bundle, the way "generic bundles" work in the rust type system prevents nice `..default()` syntax, and changing projections at runtime is much easier with an enum (ex for editor scenarios). I'm open to discussing this choice, but I'm relatively certain we will all come to the same conclusion here. Camera2dBundle and Camera3dBundle are much clearer than being generic on marker components / using non-default constructors.

If you want to run a custom render graph on a camera, just set the `CameraRenderGraph` component:

```rust
commands.spawn_bundle(Camera3dBundle {
    camera_render_graph: CameraRenderGraph::new(some_render_graph_name),
    ..default()
})
```

Just note that if the graph requires data from specific components to work (such as `Camera3d` config, which is provided in the `Camera3dBundle`), make sure the relevant components have been added.

Speaking of using components to configure graphs / passes, there are a number of new configuration options:

```rust
commands.spawn_bundle(Camera3dBundle {
    camera_3d: Camera3d {
        // overrides the default global clear color 
        clear_color: ClearColorConfig::Custom(Color::RED),
        ..default()
    },
    ..default()
})

commands.spawn_bundle(Camera3dBundle {
    camera_3d: Camera3d {
        // disables clearing
        clear_color: ClearColorConfig::None,
        ..default()
    },
    ..default()
})
```

Expect to see more of the "graph configuration Components on Cameras" pattern in the future.

By popular demand, UI no longer requires a dedicated camera. `UiCameraBundle` has been removed. `Camera2dBundle` and `Camera3dBundle` now both default to rendering UI as part of their own render graphs. To disable UI rendering for a camera, disable it using the CameraUi component:

```rust
commands
    .spawn_bundle(Camera3dBundle::default())
    .insert(CameraUi {
        is_enabled: false,
        ..default()
    })
```

## Other Changes

* The separate clear pass has been removed. We should revisit this for things like sky rendering, but I think this PR should "keep it simple" until we're ready to properly support that (for code complexity and performance reasons). We can come up with the right design for a modular clear pass in a followup pr.
* I reorganized bevy_core_pipeline into Core2dPlugin and Core3dPlugin (and core_2d / core_3d modules). Everything is pretty much the same as before, just logically separate. I've moved relevant types (like Camera2d, Camera3d, Camera3dBundle, Camera2dBundle) into their relevant modules, which is what motivated this reorganization.
* I adapted the `scene_viewer` example (which relied on the ActiveCameras behavior) to the new system. I also refactored bits and pieces to be a bit simpler. 
* All of the examples have been ported to the new camera approach. `render_to_texture` and `multiple_windows` are now _much_ simpler. I removed `two_passes` because it is less relevant with the new approach. If someone wants to add a new "layered custom pass with CameraRenderGraph" example, that might fill a similar niche. But I don't feel much pressure to add that in this pr.
* Cameras now have `target_logical_size` and `target_physical_size` fields, which makes finding the size of a camera's render target _much_ simpler. As a result, the `Assets<Image>` and `Windows` parameters were removed from `Camera::world_to_screen`, making that operation much more ergonomic.
* Render order ambiguities between cameras with the same target and the same priority now produce a warning. This accomplishes two goals:
    1. Now that there is no "global" active camera, by default spawning two cameras will result in two renders (one covering the other). This would be a silent performance killer that would be hard to detect after the fact. By detecting ambiguities, we can provide a helpful warning when this occurs.
    2. Render order ambiguities could result in unexpected / unpredictable render results. Resolving them makes sense.

## Follow Up Work

* Per-Camera viewports, which will make it possible to render to a smaller area inside of a RenderTarget (great for something like splitscreen)
* Camera-specific MSAA config (should use the same "overriding" pattern used for ClearColor)
* Graph Based Camera Ordering: priorities are simple, but they make complicated ordering constraints harder to express. We should consider adopting a "graph based" camera ordering model with "before" and "after" relationships to other cameras (or build it "on top" of the priority system).
* Consider allowing graphs to run subgraphs from any nest level (aka a global namespace for graphs). Right now the 2d and 3d graphs each need their own UI subgraph, which feels "fine" in the short term. But being able to share subgraphs between other subgraphs seems valuable.
* Consider splitting `bevy_core_pipeline` into `bevy_core_2d` and `bevy_core_3d` packages. Theres a shared "clear color" dependency here, which would need a new home.
2022-06-02 00:12:17 +00:00
Félix Lescaudey de Maneville
f000c2b951 Clippy improvements (#4665)
# Objective

Follow up to my previous MR #3718 to add new clippy warnings to bevy:

- [x] [~~option_if_let_else~~](https://rust-lang.github.io/rust-clippy/master/#option_if_let_else) (reverted)
- [x] [redundant_else](https://rust-lang.github.io/rust-clippy/master/#redundant_else)
- [x] [match_same_arms](https://rust-lang.github.io/rust-clippy/master/#match_same_arms)
- [x] [semicolon_if_nothing_returned](https://rust-lang.github.io/rust-clippy/master/#semicolon_if_nothing_returned)
- [x] [explicit_iter_loop](https://rust-lang.github.io/rust-clippy/master/#explicit_iter_loop)
- [x] [map_flatten](https://rust-lang.github.io/rust-clippy/master/#map_flatten)

There is one commit per clippy warning, and the matching flags are added to the CI execution.

To test the CI execution you may run `cargo run -p ci -- clippy` at the root.

I choose the add the flags in the `ci` tool crate to avoid having them in every `lib.rs` but I guess it could become an issue with suprise warnings coming up after a commit/push


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-05-31 01:38:07 +00:00
Robert Swain
a0a3d8798b ExtractResourcePlugin (#3745)
# Objective

- Add an `ExtractResourcePlugin` for convenience and consistency

## Solution

- Add an `ExtractResourcePlugin` similar to `ExtractComponentPlugin` but for ECS `Resource`s. The system that is executed simply clones the main world resource into a render world resource, if and only if the main world resource was either added or changed since the last execution of the system.
- Add an `ExtractResource` trait with a `fn extract_resource(res: &Self) -> Self` function. This is used by the `ExtractResourcePlugin` to extract the resource
- Add a derive macro for `ExtractResource` on a `Resource` with the `Clone` trait, that simply returns `res.clone()`
- Use `ExtractResourcePlugin` wherever both possible and appropriate
2022-05-30 18:36:03 +00:00
Thierry Berger
deeaf64897 shader examples wording coherence (#4810)
# Objective

I noticed different examples descriptions were not using the same structure:
![different_wordings_examples](https://user-images.githubusercontent.com/2290685/169487055-ab76743e-3400-486f-b672-e8f60455b8e4.png)

This results in sentences that a reader has to read differently each time, which might result in information being hard to find, especially foreign language users.

Original discord discussion: https://discord.com/channels/691052431525675048/976846499889705020

## Solution

- Use less different words, similar structure and being straight to the point.

---

## Changelog

- Examples descriptions more accessible.
2022-05-30 15:57:25 +00:00
Teodor Tanasoaia
7cb4d3cb43 Migrate to encase from crevice (#4339)
# Objective

- Unify buffer APIs
- Also see #4272

## Solution

- Replace vendored `crevice` with `encase`

---

## Changelog

Changed `StorageBuffer`
Added `DynamicStorageBuffer`
Replaced `UniformVec` with `UniformBuffer`
Replaced `DynamicUniformVec` with `DynamicUniformBuffer`

## Migration Guide

### `StorageBuffer`

removed `set_body()`, `values()`, `values_mut()`, `clear()`, `push()`, `append()`
added `set()`, `get()`, `get_mut()`

### `UniformVec` -> `UniformBuffer`

renamed `uniform_buffer()` to `buffer()`
removed `len()`, `is_empty()`, `capacity()`, `push()`, `reserve()`, `clear()`, `values()`
added `set()`, `get()`

### `DynamicUniformVec` -> `DynamicUniformBuffer`

renamed `uniform_buffer()` to `buffer()`
removed `capacity()`, `reserve()`


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-05-18 21:09:21 +00:00
Mark Schmale
1ba7429371 Doc/module style doc blocks for examples (#4438)
# Objective

Provide a starting point for #3951, or a partial solution. 
Providing a few comment blocks to discuss, and hopefully find better one in the process. 

## Solution

Since I am pretty new to pretty much anything in this context, I figured I'd just start with a draft for some file level doc blocks. For some of them I found more relevant details (or at least things I considered interessting), for some others there is less. 

## Changelog

- Moved some existing comments from main() functions in the 2d examples to the file header level
- Wrote some more comment blocks for most other 2d examples

TODO: 
- [x] 2d/sprite_sheet, wasnt able to come up with something good yet 
- [x] all other example groups...


Also: Please let me know if the commit style is okay, or to verbose. I could certainly squash these things, or add more details if needed. 
I also hope its okay to raise this PR this early, with just a few files changed. Took me long enough and I dont wanted to let it go to waste because I lost motivation to do the whole thing. Additionally I am somewhat uncertain over the style and contents of the commets. So let me know what you thing please.
2022-05-16 13:53:20 +00:00
Aevyrie
4aa56050b6 Add infallible resource getters for WorldCell (#4104)
# Objective

- Eliminate all `worldcell.get_resource().unwrap()` cases.
- Provide helpful messages on panic.

## Solution

- Adds infallible resource getters to `WorldCell`, mirroring `World`.
2022-04-25 23:19:13 +00:00
Robert Swain
c5963b4fd5 Use storage buffers for clustered forward point lights (#3989)
# Objective

- Make use of storage buffers, where they are available, for clustered forward bindings to support far more point lights in a scene
- Fixes #3605 
- Based on top of #4079 

This branch on an M1 Max can keep 60fps with about 2150 point lights of radius 1m in the Sponza scene where I've been testing. The bottleneck is mostly assigning lights to clusters which grows faster than linearly (I think 1000 lights was about 1.5ms and 5000 was 7.5ms). I have seen papers and presentations leveraging compute shaders that can get this up to over 1 million. That said, I think any further optimisations should probably be done in a separate PR.

## Solution

- Add `RenderDevice` to the `Material` and `SpecializedMaterial` trait `::key()` functions to allow setting flags on the keys depending on feature/limit availability
- Make `GpuPointLights` and `ViewClusterBuffers` into enums containing `UniformVec` and `StorageBuffer` variants. Implement the necessary API on them to make usage the same for both cases, and the only difference is at initialisation time.
- Appropriate shader defs in the shader code to handle the two cases

## Context on some decisions / open questions

- I'm using `max_storage_buffers_per_shader_stage >= 3` as a check to see if storage buffers are supported. I was thinking about diving into 'binding resource management' but it feels like we don't have enough use cases to understand the problem yet, and it is mostly a separate concern to this PR, so I think it should be handled separately.
- Should `ViewClusterBuffers` and `ViewClusterBindings` be merged, duplicating the count variables into the enum variants?


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-04-07 16:16:35 +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
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
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
Carter Anderson
b6a647cc01 default() shorthand (#4071)
Adds a `default()` shorthand for `Default::default()` ... because life is too short to constantly type `Default::default()`.

```rust
use bevy::prelude::*;

#[derive(Default)]
struct Foo {
  bar: usize,
  baz: usize,
}

// Normally you would do this:
let foo = Foo {
  bar: 10,
  ..Default::default()
};

// But now you can do this:
let foo = Foo {
  bar: 10,
  ..default()
};
```

The examples have been adapted to use `..default()`. I've left internal crates as-is for now because they don't pull in the bevy prelude, and the ergonomics of each case should be considered individually.
2022-03-01 20:52:09 +00:00
Jakob Hellermann
3ffa655cdd examples: add screenspace texture shader example (#4063)
Adds a new shader example showing how to sample a texture with screenspace coordinates, similar to the end [portal in minecraft](https://bugs.mojang.com/secure/attachment/163759/portal_frame_112.gif).

https://user-images.githubusercontent.com/22177966/156031195-33d14ed8-733f-4d9e-b1da-0fc807c994a5.mp4

I just used the already existent `models/FlightHelmet/FlightHelmet_Materials_LensesMat_OcclusionRoughMetal.png` texture but maybe we should use a dedicated texture for the example. Suggestions welcome.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-02-28 22:55:14 +00:00
Alice Cecile
557ab9897a Make get_resource (and friends) infallible (#4047)
# Objective

- In the large majority of cases, users were calling `.unwrap()` immediately after `.get_resource`.
- Attempting to add more helpful error messages here resulted in endless manual boilerplate (see #3899 and the linked PRs).

## Solution

- Add an infallible variant named `.resource` and so on.
- Use these infallible variants over `.get_resource().unwrap()` across the code base.

## Notes

I did not provide equivalent methods on `WorldCell`, in favor of removing it entirely in #3939.

## Migration Guide

Infallible variants of `.get_resource` have been added that implicitly panic, rather than needing to be unwrapped.

Replace `world.get_resource::<Foo>().unwrap()` with `world.resource::<Foo>()`.

## Impact

- `.unwrap` search results before: 1084
- `.unwrap` search results after: 942
- internal `unwrap_or_else` calls added: 4
- trivial unwrap calls removed from tests and code: 146
- uses of the new `try_get_resource` API: 11
- percentage of the time the unwrapping API was used internally: 93%
2022-02-27 22:37:18 +00:00
Carter Anderson
e369a8ad51 Mesh vertex buffer layouts (#3959)
This PR makes a number of changes to how meshes and vertex attributes are handled, which the goal of enabling easy and flexible custom vertex attributes:
* Reworks the `Mesh` type to use the newly added `VertexAttribute` internally
  * `VertexAttribute` defines the name, a unique `VertexAttributeId`, and a `VertexFormat`
  *  `VertexAttributeId` is used to produce consistent sort orders for vertex buffer generation, replacing the more expensive and often surprising "name based sorting"  
  * Meshes can be used to generate a `MeshVertexBufferLayout`, which defines the layout of the gpu buffer produced by the mesh. `MeshVertexBufferLayouts` can then be used to generate actual `VertexBufferLayouts` according to the requirements of a specific pipeline. This decoupling of "mesh layout" vs "pipeline vertex buffer layout" is what enables custom attributes. We don't need to standardize _mesh layouts_ or contort meshes to meet the needs of a specific pipeline. As long as the mesh has what the pipeline needs, it will work transparently. 
* Mesh-based pipelines now specialize on `&MeshVertexBufferLayout` via the new `SpecializedMeshPipeline` trait (which behaves like `SpecializedPipeline`, but adds `&MeshVertexBufferLayout`). The integrity of the pipeline cache is maintained because the `MeshVertexBufferLayout` is treated as part of the key (which is fully abstracted from implementers of the trait ... no need to add any additional info to the specialization key).    
* Hashing `MeshVertexBufferLayout` is too expensive to do for every entity, every frame. To make this scalable, I added a generalized "pre-hashing" solution to `bevy_utils`: `Hashed<T>` keys and `PreHashMap<K, V>` (which uses `Hashed<T>` internally) . Why didn't I just do the quick and dirty in-place "pre-compute hash and use that u64 as a key in a hashmap" that we've done in the past? Because its wrong! Hashes by themselves aren't enough because two different values can produce the same hash. Re-hashing a hash is even worse! I decided to build a generalized solution because this pattern has come up in the past and we've chosen to do the wrong thing. Now we can do the right thing! This did unfortunately require pulling in `hashbrown` and using that in `bevy_utils`, because avoiding re-hashes requires the `raw_entry_mut` api, which isn't stabilized yet (and may never be ... `entry_ref` has favor now, but also isn't available yet). If std's HashMap ever provides the tools we need, we can move back to that. Note that adding `hashbrown` doesn't increase our dependency count because it was already in our tree. I will probably break these changes out into their own PR.
* Specializing on `MeshVertexBufferLayout` has one non-obvious behavior: it can produce identical pipelines for two different MeshVertexBufferLayouts. To optimize the number of active pipelines / reduce re-binds while drawing, I de-duplicate pipelines post-specialization using the final `VertexBufferLayout` as the key.  For example, consider a pipeline that needs the layout `(position, normal)` and is specialized using two meshes: `(position, normal, uv)` and `(position, normal, other_vec2)`. If both of these meshes result in `(position, normal)` specializations, we can use the same pipeline! Now we do. Cool!

To briefly illustrate, this is what the relevant section of `MeshPipeline`'s specialization code looks like now:

```rust
impl SpecializedMeshPipeline for MeshPipeline {
    type Key = MeshPipelineKey;

    fn specialize(
        &self,
        key: Self::Key,
        layout: &MeshVertexBufferLayout,
    ) -> RenderPipelineDescriptor {
        let mut vertex_attributes = vec![
            Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
            Mesh::ATTRIBUTE_NORMAL.at_shader_location(1),
            Mesh::ATTRIBUTE_UV_0.at_shader_location(2),
        ];

        let mut shader_defs = Vec::new();
        if layout.contains(Mesh::ATTRIBUTE_TANGENT) {
            shader_defs.push(String::from("VERTEX_TANGENTS"));
            vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(3));
        }

        let vertex_buffer_layout = layout
            .get_layout(&vertex_attributes)
            .expect("Mesh is missing a vertex attribute");
```

Notice that this is _much_ simpler than it was before. And now any mesh with any layout can be used with this pipeline, provided it has vertex postions, normals, and uvs. We even got to remove `HAS_TANGENTS` from MeshPipelineKey and `has_tangents` from `GpuMesh`, because that information is redundant with `MeshVertexBufferLayout`.

This is still a draft because I still need to:

* Add more docs
* Experiment with adding error handling to mesh pipeline specialization (which would print errors at runtime when a mesh is missing a vertex attribute required by a pipeline). If it doesn't tank perf, we'll keep it.
* Consider breaking out the PreHash / hashbrown changes into a separate PR.
* Add an example illustrating this change
* Verify that the "mesh-specialized pipeline de-duplication code" works properly

Please dont yell at me for not doing these things yet :) Just trying to get this in peoples' hands asap.

Alternative to #3120
Fixes #3030


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-02-23 23:21:13 +00:00
danieleades
d8974e7c3d small and mostly pointless refactoring (#2934)
What is says on the tin.

This has got more to do with making `clippy` slightly more *quiet* than it does with changing anything that might greatly impact readability or performance.

that said, deriving `Default` for a couple of structs is a nice easy win
2022-02-13 22:33:55 +00:00
Jakob Hellermann
d305e4f026 only use unique type UUIDs (#3579)
Out of curiosity I ran `rg -F -I '#[uuid = "' | sort` to see if there were any duplicate UUIDs, and they were. Now there aren't any.
2022-02-12 19:58:02 +00:00
Gwen
b11ee3ffb8 Remove duplicate call to set_vertex_buffer(0, ...) in shader_instancing example (#3738)
## Objective

The [`DrawMeshInstanced`] command in the example sets vertex buffer 0 twice, with two identical calls to:

```rs
pass.set_vertex_buffer(0, gpu_mesh.vertex_buffer.slice(..));
```

## Solution

Remove the second call as it is unecessary.

[`DrawMeshInstanced`]: f3de12bc5e/examples/shader/shader_instancing.rs (L217-L258)
2022-02-04 03:37:40 +00:00
Charles Giguere
435fb7af4f Improve shader_material example documentation (#3601)
# Objective

While trying to learn how to use custom shaders, I had difficulty figuring out how to use a vertex shader. My confusion was mostly because all the other shader examples used a custom pipeline, but I didn't want a custom pipeline. After digging around I realised that I simply needed to add a function to the `impl Material` block. I also searched what was the default shader used, because it wasn't obvious to me where to find it.

## Solution

Added a few comments explaining what is going on in the example and a link to the default shader.
2022-01-26 18:52:54 +00:00
luke.biel
6d76229c38 Fix a typo in shader_defs example (#3762)
# Objective

As in title, I'm already looking through these files so may as well rename `pipline` to `pipeline`
2022-01-24 23:44:08 +00:00
Robert Swain
55da315432 bevy_render: Provide a way to opt-out of the built-in frustum culling (#3711)
# Objective

- Allow opting-out of the built-in frustum culling for cases where its behaviour would be incorrect
- Make use of the this in the shader_instancing example that uses a custom instancing method. The built-in frustum culling breaks the custom instancing in the shader_instancing example if the camera is moved to:

```rust
    commands.spawn_bundle(PerspectiveCameraBundle {
        transform: Transform::from_xyz(12.0, 0.0, 15.0)
            .looking_at(Vec3::new(12.0, 0.0, 0.0), Vec3::Y),
        ..Default::default()
    });
```

...such that the Aabb of the cube Mesh that is at the origin goes completely out of view. This incorrectly (for the purpose of the custom instancing) culls the `Mesh` and so culls all instances even though some may be visible.


## Solution

- Add a `NoFrustumCulling` marker component
- Do not compute and add an `Aabb` to `Mesh` entities without an `Aabb` if they have a `NoFrustumCulling` marker component
- Do not apply frustum culling to entities with the `NoFrustumCulling` marker component
2022-01-17 22:55:44 +00:00
Jakob Hellermann
b1476015d9 add some more pipelined-rendering shader examples (#3041)
based on #3031 

Adds some examples showing of how to use the new pipelined rendering for custom shaders.

- a minimal shader example which doesn't use render assets
- the same but using glsl
- an example showing how to render instanced data
- a shader which uses the seconds since startup to animate some textures


Instancing shader:
![grafik](https://user-images.githubusercontent.com/22177966/139299294-e176b62a-53d1-4287-9a66-02fb55affc02.png)
Animated shader:
![animate_shader](https://user-images.githubusercontent.com/22177966/139299718-2940c0f3-8480-4ee0-98d7-b6ba40dc1472.gif)
(the gif makes it look a bit ugly)

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-01-05 19:43:11 +00:00
Carter Anderson
963e2f08a2 Materials and MaterialPlugin (#3428)
This adds "high level" `Material` and `SpecializedMaterial` traits, which can be used with a `MaterialPlugin<T: SpecializedMaterial>`. `MaterialPlugin` automatically registers the appropriate resources, draw functions, and queue systems. The `Material` trait is simpler, and should cover most use cases. `SpecializedMaterial` is like `Material`, but it also requires defining a "specialization key" (see #3031). `Material` has a trivial blanket impl of `SpecializedMaterial`, which allows us to use the same types + functions for both.

This makes defining custom 3d materials much simpler (see the `shader_material` example diff) and ensures consistent behavior across all 3d materials (both built in and custom). I ported the built in `StandardMaterial` to `MaterialPlugin`. There is also a new `MaterialMeshBundle<T: SpecializedMaterial>`, which `PbrBundle` aliases to.
2021-12-25 21:45:43 +00:00
Jakob Hellermann
adb3ad399c make sub_app return an &App and add sub_app_mut() -> &mut App (#3309)
It's sometimes useful to have a reference to an app a sub app at the same time, which is only possible with an immutable reference.
2021-12-24 06:57:30 +00:00
François
79d36e7c28 Prepare crevice for vendored release (#3394)
# Objective

- Our crevice is still called "crevice", which we can't use for a release
- Users would need to use our "crevice" directly to be able to use the derive macro

## Solution

- Rename crevice to bevy_crevice, and crevice-derive to bevy-crevice-derive
- Re-export it from bevy_render, and use it from bevy_render everywhere
- Fix derive macro to work either from bevy_render, from bevy_crevice, or from bevy

## Remaining

- It is currently re-exported as `bevy::render::bevy_crevice`, is it the path we want?
- After a brief suggestion to Cart, I changed the version to follow Bevy version instead of crevice, do we want that?
- Crevice README.md need to be updated
- in the `Cargo.toml`, there are a few things to change. How do we want to change them? How do we keep attributions to original Crevice?
```
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
documentation = "https://docs.rs/crevice"
homepage = "https://github.com/LPGhatguy/crevice"
repository = "https://github.com/LPGhatguy/crevice"
```


Co-authored-by: François <8672791+mockersf@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-23 22:49:12 +00:00
davier
c79ec9cad6 Fix custom mesh pipelines (#3381)
# Objective

Fixes #3379 

## Solution

The custom mesh pipelines needed to be specialized on each mesh's primitive topology, as done in `queue_meshes()`

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-20 20:33:39 +00:00
Carter Anderson
ffecb05a0a Replace old renderer with new renderer (#3312)
This makes the [New Bevy Renderer](#2535) the default (and only) renderer. The new renderer isn't _quite_ ready for the final release yet, but I want as many people as possible to start testing it so we can identify bugs and address feedback prior to release.

The examples are all ported over and operational with a few exceptions:

* I removed a good portion of the examples in the `shader` folder. We still have some work to do in order to make these examples possible / ergonomic / worthwhile: #3120 and "high level shader material plugins" are the big ones. This is a temporary measure.
* Temporarily removed the multiple_windows example: doing this properly in the new renderer will require the upcoming "render targets" changes. Same goes for the render_to_texture example.
* Removed z_sort_debug: entity visibility sort info is no longer available in app logic. we could do this on the "render app" side, but i dont consider it a priority.
2021-12-14 03:58:23 +00:00
François
3de391be21 fix calls to as_rgba_linear (#3200)
# Objective

- After #3192, some places where `as_rgba_linear` was called were doing too many conversions

## Solution

- Fix the conversions
2021-11-28 10:40:42 +00:00
Carter Anderson
8009af3879 Merge New Renderer 2021-11-22 23:57:42 -08:00
Carter Anderson
2e79951659 Shader Imports. Decouple Mesh logic from PBR (#3137)
## Shader Imports

This adds "whole file" shader imports. These come in two flavors:

### Asset Path Imports

```rust
// /assets/shaders/custom.wgsl

#import "shaders/custom_material.wgsl"

[[stage(fragment)]]
fn fragment() -> [[location(0)]] vec4<f32> {
    return get_color();
}
```

```rust
// /assets/shaders/custom_material.wgsl

[[block]]
struct CustomMaterial {
    color: vec4<f32>;
};
[[group(1), binding(0)]]
var<uniform> material: CustomMaterial;
```

### Custom Path Imports

Enables defining custom import paths. These are intended to be used by crates to export shader functionality:

```rust
// bevy_pbr2/src/render/pbr.wgsl

#import bevy_pbr::mesh_view_bind_group
#import bevy_pbr::mesh_bind_group

[[block]]
struct StandardMaterial {
    base_color: vec4<f32>;
    emissive: vec4<f32>;
    perceptual_roughness: f32;
    metallic: f32;
    reflectance: f32;
    flags: u32;
};

/* rest of PBR fragment shader here */
```

```rust
impl Plugin for MeshRenderPlugin {
    fn build(&self, app: &mut bevy_app::App) {
        let mut shaders = app.world.get_resource_mut::<Assets<Shader>>().unwrap();
        shaders.set_untracked(
            MESH_BIND_GROUP_HANDLE,
            Shader::from_wgsl(include_str!("mesh_bind_group.wgsl"))
                .with_import_path("bevy_pbr::mesh_bind_group"),
        );
        shaders.set_untracked(
            MESH_VIEW_BIND_GROUP_HANDLE,
            Shader::from_wgsl(include_str!("mesh_view_bind_group.wgsl"))
                .with_import_path("bevy_pbr::mesh_view_bind_group"),
        );
```

By convention these should use rust-style module paths that start with the crate name. Ultimately we might enforce this convention.

Note that this feature implements _run time_ import resolution. Ultimately we should move the import logic into an asset preprocessor once Bevy gets support for that.

## Decouple Mesh Logic from PBR Logic via MeshRenderPlugin

This breaks out mesh rendering code from PBR material code, which improves the legibility of the code, decouples mesh logic from PBR logic, and opens the door for a future `MaterialPlugin<T: Material>` that handles all of the pipeline setup for arbitrary shader materials.

## Removed `RenderAsset<Shader>` in favor of extracting shaders into RenderPipelineCache

This simplifies the shader import implementation and removes the need to pass around `RenderAssets<Shader>`.

##  RenderCommands are now fallible

This allows us to cleanly handle pipelines+shaders not being ready yet. We can abort a render command early in these cases, preventing bevy from trying to bind group / do draw calls for pipelines that couldn't be bound. This could also be used in the future for things like "components not existing on entities yet". 

# Next Steps

* Investigate using Naga for "partial typed imports" (ex: `#import bevy_pbr::material::StandardMaterial`, which would import only the StandardMaterial struct)
* Implement `MaterialPlugin<T: Material>` for low-boilerplate custom material shaders
* Move shader import logic into the asset preprocessor once bevy gets support for that.

Fixes #3132
2021-11-18 03:45:02 +00:00
Carter Anderson
9a4cc42b38 EntityRenderCommand and PhaseItemRenderCommand (#3111)
Adds new `EntityRenderCommand`, `EntityPhaseItem`, and `CachedPipelinePhaseItem` traits to make it possible to reuse RenderCommands across phases. This should be helpful for features like #3072 . It also makes the trait impls slightly less generic-ey in the common cases.

This also fixes the custom shader examples to account for the recent Frustum Culling and MSAA changes (the UX for these things will be improved later).
2021-11-12 22:27:17 +00:00
Carter Anderson
015617a774 Pipeline Specialization, Shader Assets, and Shader Preprocessing (#3031)
## New Features
This adds the following to the new renderer:

* **Shader Assets**
  * Shaders are assets again! Users no longer need to call `include_str!` for their shaders
  * Shader hot-reloading
* **Shader Defs / Shader Preprocessing**
  * Shaders now support `# ifdef NAME`, `# ifndef NAME`, and `# endif` preprocessor directives
* **Bevy RenderPipelineDescriptor and RenderPipelineCache**
  * Bevy now provides its own `RenderPipelineDescriptor` and the wgpu version is now exported as `RawRenderPipelineDescriptor`. This allows users to define pipelines with `Handle<Shader>` instead of needing to manually compile and reference `ShaderModules`, enables passing in shader defs to configure the shader preprocessor, makes hot reloading possible (because the descriptor can be owned and used to create new pipelines when a shader changes), and opens the doors to pipeline specialization.
  * The `RenderPipelineCache` now handles compiling and re-compiling Bevy RenderPipelineDescriptors. It has internal PipelineLayout and ShaderModule caches. Users receive a `CachedPipelineId`, which can be used to look up the actual `&RenderPipeline` during rendering. 
* **Pipeline Specialization**
  * This enables defining per-entity-configurable pipelines that specialize on arbitrary custom keys. In practice this will involve specializing based on things like MSAA values, Shader Defs, Bind Group existence, and Vertex Layouts.
  * Adds a `SpecializedPipeline` trait and `SpecializedPipelines<MyPipeline>` resource. This is a simple layer that generates Bevy RenderPipelineDescriptors based on a custom key defined for the pipeline.
  * Specialized pipelines are also hot-reloadable.
  * This was the result of experimentation with two different approaches:
    1. **"generic immediate mode multi-key hash pipeline specialization"**
      * breaks up the pipeline into multiple "identities" (the core pipeline definition, shader defs, mesh layout, bind group layout). each of these identities has its own key. looking up / compiling a specific version of a pipeline requires composing all of these keys together
      * the benefit of this approach is that it works for all pipelines / the pipeline is fully identified by the keys. the multiple keys allow pre-hashing parts of the pipeline identity where possible (ex: pre compute the mesh identity for all meshes)
      * the downside is that any per-entity data that informs the values of these keys could require expensive re-hashes. computing each key for each sprite tanked bevymark performance (sprites don't actually need this level of specialization yet ... but things like pbr and future sprite scenarios might). 
      * this is the approach rafx used last time i checked
    2. **"custom key specialization"**
      * Pipelines by default are not specialized
      * Pipelines that need specialization implement a SpecializedPipeline trait with a custom key associated type
      * This allows specialization keys to encode exactly the amount of information required (instead of needing to be a combined hash of the entire pipeline). Generally this should fit in a small number of bytes. Per-entity specialization barely registers anymore on things like bevymark. It also makes things like "shader defs" way cheaper to hash because we can use context specific bitflags instead of strings.
      * Despite the extra trait, it actually generally makes pipeline definitions + lookups simpler: managing multiple keys (and making the appropriate calls to manage these keys) was way more complicated.
  * I opted for custom key specialization. It performs better generally and in my opinion is better UX. Fortunately the way this is implemented also allows for custom caches as this all builds on a common abstraction: the RenderPipelineCache. The built in custom key trait is just a simple / pre-defined way to interact with the cache 

## Callouts

* The SpecializedPipeline trait makes it easy to inherit pipeline configuration in custom pipelines. The changes to `custom_shader_pipelined` and the new `shader_defs_pipelined` example illustrate how much simpler it is to define custom pipelines based on the PbrPipeline.
* The shader preprocessor is currently pretty naive (it just uses regexes to process each line). Ultimately we might want to build a more custom parser for more performance + better error handling, but for now I'm happy to optimize for "easy to implement and understand". 

## Next Steps

* Port compute pipelines to the new system
* Add more preprocessor directives (else, elif, import)
* More flexible vertex attribute specialization / enable cheaply specializing on specific mesh vertex layouts
2021-10-28 19:07:47 +00:00
Carter Anderson
43e8a156fb Upgrade to wgpu 0.11 (#2933)
Upgrades both the old and new renderer to wgpu 0.11 (and naga 0.7). This builds on @zicklag's work here #2556.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-10-08 19:55:24 +00:00
Paweł Grabarz
07ed1d053e Implement and require #[derive(Component)] on all component structs (#2254)
This implements the most minimal variant of #1843 - a derive for marker trait. This is a prerequisite to more complicated features like statically defined storage type or opt-out component reflection.

In order to make component struct's purpose explicit and avoid misuse, it must be annotated with `#[derive(Component)]` (manual impl is discouraged for compatibility). Right now this is just a marker trait, but in the future it might be expanded. Making this change early allows us to make further changes later without breaking backward compatibility for derive macro users.

This already prevents a lot of issues, like using bundles in `insert` calls. Primitive types are no longer valid components as well. This can be easily worked around by adding newtype wrappers and deriving `Component` for them.

One funny example of prevented bad code (from our own tests) is when an newtype struct or enum variant is used. Previously, it was possible to write `insert(Newtype)` instead of `insert(Newtype(value))`. That code compiled, because function pointers (in this case newtype struct constructor) implement `Send + Sync + 'static`, so we allowed them to be used as components. This is no longer the case and such invalid code will trigger a compile error.


Co-authored-by: = <=>
Co-authored-by: TheRawMeatball <therawmeatball@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-10-03 19:23:44 +00:00
Carter Anderson
08969a24b8 Modular Rendering (#2831)
This changes how render logic is composed to make it much more modular. Previously, all extraction logic was centralized for a given "type" of rendered thing. For example, we extracted meshes into a vector of ExtractedMesh, which contained the mesh and material asset handles, the transform, etc. We looked up bindings for "drawn things" using their index in the `Vec<ExtractedMesh>`. This worked fine for built in rendering, but made it hard to reuse logic for "custom" rendering. It also prevented us from reusing things like "extracted transforms" across contexts.

To make rendering more modular, I made a number of changes:

* Entities now drive rendering:
  * We extract "render components" from "app components" and store them _on_ entities. No more centralized uber lists! We now have true "ECS-driven rendering"
  * To make this perform well, I implemented #2673 in upstream Bevy for fast batch insertions into specific entities. This was merged into the `pipelined-rendering` branch here: #2815
* Reworked the `Draw` abstraction:
  * Generic `PhaseItems`: each draw phase can define its own type of "rendered thing", which can define its own "sort key"
  * Ported the 2d, 3d, and shadow phases to the new PhaseItem impl (currently Transparent2d, Transparent3d, and Shadow PhaseItems)
  * `Draw` trait and and `DrawFunctions` are now generic on PhaseItem
  * Modular / Ergonomic `DrawFunctions` via `RenderCommands`
    * RenderCommand is a trait that runs an ECS query and produces one or more RenderPass calls. Types implementing this trait can be composed to create a final DrawFunction. For example the DrawPbr DrawFunction is created from the following DrawCommand tuple. Const generics are used to set specific bind group locations:
        ```rust
         pub type DrawPbr = (
            SetPbrPipeline,
            SetMeshViewBindGroup<0>,
            SetStandardMaterialBindGroup<1>,
            SetTransformBindGroup<2>,
            DrawMesh,
        );
        ```
    * The new `custom_shader_pipelined` example illustrates how the commands above can be reused to create a custom draw function:
       ```rust
       type DrawCustom = (
           SetCustomMaterialPipeline,
           SetMeshViewBindGroup<0>,
           SetTransformBindGroup<2>,
           DrawMesh,
       );
       ``` 
* ExtractComponentPlugin and UniformComponentPlugin:
  * Simple, standardized ways to easily extract individual components and write them to GPU buffers
* Ported PBR and Sprite rendering to the new primitives above.
* Removed staging buffer from UniformVec in favor of direct Queue usage
  * Makes UniformVec much easier to use and more ergonomic. Completely removes the need for custom render graph nodes in these contexts (see the PbrNode and view Node removals and the much simpler call patterns in the relevant Prepare systems).
* Added a many_cubes_pipelined example to benchmark baseline 3d rendering performance and ensure there were no major regressions during this port. Avoiding regressions was challenging given that the old approach of extracting into centralized vectors is basically the "optimal" approach. However thanks to a various ECS optimizations and render logic rephrasing, we pretty much break even on this benchmark!
* Lifetimeless SystemParams: this will be a bit divisive, but as we continue to embrace "trait driven systems" (ex: ExtractComponentPlugin, UniformComponentPlugin, DrawCommand), the ergonomics of `(Query<'static, 'static, (&'static A, &'static B, &'static)>, Res<'static, C>)` were getting very hard to bear. As a compromise, I added "static type aliases" for the relevant SystemParams. The previous example can now be expressed like this: `(SQuery<(Read<A>, Read<B>)>, SRes<C>)`. If anyone has better ideas / conflicting opinions, please let me know!
* RunSystem trait: a way to define Systems via a trait with a SystemParam associated type. This is used to implement the various plugins mentioned above. I also added SystemParamItem and QueryItem type aliases to make "trait stye" ecs interactions nicer on the eyes (and fingers).
* RenderAsset retrying: ensures that render assets are only created when they are "ready" and allows us to create bind groups directly inside render assets (which significantly simplified the StandardMaterial code). I think ultimately we should swap this out on "asset dependency" events to wait for dependencies to load, but this will require significant asset system changes.
* Updated some built in shaders to account for missing MeshUniform fields
2021-09-23 06:16:11 +00:00
Carter Anderson
11b41206eb Add upstream bevy_ecs and prepare for custom-shaders merge (#2815)
This updates the `pipelined-rendering` branch to use the latest `bevy_ecs` from `main`. This accomplishes a couple of goals:

1. prepares for upcoming `custom-shaders` branch changes, which were what drove many of the recent bevy_ecs changes on `main`
2. prepares for the soon-to-happen merge of `pipelined-rendering` into `main`. By including bevy_ecs changes now, we make that merge simpler / easier to review. 

I split this up into 3 commits:

1. **add upstream bevy_ecs**: please don't bother reviewing this content. it has already received thorough review on `main` and is a literal copy/paste of the relevant folders (the old folders were deleted so the directories are literally exactly the same as `main`).
2. **support manual buffer application in stages**: this is used to enable the Extract step. we've already reviewed this once on the `pipelined-rendering` branch, but its worth looking at one more time in the new context of (1).
3. **support manual archetype updates in QueryState**: same situation as (2).
2021-09-14 06:14:19 +00:00
Charles Giguere
51a5070cd2 add get_single variant (#2793)
# Objective

The vast majority of `.single()` usage I've seen is immediately followed by a `.unwrap()`. Since it seems most people use it without handling the error, I think making it easier to just get what you want fast while also having a more verbose alternative when you want to handle the error could help.

## Solution

Instead of having a lot of `.unwrap()` everywhere, this PR introduces a `try_single()` variant that behaves like the current `.single()` and make the new `.single()` panic on error.
2021-09-10 20:23:50 +00:00
François
b724a0f586 Down with the system! (#2496)
# Objective

- Remove all the `.system()` possible.
- Check for remaining missing cases.

## Solution

- Remove all `.system()`, fix compile errors
- 32 calls to `.system()` remains, mostly internals, the few others should be removed after #2446
2021-07-27 23:42:36 +00:00
bjorn3
6d6bc2a8b4 Merge AppBuilder into App (#2531)
This is extracted out of eb8f973646476b4a4926ba644a77e2b3a5772159 and includes some additional changes to remove all references to AppBuilder and fix examples that still used App::build() instead of App::new(). In addition I didn't extract the sub app feature as it isn't ready yet.

You can use `git diff --diff-filter=M eb8f973646476b4a4926ba644a77e2b3a5772159` to find all differences in this PR. The `--diff-filtered=M` filters all files added in the original commit but not in this commit away.

Co-Authored-By: Carter Anderson <mcanders1@gmail.com>
2021-07-27 20:21:06 +00:00
Carter Anderson
4ac2ed7cc6 pipelined rendering proof of concept 2021-07-24 16:43:37 -07:00
Alice Cecile
e4e32598a9 Cargo fmt with unstable features (#1903)
Fresh version of #1670 off the latest main.

Mostly fixing documentation wrapping.
2021-04-21 23:19:34 +00:00
Anselmo Sampietro
9b7ed18f72 Add animate shaders example (#1765)
This PR adds an example on how to animate a shader by passing the global `time.seconds_since_startup()` to a component, and accessing that component inside the shader.

Hopefully this is the current proper solution, please let me know if it should be solved in another way.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-04-15 19:49:31 +00:00
Carter Anderson
5bccb67aa3 Remove unused material (#1898)
This doesn't do anything and complicates the example.
2021-04-13 02:39:50 +00:00
Carter Anderson
81b53d15d4 Make Commands and World apis consistent (#1703)
Resolves #1253 #1562

This makes the Commands apis consistent with World apis. This moves to a "type state" pattern (like World) where the "current entity" is stored in an `EntityCommands` builder.

In general this tends to cuts down on indentation and line count. It comes at the cost of needing to type `commands` more and adding more semicolons to terminate expressions.

I also added `spawn_bundle` to Commands because this is a common enough operation that I think its worth providing a shorthand.
2021-03-23 00:23:40 +00:00
Jonas Matser
cd8025d0a7 Remove remaining camerapos bindings (#1708)
Fixes #1706

@JeanMertz already solved it. I just ran all examples and tests.
2021-03-22 18:10:35 +00:00
Jonas Matser
45b2db7070 Rebase of existing PBR work (#1554)
This is a rebase of StarArawns PBR work from #261 with IngmarBitters work from #1160 cherry-picked on top.

I had to make a few minor changes to make some intermediate commits compile and the end result is not yet 100% what I expected, so there's a bit more work to do.

Co-authored-by: John Mitchell <toasterthegamer@gmail.com>
Co-authored-by: Ingmar Bitter <ingmar.bitter@gmail.com>
2021-03-20 03:22:33 +00:00
Carter Anderson
dd4a196329 Flexible camera bindings (#1689)
Alternative to #1203 and #1611

Camera bindings have historically been "hacked in". They were _required_ in all shaders and only supported a single Mat4. PBR (#1554) requires the CameraView matrix, but adding this using the "hacked" method forced users to either include all possible camera data in a single binding (#1203) or include all possible bindings (#1611).

This approach instead assigns each "active camera" its own RenderResourceBindings, which are populated by CameraNode. The PassNode then retrieves (and initializes) the relevant bind groups for all render pipelines used by visible entities. 

* Enables any number of camera bindings , including zero (with any set or binding number ... set 0 should still be used to avoid rebinds).
* Renames Camera binding to CameraViewProj
* Adds CameraView binding
2021-03-19 20:36:40 +00:00
François
bbb9849506 Replace default method calls from Glam types with explicit const (#1645)
it's a followup of #1550 

I think calling explicit methods/values instead of default makes the code easier to read: "what is `Quat::default()`" vs "Oh, it's `Quat::IDENTITY`"

`Transform::identity()` and `GlobalTransform::identity()` can also be consts and I replaced the calls to their `default()` impl with `identity()`
2021-03-13 18:23:39 +00:00
Carter Anderson
b17f8a4bce format comments (#1612)
Uses the new unstable comment formatting features added to rustfmt.toml.
2021-03-11 00:27:30 +00:00
Cameron Hart
f61e44db28 Update glam to 0.13.0. (#1550)
See https://github.com/bitshifter/glam-rs/blob/master/CHANGELOG.md for details on changes.

Co-authored-by: Cameron Hart <c_hart@wargaming.net>
2021-03-06 19:39:16 +00:00
Carter Anderson
3a2a68852c Bevy ECS V2 (#1525)
# Bevy ECS V2

This is a rewrite of Bevy ECS (basically everything but the new executor/schedule, which are already awesome). The overall goal was to improve the performance and versatility of Bevy ECS. Here is a quick bulleted list of changes before we dive into the details:

* Complete World rewrite
* Multiple component storage types:
    * Tables: fast cache friendly iteration, slower add/removes (previously called Archetypes)
    * Sparse Sets: fast add/remove, slower iteration
* Stateful Queries (caches query results for faster iteration. fragmented iteration is _fast_ now)
* Stateful System Params (caches expensive operations. inspired by @DJMcNab's work in #1364)
* Configurable System Params (users can set configuration when they construct their systems. once again inspired by @DJMcNab's work)
* Archetypes are now "just metadata", component storage is separate
* Archetype Graph (for faster archetype changes)
* Component Metadata
    * Configure component storage type
    * Retrieve information about component size/type/name/layout/send-ness/etc
    * Components are uniquely identified by a densely packed ComponentId
    * TypeIds are now totally optional (which should make implementing scripting easier)
* Super fast "for_each" query iterators
* Merged Resources into World. Resources are now just a special type of component
* EntityRef/EntityMut builder apis (more efficient and more ergonomic)
* Fast bitset-backed `Access<T>` replaces old hashmap-based approach everywhere
* Query conflicts are determined by component access instead of archetype component access (to avoid random failures at runtime)
    * With/Without are still taken into account for conflicts, so this should still be comfy to use
* Much simpler `IntoSystem` impl
* Significantly reduced the amount of hashing throughout the ecs in favor of Sparse Sets (indexed by densely packed ArchetypeId, ComponentId, BundleId, and TableId)
* Safety Improvements
    * Entity reservation uses a normal world reference instead of unsafe transmute
    * QuerySets no longer transmute lifetimes
    * Made traits "unsafe" where relevant
    * More thorough safety docs
* WorldCell
    * Exposes safe mutable access to multiple resources at a time in a World 
* Replaced "catch all" `System::update_archetypes(world: &World)` with `System::new_archetype(archetype: &Archetype)`
* Simpler Bundle implementation
* Replaced slow "remove_bundle_one_by_one" used as fallback for Commands::remove_bundle with fast "remove_bundle_intersection"
* Removed `Mut<T>` query impl. it is better to only support one way: `&mut T` 
* Removed with() from `Flags<T>` in favor of `Option<Flags<T>>`, which allows querying for flags to be "filtered" by default 
* Components now have is_send property (currently only resources support non-send)
* More granular module organization
* New `RemovedComponents<T>` SystemParam that replaces `query.removed::<T>()`
* `world.resource_scope()` for mutable access to resources and world at the same time
* WorldQuery and QueryFilter traits unified. FilterFetch trait added to enable "short circuit" filtering. Auto impled for cases that don't need it
* Significantly slimmed down SystemState in favor of individual SystemParam state
* System Commands changed from `commands: &mut Commands` back to `mut commands: Commands` (to allow Commands to have a World reference)

Fixes #1320

## `World` Rewrite

This is a from-scratch rewrite of `World` that fills the niche that `hecs` used to. Yes, this means Bevy ECS is no longer a "fork" of hecs. We're going out our own!

(the only shared code between the projects is the entity id allocator, which is already basically ideal)

A huge shout out to @SanderMertens (author of [flecs](https://github.com/SanderMertens/flecs)) for sharing some great ideas with me (specifically hybrid ecs storage and archetype graphs). He also helped advise on a number of implementation details.

## Component Storage (The Problem)

Two ECS storage paradigms have gained a lot of traction over the years:

* **Archetypal ECS**: 
    * Stores components in "tables" with static schemas. Each "column" stores components of a given type. Each "row" is an entity.
    * Each "archetype" has its own table. Adding/removing an entity's component changes the archetype.
    * Enables super-fast Query iteration due to its cache-friendly data layout
    * Comes at the cost of more expensive add/remove operations for an Entity's components, because all components need to be copied to the new archetype's "table"
* **Sparse Set ECS**:
    * Stores components of the same type in densely packed arrays, which are sparsely indexed by densely packed unsigned integers (Entity ids)
    * Query iteration is slower than Archetypal ECS because each entity's component could be at any position in the sparse set. This "random access" pattern isn't cache friendly. Additionally, there is an extra layer of indirection because you must first map the entity id to an index in the component array.
    * Adding/removing components is a cheap, constant time operation 

Bevy ECS V1, hecs, legion, flec, and Unity DOTS are all "archetypal ecs-es". I personally think "archetypal" storage is a good default for game engines. An entity's archetype doesn't need to change frequently in general, and it creates "fast by default" query iteration (which is a much more common operation). It is also "self optimizing". Users don't need to think about optimizing component layouts for iteration performance. It "just works" without any extra boilerplate.

Shipyard and EnTT are "sparse set ecs-es". They employ "packing" as a way to work around the "suboptimal by default" iteration performance for specific sets of components. This helps, but I didn't think this was a good choice for a general purpose engine like Bevy because:

1. "packs" conflict with each other. If bevy decides to internally pack the Transform and GlobalTransform components, users are then blocked if they want to pack some custom component with Transform.
2. users need to take manual action to optimize

Developers selecting an ECS framework are stuck with a hard choice. Select an "archetypal" framework with "fast iteration everywhere" but without the ability to cheaply add/remove components, or select a "sparse set" framework to cheaply add/remove components but with slower iteration performance.

## Hybrid Component Storage (The Solution)

In Bevy ECS V2, we get to have our cake and eat it too. It now has _both_ of the component storage types above (and more can be added later if needed):

* **Tables** (aka "archetypal" storage)
    * The default storage. If you don't configure anything, this is what you get
    * Fast iteration by default
    * Slower add/remove operations
* **Sparse Sets**
    * Opt-in
    * Slower iteration
    * Faster add/remove operations

These storage types complement each other perfectly. By default Query iteration is fast. If developers know that they want to add/remove a component at high frequencies, they can set the storage to "sparse set":

```rust
world.register_component(
    ComponentDescriptor:🆕:<MyComponent>(StorageType::SparseSet)
).unwrap();
```

## Archetypes

Archetypes are now "just metadata" ... they no longer store components directly. They do store:

* The `ComponentId`s of each of the Archetype's components (and that component's storage type)
    * Archetypes are uniquely defined by their component layouts
    * For example: entities with "table" components `[A, B, C]` _and_ "sparse set" components `[D, E]` will always be in the same archetype.
* The `TableId` associated with the archetype
    * For now each archetype has exactly one table (which can have no components),
    * There is a 1->Many relationship from Tables->Archetypes. A given table could have any number of archetype components stored in it:
        * Ex: an entity with "table storage" components `[A, B, C]` and "sparse set" components `[D, E]` will share the same `[A, B, C]` table as an entity with `[A, B, C]` table component and `[F]` sparse set components.
        * This 1->Many relationship is how we preserve fast "cache friendly" iteration performance when possible (more on this later)
* A list of entities that are in the archetype and the row id of the table they are in
* ArchetypeComponentIds
    * unique densely packed identifiers for (ArchetypeId, ComponentId) pairs
    * used by the schedule executor for cheap system access control
* "Archetype Graph Edges" (see the next section)  

## The "Archetype Graph"

Archetype changes in Bevy (and a number of other archetypal ecs-es) have historically been expensive to compute. First, you need to allocate a new vector of the entity's current component ids, add or remove components based on the operation performed, sort it (to ensure it is order-independent), then hash it to find the archetype (if it exists). And thats all before we get to the _already_ expensive full copy of all components to the new table storage.

The solution is to build a "graph" of archetypes to cache these results. @SanderMertens first exposed me to the idea (and he got it from @gjroelofs, who came up with it). They propose adding directed edges between archetypes for add/remove component operations. If `ComponentId`s are densely packed, you can use sparse sets to cheaply jump between archetypes.

Bevy takes this one step further by using add/remove `Bundle` edges instead of `Component` edges. Bevy encourages the use of `Bundles` to group add/remove operations. This is largely for "clearer game logic" reasons, but it also helps cut down on the number of archetype changes required. `Bundles` now also have densely-packed `BundleId`s. This allows us to use a _single_ edge for each bundle operation (rather than needing to traverse N edges ... one for each component). Single component operations are also bundles, so this is strictly an improvement over a "component only" graph.

As a result, an operation that used to be _heavy_ (both for allocations and compute) is now two dirt-cheap array lookups and zero allocations.

## Stateful Queries

World queries are now stateful. This allows us to:

1. Cache archetype (and table) matches
    * This resolves another issue with (naive) archetypal ECS: query performance getting worse as the number of archetypes goes up (and fragmentation occurs).
2. Cache Fetch and Filter state
    * The expensive parts of fetch/filter operations (such as hashing the TypeId to find the ComponentId) now only happen once when the Query is first constructed
3. Incrementally build up state
    * When new archetypes are added, we only process the new archetypes (no need to rebuild state for old archetypes)

As a result, the direct `World` query api now looks like this:

```rust
let mut query = world.query::<(&A, &mut B)>();
for (a, mut b) in query.iter_mut(&mut world) {
}
```

Requiring `World` to generate stateful queries (rather than letting the `QueryState` type be constructed separately) allows us to ensure that _all_ queries are properly initialized (and the relevant world state, such as ComponentIds). This enables QueryState to remove branches from its operations that check for initialization status (and also enables query.iter() to take an immutable world reference because it doesn't need to initialize anything in world).

However in systems, this is a non-breaking change. State management is done internally by the relevant SystemParam.

## Stateful SystemParams

Like Queries, `SystemParams` now also cache state. For example, `Query` system params store the "stateful query" state mentioned above. Commands store their internal `CommandQueue`. This means you can now safely use as many separate `Commands` parameters in your system as you want. `Local<T>` system params store their `T` value in their state (instead of in Resources). 

SystemParam state also enabled a significant slim-down of SystemState. It is much nicer to look at now.

Per-SystemParam state naturally insulates us from an "aliased mut" class of errors we have hit in the past (ex: using multiple `Commands` system params).

(credit goes to @DJMcNab for the initial idea and draft pr here #1364)

## Configurable SystemParams

@DJMcNab also had the great idea to make SystemParams configurable. This allows users to provide some initial configuration / values for system parameters (when possible). Most SystemParams have no config (the config type is `()`), but the `Local<T>` param now supports user-provided parameters:

```rust

fn foo(value: Local<usize>) {    
}

app.add_system(foo.system().config(|c| c.0 = Some(10)));
```

## Uber Fast "for_each" Query Iterators

Developers now have the choice to use a fast "for_each" iterator, which yields ~1.5-3x iteration speed improvements for "fragmented iteration", and minor ~1.2x iteration speed improvements for unfragmented iteration. 

```rust
fn system(query: Query<(&A, &mut B)>) {
    // you now have the option to do this for a speed boost
    query.for_each_mut(|(a, mut b)| {
    });

    // however normal iterators are still available
    for (a, mut b) in query.iter_mut() {
    }
}
```

I think in most cases we should continue to encourage "normal" iterators as they are more flexible and more "rust idiomatic". But when that extra "oomf" is needed, it makes sense to use `for_each`.

We should also consider using `for_each` for internal bevy systems to give our users a nice speed boost (but that should be a separate pr).

## Component Metadata

`World` now has a `Components` collection, which is accessible via `world.components()`. This stores mappings from `ComponentId` to `ComponentInfo`, as well as `TypeId` to `ComponentId` mappings (where relevant). `ComponentInfo` stores information about the component, such as ComponentId, TypeId, memory layout, send-ness (currently limited to resources), and storage type.

## Significantly Cheaper `Access<T>`

We used to use `TypeAccess<TypeId>` to manage read/write component/archetype-component access. This was expensive because TypeIds must be hashed and compared individually. The parallel executor got around this by "condensing" type ids into bitset-backed access types. This worked, but it had to be re-generated from the `TypeAccess<TypeId>`sources every time archetypes changed.

This pr removes TypeAccess in favor of faster bitset access everywhere. We can do this thanks to the move to densely packed `ComponentId`s and `ArchetypeComponentId`s.

## Merged Resources into World

Resources had a lot of redundant functionality with Components. They stored typed data, they had access control, they had unique ids, they were queryable via SystemParams, etc. In fact the _only_ major difference between them was that they were unique (and didn't correlate to an entity).

Separate resources also had the downside of requiring a separate set of access controls, which meant the parallel executor needed to compare more bitsets per system and manage more state.

I initially got the "separate resources" idea from `legion`. I think that design was motivated by the fact that it made the direct world query/resource lifetime interactions more manageable. It certainly made our lives easier when using Resources alongside hecs/bevy_ecs. However we already have a construct for safely and ergonomically managing in-world lifetimes: systems (which use `Access<T>` internally).

This pr merges Resources into World:

```rust
world.insert_resource(1);
world.insert_resource(2.0);
let a = world.get_resource::<i32>().unwrap();
let mut b = world.get_resource_mut::<f64>().unwrap();
*b = 3.0;
```

Resources are now just a special kind of component. They have their own ComponentIds (and their own resource TypeId->ComponentId scope, so they don't conflict wit components of the same type). They are stored in a special "resource archetype", which stores components inside the archetype using a new `unique_components` sparse set (note that this sparse set could later be used to implement Tags). This allows us to keep the code size small by reusing existing datastructures (namely Column, Archetype, ComponentFlags, and ComponentInfo). This allows us the executor to use a single `Access<ArchetypeComponentId>` per system. It should also make scripting language integration easier.

_But_ this merge did create problems for people directly interacting with `World`. What if you need mutable access to multiple resources at the same time? `world.get_resource_mut()` borrows World mutably!

## WorldCell

WorldCell applies the `Access<ArchetypeComponentId>` concept to direct world access:

```rust
let world_cell = world.cell();
let a = world_cell.get_resource_mut::<i32>().unwrap();
let b = world_cell.get_resource_mut::<f64>().unwrap();
```

This adds cheap runtime checks (a sparse set lookup of `ArchetypeComponentId` and a counter) to ensure that world accesses do not conflict with each other. Each operation returns a `WorldBorrow<'w, T>` or `WorldBorrowMut<'w, T>` wrapper type, which will release the relevant ArchetypeComponentId resources when dropped.

World caches the access sparse set (and only one cell can exist at a time), so `world.cell()` is a cheap operation. 

WorldCell does _not_ use atomic operations. It is non-send, does a mutable borrow of world to prevent other accesses, and uses a simple `Rc<RefCell<ArchetypeComponentAccess>>` wrapper in each WorldBorrow pointer. 

The api is currently limited to resource access, but it can and should be extended to queries / entity component access.

## Resource Scopes

WorldCell does not yet support component queries, and even when it does there are sometimes legitimate reasons to want a mutable world ref _and_ a mutable resource ref (ex: bevy_render and bevy_scene both need this). In these cases we could always drop down to the unsafe `world.get_resource_unchecked_mut()`, but that is not ideal!

Instead developers can use a "resource scope"

```rust
world.resource_scope(|world: &mut World, a: &mut A| {
})
```

This temporarily removes the `A` resource from `World`, provides mutable pointers to both, and re-adds A to World when finished. Thanks to the move to ComponentIds/sparse sets, this is a cheap operation.

If multiple resources are required, scopes can be nested. We could also consider adding a "resource tuple" to the api if this pattern becomes common and the boilerplate gets nasty.

## Query Conflicts Use ComponentId Instead of ArchetypeComponentId

For safety reasons, systems cannot contain queries that conflict with each other without wrapping them in a QuerySet. On bevy `main`, we use ArchetypeComponentIds to determine conflicts. This is nice because it can take into account filters:

```rust
// these queries will never conflict due to their filters
fn filter_system(a: Query<&mut A, With<B>>, b: Query<&mut B, Without<B>>) {
}
```

But it also has a significant downside:
```rust
// these queries will not conflict _until_ an entity with A, B, and C is spawned
fn maybe_conflicts_system(a: Query<(&mut A, &C)>, b: Query<(&mut A, &B)>) {
}
```

The system above will panic at runtime if an entity with A, B, and C is spawned. This makes it hard to trust that your game logic will run without crashing.

In this pr, I switched to using `ComponentId` instead. This _is_ more constraining. `maybe_conflicts_system` will now always fail, but it will do it consistently at startup. Naively, it would also _disallow_ `filter_system`, which would be a significant downgrade in usability. Bevy has a number of internal systems that rely on disjoint queries and I expect it to be a common pattern in userspace.

To resolve this, I added a new `FilteredAccess<T>` type, which wraps `Access<T>` and adds with/without filters. If two `FilteredAccess` have with/without values that prove they are disjoint, they will no longer conflict.

## EntityRef / EntityMut

World entity operations on `main` require that the user passes in an `entity` id to each operation:

```rust
let entity = world.spawn((A, )); // create a new entity with A
world.get::<A>(entity);
world.insert(entity, (B, C));
world.insert_one(entity, D);
```

This means that each operation needs to look up the entity location / verify its validity. The initial spawn operation also requires a Bundle as input. This can be awkward when no components are required (or one component is required).

These operations have been replaced by `EntityRef` and `EntityMut`, which are "builder-style" wrappers around world that provide read and read/write operations on a single, pre-validated entity:

```rust
// spawn now takes no inputs and returns an EntityMut
let entity = world.spawn()
    .insert(A) // insert a single component into the entity
    .insert_bundle((B, C)) // insert a bundle of components into the entity
    .id() // id returns the Entity id

// Returns EntityMut (or panics if the entity does not exist)
world.entity_mut(entity)
    .insert(D)
    .insert_bundle(SomeBundle::default());
{
    // returns EntityRef (or panics if the entity does not exist)
    let d = world.entity(entity)
        .get::<D>() // gets the D component
        .unwrap();
    // world.get still exists for ergonomics
    let d = world.get::<D>(entity).unwrap();
}

// These variants return Options if you want to check existence instead of panicing 
world.get_entity_mut(entity)
    .unwrap()
    .insert(E);

if let Some(entity_ref) = world.get_entity(entity) {
    let d = entity_ref.get::<D>().unwrap();
}
```

This _does not_ affect the current Commands api or terminology. I think that should be a separate conversation as that is a much larger breaking change.

## Safety Improvements

* Entity reservation in Commands uses a normal world borrow instead of an unsafe transmute
* QuerySets no longer transmutes lifetimes
* Made traits "unsafe" when implementing a trait incorrectly could cause unsafety
* More thorough safety docs

## RemovedComponents SystemParam

The old approach to querying removed components: `query.removed:<T>()` was confusing because it had no connection to the query itself. I replaced it with the following, which is both clearer and allows us to cache the ComponentId mapping in the SystemParamState:

```rust
fn system(removed: RemovedComponents<T>) {
    for entity in removed.iter() {
    }
} 
```

## Simpler Bundle implementation

Bundles are no longer responsible for sorting (or deduping) TypeInfo. They are just a simple ordered list of component types / data. This makes the implementation smaller and opens the door to an easy "nested bundle" implementation in the future (which i might even add in this pr). Duplicate detection is now done once per bundle type by World the first time a bundle is used.

## Unified WorldQuery and QueryFilter types

(don't worry they are still separate type _parameters_ in Queries .. this is a non-breaking change)

WorldQuery and QueryFilter were already basically identical apis. With the addition of `FetchState` and more storage-specific fetch methods, the overlap was even clearer (and the redundancy more painful).

QueryFilters are now just `F: WorldQuery where F::Fetch: FilterFetch`. FilterFetch requires `Fetch<Item = bool>` and adds new "short circuit" variants of fetch methods. This enables a filter tuple like `(With<A>, Without<B>, Changed<C>)` to stop evaluating the filter after the first mismatch is encountered. FilterFetch is automatically implemented for `Fetch` implementations that return bool.

This forces fetch implementations that return things like `(bool, bool, bool)` (such as the filter above) to manually implement FilterFetch and decide whether or not to short-circuit.

## More Granular Modules

World no longer globs all of the internal modules together. It now exports `core`, `system`, and `schedule` separately. I'm also considering exporting `core` submodules directly as that is still pretty "glob-ey" and unorganized (feedback welcome here).

## Remaining Draft Work (to be done in this pr)

* ~~panic on conflicting WorldQuery fetches (&A, &mut A)~~
    * ~~bevy `main` and hecs both currently allow this, but we should protect against it if possible~~
* ~~batch_iter / par_iter (currently stubbed out)~~
* ~~ChangedRes~~
    * ~~I skipped this while we sort out #1313. This pr should be adapted to account for whatever we land on there~~.
* ~~The `Archetypes` and `Tables` collections use hashes of sorted lists of component ids to uniquely identify each archetype/table. This hash is then used as the key in a HashMap to look up the relevant ArchetypeId or TableId. (which doesn't handle hash collisions properly)~~
* ~~It is currently unsafe to generate a Query from "World A", then use it on "World B" (despite the api claiming it is safe). We should probably close this gap. This could be done by adding a randomly generated WorldId to each world, then storing that id in each Query. They could then be compared to each other on each `query.do_thing(&world)` operation. This _does_ add an extra branch to each query operation, so I'm open to other suggestions if people have them.~~
* ~~Nested Bundles (if i find time)~~

## Potential Future Work

* Expand WorldCell to support queries.
* Consider not allocating in the empty archetype on `world.spawn()`
    * ex: return something like EntityMutUninit, which turns into EntityMut after an `insert` or `insert_bundle` op
    * this actually regressed performance last time i tried it, but in theory it should be faster
* Optimize SparseSet::insert (see `PERF` comment on insert)
* Replace SparseArray `Option<T>` with T::MAX to cut down on branching
    * would enable cheaper get_unchecked() operations
* upstream fixedbitset optimizations
    * fixedbitset could be allocation free for small block counts (store blocks in a SmallVec)
    * fixedbitset could have a const constructor 
* Consider implementing Tags (archetype-specific by-value data that affects archetype identity) 
    * ex: ArchetypeA could have `[A, B, C]` table components and `[D(1)]` "tag" component. ArchetypeB could have `[A, B, C]` table components and a `[D(2)]` tag component. The archetypes are different, despite both having D tags because the value inside D is different.
    * this could potentially build on top of the `archetype.unique_components` added in this pr for resource storage.
* Consider reverting `all_tuples` proc macro in favor of the old `macro_rules` implementation
    * all_tuples is more flexible and produces cleaner documentation (the macro_rules version produces weird type parameter orders due to parser constraints)
    * but unfortunately all_tuples also appears to make Rust Analyzer sad/slow when working inside of `bevy_ecs` (does not affect user code)
* Consider "resource queries" and/or "mixed resource and entity component queries" as an alternative to WorldCell
    * this is basically just "systems" so maybe it's not worth it
* Add more world ops
    * `world.clear()`
    * `world.reserve<T: Bundle>(count: usize)`
 * Try using the old archetype allocation strategy (allocate new memory on resize and copy everything over). I expect this to improve batch insertion performance at the cost of unbatched performance. But thats just a guess. I'm not an allocation perf pro :)
 * Adapt Commands apis for consistency with new World apis 

## Benchmarks

key:

* `bevy_old`: bevy `main` branch
* `bevy`: this branch
* `_foreach`: uses an optimized for_each iterator
* ` _sparse`: uses sparse set storage (if unspecified assume table storage)
* `_system`: runs inside a system (if unspecified assume test happens via direct world ops)

### Simple Insert (from ecs_bench_suite)

![image](https://user-images.githubusercontent.com/2694663/109245573-9c3ce100-7795-11eb-9003-bfd41cd5c51f.png)

### Simpler Iter (from ecs_bench_suite)

![image](https://user-images.githubusercontent.com/2694663/109245795-ffc70e80-7795-11eb-92fb-3ffad09aabf7.png)

### Fragment Iter (from ecs_bench_suite)

![image](https://user-images.githubusercontent.com/2694663/109245849-0fdeee00-7796-11eb-8d25-eb6b7a682c48.png)

### Sparse Fragmented Iter

Iterate a query that matches 5 entities from a single matching archetype, but there are 100 unmatching archetypes

![image](https://user-images.githubusercontent.com/2694663/109245916-2b49f900-7796-11eb-9a8f-ed89c203f940.png)
 
### Schedule (from ecs_bench_suite)

![image](https://user-images.githubusercontent.com/2694663/109246428-1fab0200-7797-11eb-8841-1b2161e90fa4.png)

### Add Remove Component (from ecs_bench_suite)

![image](https://user-images.githubusercontent.com/2694663/109246492-39e4e000-7797-11eb-8985-2706bd0495ab.png)


### Add Remove Component Big

Same as the test above, but each entity has 5 "large" matrix components and 1 "large" matrix component is added and removed

![image](https://user-images.githubusercontent.com/2694663/109246517-449f7500-7797-11eb-835e-28b6790daeaa.png)


### Get Component

Looks up a single component value a large number of times

![image](https://user-images.githubusercontent.com/2694663/109246129-87ad1880-7796-11eb-9fcb-c38012aa7c70.png)
2021-03-05 07:54:35 +00:00
Alexander Sepity
c2a427f1a3
Non-string labels (#1423 continued) (#1473)
Non-string labels
2021-02-18 13:20:37 -08:00
Jasen Borisov
57f9ac18d7
OrthographicProjection scaling mode + camera bundle refactoring (#400)
* add normalized orthographic projection

* custom scale for ScaledOrthographicProjection

* allow choosing base axis for ScaledOrthographicProjection

* cargo fmt

* add general (scaled) orthographic camera bundle

FIXME: does the same "far" trick from Camera2DBundle make any sense here?

* fixes

* camera bundles: rename and new ortho constructors

* unify orthographic projections

* give PerspectiveCameraBundle constructors like those of OrthographicCameraBundle

* update examples with new camera bundle syntax

* rename CameraUiBundle to UiCameraBundle

* update examples

* ScalingMode::None

* remove extra blank lines

* sane default bounds for orthographic projection

* fix alien_cake_addict example

* reorder ScalingMode enum variants

* ios example fix
2021-01-30 02:31:03 -08:00
Daniel McNab
9f2410a4ac
Add from_xyz to Transform (#1212)
* Add the from_xyz helper method to Transform

* Use `from_xyz` where possible
2021-01-06 17:17:06 -08:00
Patrik Buhring
cbc0fe1416
Modify Derive to allow unit structs for RenderResources. (#1089) 2020-12-23 17:21:10 -06:00
Carter Anderson
841755aaf2
Adopt a Fetch pattern for SystemParams (#1074) 2020-12-15 21:57:16 -08:00
Al M
2c9b7956d1
Live reloading of shaders (#937)
* Add ShaderLoader, rebuild pipelines for modified shader assets
* New example
* Add shader_update_system, ShaderError, remove specialization assets
* Don't panic on shader compilation failure
2020-12-07 12:32:13 -08:00
Carter Anderson
44b5cfeda1
fix example bindings (#1001) 2020-12-04 10:37:27 -08:00
Carter Anderson
72b2fc9843
Bevy Reflection (#926)
Bevy Reflection
2020-11-27 16:39:59 -08:00
Duncan
46fac78774
Extend the Texture asset type to support 3D data (#903)
Extend the Texture asset type to support 3D data

Textures are still loaded from images as 2D, but they can be reshaped
according to how the render pipeline would like to use them.

Also add an example of how this can be used with the texture2DArray uniform type.
2020-11-22 12:04:47 -08:00
Valentin
d458406540
Add box shape (#883)
* Add rectangular cuboid shape

Co-authored-by: Jason Lessard <jason.lessard@usherbrooke.ca>
Co-authored-by: Jason Lessard <jason.lessard@usherbrooke.ca>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2020-11-21 14:51:24 -08:00
Carter Anderson
3a6f6de277
System Inputs, Outputs, Chaining, and Registration Ergo (#876)
System Inputs, Outputs, Chaining, and Registration Ergo
2020-11-16 18:18:00 -08:00
Carter Anderson
7628f4a64e
combine bevy_ecs and bevy_hecs crates. rename XComponents to XBundle (#863)
combine bevy_ecs and bevy_hecs crates. rename XComponents to XBundle
2020-11-15 20:32:23 -08:00
Mariusz Kryński
60fa2d5f93
delegate layout reflection to RenderResourceContext (#691)
* delegate layout reflection to RenderResourceContext
Also:
 * auto-reflect DynamicBindings
 * use RenderPipeline::new, update dynamic_bindings

linting.

* add dynamic binding generation

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2020-11-10 13:20:05 -08:00
Carter Anderson
ebcdc9fb8c
Flexible ECS System Params (#798)
system params can be in any order, faster compiles, remove foreach
2020-11-08 12:34:05 -08:00
Carter Anderson
66f2f76a18
rename add_plugin_group to add_plugins (#773) 2020-11-02 19:01:17 -08:00
Nathan Stocks
9871e7e24b
Remove add_default_plugins and add MinimalPlugins for simple "headless" scenarios (#767)
Remove add_default_plugins and add MinimalPlugins for simple "headless" scenarios
2020-11-02 18:38:37 -08:00
Julian Heinken
f81ecddafc
Example for custom mesh attributes (#757)
example for custom attributes + changelog
2020-11-02 13:47:05 -08:00
Carter Anderson
c32e637384
Asset system rework and GLTF scene loading (#693) 2020-10-18 13:48:15 -07:00
Marek Legris
5acebed731
Transform and GlobalTransform are now Similarities (#596)
Transform and GlobalTransform are now Similarities.

This resolves precision errors and simplifies the api

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2020-10-18 13:03:16 -07:00
Smite Rust
b0e64d4295
update async-executor (#484)
update async-executor
2020-09-14 14:01:41 -07:00
Marek Legris
474bb5403e
Transform Rewrite (#374)
Remove individual Translation / Rotation / Scale components in favor of a combined Transform component
2020-09-14 14:00:32 -07:00
Victor "multun" Collod
d138647818 enforce cargo fmt --check 2020-08-16 05:02:06 -07:00
Carter Anderson
bb111cbafa more example cleanup and polish 2020-07-31 17:10:29 -07:00
Carter Anderson
6dadf34401 add more example comments 2020-07-28 13:45:36 -07:00
Carter Anderson
726eb37198 use rh coordinate system in 2d
z = 0 is now "farthest back" and z=1000 "farthest forward"
2020-07-19 17:00:08 -07:00
Carter Anderson
b12c4d0a48 render: simplify imports and cleanup prelude 2020-07-16 18:26:21 -07:00
Carter Anderson
1db77b2435 examples: cleanup imports 2020-07-16 17:20:42 -07:00
Carter Anderson
c81ab99dac cargo fmt 2020-07-10 01:37:06 -07:00
Carter Anderson
950e50bbb1 Bevy ECS migration 2020-07-10 01:06:21 -07:00
Carter Anderson
e75496772e legion: change query system ordering 2020-06-27 10:18:27 -07:00
Carter Anderson
92c44320ee ecs: rename EntityArchetype to ComponentSet 2020-06-25 11:21:56 -07:00
Carter Anderson
75429f4639 render: use left-handed coordinate system and y-up 2020-06-24 15:29:10 -07:00
Carter Anderson
3ee8aa8b0f camera: make camera transform in world coordinates instead of the inverse 2020-06-23 19:18:32 -07:00
Carter Anderson
faacd2778d sprite: add color to TextureAtlasSprite and make Vec3 16 bytes again to account for glsl UBO layout 2020-06-21 17:43:36 -07:00
Carter Anderson
74d0055a3d render: move dynamic_bindings to PipelineSpecialization
This is a temporary step back in ergonomics as we are no longer automatically inferring dynamic bindings from RenderResourceBindings
2020-06-17 18:10:29 -07:00
Carter Anderson
0931fd0266 fix a few things in shader examples 2020-06-17 17:44:26 -07:00
Carter Anderson
e855995145 cargo fmt 2020-06-15 12:47:35 -07:00
Carter Anderson
f799d3ac93 render: add RenderPipeline and begin moving logic there 2020-06-15 00:08:50 -07:00
Carter Anderson
fc4160ea41 AssetRenderResourceNodes now consume asset change events. Remove EntitiesWaitingForAssets in favor of DrawState. 2020-06-10 18:54:17 -07:00
Carter Anderson
3d07fbdc81 render: "Immediate Mode" draw api
This replaces Renderable with Draw/RenderPipelines components and makes various aspects of the renderer much simpler and legible
2020-06-09 23:16:48 -07:00
Carter Anderson
1426208e2f remove DrawTargets in favor of PassNodes and in preparation for "immediate mode" drawing api 2020-06-08 14:35:13 -07:00
Carter Anderson
62c434274f shader_defs: new leaner shader defs. they are now separate from uniforms 2020-06-07 22:24:53 -07:00
Carter Anderson
fd8f87400d add RenderResources/RenderResource traits to replace Uniforms/Uniform 2020-06-07 19:12:41 -07:00
Carter Anderson
5add29f8cf rename LocalToWorld -> Transform and LocalToParent -> LocalTransform 2020-06-07 13:39:50 -07:00
Carter Anderson
5ea979dd0e move shaders in examples into consts 2020-06-05 00:13:18 -07:00
Carter Anderson
21a79c56a7 camera: add position and rotation components to Perspective camera. add "sync" toggle to LocalToWorld transform. 2020-05-31 10:31:18 -07:00
Carter Anderson
51d41b2302 camera: remove active camera components in favor of camera names 2020-05-29 22:07:55 -07:00
Carter Anderson
fcc0a6303b update mesh on gpu when it changes 2020-05-16 00:21:04 -07:00
Carter Anderson
2bcb8a2a41 cargo fmt 2020-05-13 18:05:18 -07:00
Carter Anderson
6381611e89 Resource -> Res, Ref->Com 2020-05-13 17:57:08 -07:00
Carter Anderson
fb8f9e8636 RenderGraph::add_node now requires a name 2020-05-13 17:35:48 -07:00
Carter Anderson
06f3a4efb9 Use system fns for all setup code 2020-05-13 17:31:56 -07:00
Carter Anderson
70f122b92a Rename AssetStorage to Assets 2020-05-13 16:45:18 -07:00
Carter Anderson
16b568e00e Asset events and AddAsset builder 2020-05-13 16:17:44 -07:00
Carter Anderson
7b79b3de8d organize examples and add ecs guide 2020-05-01 13:12:47 -07:00