Only include distance fog in the PBR shader if the view uses it. (#17495)

Right now, we always include distance fog in the shader, which is
unfortunate as it's complex code and is rare. This commit changes it to
be a `#define` instead. I haven't confirmed that removing distance fog
meaningfully reduces VGPR usage, but it can't hurt.
This commit is contained in:
Patrick Walton 2025-01-22 21:24:54 -08:00 committed by GitHub
parent 17294eebb2
commit 56aa90240e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 32 additions and 6 deletions

View File

@ -6,7 +6,8 @@ use crate::{
TONEMAPPING_LUT_TEXTURE_BINDING_INDEX,
};
use crate::{
MeshPipelineKey, ShadowFilteringMethod, ViewFogUniformOffset, ViewLightsUniformOffset,
DistanceFog, MeshPipelineKey, ShadowFilteringMethod, ViewFogUniformOffset,
ViewLightsUniformOffset,
};
use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, Handle};
@ -328,6 +329,10 @@ impl SpecializedRenderPipeline for DeferredLightingLayout {
shader_defs.push("HAS_PREVIOUS_MORPH".into());
}
if key.contains(MeshPipelineKey::DISTANCE_FOG) {
shader_defs.push("DISTANCE_FOG".into());
}
// Always true, since we're in the deferred lighting pipeline
shader_defs.push("DEFERRED_PREPASS".into());
@ -437,6 +442,7 @@ pub fn prepare_deferred_lighting_pipelines(
(
Has<ScreenSpaceAmbientOcclusion>,
Has<ScreenSpaceReflectionsUniform>,
Has<DistanceFog>,
),
(
Has<NormalPrepass>,
@ -455,7 +461,7 @@ pub fn prepare_deferred_lighting_pipelines(
tonemapping,
dither,
shadow_filter_method,
(ssao, ssr),
(ssao, ssr, distance_fog),
(normal_prepass, depth_prepass, motion_vector_prepass),
has_environment_maps,
has_irradiance_volumes,
@ -507,6 +513,9 @@ pub fn prepare_deferred_lighting_pipelines(
if ssr {
view_key |= MeshPipelineKey::SCREEN_SPACE_REFLECTIONS;
}
if distance_fog {
view_key |= MeshPipelineKey::DISTANCE_FOG;
}
// We don't need to check to see whether the environment map is loaded
// because [`gather_light_probes`] already checked that for us before

View File

@ -702,6 +702,7 @@ pub fn queue_material_meshes<M: Material>(
Option<&Camera3d>,
Has<TemporalJitter>,
Option<&Projection>,
Has<DistanceFog>,
(
Has<RenderViewLightProbes<EnvironmentMapLight>>,
Has<RenderViewLightProbes<IrradianceVolume>>,
@ -723,6 +724,7 @@ pub fn queue_material_meshes<M: Material>(
camera_3d,
temporal_jitter,
projection,
distance_fog,
(has_environment_maps, has_irradiance_volumes),
has_oit,
) in &views
@ -814,6 +816,9 @@ pub fn queue_material_meshes<M: Material>(
if ssao {
view_key |= MeshPipelineKey::SCREEN_SPACE_AMBIENT_OCCLUSION;
}
if distance_fog {
view_key |= MeshPipelineKey::DISTANCE_FOG;
}
if let Some(camera_3d) = camera_3d {
view_key |= screen_space_specular_transmission_pipeline_key(
camera_3d.screen_space_specular_transmission_quality,

View File

@ -48,7 +48,7 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass<M: Material>(
Option<&Tonemapping>,
Option<&DebandDither>,
Option<&ShadowFilteringMethod>,
Has<ScreenSpaceAmbientOcclusion>,
(Has<ScreenSpaceAmbientOcclusion>, Has<DistanceFog>),
(
Has<NormalPrepass>,
Has<DepthPrepass>,
@ -73,7 +73,7 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass<M: Material>(
tonemapping,
dither,
shadow_filter_method,
ssao,
(ssao, distance_fog),
(normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass),
temporal_jitter,
projection,
@ -142,6 +142,9 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass<M: Material>(
if ssao {
view_key |= MeshPipelineKey::SCREEN_SPACE_AMBIENT_OCCLUSION;
}
if distance_fog {
view_key |= MeshPipelineKey::DISTANCE_FOG;
}
view_key |= MeshPipelineKey::from_primitive_topology(PrimitiveTopology::TriangleList);

View File

@ -1809,7 +1809,8 @@ bitflags::bitflags! {
const HAS_PREVIOUS_SKIN = 1 << 18;
const HAS_PREVIOUS_MORPH = 1 << 19;
const OIT_ENABLED = 1 << 20;
const LAST_FLAG = Self::OIT_ENABLED.bits();
const DISTANCE_FOG = 1 << 21;
const LAST_FLAG = Self::DISTANCE_FOG.bits();
// Bitfields
const MSAA_RESERVED_BITS = Self::MSAA_MASK_BITS << Self::MSAA_SHIFT_BITS;
@ -2268,6 +2269,10 @@ impl SpecializedMeshPipeline for MeshPipeline {
shader_defs.push("VISIBILITY_RANGE_DITHER".into());
}
if key.contains(MeshPipelineKey::DISTANCE_FOG) {
shader_defs.push("DISTANCE_FOG".into());
}
if self.binding_arrays_are_usable {
shader_defs.push("MULTIPLE_LIGHT_PROBES_IN_ARRAY".into());
shader_defs.push("MULTIPLE_LIGHTMAPS_IN_ARRAY".into());

View File

@ -759,6 +759,7 @@ fn apply_pbr_lighting(
}
#endif // PREPASS_FRAGMENT
#ifdef DISTANCE_FOG
fn apply_fog(fog_params: mesh_view_types::Fog, input_color: vec4<f32>, fragment_world_position: vec3<f32>, view_world_position: vec3<f32>) -> vec4<f32> {
let view_to_world = fragment_world_position.xyz - view_world_position.xyz;
@ -796,6 +797,7 @@ fn apply_fog(fog_params: mesh_view_types::Fog, input_color: vec4<f32>, fragment_
return input_color;
}
}
#endif // DISTANCE_FOG
#ifdef PREMULTIPLY_ALPHA
fn premultiply_alpha(standard_material_flags: u32, color: vec4<f32>) -> vec4<f32> {
@ -857,10 +859,12 @@ fn main_pass_post_lighting_processing(
) -> vec4<f32> {
var output_color = input_color;
#ifdef DISTANCE_FOG
// fog
if (view_bindings::fog.mode != mesh_view_types::FOG_MODE_OFF && (pbr_input.material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_FOG_ENABLED_BIT) != 0u) {
if ((pbr_input.material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_FOG_ENABLED_BIT) != 0u) {
output_color = apply_fog(view_bindings::fog, output_color, pbr_input.world_position.xyz, view_bindings::view.world_position.xyz);
}
#endif // DISTANCE_FOG
#ifdef TONEMAP_IN_SHADER
output_color = tone_mapping(output_color, view_bindings::view.color_grading);