Disable irradiance volumes on WebGL and WebGPU. (#11909)

They cause the number of texture bindings to overflow on those
platforms. Ultimately, we shouldn't unconditionally disable them, but
this fixes a crash blocking 0.13.

Closes #11885.
This commit is contained in:
Patrick Walton 2024-02-16 17:49:46 -08:00 committed by GitHub
parent 8127d44daa
commit 3058c17d6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 41 additions and 14 deletions

View file

@ -157,6 +157,11 @@ use super::LightProbeComponent;
pub const IRRADIANCE_VOLUME_SHADER_HANDLE: Handle<Shader> =
Handle::weak_from_u128(160299515939076705258408299184317675488);
/// On WebGL and WebGPU, we must disable irradiance volumes, as otherwise we can
/// overflow the number of texture bindings when deferred rendering is in use
/// (see issue #11885).
pub(crate) const IRRADIANCE_VOLUMES_ARE_USABLE: bool = cfg!(not(target_arch = "wasm32"));
/// The component that defines an irradiance volume.
///
/// See [`crate::irradiance_volume`] for detailed information.

View file

@ -8,6 +8,8 @@
light_probes,
};
#ifdef IRRADIANCE_VOLUMES_ARE_USABLE
// See:
// https://advances.realtimerendering.com/s2006/Mitchell-ShadingInValvesSourceEngine.pdf
// Slide 28, "Ambient Cube Basis"
@ -50,3 +52,5 @@ fn irradiance_volume_light(world_position: vec3<f32>, N: vec3<f32>) -> vec3<f32>
let NN = N * N;
return (rgb_x * NN.x + rgb_y * NN.y + rgb_z * NN.z) * query_result.intensity;
}
#endif // IRRADIANCE_VOLUMES_ARE_USABLE

View file

@ -50,6 +50,8 @@ use crate::render::{
};
use crate::*;
use self::irradiance_volume::IRRADIANCE_VOLUMES_ARE_USABLE;
use super::skin::SkinIndices;
#[derive(Default)]
@ -825,7 +827,7 @@ impl SpecializedMeshPipeline for MeshPipeline {
shader_defs.push("ENVIRONMENT_MAP".into());
}
if key.contains(MeshPipelineKey::IRRADIANCE_VOLUME) {
if key.contains(MeshPipelineKey::IRRADIANCE_VOLUME) && IRRADIANCE_VOLUMES_ARE_USABLE {
shader_defs.push("IRRADIANCE_VOLUME".into());
}
@ -865,6 +867,10 @@ impl SpecializedMeshPipeline for MeshPipeline {
shader_defs.push("MULTIPLE_LIGHT_PROBES_IN_ARRAY".into());
}
if IRRADIANCE_VOLUMES_ARE_USABLE {
shader_defs.push("IRRADIANCE_VOLUMES_ARE_USABLE".into());
}
let format = if key.contains(MeshPipelineKey::HDR) {
ViewTarget::TEXTURE_FORMAT_HDR
} else {

View file

@ -33,7 +33,10 @@ use environment_map::EnvironmentMapLight;
use crate::{
environment_map::{self, RenderViewEnvironmentMapBindGroupEntries},
irradiance_volume::{self, IrradianceVolume, RenderViewIrradianceVolumeBindGroupEntries},
irradiance_volume::{
self, IrradianceVolume, RenderViewIrradianceVolumeBindGroupEntries,
IRRADIANCE_VOLUMES_ARE_USABLE,
},
prepass, FogMeta, GlobalLightMeta, GpuFog, GpuLights, GpuPointLights, LightMeta,
LightProbesBuffer, LightProbesUniform, MeshPipeline, MeshPipelineKey, RenderViewLightProbes,
ScreenSpaceAmbientOcclusionTextures, ShadowSamplers, ViewClusterBindings, ViewShadowBindings,
@ -269,11 +272,14 @@ fn layout_entries(
));
// Irradiance volumes
let irradiance_volume_entries = irradiance_volume::get_bind_group_layout_entries(render_device);
entries = entries.extend_with_indices((
(16, irradiance_volume_entries[0]),
(17, irradiance_volume_entries[1]),
));
if IRRADIANCE_VOLUMES_ARE_USABLE {
let irradiance_volume_entries =
irradiance_volume::get_bind_group_layout_entries(render_device);
entries = entries.extend_with_indices((
(16, irradiance_volume_entries[0]),
(17, irradiance_volume_entries[1]),
));
}
// Tonemapping
let tonemapping_lut_entries = get_lut_bind_group_layout_entries();
@ -459,28 +465,32 @@ pub fn prepare_mesh_view_bind_groups(
}
}
let irradiance_volume_bind_group_entries =
RenderViewIrradianceVolumeBindGroupEntries::get(
let irradiance_volume_bind_group_entries = if IRRADIANCE_VOLUMES_ARE_USABLE {
Some(RenderViewIrradianceVolumeBindGroupEntries::get(
render_view_irradiance_volumes,
&images,
&fallback_image,
&render_device,
);
))
} else {
None
};
match irradiance_volume_bind_group_entries {
RenderViewIrradianceVolumeBindGroupEntries::Single {
Some(RenderViewIrradianceVolumeBindGroupEntries::Single {
texture_view,
sampler,
} => {
}) => {
entries = entries.extend_with_indices(((16, texture_view), (17, sampler)));
}
RenderViewIrradianceVolumeBindGroupEntries::Multiple {
Some(RenderViewIrradianceVolumeBindGroupEntries::Multiple {
ref texture_views,
sampler,
} => {
}) => {
entries = entries
.extend_with_indices(((16, texture_views.as_slice()), (17, sampler)));
}
None => {}
}
let lut_bindings = get_lut_bindings(&images, &tonemapping_luts, tonemapping);

View file

@ -46,12 +46,14 @@
#endif
@group(0) @binding(15) var environment_map_sampler: sampler;
#ifdef IRRADIANCE_VOLUMES_ARE_USABLE
#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY
@group(0) @binding(16) var irradiance_volumes: binding_array<texture_3d<f32>, 8u>;
#else
@group(0) @binding(16) var irradiance_volume: texture_3d<f32>;
#endif
@group(0) @binding(17) var irradiance_volume_sampler: sampler;
#endif
// NB: If you change these, make sure to update `tonemapping_shared.wgsl` too.
@group(0) @binding(18) var dt_lut_texture: texture_3d<f32>;