Adds support for MSAA to the new renderer. This is done using the new [pipeline specialization](#3031) support to specialize on sample count. This is an alternative implementation to #2541 that cuts out the need for complicated render graph edge management by moving the relevant target information into View entities. This reuses @superdump's clever MSAA bitflag range code from #2541.
Note that wgpu currently only supports 1 or 4 samples due to those being the values supported by WebGPU. However they do plan on exposing ways to [enable/query for natively supported sample counts](https://github.com/gfx-rs/wgpu/issues/1832). When this happens we should integrate
# Objective
Make possible to use wgpu gles backend on in the browser (wasm32 + WebGL2).
## Solution
It is built on top of old @cart patch initializing windows before wgpu. Also:
- initializes wgpu with `Backends::GL` and proper `wgpu::Limits` on wasm32
- changes default texture format to `wgpu::TextureFormat::Rgba8UnormSrgb`
Co-authored-by: Mariusz Kryński <mrk@sed.pl>
# Objective
- Fixes#2919
- Initial pixel was hard coded and not dependent on texture format
- Replace #2920 as I noticed this needed to be done also on pipeline rendering branch
## Solution
- Replace the hard coded pixel with one using the texture pixel size
# Objective
while testing wgpu/WebGL on mobile GPU I've noticed bevy always forces vertex index format to 32bit (and ignores mesh settings).
## Solution
the solution is to pass proper vertex index format in GpuIndexInfo to render_pass
## 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
# Objective
The current TODO comment is out of date
## Solution
I switched up the comment
Co-authored-by: William Batista <45850508+billyb2@users.noreply.github.com>
## Objective
Looking though the new pipelined example I stumbled on an issue with the example shader :
```
Oct 20 12:38:44.891 INFO bevy_render2::renderer: AdapterInfo { name: "Intel(R) UHD Graphics 620 (KBL GT2)", vendor: 32902, device: 22807, device_type: IntegratedGpu, backend: Vulkan }
Oct 20 12:38:44.894 INFO naga:🔙:spv::writer: Skip function Some("fetch_point_shadow")
Oct 20 12:38:44.894 INFO naga:🔙:spv::writer: Skip function Some("fetch_directional_shadow")
Oct 20 12:38:44.898 ERROR wgpu::backend::direct: Handling wgpu errors as fatal by default
thread 'main' panicked at 'wgpu error: Validation Error
Caused by:
In Device::create_shader_module
Global variable [1] 'view' is invalid
Type isn't compatible with the storage class
```
## Solution
added `<uniform>` here and there.
Note : my current mastery of shaders is about 2 days old, so this still kinda look likes wizardry
# Objective
The update to wgpu 0.11 broke CI for android. This was due to a confusion between `bevy::render::ShaderStage` and `wgpu::ShaderStage`.
## Solution
Revert the incorrect change
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>
Using RenderQueue in BufferVec allows removal of the staging buffer entirely, as well as removal of the SpriteNode.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
- removed unused RenderResourceId and SwapChainFrame (already unified with TextureView)
- added deref to BindGroup, this makes conversion to wgpu::BindGroup easier
## Solution
- cleans up the API
# Objective
Using fullscreen or trying to resize a window caused a panic. Fix that.
## Solution
- Don't wholesale overwrite the ExtractedWindows resource when extracting windows
- This could cause an accumulation of unused windows that are holding onto swap chain frames?
- Check the if width and/or height changed since the last frame
- If the size changed, recreate the swap chain
- Ensure dimensions are >= 1 to avoid panics due to any dimension being 0
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
Before using this image resulted in an `Error in Queue::write_texture: copy of 0..4 would end up overrunning the bounds of the Source buffer of size 0`
# Objective
Bevy should expose all wgpu types needed for building rendering pipelines.
Closes#2818
## Solution
Add wgpu's StencilOperation to bevy_render2::render_resource's export.
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).
# Objective
Fixes a usability problem where the user is unable to use their reference to a ComputePipeline in their compute pass.
## Solution
Implements Deref, allowing the user to obtain the reference to the underlying wgpu::ComputePipeline
# Objective
Forward perspective projections have poor floating point precision distribution over the depth range. Reverse projections fair much better, and instead of having to have a far plane, with the reverse projection, using an infinite far plane is not a problem. The infinite reverse perspective projection has become the industry standard. The renderer rework is a great time to migrate to it.
## Solution
All perspective projections, including point lights, have been moved to using `glam::Mat4::perspective_infinite_reverse_rh()` and so have no far plane. As various depth textures are shared between orthographic and perspective projections, a quirk of this PR is that the near and far planes of the orthographic projection are swapped when the Mat4 is computed. This has no impact on 2D/3D orthographic projection usage, and provides consistency in shaders, texture clear values, etc. throughout the codebase.
## Known issues
For some reason, when looking along -Z, all geometry is black. The camera can be translated up/down / strafed left/right and geometry will still be black. Moving forward/backward or rotating the camera away from looking exactly along -Z causes everything to work as expected.
I have tried to debug this issue but both in macOS and Windows I get crashes when doing pixel debugging. If anyone could reproduce this and debug it I would be very grateful. Otherwise I will have to try to debug it further without pixel debugging, though the projections and such all looked fine to me.
# Objective
- Prevent the need to have a system that synchronizes sprite sizes with their images
## Solution
- Read the sprite size from the image asset when rendering the sprite
- Replace the `size` and `resize_mode` fields of `Sprite` with a `custom_size: Option<Vec2>` that will modify the sprite's rendered size to be different than the image size, but only if it is `Some(Vec2)`
# Objective
- Avoid unnecessary work in the vertex shader of the numerous shadow passes
- Have the natural order of bind groups in the pbr shader: view, material, mesh
## Solution
- Separate out the vertex stage of pbr.wgsl into depth.wgsl
- Remove the unnecessary calculation of uv and normal, as well as removing the unnecessary vertex inputs and outputs
- Use the depth.wgsl for shadow passes
- Reorder the bind groups in pbr.wgsl and PbrShaders to be 0 - view, 1 - material, 2 - mesh in decreasing order of rebind frequency
# Objective
Allow marking meshes as not casting / receiving shadows.
## Solution
- Added `NotShadowCaster` and `NotShadowReceiver` zero-sized type components.
- Extract these components into `bool`s in `ExtractedMesh`
- Only generate `DrawShadowMesh` `Drawable`s for meshes _without_ `NotShadowCaster`
- Add a `u32` bit `flags` member to `MeshUniform` with one flag indicating whether the mesh is a shadow receiver
- If a mesh does _not_ have the `NotShadowReceiver` component, then it is a shadow receiver, and so the bit in the `MeshUniform` is set, otherwise it is not set.
- Added an example illustrating the functionality.
NOTE: I wanted to have the default state of a mesh as being a shadow caster and shadow receiver, hence the `Not*` components. However, I am on the fence about this. I don't want to have a negative performance impact, nor have people wondering why their custom meshes don't have shadows because they forgot to add `ShadowCaster` and `ShadowReceiver` components, but I also really don't like the double negatives the `Not*` approach incurs. What do you think?
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Add support for configurable shadow map sizes
## Solution
- Add `DirectionalLightShadowMap` and `PointLightShadowMap` resources, which just have size members, to the app world, and add `Extracted*` counterparts to the render world
- Use the configured sizes when rendering shadow maps
- Default sizes remain the same - 4096 for directional light shadow maps, 1024 for point light shadow maps (which are cube maps so 6 faces at 1024x1024 per light)
Makes some tweaks to the SubApp labeling introduced in #2695:
* Ergonomics improvements
* Removes unnecessary allocation when retrieving subapp label
* Removes the newly added "app macros" crate in favor of bevy_derive
* renamed RenderSubApp to RenderApp
@zicklag (for reference)
This is a rather simple but wide change, and it involves adding a new `bevy_app_macros` crate. Let me know if there is a better way to do any of this!
---
# Objective
- Allow adding and accessing sub-apps by using a label instead of an index
## Solution
- Migrate the bevy label implementation and derive code to the `bevy_utils` and `bevy_macro_utils` crates and then add a new `SubAppLabel` trait to the `bevy_app` crate that is used when adding or getting a sub-app from an app.
# Objective
A question was raised on Discord about the units of the `PointLight` `intensity` member.
After digging around in the bevy_pbr2 source code and [Google Filament documentation](https://google.github.io/filament/Filament.html#mjx-eqn-pointLightLuminousPower) I discovered that the intention by Filament was that the 'intensity' value for point lights would be in lumens. This makes a lot of sense as these are quite relatable units given basically all light bulbs I've seen sold over the past years are rated in lumens as people move away from thinking about how bright a bulb is relative to a non-halogen incandescent bulb.
However, it seems that the derivation of the conversion between luminous power (lumens, denoted `Φ` in the Filament formulae) and luminous intensity (lumens per steradian, `I` in the Filament formulae) was missed and I can see why as it is tucked right under equation 58 at the link above. As such, while the formula states that for a point light, `I = Φ / 4 π` we have been using `intensity` as if it were luminous intensity `I`.
Before this PR, the intensity field is luminous intensity in lumens per steradian. After this PR, the intensity field is luminous power in lumens, [as suggested by Filament](https://google.github.io/filament/Filament.html#table_lighttypesunits) (unfortunately the link jumps to the table's caption so scroll up to see the actual table).
I appreciate that it may be confusing to call this an intensity, but I think this is intended as more of a non-scientific, human-relatable general term with a bit of hand waving so that most light types can just have an intensity field and for most of them it works in the same way or at least with some relatable value. I'm inclined to think this is reasonable rather than throwing terms like luminous power, luminous intensity, blah at users.
## Solution
- Documented the `PointLight` `intensity` member as 'luminous power' in units of lumens.
- Added a table of examples relating from various types of household lighting to lumen values.
- Added in the mapping from luminous power to luminous intensity when premultiplying the intensity into the colour before it is made into a graphics uniform.
- Updated the documentation in `pbr.wgsl` to clarify the earlier confusion about the missing `/ 4 π`.
- Bumped the intensity of the point lights in `3d_scene_pipelined` to 1600 lumens.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
The default perspective projection near plane being at 1 unit feels very far away if one considers units to directly map to real world units such as metres. Not being able to see anything that is closer than 1m is unnecessarily limiting. Using a default of 0.1 makes more sense as it is difficult to even focus on things closer than 10cm in the real world.
## Solution
- Changed the default perspective projection near plane to 0.1.
# Objective
- Allow the user to set the clear color when using the pipelined renderer
## Solution
- Add a `ClearColor` resource that can be added to the world to configure the clear color
## Remaining Issues
Currently the `ClearColor` resource is cloned from the app world to the render world every frame. There are two ways I can think of around this:
1. Figure out why `app_world.is_resource_changed::<ClearColor>()` always returns `true` in the `extract` step and fix it so that we are only updating the resource when it changes
2. Require the users to add the `ClearColor` resource to the render sub-app instead of the parent app. This is currently sub-optimal until we have labled sub-apps, and probably a helper funciton on `App` such as `app.with_sub_app(RenderApp, |app| { ... })`. Even if we had that, I think it would be more than we want the user to have to think about. They shouldn't have to know about the render sub-app I don't think.
I think the first option is the best, but I could really use some help figuring out the nuance of why `is_resource_changed` is always returning true in that context.
# Objective
Fix ComputePipelineDescriptor missing from WGPU exports
## Solution
Added it to the pub use wgpu::{ ... }
Co-authored-by: Dimas <skythedragon@outlook.com>
# Objective
- Prevent the need to specify a sprite size when using the pipelined sprite renderer
## Solution
- Re-introduce the sprite auto resize system from the old renderer
# Objective
- Allow you to compile Bevy with the `bevy_sprite2` feature, but without the `bevy_pbr2` feature.
- This currently fails because the `bevy_sprite2` crate does not require the `derive` feature of the `bytemuck` crate in its `Cargo.toml`, even though it is required to compile.
## Solution
- Add the `derive` feature of `bytemuck` to the `bevy_sprite2` crate
# Objective
This fixes not having access to StorageTextureAccess in the API, which is needed for using storage textures
## Solution
Added it to the use in render_resource module
Co-authored-by: Dimas <skythedragon@outlook.com>
# Objective
Restore the functionality of sprite atlases in the new renderer.
### **Note:** This PR relies on #2555
## Solution
Mostly just a copy paste of the existing sprite atlas implementation, however I unified the rendering between sprites and atlases.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
# Objective
Port bevy_gltf to the pipelined-rendering branch.
## Solution
crates/bevy_gltf has been copied and pasted into pipelined/bevy_gltf2 and modifications were made to work with the pipelined-rendering branch. Notably vertex tangents and vertex colours are not supported.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This decouples the opinionated "core pipeline" from the new (less opinionated) bevy_render crate. The "core pipeline" is intended to be used by crates like bevy_sprites, bevy_pbr, bevy_ui, and 3rd party crates that extends core rendering functionality.
Makes the "Render App World" directly available to Extract step systems as a `RenderWorld` resource. Prior to this, there was no way to directly read / write render world state during the Extract step. The only way to make changes was through Commands (which were applied at the end of the stage).
```rust
// `thing` is an "app world resource".
fn extract_thing(thing: Res<Thing>, mut render_world: ResMut<RenderWorld>) {
render_world.insert_resource(ExtractedThing::from(thing));
}
```
RenderWorld makes a number of scenarios possible:
* When an extract system does big allocations, it is now possible to reuse them across frames by retrieving old values from RenderWorld (at the cost of reduced parallelism from unique RenderWorld borrows).
* Enables inserting into the same resource across multiple extract systems
* Enables using past RenderWorld state to inform future extract state (this should generally be avoided)
Ultimately this is just a subset of the functionality we want. In the future, it would be great to have "multi-world schedules" to enable fine grained parallelism on the render world during the extract step. But that is a research project that almost certainly won't make it into 0.6. This is a good interim solution that should easily port over to multi-world schedules if/when they land.
* 3d_scene_pipelined: Use a shallower directional light angle to provoke acne
* cornell_box_pipelined: Remove bias tweaks
* bevy_pbr2: Simplify shadow biases by moving them to linear depth
* bevy_pbr2: Do not use DepthBiasState
* bevy_pbr2: Do not use bilinear filtering for sampling depth textures
* pbr.wgsl: Remove unnecessary comment
* bevy_pbr2: Do manual shadow map depth comparisons for more flexibility
* examples: Add shadow_biases_pipelined example
This is useful for stress testing biases.
* bevy_pbr2: Scale the point light normal bias by the shadow map texel size
This allows the normal bias to be small close to the light source where the
shadow map texel to screen texel ratio is high, but is appropriately large
further away from the light source where the shadow map texel can easily cover
multiple screen texels.
* shadow_biases_pipelined: Add support for toggling directional / point light
* shadow_biases_pipelined: Cleanup
* bevy_pbr2: Scale the directional light normal bias by the shadow map texel size
* shadow_biases_pipelined: Fit the orthographic projection around the scene
* bevy_pbr2: Directional lights should have no shadows outside their projection
Before this change, sampling a fragment position from outside the ndc volume
would result in the return sample being clamped to the edge in x,y or possibly
always casting a shadow for fragment positions past the orthographic
projection's far plane.
* bevy_pbr2: Fix the default directional light normal bias
* Revert "bevy_pbr2: Do manual shadow map depth comparisons for more flexibility"
This reverts commit 7df1bab38a42d8a33bc50ca583d4be37bd9c9f0d.
* shadow_biases_pipelined: Adjust directional light normal bias in 0.1 increments
* pbr.wgsl: Add a couple of clarifying comments
* Revert "bevy_pbr2: Do not use bilinear filtering for sampling depth textures"
This reverts commit f53baab0232ce218866a45cad6902b470f4cf2c4.
* shadow_biases_pipelined: Print usage to terminal
* 3d_scene_pipelined: Use a shallower directional light angle to provoke acne
* cornell_box_pipelined: Remove bias tweaks
* bevy_pbr2: Simplify shadow biases by moving them to linear depth