Place percentage-closer soft shadows behind a feature gate to save on samplers. (#16068)

The two additional linear texture samplers that PCSS added caused us to
blow past the limit on Apple Silicon macOS and WebGL. To fix the issue,
this commit adds a `--feature pbr_pcss` feature gate that disables PCSS
if not present.

Closes #15345.
Closes #15525.
Closes #15821.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
This commit is contained in:
Patrick Walton 2024-10-24 14:16:00 -07:00 committed by GitHub
parent 897404ee1e
commit c6a66a7e96
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 37 additions and 1 deletions

View file

@ -402,6 +402,9 @@ pbr_multi_layer_material_textures = [
# Enable support for anisotropy texture in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs # Enable support for anisotropy texture in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs
pbr_anisotropy_texture = ["bevy_internal/pbr_anisotropy_texture"] pbr_anisotropy_texture = ["bevy_internal/pbr_anisotropy_texture"]
# Enable support for PCSS, at the risk of blowing past the global, per-shader sampler limit on older/lower-end GPUs
pbr_pcss = ["bevy_internal/pbr_pcss"]
# Enable some limitations to be able to use WebGL2. Please refer to the [WebGL2 and WebGPU](https://github.com/bevyengine/bevy/tree/latest/examples#webgl2-and-webgpu) section of the examples README for more information on how to run Wasm builds with WebGPU. # Enable some limitations to be able to use WebGL2. Please refer to the [WebGL2 and WebGPU](https://github.com/bevyengine/bevy/tree/latest/examples#webgl2-and-webgpu) section of the examples README for more information on how to run Wasm builds with WebGPU.
webgl2 = ["bevy_internal/webgl"] webgl2 = ["bevy_internal/webgl"]
@ -3786,6 +3789,7 @@ wasm = true
name = "pcss" name = "pcss"
path = "examples/3d/pcss.rs" path = "examples/3d/pcss.rs"
doc-scrape-examples = true doc-scrape-examples = true
required-features = ["pbr_pcss"]
[package.metadata.example.pcss] [package.metadata.example.pcss]
name = "Percentage-closer soft shadows" name = "Percentage-closer soft shadows"

View file

@ -134,6 +134,9 @@ pbr_anisotropy_texture = [
"bevy_gltf?/pbr_anisotropy_texture", "bevy_gltf?/pbr_anisotropy_texture",
] ]
# Percentage-closer soft shadows
pbr_pcss = ["bevy_pbr?/pbr_pcss"]
# Optimise for WebGL2 # Optimise for WebGL2
webgl = [ webgl = [
"bevy_core_pipeline?/webgl", "bevy_core_pipeline?/webgl",

View file

@ -14,6 +14,7 @@ webgpu = []
pbr_transmission_textures = [] pbr_transmission_textures = []
pbr_multi_layer_material_textures = [] pbr_multi_layer_material_textures = []
pbr_anisotropy_texture = [] pbr_anisotropy_texture = []
pbr_pcss = []
shader_format_glsl = ["bevy_render/shader_format_glsl"] shader_format_glsl = ["bevy_render/shader_format_glsl"]
trace = ["bevy_render/trace"] trace = ["bevy_render/trace"]
ios_simulator = ["bevy_render/ios_simulator"] ios_simulator = ["bevy_render/ios_simulator"]

View file

@ -147,8 +147,10 @@ pub const MAX_CASCADES_PER_LIGHT: usize = 1;
#[derive(Resource, Clone)] #[derive(Resource, Clone)]
pub struct ShadowSamplers { pub struct ShadowSamplers {
pub point_light_comparison_sampler: Sampler, pub point_light_comparison_sampler: Sampler,
#[cfg(feature = "pbr_pcss")]
pub point_light_linear_sampler: Sampler, pub point_light_linear_sampler: Sampler,
pub directional_light_comparison_sampler: Sampler, pub directional_light_comparison_sampler: Sampler,
#[cfg(feature = "pbr_pcss")]
pub directional_light_linear_sampler: Sampler, pub directional_light_linear_sampler: Sampler,
} }
@ -172,6 +174,7 @@ impl FromWorld for ShadowSamplers {
compare: Some(CompareFunction::GreaterEqual), compare: Some(CompareFunction::GreaterEqual),
..base_sampler_descriptor ..base_sampler_descriptor
}), }),
#[cfg(feature = "pbr_pcss")]
point_light_linear_sampler: render_device.create_sampler(&base_sampler_descriptor), point_light_linear_sampler: render_device.create_sampler(&base_sampler_descriptor),
directional_light_comparison_sampler: render_device.create_sampler( directional_light_comparison_sampler: render_device.create_sampler(
&SamplerDescriptor { &SamplerDescriptor {
@ -179,6 +182,7 @@ impl FromWorld for ShadowSamplers {
..base_sampler_descriptor ..base_sampler_descriptor
}, },
), ),
#[cfg(feature = "pbr_pcss")]
directional_light_linear_sampler: render_device directional_light_linear_sampler: render_device
.create_sampler(&base_sampler_descriptor), .create_sampler(&base_sampler_descriptor),
} }

View file

@ -1858,6 +1858,9 @@ impl SpecializedMeshPipeline for MeshPipeline {
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
shader_defs.push("WEBGL2".into()); shader_defs.push("WEBGL2".into());
#[cfg(feature = "pbr_pcss")]
shader_defs.push("PCSS_SAMPLERS_AVAILABLE".into());
if key.contains(MeshPipelineKey::TONEMAP_IN_SHADER) { if key.contains(MeshPipelineKey::TONEMAP_IN_SHADER) {
shader_defs.push("TONEMAP_IN_SHADER".into()); shader_defs.push("TONEMAP_IN_SHADER".into());
shader_defs.push(ShaderDefVal::UInt( shader_defs.push(ShaderDefVal::UInt(

View file

@ -227,6 +227,7 @@ fn layout_entries(
// Point Shadow Texture Array Comparison Sampler // Point Shadow Texture Array Comparison Sampler
(3, sampler(SamplerBindingType::Comparison)), (3, sampler(SamplerBindingType::Comparison)),
// Point Shadow Texture Array Linear Sampler // Point Shadow Texture Array Linear Sampler
#[cfg(feature = "pbr_pcss")]
(4, sampler(SamplerBindingType::Filtering)), (4, sampler(SamplerBindingType::Filtering)),
// Directional Shadow Texture Array // Directional Shadow Texture Array
( (
@ -243,6 +244,7 @@ fn layout_entries(
// Directional Shadow Texture Array Comparison Sampler // Directional Shadow Texture Array Comparison Sampler
(6, sampler(SamplerBindingType::Comparison)), (6, sampler(SamplerBindingType::Comparison)),
// Directional Shadow Texture Array Linear Sampler // Directional Shadow Texture Array Linear Sampler
#[cfg(feature = "pbr_pcss")]
(7, sampler(SamplerBindingType::Filtering)), (7, sampler(SamplerBindingType::Filtering)),
// PointLights // PointLights
( (
@ -574,9 +576,11 @@ pub fn prepare_mesh_view_bind_groups(
(1, light_binding.clone()), (1, light_binding.clone()),
(2, &shadow_bindings.point_light_depth_texture_view), (2, &shadow_bindings.point_light_depth_texture_view),
(3, &shadow_samplers.point_light_comparison_sampler), (3, &shadow_samplers.point_light_comparison_sampler),
#[cfg(feature = "pbr_pcss")]
(4, &shadow_samplers.point_light_linear_sampler), (4, &shadow_samplers.point_light_linear_sampler),
(5, &shadow_bindings.directional_light_depth_texture_view), (5, &shadow_bindings.directional_light_depth_texture_view),
(6, &shadow_samplers.directional_light_comparison_sampler), (6, &shadow_samplers.directional_light_comparison_sampler),
#[cfg(feature = "pbr_pcss")]
(7, &shadow_samplers.directional_light_linear_sampler), (7, &shadow_samplers.directional_light_linear_sampler),
(8, clusterable_objects_binding.clone()), (8, clusterable_objects_binding.clone()),
( (

View file

@ -14,14 +14,18 @@
@group(0) @binding(2) var point_shadow_textures: texture_depth_cube_array; @group(0) @binding(2) var point_shadow_textures: texture_depth_cube_array;
#endif #endif
@group(0) @binding(3) var point_shadow_textures_comparison_sampler: sampler_comparison; @group(0) @binding(3) var point_shadow_textures_comparison_sampler: sampler_comparison;
#ifdef PCSS_SAMPLERS_AVAILABLE
@group(0) @binding(4) var point_shadow_textures_linear_sampler: sampler; @group(0) @binding(4) var point_shadow_textures_linear_sampler: sampler;
#endif // PCSS_SAMPLERS_AVAILABLE
#ifdef NO_ARRAY_TEXTURES_SUPPORT #ifdef NO_ARRAY_TEXTURES_SUPPORT
@group(0) @binding(5) var directional_shadow_textures: texture_depth_2d; @group(0) @binding(5) var directional_shadow_textures: texture_depth_2d;
#else #else
@group(0) @binding(5) var directional_shadow_textures: texture_depth_2d_array; @group(0) @binding(5) var directional_shadow_textures: texture_depth_2d_array;
#endif #endif
@group(0) @binding(6) var directional_shadow_textures_comparison_sampler: sampler_comparison; @group(0) @binding(6) var directional_shadow_textures_comparison_sampler: sampler_comparison;
#ifdef PCSS_SAMPLERS_AVAILABLE
@group(0) @binding(7) var directional_shadow_textures_linear_sampler: sampler; @group(0) @binding(7) var directional_shadow_textures_linear_sampler: sampler;
#endif // PCSS_SAMPLERS_AVAILABLE
#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3 #if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3
@group(0) @binding(8) var<storage> clusterable_objects: types::ClusterableObjects; @group(0) @binding(8) var<storage> clusterable_objects: types::ClusterableObjects;

View file

@ -40,6 +40,8 @@ fn search_for_blockers_in_shadow_map_hardware(
return vec2(0.0); return vec2(0.0);
#else // WEBGL2 #else // WEBGL2
#ifdef PCSS_SAMPLERS_AVAILABLE
#ifdef NO_ARRAY_TEXTURES_SUPPORT #ifdef NO_ARRAY_TEXTURES_SUPPORT
let sampled_depth = textureSampleLevel( let sampled_depth = textureSampleLevel(
view_bindings::directional_shadow_textures, view_bindings::directional_shadow_textures,
@ -58,6 +60,10 @@ fn search_for_blockers_in_shadow_map_hardware(
#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);
#else // PCSS_SAMPLERS_AVAILABLE
return vec2(0.0);
#endif // PCSS_SAMPLERS_AVAILABLE
#endif // WEBGL2 #endif // WEBGL2
} }
@ -340,6 +346,8 @@ fn search_for_blockers_in_shadow_cubemap_hardware(
return vec2(0.0); return vec2(0.0);
#else // WEBGL2 #else // WEBGL2
#ifdef PCSS_SAMPLERS_AVAILABLE
#ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT #ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT
let sampled_depth = textureSample( let sampled_depth = textureSample(
view_bindings::point_shadow_textures, view_bindings::point_shadow_textures,
@ -357,6 +365,10 @@ fn search_for_blockers_in_shadow_cubemap_hardware(
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);
#else // PCSS_SAMPLERS_AVAILABLE
return vec2(0.0);
#endif // PCSS_SAMPLERS_AVAILABLE
#endif // WEBGL2 #endif // WEBGL2
} }

View file

@ -83,6 +83,7 @@ The default feature set enables most of the expected features of a game engine,
|mp3|MP3 audio format support| |mp3|MP3 audio format support|
|pbr_anisotropy_texture|Enable support for anisotropy texture in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| |pbr_anisotropy_texture|Enable support for anisotropy texture in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs|
|pbr_multi_layer_material_textures|Enable support for multi-layer material textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| |pbr_multi_layer_material_textures|Enable support for multi-layer material textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs|
|pbr_pcss|Enable support for PCSS, at the risk of blowing past the global, per-shader sampler limit on older/lower-end GPUs|
|pbr_transmission_textures|Enable support for transmission-related textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs| |pbr_transmission_textures|Enable support for transmission-related textures in the `StandardMaterial`, at the risk of blowing past the global, per-shader texture limit on older/lower-end GPUs|
|pnm|PNM image format support, includes pam, pbm, pgm and ppm| |pnm|PNM image format support, includes pam, pbm, pgm and ppm|
|qoi|QOI image format support| |qoi|QOI image format support|

View file

@ -32,7 +32,7 @@ fn setup(
MeshMaterial3d(materials.add(ExtendedMaterial { MeshMaterial3d(materials.add(ExtendedMaterial {
base: StandardMaterial { base: StandardMaterial {
base_color: RED.into(), base_color: RED.into(),
// can be used in forward or deferred mode. // can be used in forward or deferred mode
opaque_render_method: OpaqueRendererMethod::Auto, opaque_render_method: OpaqueRendererMethod::Auto,
// in deferred mode, only the PbrInput can be modified (uvs, color and other material properties), // in deferred mode, only the PbrInput can be modified (uvs, color and other material properties),
// in forward mode, the output can also be modified after lighting is applied. // in forward mode, the output can also be modified after lighting is applied.