Skip to content

Commit

Permalink
Update to wgpu 0.19 and raw-window-handle 0.6 (#11280)
Browse files Browse the repository at this point in the history
# Objective

Keep core dependencies up to date.

## Solution

Update the dependencies.

wgpu 0.19 only supports raw-window-handle (rwh) 0.6, so bumping that was
included in this.

The rwh 0.6 version bump is just the simplest way of doing it. There
might be a way we can take advantage of wgpu's new safe surface creation
api, but I'm not familiar enough with bevy's window management to
untangle it and my attempt ended up being a mess of lifetimes and rustc
complaining about missing trait impls (that were implemented). Thanks to
@MiniaczQ for the (much simpler) rwh 0.6 version bump code.

Unblocks #9172 and
#10812

~~This might be blocked on cpal and oboe updating their ndk versions to
0.8, as they both currently target ndk 0.7 which uses rwh 0.5.2~~ Tested
on android, and everything seems to work correctly (audio properly stops
when minimized, and plays when re-focusing the app).

---

## Changelog

- `wgpu` has been updated to 0.19! The long awaited arcanization has
been merged (for more info, see
https://gfx-rs.github.io/2023/11/24/arcanization.html), and Vulkan
should now be working again on Intel GPUs.
- Targeting WebGPU now requires that you add the new `webgpu` feature
(setting the `RUSTFLAGS` environment variable to
`--cfg=web_sys_unstable_apis` is still required). This feature currently
overrides the `webgl2` feature if you have both enabled (the `webgl2`
feature is enabled by default), so it is not recommended to add it as a
default feature to libraries without putting it behind a flag that
allows library users to opt out of it! In the future we plan on
supporting wasm binaries that can target both webgl2 and webgpu now that
wgpu added support for doing so (see
#11505).
- `raw-window-handle` has been updated to version 0.6.

## Migration Guide

- `bevy_render::instance_index::get_instance_index()` has been removed
as the webgl2 workaround is no longer required as it was fixed upstream
in wgpu. The `BASE_INSTANCE_WORKAROUND` shaderdef has also been removed.
- WebGPU now requires the new `webgpu` feature to be enabled. The
`webgpu` feature currently overrides the `webgl2` feature so you no
longer need to disable all default features and re-add them all when
targeting `webgpu`, but binaries built with both the `webgpu` and
`webgl2` features will only target the webgpu backend, and will only
work on browsers that support WebGPU.
- Places where you conditionally compiled things for webgl2 need to be
updated because of this change, eg:
- `#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]`
becomes `#[cfg(any(not(feature = "webgl") ,not(target_arch = "wasm32"),
feature = "webgpu"))]`
- `#[cfg(all(feature = "webgl", target_arch = "wasm32"))]` becomes
`#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature =
"webgpu")))]`
- `if cfg!(all(feature = "webgl", target_arch = "wasm32"))` becomes `if
cfg!(all(feature = "webgl", target_arch = "wasm32", not(feature =
"webgpu")))`
- `create_texture_with_data` now also takes a `TextureDataOrder`. You
can probably just set this to `TextureDataOrder::default()`
- `TextureFormat`'s `block_size` has been renamed to `block_copy_size`
- See the `wgpu` changelog for anything I might've missed:
https:/gfx-rs/wgpu/blob/trunk/CHANGELOG.md

---------

Co-authored-by: François <[email protected]>
  • Loading branch information
Elabajaba and mockersf authored Jan 26, 2024
1 parent dd4d07d commit 35ac1b1
Show file tree
Hide file tree
Showing 45 changed files with 260 additions and 203 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,12 @@ shader_format_spirv = ["bevy_internal/shader_format_spirv"]
# Enable support for transmission-related textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs
pbr_transmission_textures = ["bevy_internal/pbr_transmission_textures"]

# Enable some limitations to be able to use WebGL2. If not enabled, it will default to WebGPU in Wasm. Please refer to the [WebGL2 and WebGPU](https:/bevyengine/bevy/tree/latest/examples#webgl2-and-webgpu) section of the examples README for more information on how to run Wasm builds with WebGPU.
# Enable some limitations to be able to use WebGL2. Please refer to the [WebGL2 and WebGPU](https:/bevyengine/bevy/tree/latest/examples#webgl2-and-webgpu) section of the examples README for more information on how to run Wasm builds with WebGPU.
webgl2 = ["bevy_internal/webgl"]

# Enable support for WebGPU in Wasm. When enabled, this feature will override the `webgl2` feature and you won't be able to run Wasm builds with WebGL2, only with WebGPU. Requires the `RUSTFLAGS` environment variable to be set to `--cfg=web_sys_unstable_apis` when building.
webgpu = ["bevy_internal/webgpu"]

# Enables the built-in asset processor for processed assets.
asset_processor = ["bevy_internal/asset_processor"]

Expand Down
1 change: 1 addition & 0 deletions crates/bevy_core_pipeline/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ keywords = ["bevy"]
[features]
trace = []
webgl = []
webgpu = []
tonemapping_luts = ["bevy_render/ktx2", "bevy_render/zstd"]

[dependencies]
Expand Down
24 changes: 18 additions & 6 deletions crates/bevy_core_pipeline/src/bloom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,24 +294,32 @@ impl ViewNode for BloomNode {
#[derive(Component)]
struct BloomTexture {
// First mip is half the screen resolution, successive mips are half the previous
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
#[cfg(any(
not(feature = "webgl"),
not(target_arch = "wasm32"),
feature = "webgpu"
))]
texture: CachedTexture,
// WebGL does not support binding specific mip levels for sampling, fallback to separate textures instead
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
texture: Vec<CachedTexture>,
mip_count: u32,
}

impl BloomTexture {
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
#[cfg(any(
not(feature = "webgl"),
not(target_arch = "wasm32"),
feature = "webgpu"
))]
fn view(&self, base_mip_level: u32) -> TextureView {
self.texture.texture.create_view(&TextureViewDescriptor {
base_mip_level,
mip_level_count: Some(1u32),
..Default::default()
})
}
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
fn view(&self, base_mip_level: u32) -> TextureView {
self.texture[base_mip_level as usize]
.texture
Expand Down Expand Up @@ -354,9 +362,13 @@ fn prepare_bloom_textures(
view_formats: &[],
};

#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
#[cfg(any(
not(feature = "webgl"),
not(target_arch = "wasm32"),
feature = "webgpu"
))]
let texture = texture_cache.get(&render_device, texture_descriptor);
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
let texture: Vec<CachedTexture> = (0..mip_count)
.map(|mip| {
texture_cache.get(
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl Node for MainPass2dNode {

// WebGL2 quirk: if ending with a render pass with a custom viewport, the viewport isn't
// reset for the next render pass so add an empty render pass without a custom viewport
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
if camera.viewport.is_some() {
#[cfg(feature = "trace")]
let _reset_viewport_pass_2d = info_span!("reset_viewport_pass_2d").entered();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl ViewNode for MainTransparentPass3dNode {

// WebGL2 quirk: if ending with a render pass with a custom viewport, the viewport isn't
// reset for the next render pass so add an empty render pass without a custom viewport
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
if camera.viewport.is_some() {
#[cfg(feature = "trace")]
let _reset_viewport_pass_3d = info_span!("reset_viewport_pass_3d").entered();
Expand Down
10 changes: 7 additions & 3 deletions crates/bevy_core_pipeline/src/deferred/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl ViewNode for DeferredGBufferPrepassNode {
// Firefox: WebGL warning: clearBufferu?[fi]v: This attachment is of type FLOAT, but this function is of type UINT.
// Appears to be unsupported: https://registry.khronos.org/webgl/specs/latest/2.0/#3.7.9
// For webgl2 we fallback to manually clearing
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
if let Some(deferred_texture) = &view_prepass_textures.deferred {
render_context.command_encoder().clear_texture(
&deferred_texture.texture.texture,
Expand All @@ -80,7 +80,7 @@ impl ViewNode for DeferredGBufferPrepassNode {
.deferred
.as_ref()
.map(|deferred_texture| {
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
{
bevy_render::render_resource::RenderPassColorAttachment {
view: &deferred_texture.texture.default_view,
Expand All @@ -91,7 +91,11 @@ impl ViewNode for DeferredGBufferPrepassNode {
},
}
}
#[cfg(not(all(feature = "webgl", target_arch = "wasm32")))]
#[cfg(any(
not(feature = "webgl"),
not(target_arch = "wasm32"),
feature = "webgpu"
))]
deferred_texture.get_attachment()
}),
);
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_gizmos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ keywords = ["bevy"]

[features]
webgl = []
webgpu = []

[dependencies]
# Bevy
Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_internal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ webgl = [
"bevy_sprite?/webgl",
]

webgpu = [
"bevy_core_pipeline?/webgpu",
"bevy_pbr?/webgpu",
"bevy_render?/webgpu",
"bevy_gizmos?/webgpu",
"bevy_sprite?/webgpu",
]

# enable systems that allow for automated testing on CI
bevy_ci_testing = [
"bevy_app/bevy_ci_testing",
Expand Down
5 changes: 3 additions & 2 deletions crates/bevy_pbr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ keywords = ["bevy"]

[features]
webgl = []
webgpu = []
shader_format_glsl = ["naga_oil/glsl"]
pbr_transmission_textures = []

Expand Down Expand Up @@ -39,11 +40,11 @@ smallvec = "1.6"
thread_local = "1.0"

[target.'cfg(target_arch = "wasm32")'.dependencies]
naga_oil = { version = "0.11" }
naga_oil = "0.12"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
# Omit the `glsl` feature in non-WebAssembly by default.
naga_oil = { version = "0.11", default-features = false, features = [
naga_oil = { version = "0.12", default-features = false, features = [
"test_shader",
] }

Expand Down
22 changes: 11 additions & 11 deletions crates/bevy_pbr/src/deferred/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ pub const DEFAULT_PBR_DEFERRED_LIGHTING_PASS_ID: u8 = 1;
pub struct PbrDeferredLightingDepthId {
depth_id: u32,

#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding_0: f32,
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding_1: f32,
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding_2: f32,
}

Expand All @@ -56,11 +56,11 @@ impl PbrDeferredLightingDepthId {
PbrDeferredLightingDepthId {
depth_id: value as u32,

#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding_0: 0.0,
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding_1: 0.0,
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding_2: 0.0,
}
}
Expand All @@ -79,11 +79,11 @@ impl Default for PbrDeferredLightingDepthId {
PbrDeferredLightingDepthId {
depth_id: DEFAULT_PBR_DEFERRED_LIGHTING_PASS_ID as u32,

#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding_0: 0.0,
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding_1: 0.0,
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
_webgl2_padding_2: 0.0,
}
}
Expand Down Expand Up @@ -245,7 +245,7 @@ impl SpecializedRenderPipeline for DeferredLightingLayout {
// Let the shader code know that it's running in a deferred pipeline.
shader_defs.push("DEFERRED_LIGHTING_PIPELINE".into());

#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
shader_defs.push("WEBGL2".into());

if key.contains(MeshPipelineKey::TONEMAP_IN_SHADER) {
Expand Down Expand Up @@ -310,7 +310,7 @@ impl SpecializedRenderPipeline for DeferredLightingLayout {
shader_defs.push("SHADOW_FILTER_METHOD_JIMENEZ_14".into());
}

#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
shader_defs.push("SIXTEEN_BYTE_ALIGNMENT".into());

RenderPipelineDescriptor {
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_pbr/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,11 @@ impl CascadeShadowConfigBuilder {

impl Default for CascadeShadowConfigBuilder {
fn default() -> Self {
if cfg!(all(feature = "webgl", target_arch = "wasm32")) {
if cfg!(all(
feature = "webgl",
target_arch = "wasm32",
not(feature = "webgpu")
)) {
// Currently only support one cascade in webgl.
Self {
num_cascades: 1,
Expand Down
8 changes: 6 additions & 2 deletions crates/bevy_pbr/src/prepass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ where
// The main limitation right now is that bind group order is hardcoded in shaders.
bind_group_layouts.push(self.material_layout.clone());

#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
shader_defs.push("WEBGL2".into());

shader_defs.push("VERTEX_OUTPUT_INSTANCE_INDEX".into());
Expand Down Expand Up @@ -518,7 +518,11 @@ where
};

let mut push_constant_ranges = Vec::with_capacity(1);
if cfg!(all(feature = "webgl", target_arch = "wasm32")) {
if cfg!(all(
feature = "webgl",
target_arch = "wasm32",
not(feature = "webgpu")
)) {
push_constant_ranges.push(PushConstantRange {
stages: ShaderStages::VERTEX,
range: 0..4,
Expand Down
14 changes: 3 additions & 11 deletions crates/bevy_pbr/src/prepass/prepass.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
mesh_view_bindings::{view, previous_view_proj},
}

#import bevy_render::instance_index::get_instance_index

#ifdef DEFERRED_PREPASS
#import bevy_pbr::rgb9e5
#endif
Expand Down Expand Up @@ -74,7 +72,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
vertex.normal,
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
// See https:/gfx-rs/naga/issues/2416
get_instance_index(vertex_no_morph.instance_index)
vertex_no_morph.instance_index
);
#endif // SKINNED

Expand All @@ -84,7 +82,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
vertex.tangent,
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
// See https:/gfx-rs/naga/issues/2416
get_instance_index(vertex_no_morph.instance_index)
vertex_no_morph.instance_index
);
#endif // VERTEX_TANGENTS
#endif // NORMAL_PREPASS_OR_DEFERRED_PREPASS
Expand All @@ -107,13 +105,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
#ifdef VERTEX_OUTPUT_INSTANCE_INDEX
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
// See https:/gfx-rs/naga/issues/2416
out.instance_index = get_instance_index(vertex_no_morph.instance_index);
#endif
#ifdef BASE_INSTANCE_WORKAROUND
// Hack: this ensures the push constant is always used, which works around this issue:
// https:/bevyengine/bevy/issues/10509
// This can be removed when wgpu 0.19 is released
out.position.x += min(f32(get_instance_index(0u)), 0.0);
out.instance_index = vertex_no_morph.instance_index;
#endif

return out;
Expand Down
52 changes: 40 additions & 12 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,21 @@ pub const MAX_UNIFORM_BUFFER_POINT_LIGHTS: usize = 256;

//NOTE: When running bevy on Adreno GPU chipsets in WebGL, any value above 1 will result in a crash
// when loading the wgsl "pbr_functions.wgsl" in the function apply_fog.
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
pub const MAX_DIRECTIONAL_LIGHTS: usize = 1;
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
#[cfg(any(
not(feature = "webgl"),
not(target_arch = "wasm32"),
feature = "webgpu"
))]
pub const MAX_DIRECTIONAL_LIGHTS: usize = 10;
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
#[cfg(any(
not(feature = "webgl"),
not(target_arch = "wasm32"),
feature = "webgpu"
))]
pub const MAX_CASCADES_PER_LIGHT: usize = 4;
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
pub const MAX_CASCADES_PER_LIGHT: usize = 1;

#[derive(Resource, Clone)]
Expand Down Expand Up @@ -698,13 +706,21 @@ pub fn prepare_lights(
let mut point_lights: Vec<_> = point_lights.iter().collect::<Vec<_>>();
let mut directional_lights: Vec<_> = directional_lights.iter().collect::<Vec<_>>();

#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
#[cfg(any(
not(feature = "webgl"),
not(target_arch = "wasm32"),
feature = "webgpu"
))]
let max_texture_array_layers = render_device.limits().max_texture_array_layers as usize;
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
#[cfg(any(
not(feature = "webgl"),
not(target_arch = "wasm32"),
feature = "webgpu"
))]
let max_texture_cubes = max_texture_array_layers / 6;
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
let max_texture_array_layers = 1;
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
let max_texture_cubes = 1;

if !*max_directional_lights_warning_emitted && directional_lights.len() > MAX_DIRECTIONAL_LIGHTS
Expand Down Expand Up @@ -1177,9 +1193,17 @@ pub fn prepare_lights(
.create_view(&TextureViewDescriptor {
label: Some("point_light_shadow_map_array_texture_view"),
format: None,
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
#[cfg(any(
not(feature = "webgl"),
not(target_arch = "wasm32"),
feature = "webgpu"
))]
dimension: Some(TextureViewDimension::CubeArray),
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(
feature = "webgl",
target_arch = "wasm32",
not(feature = "webgpu")
))]
dimension: Some(TextureViewDimension::Cube),
aspect: TextureAspect::DepthOnly,
base_mip_level: 0,
Expand All @@ -1192,9 +1216,13 @@ pub fn prepare_lights(
.create_view(&TextureViewDescriptor {
label: Some("directional_light_shadow_map_array_texture_view"),
format: None,
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
#[cfg(any(
not(feature = "webgl"),
not(target_arch = "wasm32"),
feature = "webgpu"
))]
dimension: Some(TextureViewDimension::D2Array),
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
dimension: Some(TextureViewDimension::D2),
aspect: TextureAspect::DepthOnly,
base_mip_level: 0,
Expand Down
Loading

0 comments on commit 35ac1b1

Please sign in to comment.