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, TONEMAPPING_LUT_TEXTURE_BINDING_INDEX,
}; };
use crate::{ use crate::{
MeshPipelineKey, ShadowFilteringMethod, ViewFogUniformOffset, ViewLightsUniformOffset, DistanceFog, MeshPipelineKey, ShadowFilteringMethod, ViewFogUniformOffset,
ViewLightsUniformOffset,
}; };
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, Handle}; use bevy_asset::{load_internal_asset, Handle};
@ -328,6 +329,10 @@ impl SpecializedRenderPipeline for DeferredLightingLayout {
shader_defs.push("HAS_PREVIOUS_MORPH".into()); 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 // Always true, since we're in the deferred lighting pipeline
shader_defs.push("DEFERRED_PREPASS".into()); shader_defs.push("DEFERRED_PREPASS".into());
@ -437,6 +442,7 @@ pub fn prepare_deferred_lighting_pipelines(
( (
Has<ScreenSpaceAmbientOcclusion>, Has<ScreenSpaceAmbientOcclusion>,
Has<ScreenSpaceReflectionsUniform>, Has<ScreenSpaceReflectionsUniform>,
Has<DistanceFog>,
), ),
( (
Has<NormalPrepass>, Has<NormalPrepass>,
@ -455,7 +461,7 @@ pub fn prepare_deferred_lighting_pipelines(
tonemapping, tonemapping,
dither, dither,
shadow_filter_method, shadow_filter_method,
(ssao, ssr), (ssao, ssr, distance_fog),
(normal_prepass, depth_prepass, motion_vector_prepass), (normal_prepass, depth_prepass, motion_vector_prepass),
has_environment_maps, has_environment_maps,
has_irradiance_volumes, has_irradiance_volumes,
@ -507,6 +513,9 @@ pub fn prepare_deferred_lighting_pipelines(
if ssr { if ssr {
view_key |= MeshPipelineKey::SCREEN_SPACE_REFLECTIONS; 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 // We don't need to check to see whether the environment map is loaded
// because [`gather_light_probes`] already checked that for us before // 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>, Option<&Camera3d>,
Has<TemporalJitter>, Has<TemporalJitter>,
Option<&Projection>, Option<&Projection>,
Has<DistanceFog>,
( (
Has<RenderViewLightProbes<EnvironmentMapLight>>, Has<RenderViewLightProbes<EnvironmentMapLight>>,
Has<RenderViewLightProbes<IrradianceVolume>>, Has<RenderViewLightProbes<IrradianceVolume>>,
@ -723,6 +724,7 @@ pub fn queue_material_meshes<M: Material>(
camera_3d, camera_3d,
temporal_jitter, temporal_jitter,
projection, projection,
distance_fog,
(has_environment_maps, has_irradiance_volumes), (has_environment_maps, has_irradiance_volumes),
has_oit, has_oit,
) in &views ) in &views
@ -814,6 +816,9 @@ pub fn queue_material_meshes<M: Material>(
if ssao { if ssao {
view_key |= MeshPipelineKey::SCREEN_SPACE_AMBIENT_OCCLUSION; view_key |= MeshPipelineKey::SCREEN_SPACE_AMBIENT_OCCLUSION;
} }
if distance_fog {
view_key |= MeshPipelineKey::DISTANCE_FOG;
}
if let Some(camera_3d) = camera_3d { if let Some(camera_3d) = camera_3d {
view_key |= screen_space_specular_transmission_pipeline_key( view_key |= screen_space_specular_transmission_pipeline_key(
camera_3d.screen_space_specular_transmission_quality, 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<&Tonemapping>,
Option<&DebandDither>, Option<&DebandDither>,
Option<&ShadowFilteringMethod>, Option<&ShadowFilteringMethod>,
Has<ScreenSpaceAmbientOcclusion>, (Has<ScreenSpaceAmbientOcclusion>, Has<DistanceFog>),
( (
Has<NormalPrepass>, Has<NormalPrepass>,
Has<DepthPrepass>, Has<DepthPrepass>,
@ -73,7 +73,7 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass<M: Material>(
tonemapping, tonemapping,
dither, dither,
shadow_filter_method, shadow_filter_method,
ssao, (ssao, distance_fog),
(normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass), (normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass),
temporal_jitter, temporal_jitter,
projection, projection,
@ -142,6 +142,9 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass<M: Material>(
if ssao { if ssao {
view_key |= MeshPipelineKey::SCREEN_SPACE_AMBIENT_OCCLUSION; view_key |= MeshPipelineKey::SCREEN_SPACE_AMBIENT_OCCLUSION;
} }
if distance_fog {
view_key |= MeshPipelineKey::DISTANCE_FOG;
}
view_key |= MeshPipelineKey::from_primitive_topology(PrimitiveTopology::TriangleList); 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_SKIN = 1 << 18;
const HAS_PREVIOUS_MORPH = 1 << 19; const HAS_PREVIOUS_MORPH = 1 << 19;
const OIT_ENABLED = 1 << 20; 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 // Bitfields
const MSAA_RESERVED_BITS = Self::MSAA_MASK_BITS << Self::MSAA_SHIFT_BITS; 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()); 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 { if self.binding_arrays_are_usable {
shader_defs.push("MULTIPLE_LIGHT_PROBES_IN_ARRAY".into()); shader_defs.push("MULTIPLE_LIGHT_PROBES_IN_ARRAY".into());
shader_defs.push("MULTIPLE_LIGHTMAPS_IN_ARRAY".into()); shader_defs.push("MULTIPLE_LIGHTMAPS_IN_ARRAY".into());

View File

@ -759,6 +759,7 @@ fn apply_pbr_lighting(
} }
#endif // PREPASS_FRAGMENT #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> { 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; 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; return input_color;
} }
} }
#endif // DISTANCE_FOG
#ifdef PREMULTIPLY_ALPHA #ifdef PREMULTIPLY_ALPHA
fn premultiply_alpha(standard_material_flags: u32, color: vec4<f32>) -> vec4<f32> { fn premultiply_alpha(standard_material_flags: u32, color: vec4<f32>) -> vec4<f32> {
@ -857,10 +859,12 @@ fn main_pass_post_lighting_processing(
) -> vec4<f32> { ) -> vec4<f32> {
var output_color = input_color; var output_color = input_color;
#ifdef DISTANCE_FOG
// 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); 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 #ifdef TONEMAP_IN_SHADER
output_color = tone_mapping(output_color, view_bindings::view.color_grading); output_color = tone_mapping(output_color, view_bindings::view.color_grading);