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)
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
trace_chrome = ["trace", "bevy_internal/trace_chrome"]

View File

@ -22,7 +22,7 @@ serde = { version = "1.0", features = [
], default-features = false, optional = true }
thiserror = { version = "2", default-features = false }
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 }
[features]

View File

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

View File

@ -63,9 +63,7 @@ image = { version = "0.25.2", default-features = false }
# misc
bitflags = { version = "2.3", features = ["serde"] }
bytemuck = { version = "1.5" }
wgpu-types = { version = "23", 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 }
wgpu-types = { version = "24", default-features = false }
serde = { version = "1", features = ["derive"] }
thiserror = { version = "2", default-features = false }
futures-lite = "2.0.1"

View File

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

View File

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

View File

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

View File

@ -59,6 +59,10 @@ webp = ["bevy_image/webp"]
# Enable SPIR-V 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.
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
bitflags = { version = "2.3", features = ["serde"] }
bytemuck = { version = "1.5" }
wgpu-types = { version = "23", default-features = false }
wgpu-types = { version = "24", default-features = false }
serde = { version = "1", features = ["derive"] }
hexasphere = "15.0"
thiserror = { version = "2", default-features = false }

View File

@ -6,7 +6,6 @@ use super::{
GenerateTangentsError, Indices, MeshAttributeData, MeshTrianglesError, MeshVertexAttribute,
MeshVertexAttributeId, MeshVertexBufferLayout, MeshVertexBufferLayoutRef,
MeshVertexBufferLayouts, MeshWindingInvertError, VertexAttributeValues, VertexBufferLayout,
VertexFormatSize,
};
use alloc::collections::BTreeMap;
use bevy_asset::{Asset, Handle, RenderAssetUsages};
@ -379,7 +378,7 @@ impl Mesh {
pub fn get_vertex_size(&self) -> u64 {
self.attributes
.values()
.map(|data| data.attribute.format.get_size())
.map(|data| data.attribute.format.size())
.sum()
}
@ -414,7 +413,7 @@ impl Mesh {
format: data.attribute.format,
shader_location: index as u32,
});
accumulated_offset += data.attribute.format.get_size();
accumulated_offset += data.attribute.format.size();
}
let layout = MeshVertexBufferLayout {
@ -482,7 +481,7 @@ impl Mesh {
// bundle into interleaved buffers
let mut attribute_offset = 0;
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();
for (vertex_index, attribute_bytes) in attributes_bytes
.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()
}
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.
/// Matches the [`VertexFormats`](VertexFormat).
#[derive(Clone, Debug, EnumVariantMeta)]

View File

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

View File

@ -150,7 +150,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
meshlet_view_resources.raster_cluster_rightmost_slot,
);
meshlet_view_resources.depth_pyramid.downsample_depth(
"meshlet early downsample depth",
"downsample_depth",
render_context,
meshlet_view_resources.view_size,
&meshlet_view_bind_groups.downsample_depth,
@ -202,7 +202,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
camera,
);
meshlet_view_resources.depth_pyramid.downsample_depth(
"meshlet late downsample depth",
"downsample_depth",
render_context,
meshlet_view_resources.view_size,
&meshlet_view_bind_groups.downsample_depth,
@ -270,7 +270,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
meshlet_view_resources.raster_cluster_rightmost_slot,
);
meshlet_view_resources.depth_pyramid.downsample_depth(
"meshlet early shadow downsample depth",
"downsample_depth",
render_context,
meshlet_view_resources.view_size,
&meshlet_view_bind_groups.downsample_depth,
@ -315,7 +315,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
camera,
);
meshlet_view_resources.depth_pyramid.downsample_depth(
"meshlet late shadow downsample depth",
"downsample_depth",
render_context,
meshlet_view_resources.view_size,
&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
// 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.
let early_instance_count =
atomicLoad(&indirect_parameters_metadata[instance_index].early_instance_count);
let late_instance_count =
atomicLoad(&indirect_parameters_metadata[instance_index].late_instance_count);
let early_instance_count = indirect_parameters_metadata[instance_index].early_instance_count;
let late_instance_count = indirect_parameters_metadata[instance_index].late_instance_count;
// 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
@ -135,4 +133,4 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3<u32>) {
indirect_parameters[indirect_parameters_index].vertex_count =
current_input[mesh_index].index_count;
#endif // INDEXED
}
}

View File

@ -1151,7 +1151,7 @@ impl SpecializedComputePipeline for PreprocessPipeline {
type Key = PreprocessPipelineKey;
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) {
shader_defs.push("INDIRECT".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"))
))]
dimension: Some(TextureViewDimension::Cube),
usage: None,
aspect: TextureAspect::DepthOnly,
base_mip_level: 0,
mip_level_count: None,
@ -1120,6 +1121,7 @@ pub fn prepare_lights(
dimension: Some(TextureViewDimension::D2Array),
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
dimension: Some(TextureViewDimension::D2),
usage: None,
aspect: TextureAspect::DepthOnly,
base_mip_level: 0,
mip_level_count: None,
@ -1242,6 +1244,7 @@ pub fn prepare_lights(
label: Some("point_light_shadow_map_texture_view"),
format: None,
dimension: Some(TextureViewDimension::D2),
usage: None,
aspect: TextureAspect::All,
base_mip_level: 0,
mip_level_count: None,
@ -1343,6 +1346,7 @@ pub fn prepare_lights(
label: Some("spot_light_shadow_map_texture_view"),
format: None,
dimension: Some(TextureViewDimension::D2),
usage: None,
aspect: TextureAspect::All,
base_mip_level: 0,
mip_level_count: None,
@ -1477,6 +1481,7 @@ pub fn prepare_lights(
label: Some("directional_light_shadow_map_array_texture_view"),
format: None,
dimension: Some(TextureViewDimension::D2),
usage: None,
aspect: TextureAspect::All,
base_mip_level: 0,
mip_level_count: None,

View File

@ -1733,7 +1733,7 @@ impl FromWorld for MeshPipeline {
render_queue.write_texture(
texture.as_image_copy(),
&image.data,
ImageDataLayout {
TexelCopyBufferLayout {
offset: 0,
bytes_per_row: Some(image.width() * format_size as u32),
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_linear_sampler,
light_local,
0.0,
0u,
);
#else // NO_ARRAY_TEXTURES_SUPPORT
let sampled_depth = textureSampleLevel(
@ -55,7 +55,7 @@ fn search_for_blockers_in_shadow_map_hardware(
view_bindings::directional_shadow_textures_linear_sampler,
light_local,
array_index,
0.0,
0u,
);
#endif // NO_ARRAY_TEXTURES_SUPPORT
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.
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 =
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 min_depth: f32;

View File

@ -116,7 +116,7 @@ uuid = { version = "1.13.1", default-features = false, optional = true, features
"serde",
] }
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]
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
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"]
tracing-tracy = []
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.
# 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.
wgpu = { version = "23.0.1", default-features = false, features = [
wgpu = { version = "24", default-features = false, features = [
"wgsl",
"dx12",
"metal",
"naga-ir",
"fragile-send-sync-non-atomic-wasm",
] }
naga = { version = "23", features = ["wgsl-in"] }
naga = { version = "24", features = ["wgsl-in"] }
serde = { version = "1", features = ["derive"] }
bytemuck = { version = "1.5", features = ["derive", "must_cast"] }
downcast-rs = { version = "2", default-features = false, features = ["std"] }
@ -101,7 +105,7 @@ fixedbitset = { version = "0.5" }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
# 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",
] }
@ -109,7 +113,7 @@ naga_oil = { version = "0.16", default-features = false, features = [
proptest = "1"
[target.'cfg(target_arch = "wasm32")'.dependencies]
naga_oil = "0.16"
naga_oil = "0.17"
js-sys = "0.3"
web-sys = { version = "0.3.67", features = [
'Blob',

View File

@ -975,16 +975,22 @@ impl FromWorld for GpuPreprocessingSupport {
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 ||
is_non_supported_android_device(adapter)
let feature_support = device.features().contains(
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
} else if !device
.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)
{
} else if !(feature_support && limit_support && downlevel_support) {
GpuPreprocessingMode::PreprocessingOnly
} else {
GpuPreprocessingMode::Culling

View File

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

View File

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

View File

@ -295,11 +295,17 @@ impl Plugin for RenderPlugin {
.cloned();
let settings = render_creation.clone();
let async_renderer = async move {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends,
dx12_shader_compiler: settings.dx12_shader_compiler.clone(),
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| {

View File

@ -196,7 +196,7 @@ impl RenderAsset for RenderMesh {
let mut vertex_size = 0;
for attribute_data in mesh.attributes() {
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();

View File

@ -6,7 +6,6 @@ use crate::{
renderer::RenderDevice,
texture::GpuImage,
};
use alloc::sync::Arc;
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::system::{SystemParam, SystemParamItem};
pub use bevy_render_macros::AsBindGroup;
@ -29,7 +28,7 @@ define_atomic_id!(BindGroupId);
#[derive(Clone, Debug)]
pub struct BindGroup {
id: BindGroupId,
value: Arc<WgpuWrapper<wgpu::BindGroup>>,
value: WgpuWrapper<wgpu::BindGroup>,
}
impl BindGroup {
@ -58,7 +57,7 @@ impl From<wgpu::BindGroup> for BindGroup {
fn from(value: wgpu::BindGroup) -> Self {
BindGroup {
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::renderer::WgpuWrapper;
use alloc::sync::Arc;
use core::ops::Deref;
define_atomic_id!(BindGroupLayoutId);
@ -16,7 +15,7 @@ define_atomic_id!(BindGroupLayoutId);
#[derive(Clone, Debug)]
pub struct BindGroupLayout {
id: BindGroupLayoutId,
value: Arc<WgpuWrapper<wgpu::BindGroupLayout>>,
value: WgpuWrapper<wgpu::BindGroupLayout>,
}
impl PartialEq for BindGroupLayout {
@ -50,7 +49,7 @@ impl From<wgpu::BindGroupLayout> for BindGroupLayout {
fn from(value: wgpu::BindGroupLayout) -> Self {
BindGroupLayout {
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::renderer::WgpuWrapper;
use alloc::sync::Arc;
use core::ops::{Bound, Deref, RangeBounds};
define_atomic_id!(BufferId);
@ -8,8 +7,7 @@ define_atomic_id!(BufferId);
#[derive(Clone, Debug)]
pub struct Buffer {
id: BufferId,
value: Arc<WgpuWrapper<wgpu::Buffer>>,
size: wgpu::BufferAddress,
value: WgpuWrapper<wgpu::Buffer>,
}
impl Buffer {
@ -28,7 +26,7 @@ impl Buffer {
let size = match bounds.end_bound() {
Bound::Included(&bound) => bound + 1,
Bound::Excluded(&bound) => bound,
Bound::Unbounded => self.size,
Bound::Unbounded => self.value.size(),
} - offset;
BufferSlice {
id: self.id,
@ -48,8 +46,7 @@ impl From<wgpu::Buffer> for Buffer {
fn from(value: wgpu::Buffer) -> Self {
Buffer {
id: BufferId::new(),
size: value.size(),
value: Arc::new(WgpuWrapper::new(value)),
value: WgpuWrapper::new(value),
}
}
}

View File

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

View File

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

View File

@ -1,6 +1,5 @@
use crate::define_atomic_id;
use crate::renderer::WgpuWrapper;
use alloc::sync::Arc;
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::resource::Resource;
use core::ops::Deref;
@ -23,7 +22,7 @@ define_atomic_id!(TextureId);
#[derive(Clone, Debug)]
pub struct Texture {
id: TextureId,
value: Arc<WgpuWrapper<wgpu::Texture>>,
value: WgpuWrapper<wgpu::Texture>,
}
impl Texture {
@ -43,7 +42,7 @@ impl From<wgpu::Texture> for Texture {
fn from(value: wgpu::Texture) -> Self {
Texture {
id: TextureId::new(),
value: Arc::new(WgpuWrapper::new(value)),
value: WgpuWrapper::new(value),
}
}
}
@ -63,18 +62,16 @@ define_atomic_id!(TextureViewId);
#[derive(Clone, Debug)]
pub struct TextureView {
id: TextureViewId,
value: Arc<WgpuWrapper<wgpu::TextureView>>,
value: WgpuWrapper<wgpu::TextureView>,
}
pub struct SurfaceTexture {
value: Arc<WgpuWrapper<wgpu::SurfaceTexture>>,
value: WgpuWrapper<wgpu::SurfaceTexture>,
}
impl SurfaceTexture {
pub fn try_unwrap(self) -> Option<wgpu::SurfaceTexture> {
Arc::try_unwrap(self.value)
.map(WgpuWrapper::into_inner)
.ok()
pub fn present(self) {
self.value.into_inner().present();
}
}
@ -90,7 +87,7 @@ impl From<wgpu::TextureView> for TextureView {
fn from(value: wgpu::TextureView) -> Self {
TextureView {
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 {
fn from(value: wgpu::SurfaceTexture) -> Self {
SurfaceTexture {
value: Arc::new(WgpuWrapper::new(value)),
value: WgpuWrapper::new(value),
}
}
}
@ -131,7 +128,7 @@ define_atomic_id!(SamplerId);
#[derive(Clone, Debug)]
pub struct Sampler {
id: SamplerId,
value: Arc<WgpuWrapper<wgpu::Sampler>>,
value: WgpuWrapper<wgpu::Sampler>,
}
impl Sampler {
@ -146,7 +143,7 @@ impl From<wgpu::Sampler> for Sampler {
fn from(value: wgpu::Sampler) -> Self {
Sampler {
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>();
for window in windows.values_mut() {
if let Some(wrapped_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.
// though `present()` doesn't present the frame, it schedules it to be presented
// by wgpu.
// https://docs.rs/winit/0.29.9/wasm32-unknown-unknown/winit/window/struct.Window.html#method.pre_present_notify
surface_texture.present();
}
if let Some(surface_texture) = window.swap_chain_texture.take() {
// TODO(clean): winit docs recommends calling pre_present_notify before this.
// though `present()` doesn't present the frame, it schedules it to be presented
// by wgpu.
// https://docs.rs/winit/0.29.9/wasm32-unknown-unknown/winit/window/struct.Window.html#method.pre_present_notify
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
// that report them as supported:
// <https://github.com/gfx-rs/wgpu/issues/5488>
// WGPU also currently doesn't actually support these features yet, so we should disable
// them until they are safe to enable.
features -= wgpu::Features::RAY_QUERY;
features -= wgpu::Features::RAY_TRACING_ACCELERATION_STRUCTURE;
features -= wgpu::Features::EXPERIMENTAL_RAY_QUERY;
features -= wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE;
limits = adapter.limits();
}

View File

@ -4,7 +4,6 @@ use crate::render_resource::{
RenderPipeline, Sampler, Texture,
};
use crate::WgpuWrapper;
use alloc::sync::Arc;
use bevy_ecs::resource::Resource;
use wgpu::{
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.
#[derive(Resource, Clone)]
pub struct RenderDevice {
device: Arc<WgpuWrapper<wgpu::Device>>,
device: WgpuWrapper<wgpu::Device>,
}
impl From<wgpu::Device> for RenderDevice {
fn from(device: wgpu::Device) -> Self {
Self::new(Arc::new(WgpuWrapper::new(device)))
Self::new(WgpuWrapper::new(device))
}
}
impl RenderDevice {
pub fn new(device: Arc<WgpuWrapper<wgpu::Device>>) -> Self {
pub fn new(device: WgpuWrapper<wgpu::Device>) -> Self {
Self { device }
}

View File

@ -71,10 +71,10 @@ impl Default for WgpuSettings {
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 =
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);
@ -100,13 +100,27 @@ impl Default for WgpuSettings {
limits
};
let dx12_compiler =
wgpu::util::dx12_shader_compiler_from_env().unwrap_or(Dx12Compiler::Dxc {
dxil_path: None,
dxc_path: None,
let dx12_shader_compiler =
Dx12Compiler::from_env().unwrap_or(if cfg!(feature = "statically-linked-dxc") {
Dx12Compiler::StaticDxc
} 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();
@ -119,7 +133,7 @@ impl Default for WgpuSettings {
disabled_features: None,
limits,
constrained_limits: None,
dx12_shader_compiler: dx12_compiler,
dx12_shader_compiler,
gles3_minor_version,
instance_flags,
memory_hints: MemoryHints::default(),

View File

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

View File

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

View File

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

View File

@ -58,7 +58,7 @@ cfg-if = "1.0"
raw-window-handle = "0.6"
serde = { version = "1.0", features = ["derive"], optional = true }
bytemuck = { version = "1.5", optional = true }
wgpu-types = { version = "23", optional = true }
wgpu-types = { version = "24", optional = true }
accesskit = "0.17"
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_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)|
|statically-linked-dxc|Statically linked DXC shader compiler for DirectX 12|
|symphonia-aac|AAC audio format 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)|

View File

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