Skip to content

Commit

Permalink
Allow extract_meshes_for_gpu_building and extract_mesh_materials
Browse files Browse the repository at this point in the history
…to run in parallel. (#16799)

The only thing that was preventing `extract_meshes_for_gpu_building` and
`extract_mesh_materials` from running in parallel was the
`ResMut<RenderMeshMaterialIds>`. This lookup can be safely moved to the
`collect_meshes_for_gpu_building` phase, which runs after the extraction
phase.

This results in a small win on `many_cubes`. `extract_mesh_materials` is
currently nonretained, so it's still slow, but running it in parallel is
an easy win.

Before:
![Screenshot 2024-12-13
015318](https://github.com/user-attachments/assets/e5cfa4d6-3feb-40b7-8405-f727de2c2813)

After:
![Screenshot 2024-12-13
015300](https://github.com/user-attachments/assets/7dc08135-aa1d-4e3a-a863-d2b7492f865f)
  • Loading branch information
pcwalton authored Dec 17, 2024
1 parent 40df1ea commit 7be844b
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 25 deletions.
7 changes: 1 addition & 6 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,12 +283,7 @@ where
.add_render_command::<Opaque3d, DrawMaterial<M>>()
.add_render_command::<AlphaMask3d, DrawMaterial<M>>()
.init_resource::<SpecializedMeshPipelines<MaterialPipeline<M>>>()
.add_systems(
ExtractSchedule,
extract_mesh_materials::<M>
.before(extract_meshes_for_cpu_building)
.before(extract_meshes_for_gpu_building),
)
.add_systems(ExtractSchedule, extract_mesh_materials::<M>)
.add_systems(
Render,
queue_material_meshes::<M>
Expand Down
35 changes: 16 additions & 19 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use bevy_render::{
camera::Camera,
mesh::*,
primitives::Aabb,
render_asset::{ExtractAssetsSet, RenderAssets},
render_asset::RenderAssets,
render_phase::{
BinnedRenderPhasePlugin, PhaseItem, PhaseItemExtraIndex, RenderCommand,
RenderCommandResult, SortedRenderPhasePlugin, TrackedRenderPass,
Expand All @@ -44,6 +44,7 @@ use bevy_render::{
};
use bevy_transform::components::GlobalTransform;
use bevy_utils::{
default,
hashbrown::hash_map::Entry,
tracing::{error, warn},
HashMap, Parallel,
Expand Down Expand Up @@ -208,8 +209,7 @@ impl Plugin for MeshRenderPlugin {
.add_systems(
ExtractSchedule,
extract_meshes_for_gpu_building
.in_set(ExtractMeshesSet)
.after(ExtractAssetsSet),
.in_set(ExtractMeshesSet),
)
.add_systems(
Render,
Expand Down Expand Up @@ -237,9 +237,7 @@ impl Plugin for MeshRenderPlugin {
.insert_resource(cpu_batched_instance_buffer)
.add_systems(
ExtractSchedule,
extract_meshes_for_cpu_building
.in_set(ExtractMeshesSet)
.after(ExtractAssetsSet),
extract_meshes_for_cpu_building.in_set(ExtractMeshesSet),
)
.add_systems(
Render,
Expand Down Expand Up @@ -624,7 +622,6 @@ impl RenderMeshInstanceShared {
fn from_components(
previous_transform: Option<&PreviousGlobalTransform>,
mesh: &Mesh3d,
material_bindings_index: MaterialBindingId,
not_shadow_caster: bool,
no_automatic_batching: bool,
) -> Self {
Expand All @@ -642,7 +639,8 @@ impl RenderMeshInstanceShared {
RenderMeshInstanceShared {
mesh_asset_id: mesh.id(),
flags: mesh_instance_flags,
material_bindings_index,
// This gets filled in later, during `RenderMeshGpuBuilder::update`.
material_bindings_index: default(),
}
}

Expand Down Expand Up @@ -901,12 +899,13 @@ impl RenderMeshInstanceGpuBuilder {
/// [`MeshInputUniform`] tables, replacing the existing entry if applicable.
#[allow(clippy::too_many_arguments)]
fn update(
self,
mut self,
entity: MainEntity,
render_mesh_instances: &mut MainEntityHashMap<RenderMeshInstanceGpu>,
current_input_buffer: &mut InstanceInputUniformBuffer<MeshInputUniform>,
previous_input_buffer: &mut InstanceInputUniformBuffer<MeshInputUniform>,
mesh_allocator: &MeshAllocator,
mesh_material_ids: &RenderMeshMaterialIds,
render_lightmaps: &RenderLightmaps,
skin_indices: &SkinIndices,
) -> u32 {
Expand All @@ -925,6 +924,10 @@ impl RenderMeshInstanceGpuBuilder {
None => u32::MAX,
};

// Look up the material index.
let mesh_material_binding_id = mesh_material_ids.mesh_material_binding_id(entity);
self.shared.material_bindings_index = mesh_material_binding_id;

let lightmap_slot = match render_lightmaps.render_lightmaps.get(&entity) {
Some(render_lightmap) => u16::from(*render_lightmap.slot_index),
None => u16::MAX,
Expand Down Expand Up @@ -1067,7 +1070,6 @@ pub struct ExtractMeshesSet;
pub fn extract_meshes_for_cpu_building(
mut render_mesh_instances: ResMut<RenderMeshInstances>,
render_visibility_ranges: Res<RenderVisibilityRanges>,
mesh_material_ids: Res<RenderMeshMaterialIds>,
mut render_mesh_instance_queues: Local<Parallel<Vec<(Entity, RenderMeshInstanceCpu)>>>,
meshes_query: Extract<
Query<(
Expand Down Expand Up @@ -1105,9 +1107,6 @@ pub fn extract_meshes_for_cpu_building(
return;
}

let mesh_material_binding_id =
mesh_material_ids.mesh_material_binding_id(MainEntity::from(entity));

let mut lod_index = None;
if visibility_range {
lod_index = render_visibility_ranges.lod_index_for_entity(entity.into());
Expand All @@ -1124,7 +1123,6 @@ pub fn extract_meshes_for_cpu_building(
let shared = RenderMeshInstanceShared::from_components(
previous_transform,
mesh,
mesh_material_binding_id,
not_shadow_caster,
no_automatic_batching,
);
Expand Down Expand Up @@ -1176,7 +1174,6 @@ pub fn extract_meshes_for_cpu_building(
pub fn extract_meshes_for_gpu_building(
mut render_mesh_instances: ResMut<RenderMeshInstances>,
render_visibility_ranges: Res<RenderVisibilityRanges>,
mesh_material_ids: Res<RenderMeshMaterialIds>,
mut render_mesh_instance_queues: ResMut<RenderMeshInstanceGpuQueues>,
changed_meshes_query: Extract<
Query<
Expand Down Expand Up @@ -1256,9 +1253,6 @@ pub fn extract_meshes_for_gpu_building(
return;
}

let mesh_material_binding_id =
mesh_material_ids.mesh_material_binding_id(MainEntity::from(entity));

let mut lod_index = None;
if visibility_range {
lod_index = render_visibility_ranges.lod_index_for_entity(entity.into());
Expand All @@ -1275,7 +1269,6 @@ pub fn extract_meshes_for_gpu_building(
let shared = RenderMeshInstanceShared::from_components(
previous_transform,
mesh,
mesh_material_binding_id,
not_shadow_caster,
no_automatic_batching,
);
Expand Down Expand Up @@ -1358,6 +1351,7 @@ fn set_mesh_motion_vector_flags(

/// Creates the [`RenderMeshInstanceGpu`]s and [`MeshInputUniform`]s when GPU
/// mesh uniforms are built.
#[allow(clippy::too_many_arguments)]
pub fn collect_meshes_for_gpu_building(
render_mesh_instances: ResMut<RenderMeshInstances>,
batched_instance_buffers: ResMut<
Expand All @@ -1366,6 +1360,7 @@ pub fn collect_meshes_for_gpu_building(
mut mesh_culling_data_buffer: ResMut<MeshCullingDataBuffer>,
mut render_mesh_instance_queues: ResMut<RenderMeshInstanceGpuQueues>,
mesh_allocator: Res<MeshAllocator>,
mesh_material_ids: Res<RenderMeshMaterialIds>,
render_lightmaps: Res<RenderLightmaps>,
skin_indices: Res<SkinIndices>,
) {
Expand Down Expand Up @@ -1403,6 +1398,7 @@ pub fn collect_meshes_for_gpu_building(
current_input_buffer,
previous_input_buffer,
&mesh_allocator,
&mesh_material_ids,
&render_lightmaps,
&skin_indices,
);
Expand All @@ -1428,6 +1424,7 @@ pub fn collect_meshes_for_gpu_building(
current_input_buffer,
previous_input_buffer,
&mesh_allocator,
&mesh_material_ids,
&render_lightmaps,
&skin_indices,
);
Expand Down

0 comments on commit 7be844b

Please sign in to comment.