Skip to content

Commit b45248b

Browse files
pcwaltonBD103
authored andcommitted
Use multidraw for shadows when GPU culling is in use. (#16692)
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.
1 parent 3cd8f83 commit b45248b

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

crates/bevy_pbr/src/render/light.rs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use bevy_render::{
1515
batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport},
1616
camera::SortedCameras,
1717
mesh::allocator::MeshAllocator,
18+
view::GpuCulling,
1819
};
1920
use bevy_render::{
2021
diagnostic::RecordDiagnostics,
@@ -686,6 +687,7 @@ pub fn prepare_lights(
686687
&ExtractedView,
687688
&ExtractedClusterConfig,
688689
Option<&RenderLayers>,
690+
Has<GpuCulling>,
689691
),
690692
With<Camera3d>,
691693
>,
@@ -1094,14 +1096,20 @@ pub fn prepare_lights(
10941096
let mut live_views = EntityHashSet::with_capacity_and_hasher(views_count, EntityHash);
10951097

10961098
// set up light data for each view
1097-
for (entity, extracted_view, clusters, maybe_layers) in sorted_cameras
1099+
for (entity, extracted_view, clusters, maybe_layers, has_gpu_culling) in sorted_cameras
10981100
.0
10991101
.iter()
11001102
.filter_map(|sorted_camera| views.get(sorted_camera.entity).ok())
11011103
{
11021104
live_views.insert(entity);
11031105
let mut view_lights = Vec::new();
11041106

1107+
let gpu_preprocessing_mode = gpu_preprocessing_support.min(if has_gpu_culling {
1108+
GpuPreprocessingMode::Culling
1109+
} else {
1110+
GpuPreprocessingMode::PreprocessingOnly
1111+
});
1112+
11051113
let is_orthographic = extracted_view.clip_from_view.w_axis.w == 1.0;
11061114
let cluster_factors_zw = calculate_cluster_factors(
11071115
clusters.near,
@@ -1229,15 +1237,15 @@ pub fn prepare_lights(
12291237
},
12301238
));
12311239

1240+
if matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) {
1241+
commands.entity(view_light_entity).insert(GpuCulling);
1242+
}
1243+
12321244
view_lights.push(view_light_entity);
12331245

12341246
if first {
12351247
// Subsequent views with the same light entity will reuse the same shadow map
1236-
// TODO: Implement GPU culling for shadow passes.
1237-
shadow_render_phases.insert_or_clear(
1238-
view_light_entity,
1239-
gpu_preprocessing_support.min(GpuPreprocessingMode::PreprocessingOnly),
1240-
);
1248+
shadow_render_phases.insert_or_clear(view_light_entity, gpu_preprocessing_mode);
12411249
live_shadow_mapping_lights.insert(view_light_entity);
12421250
}
12431251
}
@@ -1321,14 +1329,15 @@ pub fn prepare_lights(
13211329
LightEntity::Spot { light_entity },
13221330
));
13231331

1332+
if matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) {
1333+
commands.entity(view_light_entity).insert(GpuCulling);
1334+
}
1335+
13241336
view_lights.push(view_light_entity);
13251337

13261338
if first {
13271339
// Subsequent views with the same light entity will reuse the same shadow map
1328-
shadow_render_phases.insert_or_clear(
1329-
view_light_entity,
1330-
gpu_preprocessing_support.min(GpuPreprocessingMode::PreprocessingOnly),
1331-
);
1340+
shadow_render_phases.insert_or_clear(view_light_entity, gpu_preprocessing_mode);
13321341
live_shadow_mapping_lights.insert(view_light_entity);
13331342
}
13341343
}
@@ -1454,15 +1463,17 @@ pub fn prepare_lights(
14541463
cascade_index,
14551464
},
14561465
));
1466+
1467+
if matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) {
1468+
commands.entity(view_light_entity).insert(GpuCulling);
1469+
}
1470+
14571471
view_lights.push(view_light_entity);
14581472

14591473
// Subsequent views with the same light entity will **NOT** reuse the same shadow map
14601474
// (Because the cascades are unique to each view)
14611475
// TODO: Implement GPU culling for shadow passes.
1462-
shadow_render_phases.insert_or_clear(
1463-
view_light_entity,
1464-
gpu_preprocessing_support.min(GpuPreprocessingMode::PreprocessingOnly),
1465-
);
1476+
shadow_render_phases.insert_or_clear(view_light_entity, gpu_preprocessing_mode);
14661477
live_shadow_mapping_lights.insert(view_light_entity);
14671478
}
14681479
}

0 commit comments

Comments
 (0)