Skip to content

Commit

Permalink
Use multidraw for shadows when GPU culling is in use. (bevyengine#16692)
Browse files Browse the repository at this point in the history
This patch makes shadows use multidraw when the camera they'll be drawn
to has the `GpuCulling` component. This results in a significant
reduction in drawcalls; Bistro Exterior drops to 3 drawcalls for each
shadow cascade.

Note that PR bevyengine#16670 will remove the `GpuCulling` component, making
shadows automatically use multidraw. Beware of that when testing this
patch; before bevyengine#16670 lands, you'll need to manually add `GpuCulling` to
your camera in order to see any performance benefits.
  • Loading branch information
pcwalton authored and BD103 committed Dec 10, 2024
1 parent 3cd8f83 commit b45248b
Showing 1 changed file with 25 additions and 14 deletions.
39 changes: 25 additions & 14 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use bevy_render::{
batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport},
camera::SortedCameras,
mesh::allocator::MeshAllocator,
view::GpuCulling,
};
use bevy_render::{
diagnostic::RecordDiagnostics,
Expand Down Expand Up @@ -686,6 +687,7 @@ pub fn prepare_lights(
&ExtractedView,
&ExtractedClusterConfig,
Option<&RenderLayers>,
Has<GpuCulling>,
),
With<Camera3d>,
>,
Expand Down Expand Up @@ -1094,14 +1096,20 @@ pub fn prepare_lights(
let mut live_views = EntityHashSet::with_capacity_and_hasher(views_count, EntityHash);

// set up light data for each view
for (entity, extracted_view, clusters, maybe_layers) in sorted_cameras
for (entity, extracted_view, clusters, maybe_layers, has_gpu_culling) in sorted_cameras
.0
.iter()
.filter_map(|sorted_camera| views.get(sorted_camera.entity).ok())
{
live_views.insert(entity);
let mut view_lights = Vec::new();

let gpu_preprocessing_mode = gpu_preprocessing_support.min(if has_gpu_culling {
GpuPreprocessingMode::Culling
} else {
GpuPreprocessingMode::PreprocessingOnly
});

let is_orthographic = extracted_view.clip_from_view.w_axis.w == 1.0;
let cluster_factors_zw = calculate_cluster_factors(
clusters.near,
Expand Down Expand Up @@ -1229,15 +1237,15 @@ pub fn prepare_lights(
},
));

if matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) {
commands.entity(view_light_entity).insert(GpuCulling);
}

view_lights.push(view_light_entity);

if first {
// Subsequent views with the same light entity will reuse the same shadow map
// TODO: Implement GPU culling for shadow passes.
shadow_render_phases.insert_or_clear(
view_light_entity,
gpu_preprocessing_support.min(GpuPreprocessingMode::PreprocessingOnly),
);
shadow_render_phases.insert_or_clear(view_light_entity, gpu_preprocessing_mode);
live_shadow_mapping_lights.insert(view_light_entity);
}
}
Expand Down Expand Up @@ -1321,14 +1329,15 @@ pub fn prepare_lights(
LightEntity::Spot { light_entity },
));

if matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) {
commands.entity(view_light_entity).insert(GpuCulling);
}

view_lights.push(view_light_entity);

if first {
// Subsequent views with the same light entity will reuse the same shadow map
shadow_render_phases.insert_or_clear(
view_light_entity,
gpu_preprocessing_support.min(GpuPreprocessingMode::PreprocessingOnly),
);
shadow_render_phases.insert_or_clear(view_light_entity, gpu_preprocessing_mode);
live_shadow_mapping_lights.insert(view_light_entity);
}
}
Expand Down Expand Up @@ -1454,15 +1463,17 @@ pub fn prepare_lights(
cascade_index,
},
));

if matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) {
commands.entity(view_light_entity).insert(GpuCulling);
}

view_lights.push(view_light_entity);

// Subsequent views with the same light entity will **NOT** reuse the same shadow map
// (Because the cascades are unique to each view)
// TODO: Implement GPU culling for shadow passes.
shadow_render_phases.insert_or_clear(
view_light_entity,
gpu_preprocessing_support.min(GpuPreprocessingMode::PreprocessingOnly),
);
shadow_render_phases.insert_or_clear(view_light_entity, gpu_preprocessing_mode);
live_shadow_mapping_lights.insert(view_light_entity);
}
}
Expand Down

0 comments on commit b45248b

Please sign in to comment.