mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Update to wgpu 0.19 and raw-window-handle 0.6 (#11280)
# 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 https://github.com/bevyengine/bevy/pull/9172 and https://github.com/bevyengine/bevy/pull/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 https://github.com/bevyengine/bevy/issues/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://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md --------- Co-authored-by: François <mockersf@gmail.com>
This commit is contained in:
parent
dd4d07dc9c
commit
35ac1b152e
45 changed files with 260 additions and 203 deletions
|
@ -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://github.com/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://github.com/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"]
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ keywords = ["bevy"]
|
|||
[features]
|
||||
trace = []
|
||||
webgl = []
|
||||
webgpu = []
|
||||
tonemapping_luts = ["bevy_render/ktx2", "bevy_render/zstd"]
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -294,16 +294,24 @@ 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,
|
||||
|
@ -311,7 +319,7 @@ impl BloomTexture {
|
|||
..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
|
||||
|
@ -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(
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -10,6 +10,7 @@ keywords = ["bevy"]
|
|||
|
||||
[features]
|
||||
webgl = []
|
||||
webgpu = []
|
||||
|
||||
[dependencies]
|
||||
# Bevy
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -10,6 +10,7 @@ keywords = ["bevy"]
|
|||
|
||||
[features]
|
||||
webgl = []
|
||||
webgpu = []
|
||||
shader_format_glsl = ["naga_oil/glsl"]
|
||||
pbr_transmission_textures = []
|
||||
|
||||
|
@ -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",
|
||||
] }
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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());
|
||||
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
@ -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://github.com/gfx-rs/naga/issues/2416
|
||||
get_instance_index(vertex_no_morph.instance_index)
|
||||
vertex_no_morph.instance_index
|
||||
);
|
||||
#endif // SKINNED
|
||||
|
||||
|
@ -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://github.com/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
|
||||
|
@ -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://github.com/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://github.com/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;
|
||||
|
|
|
@ -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)]
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
|
|
@ -806,7 +806,7 @@ impl SpecializedMeshPipeline for MeshPipeline {
|
|||
shader_defs.push("VIEW_PROJECTION_ORTHOGRAPHIC".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) {
|
||||
|
@ -899,7 +899,11 @@ impl SpecializedMeshPipeline for MeshPipeline {
|
|||
}
|
||||
|
||||
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,
|
||||
|
@ -1180,7 +1184,7 @@ impl<P: PhaseItem> RenderCommand<P> for DrawMesh {
|
|||
pass.set_vertex_buffer(0, gpu_mesh.vertex_buffer.slice(..));
|
||||
|
||||
let batch_range = item.batch_range();
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
pass.set_push_constants(
|
||||
ShaderStages::VERTEX,
|
||||
0,
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
forward_io::{Vertex, VertexOutput},
|
||||
view_transformations::position_world_to_clip,
|
||||
}
|
||||
#import bevy_render::instance_index::get_instance_index
|
||||
|
||||
#ifdef MORPH_TARGETS
|
||||
fn morph_vertex(vertex_in: Vertex) -> Vertex {
|
||||
|
@ -54,7 +53,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://github.com/gfx-rs/naga/issues/2416
|
||||
get_instance_index(vertex_no_morph.instance_index)
|
||||
vertex_no_morph.instance_index
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -78,7 +77,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://github.com/gfx-rs/naga/issues/2416
|
||||
get_instance_index(vertex_no_morph.instance_index)
|
||||
vertex_no_morph.instance_index
|
||||
);
|
||||
#endif
|
||||
|
||||
|
@ -89,14 +88,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://github.com/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://github.com/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;
|
||||
|
|
|
@ -6,17 +6,15 @@
|
|||
mesh_types::MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT,
|
||||
view_transformations::position_world_to_clip,
|
||||
}
|
||||
#import bevy_render::{
|
||||
instance_index::get_instance_index,
|
||||
maths::{affine_to_square, mat2x4_f32_to_mat3x3_unpack},
|
||||
}
|
||||
#import bevy_render::maths::{affine_to_square, mat2x4_f32_to_mat3x3_unpack}
|
||||
|
||||
|
||||
fn get_model_matrix(instance_index: u32) -> mat4x4<f32> {
|
||||
return affine_to_square(mesh[get_instance_index(instance_index)].model);
|
||||
return affine_to_square(mesh[instance_index].model);
|
||||
}
|
||||
|
||||
fn get_previous_model_matrix(instance_index: u32) -> mat4x4<f32> {
|
||||
return affine_to_square(mesh[get_instance_index(instance_index)].previous_model);
|
||||
return affine_to_square(mesh[instance_index].previous_model);
|
||||
}
|
||||
|
||||
fn mesh_position_local_to_world(model: mat4x4<f32>, vertex_position: vec4<f32>) -> vec4<f32> {
|
||||
|
|
|
@ -21,9 +21,13 @@ use bevy_render::{
|
|||
view::{Msaa, ViewUniform, ViewUniforms},
|
||||
};
|
||||
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
use bevy_render::render_resource::binding_types::texture_cube;
|
||||
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
|
||||
#[cfg(any(
|
||||
not(feature = "webgl"),
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "webgpu"
|
||||
))]
|
||||
use bevy_render::render_resource::binding_types::{texture_2d_array, texture_cube_array};
|
||||
|
||||
use crate::{
|
||||
|
@ -182,9 +186,13 @@ fn layout_entries(
|
|||
// Point Shadow Texture Cube Array
|
||||
(
|
||||
2,
|
||||
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
|
||||
#[cfg(any(
|
||||
not(feature = "webgl"),
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "webgpu"
|
||||
))]
|
||||
texture_cube_array(TextureSampleType::Depth),
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
texture_cube(TextureSampleType::Depth),
|
||||
),
|
||||
// Point Shadow Texture Array Sampler
|
||||
|
@ -192,9 +200,13 @@ fn layout_entries(
|
|||
// Directional Shadow Texture Array
|
||||
(
|
||||
4,
|
||||
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
|
||||
#[cfg(any(
|
||||
not(feature = "webgl"),
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "webgpu"
|
||||
))]
|
||||
texture_2d_array(TextureSampleType::Depth),
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
texture_2d(TextureSampleType::Depth),
|
||||
),
|
||||
// Directional Shadow Texture Array Sampler
|
||||
|
|
|
@ -340,6 +340,7 @@ impl FromWorld for SsaoPipelines {
|
|||
usage: TextureUsages::TEXTURE_BINDING,
|
||||
view_formats: &[],
|
||||
}),
|
||||
TextureDataOrder::default(),
|
||||
bytemuck::cast_slice(&generate_hilbert_index_lut()),
|
||||
)
|
||||
.create_view(&TextureViewDescriptor::default());
|
||||
|
|
|
@ -32,6 +32,7 @@ tracing-tracy = []
|
|||
wgpu_trace = ["wgpu/trace"]
|
||||
ci_limits = []
|
||||
webgl = ["wgpu/webgl"]
|
||||
webgpu = ["wgpu/webgpu"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
|
@ -62,12 +63,16 @@ image = { version = "0.24", default-features = false }
|
|||
codespan-reporting = "0.11.0"
|
||||
# `fragile-send-sync-non-atomic-wasm` feature means we can't use WASM threads for rendering
|
||||
# It is enabled for now to avoid having to do a significant overhaul of the renderer just for wasm
|
||||
wgpu = { version = "0.18", features = [
|
||||
wgpu = { version = "0.19.1", default-features = false, features = [
|
||||
"wgsl",
|
||||
"dx12",
|
||||
"metal",
|
||||
"naga",
|
||||
"naga-ir",
|
||||
"fragile-send-sync-non-atomic-wasm",
|
||||
] }
|
||||
naga = { version = "0.14.2", features = ["wgsl-in"] }
|
||||
naga_oil = { version = "0.11", default-features = false, features = [
|
||||
naga = { version = "0.19", features = ["wgsl-in"] }
|
||||
naga_oil = { version = "0.12", default-features = false, features = [
|
||||
"test_shader",
|
||||
] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
|
|
@ -56,7 +56,7 @@ pub struct GlobalsUniform {
|
|||
/// It wraps to zero when it reaches the maximum value of a u32.
|
||||
frame_count: u32,
|
||||
/// WebGL2 structs must be 16 byte aligned.
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
_wasm_padding: f32,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#define_import_path bevy_render::instance_index
|
||||
|
||||
#ifdef BASE_INSTANCE_WORKAROUND
|
||||
// naga and wgpu should polyfill WGSL instance_index functionality where it is
|
||||
// not available in GLSL. Until that is done, we can work around it in bevy
|
||||
// using a push constant which is converted to a uniform by naga and wgpu.
|
||||
// https://github.com/gfx-rs/wgpu/issues/1573
|
||||
var<push_constant> base_instance: i32;
|
||||
|
||||
fn get_instance_index(instance_index: u32) -> u32 {
|
||||
return u32(base_instance) + instance_index;
|
||||
}
|
||||
#else
|
||||
fn get_instance_index(instance_index: u32) -> u32 {
|
||||
return instance_index;
|
||||
}
|
||||
#endif
|
|
@ -259,11 +259,12 @@ impl Plugin for RenderPlugin {
|
|||
flags: settings.instance_flags,
|
||||
gles_minor_version: settings.gles3_minor_version,
|
||||
});
|
||||
|
||||
// SAFETY: Plugins should be set up on the main thread.
|
||||
let surface = primary_window.map(|wrapper| unsafe {
|
||||
let handle = wrapper.get_handle();
|
||||
instance
|
||||
.create_surface(&handle)
|
||||
.create_surface(handle)
|
||||
.expect("Failed to create wgpu surface")
|
||||
});
|
||||
|
||||
|
@ -332,16 +333,6 @@ impl Plugin for RenderPlugin {
|
|||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
load_internal_asset!(
|
||||
app,
|
||||
INSTANCE_INDEX_SHADER_HANDLE,
|
||||
"instance_index.wgsl",
|
||||
Shader::from_wgsl_with_defs,
|
||||
vec![
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
"BASE_INSTANCE_WORKAROUND".into()
|
||||
]
|
||||
);
|
||||
load_internal_asset!(app, MATHS_SHADER_HANDLE, "maths.wgsl", Shader::from_wgsl);
|
||||
if let Some(future_renderer_resources) =
|
||||
app.world.remove_resource::<FutureRendererResources>()
|
||||
|
|
|
@ -15,7 +15,11 @@ use wgpu::{BindingResource, Limits};
|
|||
// `max_uniform_buffer_binding_size`. On macOS this ends up being the minimum
|
||||
// size of the uniform buffer as well as the size of each chunk of data at a
|
||||
// dynamic offset.
|
||||
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
|
||||
#[cfg(any(
|
||||
not(feature = "webgl"),
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "webgpu"
|
||||
))]
|
||||
const MAX_REASONABLE_UNIFORM_BUFFER_BINDING_SIZE: u32 = 1 << 20;
|
||||
|
||||
// WebGL2 quirk: using uniform buffers larger than 4KB will cause extremely
|
||||
|
@ -23,7 +27,7 @@ const MAX_REASONABLE_UNIFORM_BUFFER_BINDING_SIZE: u32 = 1 << 20;
|
|||
// This is due to older shader compilers/GPUs that don't support dynamically
|
||||
// indexing uniform buffers, and instead emulate it with large switch statements
|
||||
// over buffer indices that take a long time to compile.
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
const MAX_REASONABLE_UNIFORM_BUFFER_BINDING_SIZE: u32 = 1 << 12;
|
||||
|
||||
/// Similar to [`DynamicUniformBuffer`], except every N elements (depending on size)
|
||||
|
|
|
@ -32,7 +32,7 @@ pub use uniform_buffer::*;
|
|||
|
||||
// TODO: decide where re-exports should go
|
||||
pub use wgpu::{
|
||||
util::{BufferInitDescriptor, DrawIndexedIndirect, DrawIndirect},
|
||||
util::{BufferInitDescriptor, DrawIndexedIndirectArgs, DrawIndirectArgs, TextureDataOrder},
|
||||
AdapterInfo as WgpuAdapterInfo, AddressMode, BindGroupDescriptor, BindGroupEntry,
|
||||
BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, BlendComponent,
|
||||
BlendFactor, BlendOperation, BlendState, BufferAddress, BufferAsyncError, BufferBinding,
|
||||
|
|
|
@ -277,7 +277,7 @@ impl ShaderCache {
|
|||
Entry::Occupied(entry) => entry.into_mut(),
|
||||
Entry::Vacant(entry) => {
|
||||
let mut shader_defs = shader_defs.to_vec();
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
{
|
||||
shader_defs.push("NO_ARRAY_TEXTURES_SUPPORT".into());
|
||||
shader_defs.push("SIXTEEN_BYTE_ALIGNMENT".into());
|
||||
|
|
|
@ -133,7 +133,7 @@ const GPU_NOT_FOUND_ERROR_MESSAGE: &str = if cfg!(target_os = "linux") {
|
|||
pub async fn initialize_renderer(
|
||||
instance: &Instance,
|
||||
options: &WgpuSettings,
|
||||
request_adapter_options: &RequestAdapterOptions<'_>,
|
||||
request_adapter_options: &RequestAdapterOptions<'_, '_>,
|
||||
) -> (RenderDevice, RenderQueue, RenderAdapterInfo, RenderAdapter) {
|
||||
let adapter = instance
|
||||
.request_adapter(request_adapter_options)
|
||||
|
@ -280,8 +280,8 @@ pub async fn initialize_renderer(
|
|||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: options.device_label.as_ref().map(|a| a.as_ref()),
|
||||
features,
|
||||
limits,
|
||||
required_features: features,
|
||||
required_limits: limits,
|
||||
},
|
||||
trace_path,
|
||||
)
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::render_resource::{
|
|||
use bevy_ecs::system::Resource;
|
||||
use wgpu::{
|
||||
util::DeviceExt, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor,
|
||||
BindGroupLayoutEntry, BufferAsyncError, BufferBindingType,
|
||||
BindGroupLayoutEntry, BufferAsyncError, BufferBindingType, MaintainResult,
|
||||
};
|
||||
|
||||
use super::RenderQueue;
|
||||
|
@ -61,7 +61,7 @@ impl RenderDevice {
|
|||
///
|
||||
/// no-op on the web, device is automatically polled.
|
||||
#[inline]
|
||||
pub fn poll(&self, maintain: wgpu::Maintain) -> bool {
|
||||
pub fn poll(&self, maintain: wgpu::Maintain) -> MaintainResult {
|
||||
self.device.poll(maintain)
|
||||
}
|
||||
|
||||
|
@ -161,11 +161,12 @@ impl RenderDevice {
|
|||
&self,
|
||||
render_queue: &RenderQueue,
|
||||
desc: &wgpu::TextureDescriptor,
|
||||
order: wgpu::util::TextureDataOrder,
|
||||
data: &[u8],
|
||||
) -> Texture {
|
||||
let wgpu_texture = self
|
||||
.device
|
||||
.create_texture_with_data(render_queue.as_ref(), desc, data);
|
||||
let wgpu_texture =
|
||||
self.device
|
||||
.create_texture_with_data(render_queue.as_ref(), desc, order, data);
|
||||
Texture::from(wgpu_texture)
|
||||
}
|
||||
|
||||
|
|
|
@ -54,8 +54,14 @@ pub struct WgpuSettings {
|
|||
|
||||
impl Default for WgpuSettings {
|
||||
fn default() -> Self {
|
||||
let default_backends = if cfg!(all(feature = "webgl", target_arch = "wasm32")) {
|
||||
let default_backends = if cfg!(all(
|
||||
feature = "webgl",
|
||||
target_arch = "wasm32",
|
||||
not(feature = "webgpu")
|
||||
)) {
|
||||
Backends::GL
|
||||
} else if cfg!(all(feature = "webgpu", target_arch = "wasm32")) {
|
||||
Backends::BROWSER_WEBGPU
|
||||
} else {
|
||||
Backends::all()
|
||||
};
|
||||
|
@ -67,8 +73,11 @@ impl Default for WgpuSettings {
|
|||
|
||||
let priority = settings_priority_from_env().unwrap_or(WgpuSettingsPriority::Functionality);
|
||||
|
||||
let limits = if cfg!(all(feature = "webgl", target_arch = "wasm32"))
|
||||
|| matches!(priority, WgpuSettingsPriority::WebGL2)
|
||||
let limits = if cfg!(all(
|
||||
feature = "webgl",
|
||||
target_arch = "wasm32",
|
||||
not(feature = "webgpu")
|
||||
)) || matches!(priority, WgpuSettingsPriority::WebGL2)
|
||||
{
|
||||
wgpu::Limits::downlevel_webgl2_defaults()
|
||||
} else {
|
||||
|
|
|
@ -98,7 +98,12 @@ fn fallback_image_new(
|
|||
}
|
||||
|
||||
let texture = if create_texture_with_data {
|
||||
render_device.create_texture_with_data(render_queue, &image.texture_descriptor, &image.data)
|
||||
render_device.create_texture_with_data(
|
||||
render_queue,
|
||||
&image.texture_descriptor,
|
||||
wgpu::util::TextureDataOrder::default(),
|
||||
&image.data,
|
||||
)
|
||||
} else {
|
||||
render_device.create_texture(&image.texture_descriptor)
|
||||
};
|
||||
|
|
|
@ -793,7 +793,7 @@ impl TextureFormatPixelInfo for TextureFormat {
|
|||
fn pixel_size(&self) -> usize {
|
||||
let info = self;
|
||||
match info.block_dimensions() {
|
||||
(1, 1) => info.block_size(None).unwrap() as usize,
|
||||
(1, 1) => info.block_copy_size(None).unwrap() as usize,
|
||||
_ => panic!("Using pixel_size for compressed textures is invalid"),
|
||||
}
|
||||
}
|
||||
|
@ -831,6 +831,8 @@ impl RenderAsset for Image {
|
|||
let texture = render_device.create_texture_with_data(
|
||||
render_queue,
|
||||
&self.texture_descriptor,
|
||||
// TODO: Is this correct? Do we need to use `MipMajor` if it's a ktx2 file?
|
||||
wgpu::util::TextureDataOrder::default(),
|
||||
&self.data,
|
||||
);
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ pub fn ktx2_buffer_to_image(
|
|||
texture_format_info.block_dimensions().1,
|
||||
);
|
||||
// Texture is not a depth or stencil format, it is possible to pass `None` and unwrap
|
||||
let block_bytes = texture_format_info.block_size(None).unwrap();
|
||||
let block_bytes = texture_format_info.block_copy_size(None).unwrap();
|
||||
|
||||
let transcoder = LowLevelUastcTranscoder::new();
|
||||
for (level, level_data) in levels.iter().enumerate() {
|
||||
|
@ -240,7 +240,7 @@ pub fn ktx2_buffer_to_image(
|
|||
texture_format_info.block_dimensions().1 as usize,
|
||||
);
|
||||
// Texture is not a depth or stencil format, it is possible to pass `None` and unwrap
|
||||
let block_bytes = texture_format_info.block_size(None).unwrap() as usize;
|
||||
let block_bytes = texture_format_info.block_copy_size(None).unwrap() as usize;
|
||||
|
||||
let mut wgpu_data = vec![Vec::default(); (layer_count * face_count) as usize];
|
||||
for (level, level_data) in levels.iter().enumerate() {
|
||||
|
|
|
@ -16,7 +16,9 @@ use std::{
|
|||
ops::{Deref, DerefMut},
|
||||
sync::PoisonError,
|
||||
};
|
||||
use wgpu::{BufferUsages, TextureFormat, TextureUsages, TextureViewDescriptor};
|
||||
use wgpu::{
|
||||
BufferUsages, SurfaceTargetUnsafe, TextureFormat, TextureUsages, TextureViewDescriptor,
|
||||
};
|
||||
|
||||
pub mod screenshot;
|
||||
|
||||
|
@ -193,7 +195,8 @@ fn extract_windows(
|
|||
}
|
||||
|
||||
struct SurfaceData {
|
||||
surface: wgpu::Surface,
|
||||
// TODO: what lifetime should this be?
|
||||
surface: wgpu::Surface<'static>,
|
||||
format: TextureFormat,
|
||||
}
|
||||
|
||||
|
@ -253,12 +256,16 @@ pub fn prepare_windows(
|
|||
.surfaces
|
||||
.entry(window.entity)
|
||||
.or_insert_with(|| {
|
||||
let surface_target = SurfaceTargetUnsafe::RawHandle {
|
||||
raw_display_handle: window.handle.display_handle,
|
||||
raw_window_handle: window.handle.window_handle,
|
||||
};
|
||||
// SAFETY: The window handles in ExtractedWindows will always be valid objects to create surfaces on
|
||||
let surface = unsafe {
|
||||
// NOTE: On some OSes this MUST be called from the main thread.
|
||||
// As of wgpu 0.15, only fallible if the given window is a HTML canvas and obtaining a WebGPU or WebGL2 context fails.
|
||||
render_instance
|
||||
.create_surface(&window.handle.get_handle())
|
||||
.create_surface_unsafe(surface_target)
|
||||
.expect("Failed to create wgpu surface")
|
||||
};
|
||||
let caps = surface.get_capabilities(&render_adapter);
|
||||
|
@ -293,6 +300,12 @@ pub fn prepare_windows(
|
|||
PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync,
|
||||
PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync,
|
||||
},
|
||||
// TODO: Expose this as a setting somewhere
|
||||
// 2 is wgpu's default/what we've been using so far.
|
||||
// 1 is the minimum, but may cause lower framerates due to the cpu waiting for the gpu to finish
|
||||
// all work for the previous frame before starting work on the next frame, which then means the gpu
|
||||
// has to wait for the cpu to finish to start on the next frame.
|
||||
desired_maximum_frame_latency: 2,
|
||||
alpha_mode: match window.alpha_mode {
|
||||
CompositeAlphaMode::Auto => wgpu::CompositeAlphaMode::Auto,
|
||||
CompositeAlphaMode::Opaque => wgpu::CompositeAlphaMode::Opaque,
|
||||
|
@ -347,6 +360,7 @@ pub fn prepare_windows(
|
|||
let may_erroneously_timeout = || {
|
||||
render_instance
|
||||
.enumerate_adapters(wgpu::Backends::VULKAN)
|
||||
.iter()
|
||||
.any(|adapter| {
|
||||
let name = adapter.get_info().name;
|
||||
name.starts_with("Radeon")
|
||||
|
|
|
@ -10,6 +10,7 @@ keywords = ["bevy"]
|
|||
|
||||
[features]
|
||||
webgl = []
|
||||
webgpu = []
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
|
|
|
@ -511,7 +511,11 @@ impl SpecializedMeshPipeline for Mesh2dPipeline {
|
|||
false => TextureFormat::bevy_default(),
|
||||
};
|
||||
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,
|
||||
|
@ -688,7 +692,7 @@ impl<P: PhaseItem> RenderCommand<P> for DrawMesh2d {
|
|||
pass.set_vertex_buffer(0, gpu_mesh.vertex_buffer.slice(..));
|
||||
|
||||
let batch_range = item.batch_range();
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
pass.set_push_constants(
|
||||
ShaderStages::VERTEX,
|
||||
0,
|
||||
|
|
|
@ -4,13 +4,10 @@
|
|||
mesh2d_view_bindings::view,
|
||||
mesh2d_bindings::mesh,
|
||||
}
|
||||
#import bevy_render::{
|
||||
instance_index::get_instance_index,
|
||||
maths::{affine_to_square, mat2x4_f32_to_mat3x3_unpack},
|
||||
}
|
||||
#import bevy_render::maths::{affine_to_square, mat2x4_f32_to_mat3x3_unpack}
|
||||
|
||||
fn get_model_matrix(instance_index: u32) -> mat4x4<f32> {
|
||||
return affine_to_square(mesh[get_instance_index(instance_index)].model);
|
||||
return affine_to_square(mesh[instance_index].model);
|
||||
}
|
||||
|
||||
fn mesh2d_position_local_to_world(model: mat4x4<f32>, vertex_position: vec4<f32>) -> vec4<f32> {
|
||||
|
@ -31,8 +28,8 @@ fn mesh2d_position_local_to_clip(model: mat4x4<f32>, vertex_position: vec4<f32>)
|
|||
|
||||
fn mesh2d_normal_local_to_world(vertex_normal: vec3<f32>, instance_index: u32) -> vec3<f32> {
|
||||
return mat2x4_f32_to_mat3x3_unpack(
|
||||
mesh[get_instance_index(instance_index)].inverse_transpose_model_a,
|
||||
mesh[get_instance_index(instance_index)].inverse_transpose_model_b,
|
||||
mesh[instance_index].inverse_transpose_model_a,
|
||||
mesh[instance_index].inverse_transpose_model_b,
|
||||
) * vertex_normal;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ bevy_input = { path = "../bevy_input", version = "0.12.0" }
|
|||
|
||||
# other
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
raw-window-handle = "0.5"
|
||||
raw-window-handle = "0.6"
|
||||
smol_str = "0.2"
|
||||
|
||||
[lints]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use bevy_ecs::prelude::Component;
|
||||
use raw_window_handle::{
|
||||
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
|
||||
DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, RawDisplayHandle,
|
||||
RawWindowHandle, WindowHandle,
|
||||
};
|
||||
|
||||
/// A wrapper over [`RawWindowHandle`] and [`RawDisplayHandle`] that allows us to safely pass it across threads.
|
||||
|
@ -17,7 +18,7 @@ pub struct RawHandleWrapper {
|
|||
}
|
||||
|
||||
impl RawHandleWrapper {
|
||||
/// Returns a [`HasRawWindowHandle`] + [`HasRawDisplayHandle`] impl, which exposes [`RawWindowHandle`] and [`RawDisplayHandle`].
|
||||
/// Returns a [`HasWindowHandle`] + [`HasDisplayHandle`] impl, which exposes [`WindowHandle`] and [`DisplayHandle`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
|
@ -46,26 +47,26 @@ unsafe impl Sync for RawHandleWrapper {}
|
|||
/// In many cases, this should only be constructed on the main thread.
|
||||
pub struct ThreadLockedRawWindowHandleWrapper(RawHandleWrapper);
|
||||
|
||||
impl HasWindowHandle for ThreadLockedRawWindowHandleWrapper {
|
||||
fn window_handle(&self) -> Result<WindowHandle, HandleError> {
|
||||
// SAFETY: the caller has validated that this is a valid context to get [`RawHandleWrapper`]
|
||||
// as otherwise an instance of this type could not have been constructed
|
||||
// NOTE: we cannot simply impl HasRawWindowHandle for RawHandleWrapper,
|
||||
// as the `raw_window_handle` method is safe. We cannot guarantee that all calls
|
||||
// of this method are correct (as it may be off the main thread on an incompatible platform),
|
||||
// and so exposing a safe method to get a [`RawWindowHandle`] directly would be UB.
|
||||
unsafe impl HasRawWindowHandle for ThreadLockedRawWindowHandleWrapper {
|
||||
fn raw_window_handle(&self) -> RawWindowHandle {
|
||||
self.0.window_handle
|
||||
Ok(unsafe { WindowHandle::borrow_raw(self.0.window_handle) })
|
||||
}
|
||||
}
|
||||
|
||||
impl HasDisplayHandle for ThreadLockedRawWindowHandleWrapper {
|
||||
fn display_handle(&self) -> Result<DisplayHandle, HandleError> {
|
||||
// SAFETY: the caller has validated that this is a valid context to get [`RawDisplayHandle`]
|
||||
// as otherwise an instance of this type could not have been constructed
|
||||
// NOTE: we cannot simply impl HasRawDisplayHandle for RawHandleWrapper,
|
||||
// as the `raw_display_handle` method is safe. We cannot guarantee that all calls
|
||||
// of this method are correct (as it may be off the main thread on an incompatible platform),
|
||||
// and so exposing a safe method to get a [`RawDisplayHandle`] directly would be UB.
|
||||
unsafe impl HasRawDisplayHandle for ThreadLockedRawWindowHandleWrapper {
|
||||
fn raw_display_handle(&self) -> RawDisplayHandle {
|
||||
self.0.display_handle
|
||||
Ok(unsafe { DisplayHandle::borrow_raw(self.0.display_handle) })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,19 +28,18 @@ bevy_utils = { path = "../bevy_utils", version = "0.12.0" }
|
|||
bevy_tasks = { path = "../bevy_tasks", version = "0.12.0" }
|
||||
|
||||
# other
|
||||
# feature rwh_05 refers to window_raw_handle@v0.5,
|
||||
# updating to rwh_06 is blocked until wgpu 0.19 release lands.
|
||||
winit = { version = "0.29", default-features = false, features = ["rwh_05"] }
|
||||
# feature rwh_06 refers to window_raw_handle@v0.6
|
||||
winit = { version = "0.29", default-features = false, features = ["rwh_06"] }
|
||||
accesskit_winit = { version = "0.17", default-features = false, features = [
|
||||
"rwh_05",
|
||||
"rwh_06",
|
||||
] }
|
||||
approx = { version = "0.5", default-features = false }
|
||||
raw-window-handle = "0.5"
|
||||
raw-window-handle = "0.6"
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
winit = { version = "0.29", default-features = false, features = [
|
||||
"android-native-activity",
|
||||
"rwh_05",
|
||||
"rwh_06",
|
||||
] }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
|
|
|
@ -797,7 +797,7 @@ pub fn winit_runner(mut app: App) {
|
|||
.world
|
||||
.query_filtered::<(Entity, &Window), (With<CachedWindow>, Without<bevy_window::RawHandleWrapper>)>();
|
||||
if let Ok((entity, window)) = query.get_single(&app.world) {
|
||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||
let window = window.clone();
|
||||
|
||||
let (
|
||||
|
@ -820,8 +820,8 @@ pub fn winit_runner(mut app: App) {
|
|||
);
|
||||
|
||||
let wrapper = RawHandleWrapper {
|
||||
window_handle: winit_window.raw_window_handle(),
|
||||
display_handle: winit_window.raw_display_handle(),
|
||||
window_handle: winit_window.window_handle().unwrap().as_raw(),
|
||||
display_handle: winit_window.display_handle().unwrap().as_raw(),
|
||||
};
|
||||
|
||||
app.world.entity_mut(entity).insert(wrapper);
|
||||
|
|
|
@ -12,8 +12,8 @@ use bevy_utils::{
|
|||
EntityHashMap,
|
||||
};
|
||||
use bevy_window::{RawHandleWrapper, Window, WindowClosed, WindowCreated};
|
||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||
|
||||
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||
use winit::{
|
||||
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize},
|
||||
event_loop::EventLoopWindowTarget,
|
||||
|
@ -74,8 +74,8 @@ pub(crate) fn create_windows<'a>(
|
|||
commands
|
||||
.entity(entity)
|
||||
.insert(RawHandleWrapper {
|
||||
window_handle: winit_window.raw_window_handle(),
|
||||
display_handle: winit_window.raw_display_handle(),
|
||||
window_handle: winit_window.window_handle().unwrap().as_raw(),
|
||||
display_handle: winit_window.display_handle().unwrap().as_raw(),
|
||||
})
|
||||
.insert(CachedWindow {
|
||||
window: window.clone(),
|
||||
|
|
|
@ -238,8 +238,7 @@ ruby -run -ehttpd examples/wasm
|
|||
|
||||
Bevy support for WebGPU is being worked on, but is currently experimental.
|
||||
|
||||
To build for WebGPU, you'll need to disable default features and add all those you need, making sure to omit the `webgl2` feature.
|
||||
|
||||
To build for WebGPU, you'll need to enable the `webgpu` feature. This will override the `webgl2` feature, and builds with the `webgpu` feature enabled won't be able to run on browsers that don't support WebGPU.
|
||||
WebGPU depends on unstable APIs so you will also need to pass the `web_sys_unstable_apis` flag to your builds. For example:
|
||||
|
||||
```sh
|
||||
|
|
|
@ -34,7 +34,7 @@ The default feature set enables most of the expected features of a game engine,
|
|||
|png|PNG image format support|
|
||||
|tonemapping_luts|Include tonemapping Look Up Tables KTX2 files. If everything is pink, you need to enable this feature or change the `Tonemapping` method on your `Camera2dBundle` or `Camera3dBundle`.|
|
||||
|vorbis|OGG/VORBIS audio format support|
|
||||
|webgl2|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://github.com/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|Enable some limitations to be able to use WebGL2. Please refer to the [WebGL2 and WebGPU](https://github.com/bevyengine/bevy/tree/latest/examples#webgl2-and-webgpu) section of the examples README for more information on how to run Wasm builds with WebGPU.|
|
||||
|x11|X11 display server support|
|
||||
|zstd|For KTX2 supercompression|
|
||||
|
||||
|
@ -80,6 +80,7 @@ The default feature set enables most of the expected features of a game engine,
|
|||
|trace_tracy_memory|Tracing support, with memory profiling, exposing a port for Tracy|
|
||||
|wav|WAV audio format support|
|
||||
|wayland|Wayland display server support|
|
||||
|webgpu|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.|
|
||||
|webp|WebP image format support|
|
||||
|wgpu_trace|Save a trace of all wgpu calls|
|
||||
|zlib|For KTX2 supercompression|
|
||||
|
|
|
@ -562,8 +562,7 @@ ruby -run -ehttpd examples/wasm
|
|||
|
||||
Bevy support for WebGPU is being worked on, but is currently experimental.
|
||||
|
||||
To build for WebGPU, you'll need to disable default features and add all those you need, making sure to omit the `webgl2` feature.
|
||||
|
||||
To build for WebGPU, you'll need to enable the `webgpu` feature. This will override the `webgl2` feature, and builds with the `webgpu` feature enabled won't be able to run on browsers that don't support WebGPU.
|
||||
WebGPU depends on unstable APIs so you will also need to pass the `web_sys_unstable_apis` flag to your builds. For example:
|
||||
|
||||
```sh
|
||||
|
|
|
@ -44,7 +44,7 @@ fn main() {
|
|||
|
||||
assert!(!cli.examples.is_empty(), "must have at least one example");
|
||||
|
||||
let mut default_features = true;
|
||||
let default_features = true;
|
||||
let mut features: Vec<&str> = cli.features.iter().map(|f| f.as_str()).collect();
|
||||
if let Some(frames) = cli.frames {
|
||||
let mut file = File::create("ci_testing_config.ron").unwrap();
|
||||
|
@ -56,30 +56,7 @@ fn main() {
|
|||
match cli.api {
|
||||
WebApi::Webgl2 => (),
|
||||
WebApi::Webgpu => {
|
||||
features.push("animation");
|
||||
features.push("bevy_asset");
|
||||
features.push("bevy_audio");
|
||||
features.push("bevy_gilrs");
|
||||
features.push("bevy_scene");
|
||||
features.push("bevy_winit");
|
||||
features.push("bevy_core_pipeline");
|
||||
features.push("bevy_pbr");
|
||||
features.push("bevy_gltf");
|
||||
features.push("bevy_render");
|
||||
features.push("bevy_sprite");
|
||||
features.push("bevy_text");
|
||||
features.push("bevy_ui");
|
||||
features.push("png");
|
||||
features.push("hdr");
|
||||
features.push("ktx2");
|
||||
features.push("zstd");
|
||||
features.push("vorbis");
|
||||
features.push("x11");
|
||||
features.push("bevy_gizmos");
|
||||
features.push("android_shared_stdcxx");
|
||||
features.push("tonemapping_luts");
|
||||
features.push("default_font");
|
||||
default_features = false;
|
||||
features.push("webgpu");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue