Skip to content

Commit c1f9764

Browse files
committed
Build batches across phases in parallel.
Currently, invocations of `batch_and_prepare_binned_render_phase` and `batch_and_prepare_sorted_render_phase` can't run in parallel because they write to scene-global GPU buffers. After PR #17698, `batch_and_prepare_binned_render_phase` started accounting for the lion's share of the CPU time, causing us to be strongly CPU bound on scenes like Caldera when occlusion culling was on (because of the overhead of batching for the Z-prepass). Although I eventually plan to optimize `batch_and_prepare_binned_render_phase`, we can obtain significant wins now by parallelizing that system across phases. This commit splits all GPU buffers that `batch_and_prepare_binned_render_phase` and `batch_and_prepare_sorted_render_phase` touches into separate buffers for each phase so that the scheduler will run those phases in parallel. At the end of batch preparation, we gather the render phases up into a single resource with a new *collection* phase. Because we already run mesh preprocessing separately for each phase in order to make occlusion culling work, this is actually a cleaner separation. For example, mesh output indices (the unique ID that identifies each mesh instance on GPU) are now guaranteed to be sequential starting from 0, which will simplify the forthcoming work to remove them in favor of the compute dispatch ID. On Caldera, this brings the frame time down to approximately 9.1 ms with occlusion culling on.
1 parent ea57841 commit c1f9764

File tree

13 files changed

+968
-425
lines changed

13 files changed

+968
-425
lines changed

crates/bevy_pbr/src/decal/forward.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ impl Plugin for ForwardDecalPlugin {
4848
app.add_plugins(MaterialPlugin::<ForwardDecalMaterial<StandardMaterial>> {
4949
prepass_enabled: false,
5050
shadows_enabled: false,
51+
allow_copies_from_indirect_parameters: false,
5152
..Default::default()
5253
});
5354
}

crates/bevy_pbr/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,12 @@ pub struct PbrPlugin {
182182
/// This requires compute shader support and so will be forcibly disabled if
183183
/// the platform doesn't support those.
184184
pub use_gpu_instance_buffer_builder: bool,
185+
/// If true, this sets the `COPY_SRC` flag on indirect draw parameters so
186+
/// that they can be read back to CPU.
187+
///
188+
/// This is a debugging feature that may reduce performance. It primarily
189+
/// exists for the `occlusion_culling` example.
190+
pub allow_copies_from_indirect_parameters: bool,
185191
}
186192

187193
impl Default for PbrPlugin {
@@ -190,6 +196,7 @@ impl Default for PbrPlugin {
190196
prepass_enabled: true,
191197
add_default_deferred_lighting_plugin: true,
192198
use_gpu_instance_buffer_builder: true,
199+
allow_copies_from_indirect_parameters: false,
193200
}
194201
}
195202
}
@@ -333,9 +340,13 @@ impl Plugin for PbrPlugin {
333340
.add_plugins((
334341
MeshRenderPlugin {
335342
use_gpu_instance_buffer_builder: self.use_gpu_instance_buffer_builder,
343+
allow_copies_from_indirect_parameters: self
344+
.allow_copies_from_indirect_parameters,
336345
},
337346
MaterialPlugin::<StandardMaterial> {
338347
prepass_enabled: self.prepass_enabled,
348+
allow_copies_from_indirect_parameters: self
349+
.allow_copies_from_indirect_parameters,
339350
..Default::default()
340351
},
341352
ScreenSpaceAmbientOcclusionPlugin,

crates/bevy_pbr/src/material.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,12 @@ pub struct MaterialPlugin<M: Material> {
252252
pub prepass_enabled: bool,
253253
/// Controls if shadows are enabled for the Material.
254254
pub shadows_enabled: bool,
255+
/// If true, this sets the `COPY_SRC` flag on indirect draw parameters so
256+
/// that they can be read back to CPU.
257+
///
258+
/// This is a debugging feature that may reduce performance. It primarily
259+
/// exists for the `occlusion_culling` example.
260+
pub allow_copies_from_indirect_parameters: bool,
255261
pub _marker: PhantomData<M>,
256262
}
257263

@@ -260,6 +266,7 @@ impl<M: Material> Default for MaterialPlugin<M> {
260266
Self {
261267
prepass_enabled: true,
262268
shadows_enabled: true,
269+
allow_copies_from_indirect_parameters: false,
263270
_marker: Default::default(),
264271
}
265272
}
@@ -374,7 +381,9 @@ where
374381
}
375382

376383
if self.prepass_enabled {
377-
app.add_plugins(PrepassPlugin::<M>::default());
384+
app.add_plugins(PrepassPlugin::<M>::new(
385+
self.allow_copies_from_indirect_parameters,
386+
));
378387
}
379388
}
380389

crates/bevy_pbr/src/prepass/mod.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,22 @@ where
146146
/// Sets up the prepasses for a [`Material`].
147147
///
148148
/// This depends on the [`PrepassPipelinePlugin`].
149-
pub struct PrepassPlugin<M: Material>(PhantomData<M>);
149+
pub struct PrepassPlugin<M: Material> {
150+
/// If true, this sets the `COPY_SRC` flag on indirect draw parameters so
151+
/// that they can be read back to CPU.
152+
///
153+
/// This is a debugging feature that may reduce performance. It primarily
154+
/// exists for the `occlusion_culling` example.
155+
pub allow_copies_from_indirect_parameters: bool,
156+
pub phantom: PhantomData<M>,
157+
}
150158

151-
impl<M: Material> Default for PrepassPlugin<M> {
152-
fn default() -> Self {
153-
Self(Default::default())
159+
impl<M: Material> PrepassPlugin<M> {
160+
pub fn new(allow_copies_from_indirect_parameters: bool) -> Self {
161+
PrepassPlugin {
162+
allow_copies_from_indirect_parameters,
163+
phantom: PhantomData,
164+
}
154165
}
155166
}
156167

@@ -176,8 +187,12 @@ where
176187
),
177188
)
178189
.add_plugins((
179-
BinnedRenderPhasePlugin::<Opaque3dPrepass, MeshPipeline>::default(),
180-
BinnedRenderPhasePlugin::<AlphaMask3dPrepass, MeshPipeline>::default(),
190+
BinnedRenderPhasePlugin::<Opaque3dPrepass, MeshPipeline>::new(
191+
self.allow_copies_from_indirect_parameters,
192+
),
193+
BinnedRenderPhasePlugin::<AlphaMask3dPrepass, MeshPipeline>::new(
194+
self.allow_copies_from_indirect_parameters,
195+
),
181196
));
182197
}
183198

0 commit comments

Comments
 (0)