Upgrade to wgpu v24 (#17542)

Didn't remove WgpuWrapper. Not sure if it's needed or not still.

## Testing

- Did you test these changes? If so, how? Example runner
- Are there any parts that need more testing? Web (portable atomics
thingy?), DXC.

## Migration Guide
- Bevy has upgraded to [wgpu
v24](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v2400-2025-01-15).
- When using the DirectX 12 rendering backend, the new priority system
for choosing a shader compiler is as follows:
- If the `WGPU_DX12_COMPILER` environment variable is set at runtime, it
is used
- Else if the new `statically-linked-dxc` feature is enabled, a custom
version of DXC will be statically linked into your app at compile time.
- Else Bevy will look in the app's working directory for
`dxcompiler.dll` and `dxil.dll` at runtime.
- Else if they are missing, Bevy will fall back to FXC (not recommended)

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: IceSentry <c.giguere42@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
This commit is contained in:
JMS55 2025-02-09 11:40:53 -08:00 committed by GitHub
parent 33e83330eb
commit 669d139c13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 174 additions and 175 deletions

View File

@ -256,6 +256,9 @@ bevy_remote = ["bevy_internal/bevy_remote"]
# Enable passthrough loading for SPIR-V shaders (Only supported on Vulkan, shader capabilities and extensions must agree with the platform implementation) # Enable passthrough loading for SPIR-V shaders (Only supported on Vulkan, shader capabilities and extensions must agree with the platform implementation)
spirv_shader_passthrough = ["bevy_internal/spirv_shader_passthrough"] spirv_shader_passthrough = ["bevy_internal/spirv_shader_passthrough"]
# Statically linked DXC shader compiler for DirectX 12
statically-linked-dxc = ["bevy_internal/statically-linked-dxc"]
# Tracing support, saving a file in Chrome Tracing format # Tracing support, saving a file in Chrome Tracing format
trace_chrome = ["trace", "bevy_internal/trace_chrome"] trace_chrome = ["trace", "bevy_internal/trace_chrome"]

View File

@ -22,7 +22,7 @@ serde = { version = "1.0", features = [
], default-features = false, optional = true } ], default-features = false, optional = true }
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }
derive_more = { version = "1", default-features = false, features = ["from"] } derive_more = { version = "1", default-features = false, features = ["from"] }
wgpu-types = { version = "23", default-features = false, optional = true } wgpu-types = { version = "24", default-features = false, optional = true }
encase = { version = "0.10", default-features = false, optional = true } encase = { version = "0.10", default-features = false, optional = true }
[features] [features]

View File

@ -484,6 +484,7 @@ pub fn create_depth_pyramid_dummy_texture(
label: Some(texture_view_label), label: Some(texture_view_label),
format: Some(TextureFormat::R32Float), format: Some(TextureFormat::R32Float),
dimension: Some(TextureViewDimension::D2), dimension: Some(TextureViewDimension::D2),
usage: None,
aspect: TextureAspect::All, aspect: TextureAspect::All,
base_mip_level: 0, base_mip_level: 0,
mip_level_count: Some(1), mip_level_count: Some(1),
@ -551,6 +552,7 @@ impl ViewDepthPyramid {
label: Some(texture_view_label), label: Some(texture_view_label),
format: Some(TextureFormat::R32Float), format: Some(TextureFormat::R32Float),
dimension: Some(TextureViewDimension::D2), dimension: Some(TextureViewDimension::D2),
usage: None,
aspect: TextureAspect::All, aspect: TextureAspect::All,
base_mip_level: i as u32, base_mip_level: i as u32,
mip_level_count: Some(1), mip_level_count: Some(1),

View File

@ -63,9 +63,7 @@ image = { version = "0.25.2", default-features = false }
# misc # misc
bitflags = { version = "2.3", features = ["serde"] } bitflags = { version = "2.3", features = ["serde"] }
bytemuck = { version = "1.5" } bytemuck = { version = "1.5" }
wgpu-types = { version = "23", default-features = false } wgpu-types = { version = "24", default-features = false }
# TODO: remove dependency on wgpu once https://github.com/gfx-rs/wgpu/pull/6648, 6649 and 6650 have been released
wgpu = { version = "23.0.1", default-features = false }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }
futures-lite = "2.0.1" futures-lite = "2.0.1"

View File

@ -2,8 +2,9 @@
use ddsfile::{Caps2, D3DFormat, Dds, DxgiFormat}; use ddsfile::{Caps2, D3DFormat, Dds, DxgiFormat};
use std::io::Cursor; use std::io::Cursor;
use wgpu::TextureViewDescriptor; use wgpu_types::{
use wgpu_types::{Extent3d, TextureDimension, TextureFormat, TextureViewDimension}; Extent3d, TextureDimension, TextureFormat, TextureViewDescriptor, TextureViewDimension,
};
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use {bevy_utils::once, tracing::warn}; use {bevy_utils::once, tracing::warn};
@ -283,8 +284,7 @@ pub fn dds_format_to_texture_format(
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use wgpu::util::TextureDataOrder; use wgpu_types::{TextureDataOrder, TextureDescriptor, TextureDimension, TextureFormat};
use wgpu_types::{TextureDescriptor, TextureDimension, TextureFormat};
use crate::CompressedImageFormats; use crate::CompressedImageFormats;

View File

@ -13,10 +13,10 @@ use bevy_math::{AspectRatio, UVec2, UVec3, Vec2};
use core::hash::Hash; use core::hash::Hash;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use thiserror::Error; use thiserror::Error;
use wgpu::{SamplerDescriptor, TextureViewDescriptor};
use wgpu_types::{ use wgpu_types::{
AddressMode, CompareFunction, Extent3d, Features, FilterMode, SamplerBorderColor, AddressMode, CompareFunction, Extent3d, Features, FilterMode, SamplerBorderColor,
TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, SamplerDescriptor, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
TextureViewDescriptor,
}; };
pub trait BevyDefault { pub trait BevyDefault {
@ -343,7 +343,7 @@ pub struct Image {
pub texture_descriptor: TextureDescriptor<Option<&'static str>, &'static [TextureFormat]>, pub texture_descriptor: TextureDescriptor<Option<&'static str>, &'static [TextureFormat]>,
/// The [`ImageSampler`] to use during rendering. /// The [`ImageSampler`] to use during rendering.
pub sampler: ImageSampler, pub sampler: ImageSampler,
pub texture_view_descriptor: Option<TextureViewDescriptor<'static>>, pub texture_view_descriptor: Option<TextureViewDescriptor<Option<&'static str>>>,
pub asset_usage: RenderAssetUsages, pub asset_usage: RenderAssetUsages,
} }
@ -559,7 +559,7 @@ impl ImageSamplerDescriptor {
} }
} }
pub fn as_wgpu(&self) -> SamplerDescriptor { pub fn as_wgpu(&self) -> SamplerDescriptor<Option<&str>> {
SamplerDescriptor { SamplerDescriptor {
label: self.label.as_deref(), label: self.label.as_deref(),
address_mode_u: self.address_mode_u.into(), address_mode_u: self.address_mode_u.into(),
@ -669,8 +669,8 @@ impl From<SamplerBorderColor> for ImageSamplerBorderColor {
} }
} }
impl<'a> From<SamplerDescriptor<'a>> for ImageSamplerDescriptor { impl From<SamplerDescriptor<Option<&str>>> for ImageSamplerDescriptor {
fn from(value: SamplerDescriptor) -> Self { fn from(value: SamplerDescriptor<Option<&str>>) -> Self {
ImageSamplerDescriptor { ImageSamplerDescriptor {
label: value.label.map(ToString::to_string), label: value.label.map(ToString::to_string),
address_mode_u: value.address_mode_u.into(), address_mode_u: value.address_mode_u.into(),

View File

@ -13,9 +13,9 @@ use ktx2::{
BasicDataFormatDescriptor, ChannelTypeQualifiers, ColorModel, DataFormatDescriptorHeader, BasicDataFormatDescriptor, ChannelTypeQualifiers, ColorModel, DataFormatDescriptorHeader,
Header, SampleInformation, Header, SampleInformation,
}; };
use wgpu::TextureViewDescriptor;
use wgpu_types::{ use wgpu_types::{
AstcBlock, AstcChannel, Extent3d, TextureDimension, TextureFormat, TextureViewDimension, AstcBlock, AstcChannel, Extent3d, TextureDimension, TextureFormat, TextureViewDescriptor,
TextureViewDimension,
}; };
use super::{CompressedImageFormats, DataFormat, Image, TextureError, TranscodeFormat}; use super::{CompressedImageFormats, DataFormat, Image, TextureError, TranscodeFormat};

View File

@ -59,6 +59,10 @@ webp = ["bevy_image/webp"]
# Enable SPIR-V passthrough # Enable SPIR-V passthrough
spirv_shader_passthrough = ["bevy_render/spirv_shader_passthrough"] spirv_shader_passthrough = ["bevy_render/spirv_shader_passthrough"]
# Statically linked DXC shader compiler for DirectX 12
# TODO: When wgpu switches to DirectX 12 instead of Vulkan by default on windows, make this a default feature
statically-linked-dxc = ["bevy_render/statically-linked-dxc"]
# Include tonemapping LUT KTX2 files. # Include tonemapping LUT KTX2 files.
tonemapping_luts = ["bevy_core_pipeline/tonemapping_luts"] tonemapping_luts = ["bevy_core_pipeline/tonemapping_luts"]

View File

@ -29,7 +29,7 @@ bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-d
# other # other
bitflags = { version = "2.3", features = ["serde"] } bitflags = { version = "2.3", features = ["serde"] }
bytemuck = { version = "1.5" } bytemuck = { version = "1.5" }
wgpu-types = { version = "23", default-features = false } wgpu-types = { version = "24", default-features = false }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
hexasphere = "15.0" hexasphere = "15.0"
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }

View File

@ -6,7 +6,6 @@ use super::{
GenerateTangentsError, Indices, MeshAttributeData, MeshTrianglesError, MeshVertexAttribute, GenerateTangentsError, Indices, MeshAttributeData, MeshTrianglesError, MeshVertexAttribute,
MeshVertexAttributeId, MeshVertexBufferLayout, MeshVertexBufferLayoutRef, MeshVertexAttributeId, MeshVertexBufferLayout, MeshVertexBufferLayoutRef,
MeshVertexBufferLayouts, MeshWindingInvertError, VertexAttributeValues, VertexBufferLayout, MeshVertexBufferLayouts, MeshWindingInvertError, VertexAttributeValues, VertexBufferLayout,
VertexFormatSize,
}; };
use alloc::collections::BTreeMap; use alloc::collections::BTreeMap;
use bevy_asset::{Asset, Handle, RenderAssetUsages}; use bevy_asset::{Asset, Handle, RenderAssetUsages};
@ -379,7 +378,7 @@ impl Mesh {
pub fn get_vertex_size(&self) -> u64 { pub fn get_vertex_size(&self) -> u64 {
self.attributes self.attributes
.values() .values()
.map(|data| data.attribute.format.get_size()) .map(|data| data.attribute.format.size())
.sum() .sum()
} }
@ -414,7 +413,7 @@ impl Mesh {
format: data.attribute.format, format: data.attribute.format,
shader_location: index as u32, shader_location: index as u32,
}); });
accumulated_offset += data.attribute.format.get_size(); accumulated_offset += data.attribute.format.size();
} }
let layout = MeshVertexBufferLayout { let layout = MeshVertexBufferLayout {
@ -482,7 +481,7 @@ impl Mesh {
// bundle into interleaved buffers // bundle into interleaved buffers
let mut attribute_offset = 0; let mut attribute_offset = 0;
for attribute_data in self.attributes.values() { for attribute_data in self.attributes.values() {
let attribute_size = attribute_data.attribute.format.get_size() as usize; let attribute_size = attribute_data.attribute.format.size() as usize;
let attributes_bytes = attribute_data.values.get_bytes(); let attributes_bytes = attribute_data.values.get_bytes();
for (vertex_index, attribute_bytes) in attributes_bytes for (vertex_index, attribute_bytes) in attributes_bytes
.chunks_exact(attribute_size) .chunks_exact(attribute_size)

View File

@ -165,51 +165,6 @@ pub fn face_normal(a: [f32; 3], b: [f32; 3], c: [f32; 3]) -> [f32; 3] {
(b - a).cross(c - a).normalize().into() (b - a).cross(c - a).normalize().into()
} }
pub trait VertexFormatSize {
fn get_size(self) -> u64;
}
impl VertexFormatSize for VertexFormat {
fn get_size(self) -> u64 {
use core::mem::size_of;
let size = match self {
VertexFormat::Uint8x2 | VertexFormat::Unorm8x2 => size_of::<u8>() * 2,
VertexFormat::Uint8x4 | VertexFormat::Unorm8x4 => size_of::<u8>() * 4,
VertexFormat::Sint8x2 | VertexFormat::Snorm8x2 => size_of::<i8>() * 2,
VertexFormat::Sint8x4 | VertexFormat::Snorm8x4 => size_of::<i8>() * 4,
VertexFormat::Unorm10_10_10_2 => 10 + 10 + 10 + 2,
VertexFormat::Uint16x2 | VertexFormat::Unorm16x2 => size_of::<u16>() * 2,
VertexFormat::Uint16x4 | VertexFormat::Unorm16x4 => size_of::<u16>() * 4,
VertexFormat::Sint16x2 | VertexFormat::Snorm16x2 => size_of::<i16>() * 2,
VertexFormat::Sint16x4 | VertexFormat::Snorm16x4 => size_of::<i16>() * 4,
// NOTE: As of the time of writing this code, `f16` is not a stabilized primitive, so we
// can't use `size_of::<f16>()` here.
VertexFormat::Float16x2 => 2 * 2,
VertexFormat::Float16x4 => 2 * 4,
VertexFormat::Float32 => size_of::<f32>(),
VertexFormat::Float32x2 => size_of::<f32>() * 2,
VertexFormat::Float32x3 => size_of::<f32>() * 3,
VertexFormat::Float32x4 => size_of::<f32>() * 4,
VertexFormat::Uint32 => size_of::<u32>(),
VertexFormat::Uint32x2 => size_of::<u32>() * 2,
VertexFormat::Uint32x3 => size_of::<u32>() * 3,
VertexFormat::Uint32x4 => size_of::<u32>() * 4,
VertexFormat::Sint32 => size_of::<i32>(),
VertexFormat::Sint32x2 => size_of::<i32>() * 2,
VertexFormat::Sint32x3 => size_of::<i32>() * 3,
VertexFormat::Sint32x4 => size_of::<i32>() * 4,
VertexFormat::Float64 => size_of::<f64>(),
VertexFormat::Float64x2 => size_of::<f64>() * 2,
VertexFormat::Float64x3 => size_of::<f64>() * 3,
VertexFormat::Float64x4 => size_of::<f64>() * 4,
};
// We can safely cast `size` (a `usize`) into a `u64`, as we don't even reach the limits of
// of a `u8`.
size.try_into().unwrap()
}
}
/// Contains an array where each entry describes a property of a single vertex. /// Contains an array where each entry describes a property of a single vertex.
/// Matches the [`VertexFormats`](VertexFormat). /// Matches the [`VertexFormats`](VertexFormat).
#[derive(Clone, Debug, EnumVariantMeta)] #[derive(Clone, Debug, EnumVariantMeta)]

View File

@ -56,8 +56,7 @@ use self::{
}, },
visibility_buffer_raster_node::MeshletVisibilityBufferRasterPassNode, visibility_buffer_raster_node::MeshletVisibilityBufferRasterPassNode,
}; };
use crate::graph::NodePbr; use crate::{graph::NodePbr, PreviousGlobalTransform};
use crate::PreviousGlobalTransform;
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, weak_handle, AssetApp, AssetId, Handle}; use bevy_asset::{load_internal_asset, weak_handle, AssetApp, AssetId, Handle};
use bevy_core_pipeline::{ use bevy_core_pipeline::{

View File

@ -150,7 +150,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
meshlet_view_resources.raster_cluster_rightmost_slot, meshlet_view_resources.raster_cluster_rightmost_slot,
); );
meshlet_view_resources.depth_pyramid.downsample_depth( meshlet_view_resources.depth_pyramid.downsample_depth(
"meshlet early downsample depth", "downsample_depth",
render_context, render_context,
meshlet_view_resources.view_size, meshlet_view_resources.view_size,
&meshlet_view_bind_groups.downsample_depth, &meshlet_view_bind_groups.downsample_depth,
@ -202,7 +202,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
camera, camera,
); );
meshlet_view_resources.depth_pyramid.downsample_depth( meshlet_view_resources.depth_pyramid.downsample_depth(
"meshlet late downsample depth", "downsample_depth",
render_context, render_context,
meshlet_view_resources.view_size, meshlet_view_resources.view_size,
&meshlet_view_bind_groups.downsample_depth, &meshlet_view_bind_groups.downsample_depth,
@ -270,7 +270,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
meshlet_view_resources.raster_cluster_rightmost_slot, meshlet_view_resources.raster_cluster_rightmost_slot,
); );
meshlet_view_resources.depth_pyramid.downsample_depth( meshlet_view_resources.depth_pyramid.downsample_depth(
"meshlet early shadow downsample depth", "downsample_depth",
render_context, render_context,
meshlet_view_resources.view_size, meshlet_view_resources.view_size,
&meshlet_view_bind_groups.downsample_depth, &meshlet_view_bind_groups.downsample_depth,
@ -315,7 +315,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
camera, camera,
); );
meshlet_view_resources.depth_pyramid.downsample_depth( meshlet_view_resources.depth_pyramid.downsample_depth(
"meshlet late shadow downsample depth", "downsample_depth",
render_context, render_context,
meshlet_view_resources.view_size, meshlet_view_resources.view_size,
&meshlet_view_bind_groups.downsample_depth, &meshlet_view_bind_groups.downsample_depth,

View File

@ -63,10 +63,8 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3<u32>) {
// If we aren't using `multi_draw_indirect_count`, we have a 1:1 fixed // If we aren't using `multi_draw_indirect_count`, we have a 1:1 fixed
// assignment of batches to slots in the indirect parameters buffer, so we // assignment of batches to slots in the indirect parameters buffer, so we
// can just use the instance index as the index of our indirect parameters. // can just use the instance index as the index of our indirect parameters.
let early_instance_count = let early_instance_count = indirect_parameters_metadata[instance_index].early_instance_count;
atomicLoad(&indirect_parameters_metadata[instance_index].early_instance_count); let late_instance_count = indirect_parameters_metadata[instance_index].late_instance_count;
let late_instance_count =
atomicLoad(&indirect_parameters_metadata[instance_index].late_instance_count);
// If in the early phase, we draw only the early meshes. If in the late // If in the early phase, we draw only the early meshes. If in the late
// phase, we draw only the late meshes. If in the main phase, draw all the // phase, we draw only the late meshes. If in the main phase, draw all the
@ -135,4 +133,4 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3<u32>) {
indirect_parameters[indirect_parameters_index].vertex_count = indirect_parameters[indirect_parameters_index].vertex_count =
current_input[mesh_index].index_count; current_input[mesh_index].index_count;
#endif // INDEXED #endif // INDEXED
} }

View File

@ -1151,7 +1151,7 @@ impl SpecializedComputePipeline for PreprocessPipeline {
type Key = PreprocessPipelineKey; type Key = PreprocessPipelineKey;
fn specialize(&self, key: Self::Key) -> ComputePipelineDescriptor { fn specialize(&self, key: Self::Key) -> ComputePipelineDescriptor {
let mut shader_defs = vec![]; let mut shader_defs = vec!["WRITE_INDIRECT_PARAMETERS_METADATA".into()];
if key.contains(PreprocessPipelineKey::FRUSTUM_CULLING) { if key.contains(PreprocessPipelineKey::FRUSTUM_CULLING) {
shader_defs.push("INDIRECT".into()); shader_defs.push("INDIRECT".into());
shader_defs.push("FRUSTUM_CULLING".into()); shader_defs.push("FRUSTUM_CULLING".into());

View File

@ -1077,6 +1077,7 @@ pub fn prepare_lights(
all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")) all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu"))
))] ))]
dimension: Some(TextureViewDimension::Cube), dimension: Some(TextureViewDimension::Cube),
usage: None,
aspect: TextureAspect::DepthOnly, aspect: TextureAspect::DepthOnly,
base_mip_level: 0, base_mip_level: 0,
mip_level_count: None, mip_level_count: None,
@ -1120,6 +1121,7 @@ pub fn prepare_lights(
dimension: Some(TextureViewDimension::D2Array), dimension: Some(TextureViewDimension::D2Array),
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
dimension: Some(TextureViewDimension::D2), dimension: Some(TextureViewDimension::D2),
usage: None,
aspect: TextureAspect::DepthOnly, aspect: TextureAspect::DepthOnly,
base_mip_level: 0, base_mip_level: 0,
mip_level_count: None, mip_level_count: None,
@ -1242,6 +1244,7 @@ pub fn prepare_lights(
label: Some("point_light_shadow_map_texture_view"), label: Some("point_light_shadow_map_texture_view"),
format: None, format: None,
dimension: Some(TextureViewDimension::D2), dimension: Some(TextureViewDimension::D2),
usage: None,
aspect: TextureAspect::All, aspect: TextureAspect::All,
base_mip_level: 0, base_mip_level: 0,
mip_level_count: None, mip_level_count: None,
@ -1343,6 +1346,7 @@ pub fn prepare_lights(
label: Some("spot_light_shadow_map_texture_view"), label: Some("spot_light_shadow_map_texture_view"),
format: None, format: None,
dimension: Some(TextureViewDimension::D2), dimension: Some(TextureViewDimension::D2),
usage: None,
aspect: TextureAspect::All, aspect: TextureAspect::All,
base_mip_level: 0, base_mip_level: 0,
mip_level_count: None, mip_level_count: None,
@ -1477,6 +1481,7 @@ pub fn prepare_lights(
label: Some("directional_light_shadow_map_array_texture_view"), label: Some("directional_light_shadow_map_array_texture_view"),
format: None, format: None,
dimension: Some(TextureViewDimension::D2), dimension: Some(TextureViewDimension::D2),
usage: None,
aspect: TextureAspect::All, aspect: TextureAspect::All,
base_mip_level: 0, base_mip_level: 0,
mip_level_count: None, mip_level_count: None,

View File

@ -1733,7 +1733,7 @@ impl FromWorld for MeshPipeline {
render_queue.write_texture( render_queue.write_texture(
texture.as_image_copy(), texture.as_image_copy(),
&image.data, &image.data,
ImageDataLayout { TexelCopyBufferLayout {
offset: 0, offset: 0,
bytes_per_row: Some(image.width() * format_size as u32), bytes_per_row: Some(image.width() * format_size as u32),
rows_per_image: None, rows_per_image: None,

View File

@ -47,7 +47,7 @@ fn search_for_blockers_in_shadow_map_hardware(
view_bindings::directional_shadow_textures, view_bindings::directional_shadow_textures,
view_bindings::directional_shadow_textures_linear_sampler, view_bindings::directional_shadow_textures_linear_sampler,
light_local, light_local,
0.0, 0u,
); );
#else // NO_ARRAY_TEXTURES_SUPPORT #else // NO_ARRAY_TEXTURES_SUPPORT
let sampled_depth = textureSampleLevel( let sampled_depth = textureSampleLevel(
@ -55,7 +55,7 @@ fn search_for_blockers_in_shadow_map_hardware(
view_bindings::directional_shadow_textures_linear_sampler, view_bindings::directional_shadow_textures_linear_sampler,
light_local, light_local,
array_index, array_index,
0.0, 0u,
); );
#endif // NO_ARRAY_TEXTURES_SUPPORT #endif // NO_ARRAY_TEXTURES_SUPPORT
return select(vec2(0.0), vec2(sampled_depth, 1.0), sampled_depth >= depth); return select(vec2(0.0), vec2(sampled_depth, 1.0), sampled_depth >= depth);

View File

@ -242,9 +242,9 @@ fn depth_raymarch_distance_fn_evaluate(
// * The shrink-wrap surface is no longer continuous, so it's possible for rays to miss it. // * The shrink-wrap surface is no longer continuous, so it's possible for rays to miss it.
let linear_depth = let linear_depth =
1.0 / textureSampleLevel(depth_prepass_texture, depth_linear_sampler, interp_uv, 0.0); 1.0 / textureSampleLevel(depth_prepass_texture, depth_linear_sampler, interp_uv, 0u);
let unfiltered_depth = let unfiltered_depth =
1.0 / textureSampleLevel(depth_prepass_texture, depth_nearest_sampler, interp_uv, 0.0); 1.0 / textureSampleLevel(depth_prepass_texture, depth_nearest_sampler, interp_uv, 0u);
var max_depth: f32; var max_depth: f32;
var min_depth: f32; var min_depth: f32;

View File

@ -116,7 +116,7 @@ uuid = { version = "1.13.1", default-features = false, optional = true, features
"serde", "serde",
] } ] }
variadics_please = "1.1" variadics_please = "1.1"
wgpu-types = { version = "23", features = ["serde"], optional = true } wgpu-types = { version = "24", features = ["serde"], optional = true }
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
uuid = { version = "1.13.1", default-features = false, features = ["js"] } uuid = { version = "1.13.1", default-features = false, features = ["js"] }

View File

@ -24,6 +24,10 @@ shader_format_spirv = ["wgpu/spirv", "naga/spv-in", "naga/spv-out"]
# Enable SPIR-V shader passthrough # Enable SPIR-V shader passthrough
spirv_shader_passthrough = ["wgpu/spirv"] spirv_shader_passthrough = ["wgpu/spirv"]
# Statically linked DXC shader compiler for DirectX 12
# TODO: When wgpu switches to DirectX 12 instead of Vulkan by default on windows, make this a default feature
statically-linked-dxc = ["wgpu/static-dxc"]
trace = ["profiling"] trace = ["profiling"]
tracing-tracy = [] tracing-tracy = []
ci_limits = [] ci_limits = []
@ -70,14 +74,14 @@ codespan-reporting = "0.11.0"
# It is enabled for now to avoid having to do a significant overhaul of the renderer just for wasm. # It is enabled for now to avoid having to do a significant overhaul of the renderer just for wasm.
# When the 'atomics' feature is enabled `fragile-send-sync-non-atomic` does nothing # When the 'atomics' feature is enabled `fragile-send-sync-non-atomic` does nothing
# and Bevy instead wraps `wgpu` types to verify they are not used off their origin thread. # and Bevy instead wraps `wgpu` types to verify they are not used off their origin thread.
wgpu = { version = "23.0.1", default-features = false, features = [ wgpu = { version = "24", default-features = false, features = [
"wgsl", "wgsl",
"dx12", "dx12",
"metal", "metal",
"naga-ir", "naga-ir",
"fragile-send-sync-non-atomic-wasm", "fragile-send-sync-non-atomic-wasm",
] } ] }
naga = { version = "23", features = ["wgsl-in"] } naga = { version = "24", features = ["wgsl-in"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
bytemuck = { version = "1.5", features = ["derive", "must_cast"] } bytemuck = { version = "1.5", features = ["derive", "must_cast"] }
downcast-rs = { version = "2", default-features = false, features = ["std"] } downcast-rs = { version = "2", default-features = false, features = ["std"] }
@ -101,7 +105,7 @@ fixedbitset = { version = "0.5" }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
# Omit the `glsl` feature in non-WebAssembly by default. # Omit the `glsl` feature in non-WebAssembly by default.
naga_oil = { version = "0.16", default-features = false, features = [ naga_oil = { version = "0.17", default-features = false, features = [
"test_shader", "test_shader",
] } ] }
@ -109,7 +113,7 @@ naga_oil = { version = "0.16", default-features = false, features = [
proptest = "1" proptest = "1"
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
naga_oil = "0.16" naga_oil = "0.17"
js-sys = "0.3" js-sys = "0.3"
web-sys = { version = "0.3.67", features = [ web-sys = { version = "0.3.67", features = [
'Blob', 'Blob',

View File

@ -975,16 +975,22 @@ impl FromWorld for GpuPreprocessingSupport {
crate::get_adreno_model(adapter).is_some_and(|model| model != 720 && model <= 730) crate::get_adreno_model(adapter).is_some_and(|model| model != 720 && model <= 730)
} }
let max_supported_mode = if device.limits().max_compute_workgroup_size_x == 0 || let feature_support = device.features().contains(
is_non_supported_android_device(adapter) Features::INDIRECT_FIRST_INSTANCE
| Features::MULTI_DRAW_INDIRECT
| Features::PUSH_CONSTANTS,
);
// Depth downsampling for occlusion culling requires 12 textures
let limit_support = device.limits().max_storage_textures_per_shader_stage >= 12;
let downlevel_support = adapter.get_downlevel_capabilities().flags.contains(
DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW
);
let max_supported_mode = if device.limits().max_compute_workgroup_size_x == 0
|| is_non_supported_android_device(adapter)
{ {
GpuPreprocessingMode::None GpuPreprocessingMode::None
} else if !device } else if !(feature_support && limit_support && downlevel_support) {
.features()
.contains(Features::INDIRECT_FIRST_INSTANCE | Features::MULTI_DRAW_INDIRECT) ||
!adapter.get_downlevel_capabilities().flags.contains(
DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW)
{
GpuPreprocessingMode::PreprocessingOnly GpuPreprocessingMode::PreprocessingOnly
} else { } else {
GpuPreprocessingMode::Culling GpuPreprocessingMode::Culling

View File

@ -50,8 +50,13 @@ struct IndirectParametersMetadata {
mesh_index: u32, mesh_index: u32,
base_output_index: u32, base_output_index: u32,
batch_set_index: u32, batch_set_index: u32,
#ifdef WRITE_INDIRECT_PARAMETERS_METADATA
early_instance_count: atomic<u32>, early_instance_count: atomic<u32>,
late_instance_count: atomic<u32>, late_instance_count: atomic<u32>,
#else
early_instance_count: u32,
late_instance_count: u32,
#endif
} }
struct IndirectBatchSet { struct IndirectBatchSet {

View File

@ -1,7 +1,10 @@
use crate::{ use crate::{
extract_component::ExtractComponentPlugin, extract_component::ExtractComponentPlugin,
render_asset::RenderAssets, render_asset::RenderAssets,
render_resource::{Buffer, BufferUsages, Extent3d, ImageDataLayout, Texture, TextureFormat}, render_resource::{
Buffer, BufferUsages, CommandEncoder, Extent3d, TexelCopyBufferLayout, Texture,
TextureFormat,
},
renderer::{render_system, RenderDevice}, renderer::{render_system, RenderDevice},
storage::{GpuShaderStorageBuffer, ShaderStorageBuffer}, storage::{GpuShaderStorageBuffer, ShaderStorageBuffer},
sync_world::MainEntity, sync_world::MainEntity,
@ -28,7 +31,6 @@ use encase::internal::ReadFrom;
use encase::private::Reader; use encase::private::Reader;
use encase::ShaderType; use encase::ShaderType;
use tracing::warn; use tracing::warn;
use wgpu::CommandEncoder;
/// A plugin that enables reading back gpu buffers and textures to the cpu. /// A plugin that enables reading back gpu buffers and textures to the cpu.
pub struct GpuReadbackPlugin { pub struct GpuReadbackPlugin {
@ -185,7 +187,7 @@ impl GpuReadbackBufferPool {
enum ReadbackSource { enum ReadbackSource {
Texture { Texture {
texture: Texture, texture: Texture,
layout: ImageDataLayout, layout: TexelCopyBufferLayout,
size: Extent3d, size: Extent3d,
}, },
Buffer { Buffer {
@ -295,7 +297,7 @@ pub(crate) fn submit_readback_commands(world: &World, command_encoder: &mut Comm
} => { } => {
command_encoder.copy_texture_to_buffer( command_encoder.copy_texture_to_buffer(
texture.as_image_copy(), texture.as_image_copy(),
wgpu::ImageCopyBuffer { wgpu::TexelCopyBufferInfo {
buffer: &readback.buffer, buffer: &readback.buffer,
layout: *layout, layout: *layout,
}, },
@ -354,9 +356,9 @@ pub(crate) const fn get_aligned_size(extent: Extent3d, pixel_size: u32) -> u32 {
extent.height * align_byte_size(extent.width * pixel_size) * extent.depth_or_array_layers extent.height * align_byte_size(extent.width * pixel_size) * extent.depth_or_array_layers
} }
/// Get a [`ImageDataLayout`] aligned such that the image can be copied into a buffer. /// Get a [`TexelCopyBufferLayout`] aligned such that the image can be copied into a buffer.
pub(crate) fn layout_data(extent: Extent3d, format: TextureFormat) -> ImageDataLayout { pub(crate) fn layout_data(extent: Extent3d, format: TextureFormat) -> TexelCopyBufferLayout {
ImageDataLayout { TexelCopyBufferLayout {
bytes_per_row: if extent.height > 1 || extent.depth_or_array_layers > 1 { bytes_per_row: if extent.height > 1 || extent.depth_or_array_layers > 1 {
// 1 = 1 row // 1 = 1 row
Some(get_aligned_size( Some(get_aligned_size(

View File

@ -295,11 +295,17 @@ impl Plugin for RenderPlugin {
.cloned(); .cloned();
let settings = render_creation.clone(); let settings = render_creation.clone();
let async_renderer = async move { let async_renderer = async move {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends, backends,
dx12_shader_compiler: settings.dx12_shader_compiler.clone(),
flags: settings.instance_flags, flags: settings.instance_flags,
gles_minor_version: settings.gles3_minor_version, backend_options: wgpu::BackendOptions {
gl: wgpu::GlBackendOptions {
gles_minor_version: settings.gles3_minor_version,
},
dx12: wgpu::Dx12BackendOptions {
shader_compiler: settings.dx12_shader_compiler.clone(),
},
},
}); });
let surface = primary_window.and_then(|wrapper| { let surface = primary_window.and_then(|wrapper| {

View File

@ -196,7 +196,7 @@ impl RenderAsset for RenderMesh {
let mut vertex_size = 0; let mut vertex_size = 0;
for attribute_data in mesh.attributes() { for attribute_data in mesh.attributes() {
let vertex_format = attribute_data.0.format; let vertex_format = attribute_data.0.format;
vertex_size += vertex_format.get_size() as usize; vertex_size += vertex_format.size() as usize;
} }
let vertex_count = mesh.count_vertices(); let vertex_count = mesh.count_vertices();

View File

@ -6,7 +6,6 @@ use crate::{
renderer::RenderDevice, renderer::RenderDevice,
texture::GpuImage, texture::GpuImage,
}; };
use alloc::sync::Arc;
use bevy_derive::{Deref, DerefMut}; use bevy_derive::{Deref, DerefMut};
use bevy_ecs::system::{SystemParam, SystemParamItem}; use bevy_ecs::system::{SystemParam, SystemParamItem};
pub use bevy_render_macros::AsBindGroup; pub use bevy_render_macros::AsBindGroup;
@ -29,7 +28,7 @@ define_atomic_id!(BindGroupId);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct BindGroup { pub struct BindGroup {
id: BindGroupId, id: BindGroupId,
value: Arc<WgpuWrapper<wgpu::BindGroup>>, value: WgpuWrapper<wgpu::BindGroup>,
} }
impl BindGroup { impl BindGroup {
@ -58,7 +57,7 @@ impl From<wgpu::BindGroup> for BindGroup {
fn from(value: wgpu::BindGroup) -> Self { fn from(value: wgpu::BindGroup) -> Self {
BindGroup { BindGroup {
id: BindGroupId::new(), id: BindGroupId::new(),
value: Arc::new(WgpuWrapper::new(value)), value: WgpuWrapper::new(value),
} }
} }
} }

View File

@ -1,6 +1,5 @@
use crate::define_atomic_id; use crate::define_atomic_id;
use crate::renderer::WgpuWrapper; use crate::renderer::WgpuWrapper;
use alloc::sync::Arc;
use core::ops::Deref; use core::ops::Deref;
define_atomic_id!(BindGroupLayoutId); define_atomic_id!(BindGroupLayoutId);
@ -16,7 +15,7 @@ define_atomic_id!(BindGroupLayoutId);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct BindGroupLayout { pub struct BindGroupLayout {
id: BindGroupLayoutId, id: BindGroupLayoutId,
value: Arc<WgpuWrapper<wgpu::BindGroupLayout>>, value: WgpuWrapper<wgpu::BindGroupLayout>,
} }
impl PartialEq for BindGroupLayout { impl PartialEq for BindGroupLayout {
@ -50,7 +49,7 @@ impl From<wgpu::BindGroupLayout> for BindGroupLayout {
fn from(value: wgpu::BindGroupLayout) -> Self { fn from(value: wgpu::BindGroupLayout) -> Self {
BindGroupLayout { BindGroupLayout {
id: BindGroupLayoutId::new(), id: BindGroupLayoutId::new(),
value: Arc::new(WgpuWrapper::new(value)), value: WgpuWrapper::new(value),
} }
} }
} }

View File

@ -1,6 +1,5 @@
use crate::define_atomic_id; use crate::define_atomic_id;
use crate::renderer::WgpuWrapper; use crate::renderer::WgpuWrapper;
use alloc::sync::Arc;
use core::ops::{Bound, Deref, RangeBounds}; use core::ops::{Bound, Deref, RangeBounds};
define_atomic_id!(BufferId); define_atomic_id!(BufferId);
@ -8,8 +7,7 @@ define_atomic_id!(BufferId);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Buffer { pub struct Buffer {
id: BufferId, id: BufferId,
value: Arc<WgpuWrapper<wgpu::Buffer>>, value: WgpuWrapper<wgpu::Buffer>,
size: wgpu::BufferAddress,
} }
impl Buffer { impl Buffer {
@ -28,7 +26,7 @@ impl Buffer {
let size = match bounds.end_bound() { let size = match bounds.end_bound() {
Bound::Included(&bound) => bound + 1, Bound::Included(&bound) => bound + 1,
Bound::Excluded(&bound) => bound, Bound::Excluded(&bound) => bound,
Bound::Unbounded => self.size, Bound::Unbounded => self.value.size(),
} - offset; } - offset;
BufferSlice { BufferSlice {
id: self.id, id: self.id,
@ -48,8 +46,7 @@ impl From<wgpu::Buffer> for Buffer {
fn from(value: wgpu::Buffer) -> Self { fn from(value: wgpu::Buffer) -> Self {
Buffer { Buffer {
id: BufferId::new(), id: BufferId::new(),
size: value.size(), value: WgpuWrapper::new(value),
value: Arc::new(WgpuWrapper::new(value)),
} }
} }
} }

View File

@ -43,8 +43,7 @@ pub use wgpu::{
ColorWrites, CommandEncoder, CommandEncoderDescriptor, CompareFunction, ComputePass, ColorWrites, CommandEncoder, CommandEncoderDescriptor, CompareFunction, ComputePass,
ComputePassDescriptor, ComputePipelineDescriptor as RawComputePipelineDescriptor, ComputePassDescriptor, ComputePipelineDescriptor as RawComputePipelineDescriptor,
DepthBiasState, DepthStencilState, DownlevelFlags, Extent3d, Face, Features as WgpuFeatures, DepthBiasState, DepthStencilState, DownlevelFlags, Extent3d, Face, Features as WgpuFeatures,
FilterMode, FragmentState as RawFragmentState, FrontFace, ImageCopyBuffer, ImageCopyBufferBase, FilterMode, FragmentState as RawFragmentState, FrontFace, ImageSubresourceRange, IndexFormat,
ImageCopyTexture, ImageCopyTextureBase, ImageDataLayout, ImageSubresourceRange, IndexFormat,
Limits as WgpuLimits, LoadOp, Maintain, MapMode, MultisampleState, Operations, Origin3d, Limits as WgpuLimits, LoadOp, Maintain, MapMode, MultisampleState, Operations, Origin3d,
PipelineCompilationOptions, PipelineLayout, PipelineLayoutDescriptor, PolygonMode, PipelineCompilationOptions, PipelineLayout, PipelineLayoutDescriptor, PolygonMode,
PrimitiveState, PrimitiveTopology, PushConstantRange, RenderPassColorAttachment, PrimitiveState, PrimitiveTopology, PushConstantRange, RenderPassColorAttachment,
@ -52,10 +51,11 @@ pub use wgpu::{
RenderPipelineDescriptor as RawRenderPipelineDescriptor, Sampler as WgpuSampler, RenderPipelineDescriptor as RawRenderPipelineDescriptor, Sampler as WgpuSampler,
SamplerBindingType, SamplerDescriptor, ShaderModule, ShaderModuleDescriptor, ShaderSource, SamplerBindingType, SamplerDescriptor, ShaderModule, ShaderModuleDescriptor, ShaderSource,
ShaderStages, StencilFaceState, StencilOperation, StencilState, StorageTextureAccess, StoreOp, ShaderStages, StencilFaceState, StencilOperation, StencilState, StorageTextureAccess, StoreOp,
TextureAspect, TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, TexelCopyBufferInfo, TexelCopyBufferLayout, TexelCopyTextureInfo, TextureAspect,
TextureUsages, TextureView as WgpuTextureView, TextureViewDescriptor, TextureViewDimension, TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, TextureUsages,
VertexAttribute, VertexBufferLayout as RawVertexBufferLayout, VertexFormat, TextureView as WgpuTextureView, TextureViewDescriptor, TextureViewDimension, VertexAttribute,
VertexState as RawVertexState, VertexStepMode, COPY_BUFFER_ALIGNMENT, VertexBufferLayout as RawVertexBufferLayout, VertexFormat, VertexState as RawVertexState,
VertexStepMode, COPY_BUFFER_ALIGNMENT,
}; };
pub use crate::mesh::VertexBufferLayout; pub use crate::mesh::VertexBufferLayout;

View File

@ -6,7 +6,6 @@ use crate::{
render_resource::{BindGroupLayout, Shader}, render_resource::{BindGroupLayout, Shader},
}; };
use alloc::borrow::Cow; use alloc::borrow::Cow;
use alloc::sync::Arc;
use bevy_asset::Handle; use bevy_asset::Handle;
use core::ops::Deref; use core::ops::Deref;
use wgpu::{ use wgpu::{
@ -22,7 +21,7 @@ define_atomic_id!(RenderPipelineId);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct RenderPipeline { pub struct RenderPipeline {
id: RenderPipelineId, id: RenderPipelineId,
value: Arc<WgpuWrapper<wgpu::RenderPipeline>>, value: WgpuWrapper<wgpu::RenderPipeline>,
} }
impl RenderPipeline { impl RenderPipeline {
@ -36,7 +35,7 @@ impl From<wgpu::RenderPipeline> for RenderPipeline {
fn from(value: wgpu::RenderPipeline) -> Self { fn from(value: wgpu::RenderPipeline) -> Self {
RenderPipeline { RenderPipeline {
id: RenderPipelineId::new(), id: RenderPipelineId::new(),
value: Arc::new(WgpuWrapper::new(value)), value: WgpuWrapper::new(value),
} }
} }
} }
@ -59,7 +58,7 @@ define_atomic_id!(ComputePipelineId);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ComputePipeline { pub struct ComputePipeline {
id: ComputePipelineId, id: ComputePipelineId,
value: Arc<WgpuWrapper<wgpu::ComputePipeline>>, value: WgpuWrapper<wgpu::ComputePipeline>,
} }
impl ComputePipeline { impl ComputePipeline {
@ -74,7 +73,7 @@ impl From<wgpu::ComputePipeline> for ComputePipeline {
fn from(value: wgpu::ComputePipeline) -> Self { fn from(value: wgpu::ComputePipeline) -> Self {
ComputePipeline { ComputePipeline {
id: ComputePipelineId::new(), id: ComputePipelineId::new(),
value: Arc::new(WgpuWrapper::new(value)), value: WgpuWrapper::new(value),
} }
} }
} }

View File

@ -1069,6 +1069,18 @@ fn get_capabilities(features: Features, downlevel: DownlevelFlags) -> Capabiliti
Capabilities::SUBGROUP_VERTEX_STAGE, Capabilities::SUBGROUP_VERTEX_STAGE,
features.contains(Features::SUBGROUP_VERTEX), features.contains(Features::SUBGROUP_VERTEX),
); );
capabilities.set(
Capabilities::SHADER_FLOAT32_ATOMIC,
features.contains(Features::SHADER_FLOAT32_ATOMIC),
);
capabilities.set(
Capabilities::TEXTURE_ATOMIC,
features.contains(Features::TEXTURE_ATOMIC),
);
capabilities.set(
Capabilities::TEXTURE_INT64_ATOMIC,
features.contains(Features::TEXTURE_INT64_ATOMIC),
);
capabilities capabilities
} }

View File

@ -1,6 +1,5 @@
use crate::define_atomic_id; use crate::define_atomic_id;
use crate::renderer::WgpuWrapper; use crate::renderer::WgpuWrapper;
use alloc::sync::Arc;
use bevy_derive::{Deref, DerefMut}; use bevy_derive::{Deref, DerefMut};
use bevy_ecs::resource::Resource; use bevy_ecs::resource::Resource;
use core::ops::Deref; use core::ops::Deref;
@ -23,7 +22,7 @@ define_atomic_id!(TextureId);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Texture { pub struct Texture {
id: TextureId, id: TextureId,
value: Arc<WgpuWrapper<wgpu::Texture>>, value: WgpuWrapper<wgpu::Texture>,
} }
impl Texture { impl Texture {
@ -43,7 +42,7 @@ impl From<wgpu::Texture> for Texture {
fn from(value: wgpu::Texture) -> Self { fn from(value: wgpu::Texture) -> Self {
Texture { Texture {
id: TextureId::new(), id: TextureId::new(),
value: Arc::new(WgpuWrapper::new(value)), value: WgpuWrapper::new(value),
} }
} }
} }
@ -63,18 +62,16 @@ define_atomic_id!(TextureViewId);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TextureView { pub struct TextureView {
id: TextureViewId, id: TextureViewId,
value: Arc<WgpuWrapper<wgpu::TextureView>>, value: WgpuWrapper<wgpu::TextureView>,
} }
pub struct SurfaceTexture { pub struct SurfaceTexture {
value: Arc<WgpuWrapper<wgpu::SurfaceTexture>>, value: WgpuWrapper<wgpu::SurfaceTexture>,
} }
impl SurfaceTexture { impl SurfaceTexture {
pub fn try_unwrap(self) -> Option<wgpu::SurfaceTexture> { pub fn present(self) {
Arc::try_unwrap(self.value) self.value.into_inner().present();
.map(WgpuWrapper::into_inner)
.ok()
} }
} }
@ -90,7 +87,7 @@ impl From<wgpu::TextureView> for TextureView {
fn from(value: wgpu::TextureView) -> Self { fn from(value: wgpu::TextureView) -> Self {
TextureView { TextureView {
id: TextureViewId::new(), id: TextureViewId::new(),
value: Arc::new(WgpuWrapper::new(value)), value: WgpuWrapper::new(value),
} }
} }
} }
@ -98,7 +95,7 @@ impl From<wgpu::TextureView> for TextureView {
impl From<wgpu::SurfaceTexture> for SurfaceTexture { impl From<wgpu::SurfaceTexture> for SurfaceTexture {
fn from(value: wgpu::SurfaceTexture) -> Self { fn from(value: wgpu::SurfaceTexture) -> Self {
SurfaceTexture { SurfaceTexture {
value: Arc::new(WgpuWrapper::new(value)), value: WgpuWrapper::new(value),
} }
} }
} }
@ -131,7 +128,7 @@ define_atomic_id!(SamplerId);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Sampler { pub struct Sampler {
id: SamplerId, id: SamplerId,
value: Arc<WgpuWrapper<wgpu::Sampler>>, value: WgpuWrapper<wgpu::Sampler>,
} }
impl Sampler { impl Sampler {
@ -146,7 +143,7 @@ impl From<wgpu::Sampler> for Sampler {
fn from(value: wgpu::Sampler) -> Self { fn from(value: wgpu::Sampler) -> Self {
Sampler { Sampler {
id: SamplerId::new(), id: SamplerId::new(),
value: Arc::new(WgpuWrapper::new(value)), value: WgpuWrapper::new(value),
} }
} }
} }

View File

@ -87,14 +87,12 @@ pub fn render_system(world: &mut World, state: &mut SystemState<Query<Entity, Wi
let mut windows = world.resource_mut::<ExtractedWindows>(); let mut windows = world.resource_mut::<ExtractedWindows>();
for window in windows.values_mut() { for window in windows.values_mut() {
if let Some(wrapped_texture) = window.swap_chain_texture.take() { if let Some(surface_texture) = window.swap_chain_texture.take() {
if let Some(surface_texture) = wrapped_texture.try_unwrap() { // TODO(clean): winit docs recommends calling pre_present_notify before this.
// TODO(clean): winit docs recommends calling pre_present_notify before this. // though `present()` doesn't present the frame, it schedules it to be presented
// though `present()` doesn't present the frame, it schedules it to be presented // by wgpu.
// by wgpu. // https://docs.rs/winit/0.29.9/wasm32-unknown-unknown/winit/window/struct.Window.html#method.pre_present_notify
// https://docs.rs/winit/0.29.9/wasm32-unknown-unknown/winit/window/struct.Window.html#method.pre_present_notify surface_texture.present();
surface_texture.present();
}
} }
} }
@ -224,10 +222,8 @@ pub async fn initialize_renderer(
// RAY_QUERY and RAY_TRACING_ACCELERATION STRUCTURE will sometimes cause DeviceLost failures on platforms // RAY_QUERY and RAY_TRACING_ACCELERATION STRUCTURE will sometimes cause DeviceLost failures on platforms
// that report them as supported: // that report them as supported:
// <https://github.com/gfx-rs/wgpu/issues/5488> // <https://github.com/gfx-rs/wgpu/issues/5488>
// WGPU also currently doesn't actually support these features yet, so we should disable features -= wgpu::Features::EXPERIMENTAL_RAY_QUERY;
// them until they are safe to enable. features -= wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE;
features -= wgpu::Features::RAY_QUERY;
features -= wgpu::Features::RAY_TRACING_ACCELERATION_STRUCTURE;
limits = adapter.limits(); limits = adapter.limits();
} }

View File

@ -4,7 +4,6 @@ use crate::render_resource::{
RenderPipeline, Sampler, Texture, RenderPipeline, Sampler, Texture,
}; };
use crate::WgpuWrapper; use crate::WgpuWrapper;
use alloc::sync::Arc;
use bevy_ecs::resource::Resource; use bevy_ecs::resource::Resource;
use wgpu::{ use wgpu::{
util::DeviceExt, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, util::DeviceExt, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor,
@ -14,17 +13,17 @@ use wgpu::{
/// This GPU device is responsible for the creation of most rendering and compute resources. /// This GPU device is responsible for the creation of most rendering and compute resources.
#[derive(Resource, Clone)] #[derive(Resource, Clone)]
pub struct RenderDevice { pub struct RenderDevice {
device: Arc<WgpuWrapper<wgpu::Device>>, device: WgpuWrapper<wgpu::Device>,
} }
impl From<wgpu::Device> for RenderDevice { impl From<wgpu::Device> for RenderDevice {
fn from(device: wgpu::Device) -> Self { fn from(device: wgpu::Device) -> Self {
Self::new(Arc::new(WgpuWrapper::new(device))) Self::new(WgpuWrapper::new(device))
} }
} }
impl RenderDevice { impl RenderDevice {
pub fn new(device: Arc<WgpuWrapper<wgpu::Device>>) -> Self { pub fn new(device: WgpuWrapper<wgpu::Device>) -> Self {
Self { device } Self { device }
} }

View File

@ -71,10 +71,10 @@ impl Default for WgpuSettings {
Backends::all() Backends::all()
}; };
let backends = Some(wgpu::util::backend_bits_from_env().unwrap_or(default_backends)); let backends = Some(Backends::from_env().unwrap_or(default_backends));
let power_preference = let power_preference =
wgpu::util::power_preference_from_env().unwrap_or(PowerPreference::HighPerformance); PowerPreference::from_env().unwrap_or(PowerPreference::HighPerformance);
let priority = settings_priority_from_env().unwrap_or(WgpuSettingsPriority::Functionality); let priority = settings_priority_from_env().unwrap_or(WgpuSettingsPriority::Functionality);
@ -100,13 +100,27 @@ impl Default for WgpuSettings {
limits limits
}; };
let dx12_compiler = let dx12_shader_compiler =
wgpu::util::dx12_shader_compiler_from_env().unwrap_or(Dx12Compiler::Dxc { Dx12Compiler::from_env().unwrap_or(if cfg!(feature = "statically-linked-dxc") {
dxil_path: None, Dx12Compiler::StaticDxc
dxc_path: None, } else {
let dxc = "dxcompiler.dll";
let dxil = "dxil.dll";
if cfg!(target_os = "windows")
&& std::fs::metadata(dxc).is_ok()
&& std::fs::metadata(dxil).is_ok()
{
Dx12Compiler::DynamicDxc {
dxc_path: String::from(dxc),
dxil_path: String::from(dxil),
}
} else {
Dx12Compiler::Fxc
}
}); });
let gles3_minor_version = wgpu::util::gles_minor_version_from_env().unwrap_or_default(); let gles3_minor_version = Gles3MinorVersion::from_env().unwrap_or_default();
let instance_flags = InstanceFlags::default().with_env(); let instance_flags = InstanceFlags::default().with_env();
@ -119,7 +133,7 @@ impl Default for WgpuSettings {
disabled_features: None, disabled_features: None,
limits, limits,
constrained_limits: None, constrained_limits: None,
dx12_shader_compiler: dx12_compiler, dx12_shader_compiler,
gles3_minor_version, gles3_minor_version,
instance_flags, instance_flags,
memory_hints: MemoryHints::default(), memory_hints: MemoryHints::default(),

View File

@ -593,7 +593,7 @@ fn render_screenshot(
}; };
encoder.copy_texture_to_buffer( encoder.copy_texture_to_buffer(
prepared_state.texture.as_image_copy(), prepared_state.texture.as_image_copy(),
wgpu::ImageCopyBuffer { wgpu::TexelCopyBufferInfo {
buffer: &prepared_state.buffer, buffer: &prepared_state.buffer,
layout: gpu_readback::layout_data(extent, texture_format), layout: gpu_readback::layout_data(extent, texture_format),
}, },

View File

@ -360,7 +360,7 @@ impl FromWorld for Mesh2dPipeline {
render_queue.write_texture( render_queue.write_texture(
texture.as_image_copy(), texture.as_image_copy(),
&image.data, &image.data,
ImageDataLayout { TexelCopyBufferLayout {
offset: 0, offset: 0,
bytes_per_row: Some(image.width() * format_size as u32), bytes_per_row: Some(image.width() * format_size as u32),
rows_per_image: None, rows_per_image: None,

View File

@ -103,7 +103,7 @@ impl FromWorld for SpritePipeline {
render_queue.write_texture( render_queue.write_texture(
texture.as_image_copy(), texture.as_image_copy(),
&image.data, &image.data,
ImageDataLayout { TexelCopyBufferLayout {
offset: 0, offset: 0,
bytes_per_row: Some(image.width() * format_size as u32), bytes_per_row: Some(image.width() * format_size as u32),
rows_per_image: None, rows_per_image: None,

View File

@ -58,7 +58,7 @@ cfg-if = "1.0"
raw-window-handle = "0.6" raw-window-handle = "0.6"
serde = { version = "1.0", features = ["derive"], optional = true } serde = { version = "1.0", features = ["derive"], optional = true }
bytemuck = { version = "1.5", optional = true } bytemuck = { version = "1.5", optional = true }
wgpu-types = { version = "23", optional = true } wgpu-types = { version = "24", optional = true }
accesskit = "0.17" accesskit = "0.17"
tracing = { version = "0.1", default-features = false, features = ["std"] } tracing = { version = "0.1", default-features = false, features = ["std"] }

View File

@ -96,6 +96,7 @@ The default feature set enables most of the expected features of a game engine,
|shader_format_glsl|Enable support for shaders in GLSL| |shader_format_glsl|Enable support for shaders in GLSL|
|shader_format_spirv|Enable support for shaders in SPIR-V| |shader_format_spirv|Enable support for shaders in SPIR-V|
|spirv_shader_passthrough|Enable passthrough loading for SPIR-V shaders (Only supported on Vulkan, shader capabilities and extensions must agree with the platform implementation)| |spirv_shader_passthrough|Enable passthrough loading for SPIR-V shaders (Only supported on Vulkan, shader capabilities and extensions must agree with the platform implementation)|
|statically-linked-dxc|Statically linked DXC shader compiler for DirectX 12|
|symphonia-aac|AAC audio format support (through symphonia)| |symphonia-aac|AAC audio format support (through symphonia)|
|symphonia-all|AAC, FLAC, MP3, MP4, OGG/VORBIS, and WAV audio formats support (through symphonia)| |symphonia-all|AAC, FLAC, MP3, MP4, OGG/VORBIS, and WAV audio formats support (through symphonia)|
|symphonia-flac|FLAC audio format support (through symphonia)| |symphonia-flac|FLAC audio format support (through symphonia)|

View File

@ -17,8 +17,8 @@ use bevy::{
render_asset::{RenderAssetUsages, RenderAssets}, render_asset::{RenderAssetUsages, RenderAssets},
render_graph::{self, NodeRunError, RenderGraph, RenderGraphContext, RenderLabel}, render_graph::{self, NodeRunError, RenderGraph, RenderGraphContext, RenderLabel},
render_resource::{ render_resource::{
Buffer, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Extent3d, Buffer, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Extent3d, Maintain,
ImageCopyBuffer, ImageDataLayout, Maintain, MapMode, TextureDimension, TextureFormat, MapMode, TexelCopyBufferInfo, TexelCopyBufferLayout, TextureDimension, TextureFormat,
TextureUsages, TextureUsages,
}, },
renderer::{RenderContext, RenderDevice, RenderQueue}, renderer::{RenderContext, RenderDevice, RenderQueue},
@ -372,9 +372,9 @@ impl render_graph::Node for ImageCopyDriver {
encoder.copy_texture_to_buffer( encoder.copy_texture_to_buffer(
src_image.texture.as_image_copy(), src_image.texture.as_image_copy(),
ImageCopyBuffer { TexelCopyBufferInfo {
buffer: &image_copier.buffer, buffer: &image_copier.buffer,
layout: ImageDataLayout { layout: TexelCopyBufferLayout {
offset: 0, offset: 0,
bytes_per_row: Some( bytes_per_row: Some(
std::num::NonZero::<u32>::new(padded_bytes_per_row as u32) std::num::NonZero::<u32>::new(padded_bytes_per_row as u32)