Skip to content

Commit

Permalink
Wgpu 0.20 (#13186)
Browse files Browse the repository at this point in the history
Currently blocked on gfx-rs/wgpu#5774

# Objective

Update to wgpu 0.20

## Solution

Update to wgpu 0.20 and naga_oil 0.14.

## Testing

Tested a few different examples on linux (vulkan, webgl2, webgpu) and
windows (dx12 + vulkan) and they worked.

---

## Changelog

- Updated to wgpu 0.20. Note that we don't currently support wgpu's new
pipeline overridable constants, as they don't work on web currently and
need some more changes to naga_oil (and are somewhat redundant with
naga_oil's shader defs). See wgpu's changelog for more
https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v0200-2024-04-28

## Migration Guide

TODO

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
  • Loading branch information
3 people authored Jun 14, 2024
1 parent 004ba58 commit 2825ac8
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 70 deletions.
2 changes: 1 addition & 1 deletion crates/bevy_color/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", features = [
bytemuck = { version = "1", features = ["derive"] }
serde = { version = "1.0", features = ["derive"], optional = true }
thiserror = "1.0"
wgpu-types = { version = "0.19", default-features = false, optional = true }
wgpu-types = { version = "0.20", default-features = false, optional = true }
encase = { version = "0.8", default-features = false }

[features]
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_render/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ 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 = "0.19.3", default-features = false, features = [
wgpu = { version = "0.20", default-features = false, features = [
"wgsl",
"dx12",
"metal",
"naga",
"naga-ir",
"fragile-send-sync-non-atomic-wasm",
] }
naga = { version = "0.19", features = ["wgsl-in"] }
naga = { version = "0.20", features = ["wgsl-in"] }
serde = { version = "1", features = ["derive"] }
bitflags = { version = "2.3", features = ["serde"] }
bytemuck = { version = "1.5", features = ["derive", "must_cast"] }
Expand All @@ -104,12 +104,12 @@ smallvec = { version = "1.11", features = ["const_new"] }

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

[target.'cfg(target_arch = "wasm32")'.dependencies]
naga_oil = "0.13"
naga_oil = "0.14"
js-sys = "0.3"
web-sys = { version = "0.3.67", features = [
'Blob',
Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_render/src/diagnostic/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ struct FrameData {
timestamps_query_set: Option<QuerySet>,
num_timestamps: u32,
supports_timestamps_inside_passes: bool,
supports_timestamps_inside_encoders: bool,
pipeline_statistics_query_set: Option<QuerySet>,
num_pipeline_statistics: u32,
buffer_size: u64,
Expand Down Expand Up @@ -225,6 +226,8 @@ impl FrameData {
num_timestamps: 0,
supports_timestamps_inside_passes: features
.contains(Features::TIMESTAMP_QUERY_INSIDE_PASSES),
supports_timestamps_inside_encoders: features
.contains(Features::TIMESTAMP_QUERY_INSIDE_ENCODERS),
pipeline_statistics_query_set,
num_pipeline_statistics: 0,
buffer_size,
Expand Down Expand Up @@ -252,6 +255,11 @@ impl FrameData {
encoder: &mut impl WriteTimestamp,
is_inside_pass: bool,
) -> Option<u32> {
// `encoder.write_timestamp` is unsupported on WebGPU.
if !self.supports_timestamps_inside_encoders {
return None;
}

if is_inside_pass && !self.supports_timestamps_inside_passes {
return None;
}
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_render/src/mesh/mesh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,7 @@ impl VertexFormatSize for VertexFormat {
VertexFormat::Unorm8x4 => 4,
VertexFormat::Snorm8x2 => 2,
VertexFormat::Snorm8x4 => 4,
VertexFormat::Unorm10_10_10_2 => 4,
VertexFormat::Uint16x2 => 2 * 2,
VertexFormat::Uint16x4 => 2 * 4,
VertexFormat::Sint16x2 => 2 * 2,
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_render/src/render_resource/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ pub use wgpu::{
Extent3d, Face, Features as WgpuFeatures, FilterMode, FragmentState as RawFragmentState,
FrontFace, ImageCopyBuffer, ImageCopyBufferBase, ImageCopyTexture, ImageCopyTextureBase,
ImageDataLayout, ImageSubresourceRange, IndexFormat, Limits as WgpuLimits, LoadOp, Maintain,
MapMode, MultisampleState, Operations, Origin3d, PipelineLayout, PipelineLayoutDescriptor,
PolygonMode, PrimitiveState, PrimitiveTopology, PushConstantRange, RenderPassColorAttachment,
RenderPassDepthStencilAttachment, RenderPassDescriptor,
MapMode, MultisampleState, Operations, Origin3d, PipelineCompilationOptions, PipelineLayout,
PipelineLayoutDescriptor, PolygonMode, PrimitiveState, PrimitiveTopology, PushConstantRange,
RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor,
RenderPipelineDescriptor as RawRenderPipelineDescriptor, SamplerBindingType, SamplerDescriptor,
ShaderModule, ShaderModuleDescriptor, ShaderSource, ShaderStages, StencilFaceState,
StencilOperation, StencilState, StorageTextureAccess, StoreOp, TextureAspect,
Expand Down
172 changes: 110 additions & 62 deletions crates/bevy_render/src/render_resource/pipeline_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ use std::{
use thiserror::Error;
#[cfg(feature = "shader_format_spirv")]
use wgpu::util::make_spirv;
use wgpu::{DownlevelFlags, Features, VertexBufferLayout as RawVertexBufferLayout};
use wgpu::{
DownlevelFlags, Features, PipelineCompilationOptions,
VertexBufferLayout as RawVertexBufferLayout,
};

use crate::render_resource::resource_macros::*;

Expand Down Expand Up @@ -170,73 +173,17 @@ impl ShaderDefVal {

impl ShaderCache {
fn new(render_device: &RenderDevice, render_adapter: &RenderAdapter) -> Self {
const CAPABILITIES: &[(Features, Capabilities)] = &[
(Features::PUSH_CONSTANTS, Capabilities::PUSH_CONSTANT),
(Features::SHADER_F64, Capabilities::FLOAT64),
(
Features::SHADER_PRIMITIVE_INDEX,
Capabilities::PRIMITIVE_INDEX,
),
(
Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
Capabilities::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
),
(
Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
Capabilities::SAMPLER_NON_UNIFORM_INDEXING,
),
(
Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
Capabilities::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
),
(
Features::TEXTURE_FORMAT_16BIT_NORM,
Capabilities::STORAGE_TEXTURE_16BIT_NORM_FORMATS,
),
(Features::MULTIVIEW, Capabilities::MULTIVIEW),
(
Features::SHADER_EARLY_DEPTH_TEST,
Capabilities::EARLY_DEPTH_TEST,
),
];
let features = render_device.features();
let mut capabilities = Capabilities::empty();
for (feature, capability) in CAPABILITIES {
if features.contains(*feature) {
capabilities |= *capability;
}
}

const DOWNLEVEL_FLAGS_CAPABILITIES: &[(DownlevelFlags, Capabilities)] = &[
(
DownlevelFlags::CUBE_ARRAY_TEXTURES,
Capabilities::CUBE_ARRAY_TEXTURES,
),
(
DownlevelFlags::MULTISAMPLED_SHADING,
Capabilities::MULTISAMPLED_SHADING,
),
(
DownlevelFlags::CUBE_ARRAY_TEXTURES,
Capabilities::CUBE_ARRAY_TEXTURES,
),
];
for (downlevel_flag, capability) in DOWNLEVEL_FLAGS_CAPABILITIES {
if render_adapter
.get_downlevel_capabilities()
.flags
.contains(*downlevel_flag)
{
capabilities |= *capability;
}
}
let (capabilities, subgroup_stages) = get_capabilities(
render_device.features(),
render_adapter.get_downlevel_capabilities().flags,
);

#[cfg(debug_assertions)]
let composer = naga_oil::compose::Composer::default();
#[cfg(not(debug_assertions))]
let composer = naga_oil::compose::Composer::non_validating();

let composer = composer.with_capabilities(capabilities);
let composer = composer.with_capabilities(capabilities, subgroup_stages);

Self {
composer,
Expand Down Expand Up @@ -791,6 +738,12 @@ impl PipelineCache {
)
});

// TODO: Expose this somehow
let compilation_options = PipelineCompilationOptions {
constants: &std::collections::HashMap::new(),
zero_initialize_workgroup_memory: false,
};

let descriptor = RawRenderPipelineDescriptor {
multiview: None,
depth_stencil: descriptor.depth_stencil.clone(),
Expand All @@ -802,13 +755,17 @@ impl PipelineCache {
buffers: &vertex_buffer_layouts,
entry_point: descriptor.vertex.entry_point.deref(),
module: &vertex_module,
// TODO: Should this be the same as the fragment compilation options?
compilation_options: compilation_options.clone(),
},
fragment: fragment_data
.as_ref()
.map(|(module, entry_point, targets)| RawFragmentState {
entry_point,
module,
targets,
// TODO: Should this be the same as the vertex compilation options?
compilation_options,
}),
};

Expand Down Expand Up @@ -861,6 +818,11 @@ impl PipelineCache {
layout: layout.as_deref(),
module: &compute_module,
entry_point: &descriptor.entry_point,
// TODO: Expose this somehow
compilation_options: PipelineCompilationOptions {
constants: &std::collections::HashMap::new(),
zero_initialize_workgroup_memory: false,
},
};

Ok(Pipeline::ComputePipeline(
Expand Down Expand Up @@ -1027,3 +989,89 @@ pub enum PipelineCacheError {
#[error("Could not create shader module: {0}")]
CreateShaderModule(String),
}

// TODO: This needs to be kept up to date with the capabilities in the `create_validator` function in wgpu-core
// https://github.com/gfx-rs/wgpu/blob/trunk/wgpu-core/src/device/mod.rs#L449
// We use a modified version of the `create_validator` function because `naga_oil`'s composer stores the capabilities
// and subgroup shader stages instead of a `Validator`.
// We also can't use that function because `wgpu-core` isn't included in WebGPU builds.
/// Get the device capabilities and subgroup support for use in `naga_oil`.
fn get_capabilities(
features: Features,
downlevel: DownlevelFlags,
) -> (Capabilities, naga::valid::ShaderStages) {
let mut capabilities = Capabilities::empty();
capabilities.set(
Capabilities::PUSH_CONSTANT,
features.contains(Features::PUSH_CONSTANTS),
);
capabilities.set(
Capabilities::FLOAT64,
features.contains(Features::SHADER_F64),
);
capabilities.set(
Capabilities::PRIMITIVE_INDEX,
features.contains(Features::SHADER_PRIMITIVE_INDEX),
);
capabilities.set(
Capabilities::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
features.contains(Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING),
);
capabilities.set(
Capabilities::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
features.contains(Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING),
);
// TODO: This needs a proper wgpu feature
capabilities.set(
Capabilities::SAMPLER_NON_UNIFORM_INDEXING,
features.contains(Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING),
);
capabilities.set(
Capabilities::STORAGE_TEXTURE_16BIT_NORM_FORMATS,
features.contains(Features::TEXTURE_FORMAT_16BIT_NORM),
);
capabilities.set(
Capabilities::MULTIVIEW,
features.contains(Features::MULTIVIEW),
);
capabilities.set(
Capabilities::EARLY_DEPTH_TEST,
features.contains(Features::SHADER_EARLY_DEPTH_TEST),
);
capabilities.set(
Capabilities::SHADER_INT64,
features.contains(Features::SHADER_INT64),
);
capabilities.set(
Capabilities::MULTISAMPLED_SHADING,
downlevel.contains(DownlevelFlags::MULTISAMPLED_SHADING),
);
capabilities.set(
Capabilities::DUAL_SOURCE_BLENDING,
features.contains(Features::DUAL_SOURCE_BLENDING),
);
capabilities.set(
Capabilities::CUBE_ARRAY_TEXTURES,
downlevel.contains(DownlevelFlags::CUBE_ARRAY_TEXTURES),
);
capabilities.set(
Capabilities::SUBGROUP,
features.intersects(Features::SUBGROUP | Features::SUBGROUP_VERTEX),
);
capabilities.set(
Capabilities::SUBGROUP_BARRIER,
features.intersects(Features::SUBGROUP_BARRIER),
);

let mut subgroup_stages = naga::valid::ShaderStages::empty();
subgroup_stages.set(
naga::valid::ShaderStages::COMPUTE | naga::valid::ShaderStages::FRAGMENT,
features.contains(Features::SUBGROUP),
);
subgroup_stages.set(
naga::valid::ShaderStages::VERTEX,
features.contains(Features::SUBGROUP_VERTEX),
);

(capabilities, subgroup_stages)
}
12 changes: 12 additions & 0 deletions crates/bevy_render/src/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,18 @@ pub async fn initialize_renderer(
max_non_sampler_bindings: limits
.max_non_sampler_bindings
.min(constrained_limits.max_non_sampler_bindings),
max_color_attachments: limits
.max_color_attachments
.min(constrained_limits.max_color_attachments),
max_color_attachment_bytes_per_sample: limits
.max_color_attachment_bytes_per_sample
.min(constrained_limits.max_color_attachment_bytes_per_sample),
min_subgroup_size: limits
.min_subgroup_size
.max(constrained_limits.min_subgroup_size),
max_subgroup_size: limits
.max_subgroup_size
.min(constrained_limits.max_subgroup_size),
};
}

Expand Down

0 comments on commit 2825ac8

Please sign in to comment.