Skip to content

Commit

Permalink
Use multidraw for shadows when GPU culling is in use.
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 #16670 will remove the `GpuCulling` component, making
shadows automatically use multidraw. Beware of that when testing this
patch; before #16670 lands, you'll need to manually add `GpuCulling` to
your camera in order to see any performance benefits.
  • Loading branch information
pcwalton committed Dec 6, 2024
1 parent f5de3f0 commit 846e676
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 @@ -689,6 +690,7 @@ pub fn prepare_lights(
&ExtractedView,
&ExtractedClusterConfig,
Option<&RenderLayers>,
Has<GpuCulling>,
),
With<Camera3d>,
>,
Expand Down Expand Up @@ -1097,14 +1099,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 @@ -1232,15 +1240,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 @@ -1324,14 +1332,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 @@ -1457,15 +1466,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 846e676

Please sign in to comment.