Skip to content

Commit ba04239

Browse files
authored
Added SSAO support on WebGPU, with R32Float fallback. (#20960)
# Objective This PR is to add SSAO support on WebGPU. ## Solution Add r16float detect and fallback to r32float if not supported. FYI the initial ssao PR [here](#7402). ## Testing - Did you test these changes? If so, how? Yes, here is the command to test the ssao example `RUSTFLAGS="--cfg getrandom_backend=\"wasm_js\"" cargo run --example ssao --target wasm32-unknown-unknown --features webgpu` and then http://localhost:1334, make sure it supports [WebGPU](https://caniuse.com/webgpu) - Are there any parts that need more testing? N/A - How can other people (reviewers) test your changes? Is there anything specific they need to know? 1. For the R32Float fallback, only the 1st commit is needed. However, I ran into some strange flickering issue on Chrome (and Chrome canary too), so I added a "detect_r16float_support" flag and a temp fix in the 2nd and 3rd commit, which are intended to be reverted when merging. 2. with the 1st commit, Safari works fine, but Chrome has the flickering, and I fixed it by partially reverting a shader change from #20313, which is very strange. It is probably caused by some shader optimization issue in Chrome, and I have no clue why, as the change is just moving the calculation to a different function. Here is the flickering on Mac Chrome(140.0.7339.133 (Official Build) (arm64)) <img width="353" height="327" alt="chrome_ssao" src="https://github.com/user-attachments/assets/0666673f-508e-4b57-a152-19327ffdb6f3" /> - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? Tested on native(mac) and WebGPU. To test on native, set "detect_r16float_support" to false to force R32Float. I couldn't make the WebGPU ssao example running on Windows 11 Chrome or Firefox, there is some error in 'taa_pipeline' . ---
1 parent 1bd6f42 commit ba04239

File tree

4 files changed

+53
-22
lines changed

4 files changed

+53
-22
lines changed

crates/bevy_pbr/src/ssao/mod.rs

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,6 @@ impl Plugin for ScreenSpaceAmbientOcclusionPlugin {
6060
return;
6161
};
6262

63-
if !render_app
64-
.world()
65-
.resource::<RenderAdapter>()
66-
.get_texture_format_features(TextureFormat::R16Float)
67-
.allowed_usages
68-
.contains(TextureUsages::STORAGE_BINDING)
69-
{
70-
warn!("ScreenSpaceAmbientOcclusionPlugin not loaded. GPU lacks support: TextureFormat::R16Float does not support TextureUsages::STORAGE_BINDING.");
71-
return;
72-
}
73-
7463
if render_app
7564
.world()
7665
.resource::<RenderDevice>()
@@ -299,6 +288,7 @@ struct SsaoPipelines {
299288
linear_clamp_sampler: Sampler,
300289

301290
shader: Handle<Shader>,
291+
depth_format: TextureFormat,
302292
}
303293

304294
impl FromWorld for SsaoPipelines {
@@ -307,6 +297,18 @@ impl FromWorld for SsaoPipelines {
307297
let render_queue = world.resource::<RenderQueue>();
308298
let pipeline_cache = world.resource::<PipelineCache>();
309299

300+
// Detect the depth format support
301+
let render_adapter = world.resource::<RenderAdapter>();
302+
let depth_format = if render_adapter
303+
.get_texture_format_features(TextureFormat::R16Float)
304+
.allowed_usages
305+
.contains(TextureUsages::STORAGE_BINDING)
306+
{
307+
TextureFormat::R16Float
308+
} else {
309+
TextureFormat::R32Float
310+
};
311+
310312
let hilbert_index_lut = render_device
311313
.create_texture_with_data(
312314
render_queue,
@@ -364,11 +366,11 @@ impl FromWorld for SsaoPipelines {
364366
ShaderStages::COMPUTE,
365367
(
366368
texture_depth_2d(),
367-
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
368-
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
369-
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
370-
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
371-
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
369+
texture_storage_2d(depth_format, StorageTextureAccess::WriteOnly),
370+
texture_storage_2d(depth_format, StorageTextureAccess::WriteOnly),
371+
texture_storage_2d(depth_format, StorageTextureAccess::WriteOnly),
372+
texture_storage_2d(depth_format, StorageTextureAccess::WriteOnly),
373+
texture_storage_2d(depth_format, StorageTextureAccess::WriteOnly),
372374
),
373375
),
374376
);
@@ -381,7 +383,7 @@ impl FromWorld for SsaoPipelines {
381383
texture_2d(TextureSampleType::Float { filterable: true }),
382384
texture_2d(TextureSampleType::Float { filterable: false }),
383385
texture_2d(TextureSampleType::Uint),
384-
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
386+
texture_storage_2d(depth_format, StorageTextureAccess::WriteOnly),
385387
texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::WriteOnly),
386388
uniform_buffer::<GlobalsUniform>(false),
387389
uniform_buffer::<f32>(false),
@@ -396,11 +398,16 @@ impl FromWorld for SsaoPipelines {
396398
(
397399
texture_2d(TextureSampleType::Float { filterable: false }),
398400
texture_2d(TextureSampleType::Uint),
399-
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
401+
texture_storage_2d(depth_format, StorageTextureAccess::WriteOnly),
400402
),
401403
),
402404
);
403405

406+
let mut shader_defs = Vec::new();
407+
if depth_format == TextureFormat::R16Float {
408+
shader_defs.push("USE_R16FLOAT".into());
409+
}
410+
404411
let preprocess_depth_pipeline =
405412
pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
406413
label: Some("ssao_preprocess_depth_pipeline".into()),
@@ -409,6 +416,7 @@ impl FromWorld for SsaoPipelines {
409416
common_bind_group_layout.clone(),
410417
],
411418
shader: load_embedded_asset!(world, "preprocess_depth.wgsl"),
419+
shader_defs: shader_defs.clone(),
412420
..default()
413421
});
414422

@@ -420,6 +428,7 @@ impl FromWorld for SsaoPipelines {
420428
common_bind_group_layout.clone(),
421429
],
422430
shader: load_embedded_asset!(world, "spatial_denoise.wgsl"),
431+
shader_defs,
423432
..default()
424433
});
425434

@@ -437,6 +446,7 @@ impl FromWorld for SsaoPipelines {
437446
linear_clamp_sampler,
438447

439448
shader: load_embedded_asset!(world, "ssao.wgsl"),
449+
depth_format,
440450
}
441451
}
442452
}
@@ -465,6 +475,10 @@ impl SpecializedComputePipeline for SsaoPipelines {
465475
shader_defs.push("TEMPORAL_JITTER".into());
466476
}
467477

478+
if self.depth_format == TextureFormat::R16Float {
479+
shader_defs.push("USE_R16FLOAT".into());
480+
}
481+
468482
ComputePipelineDescriptor {
469483
label: Some("ssao_ssao_pipeline".into()),
470484
layout: vec![
@@ -519,6 +533,7 @@ fn prepare_ssao_textures(
519533
mut commands: Commands,
520534
mut texture_cache: ResMut<TextureCache>,
521535
render_device: Res<RenderDevice>,
536+
pipelines: Res<SsaoPipelines>,
522537
views: Query<(Entity, &ExtractedCamera, &ScreenSpaceAmbientOcclusion)>,
523538
) {
524539
for (entity, camera, ssao_settings) in &views {
@@ -535,7 +550,7 @@ fn prepare_ssao_textures(
535550
mip_level_count: 5,
536551
sample_count: 1,
537552
dimension: TextureDimension::D2,
538-
format: TextureFormat::R16Float,
553+
format: pipelines.depth_format,
539554
usage: TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING,
540555
view_formats: &[],
541556
},
@@ -549,7 +564,7 @@ fn prepare_ssao_textures(
549564
mip_level_count: 1,
550565
sample_count: 1,
551566
dimension: TextureDimension::D2,
552-
format: TextureFormat::R16Float,
567+
format: pipelines.depth_format,
553568
usage: TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING,
554569
view_formats: &[],
555570
},
@@ -563,7 +578,7 @@ fn prepare_ssao_textures(
563578
mip_level_count: 1,
564579
sample_count: 1,
565580
dimension: TextureDimension::D2,
566-
format: TextureFormat::R16Float,
581+
format: pipelines.depth_format,
567582
usage: TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING,
568583
view_formats: &[],
569584
},
@@ -671,7 +686,7 @@ fn prepare_ssao_bind_groups(
671686
.create_view(&TextureViewDescriptor {
672687
label: Some("ssao_preprocessed_depth_texture_mip_view"),
673688
base_mip_level: mip_level,
674-
format: Some(TextureFormat::R16Float),
689+
format: Some(pipelines.depth_format),
675690
dimension: Some(TextureViewDimension::D2),
676691
mip_level_count: Some(1),
677692
..default()

crates/bevy_pbr/src/ssao/preprocess_depth.wgsl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@
88
#import bevy_render::view::View
99

1010
@group(0) @binding(0) var input_depth: texture_depth_2d;
11+
#ifdef USE_R16FLOAT
1112
@group(0) @binding(1) var preprocessed_depth_mip0: texture_storage_2d<r16float, write>;
1213
@group(0) @binding(2) var preprocessed_depth_mip1: texture_storage_2d<r16float, write>;
1314
@group(0) @binding(3) var preprocessed_depth_mip2: texture_storage_2d<r16float, write>;
1415
@group(0) @binding(4) var preprocessed_depth_mip3: texture_storage_2d<r16float, write>;
1516
@group(0) @binding(5) var preprocessed_depth_mip4: texture_storage_2d<r16float, write>;
17+
#else
18+
@group(0) @binding(1) var preprocessed_depth_mip0: texture_storage_2d<r32float, write>;
19+
@group(0) @binding(2) var preprocessed_depth_mip1: texture_storage_2d<r32float, write>;
20+
@group(0) @binding(3) var preprocessed_depth_mip2: texture_storage_2d<r32float, write>;
21+
@group(0) @binding(4) var preprocessed_depth_mip3: texture_storage_2d<r32float, write>;
22+
@group(0) @binding(5) var preprocessed_depth_mip4: texture_storage_2d<r32float, write>;
23+
#endif
1624
@group(1) @binding(0) var point_clamp_sampler: sampler;
1725
@group(1) @binding(1) var linear_clamp_sampler: sampler;
1826
@group(1) @binding(2) var<uniform> view: View;

crates/bevy_pbr/src/ssao/spatial_denoise.wgsl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313

1414
@group(0) @binding(0) var ambient_occlusion_noisy: texture_2d<f32>;
1515
@group(0) @binding(1) var depth_differences: texture_2d<u32>;
16+
#ifdef USE_R16FLOAT
1617
@group(0) @binding(2) var ambient_occlusion: texture_storage_2d<r16float, write>;
18+
#else
19+
@group(0) @binding(2) var ambient_occlusion: texture_storage_2d<r32float, write>;
20+
#endif
1721
@group(1) @binding(0) var point_clamp_sampler: sampler;
1822
@group(1) @binding(1) var linear_clamp_sampler: sampler;
1923
@group(1) @binding(2) var<uniform> view: View;

crates/bevy_pbr/src/ssao/ssao.wgsl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121
@group(0) @binding(0) var preprocessed_depth: texture_2d<f32>;
2222
@group(0) @binding(1) var normals: texture_2d<f32>;
2323
@group(0) @binding(2) var hilbert_index_lut: texture_2d<u32>;
24+
#ifdef USE_R16FLOAT
2425
@group(0) @binding(3) var ambient_occlusion: texture_storage_2d<r16float, write>;
26+
#else
27+
@group(0) @binding(3) var ambient_occlusion: texture_storage_2d<r32float, write>;
28+
#endif
2529
@group(0) @binding(4) var depth_differences: texture_storage_2d<r32uint, write>;
2630
@group(0) @binding(5) var<uniform> globals: Globals;
2731
@group(0) @binding(6) var<uniform> thickness: f32;

0 commit comments

Comments
 (0)