Skip to content

Commit d40c5b5

Browse files
authored
Material, mesh, skin extraction optimization (#17976)
# Objective The extraction systems for materials, meshes, and skins previously iterated over `RemovedComponents<ViewVisibility>` in addition to more specific variants like `RemovedComponents<MeshMaterial3d<M>>`. This caused each system to loop through and check many irrelevant despawned entities—sometimes multiple times. With many material types, this overhead added up and became noticeable in frames with many despawns. <img width="1091" alt="Screenshot 2025-02-21 at 10 28 01 AM" src="https://github.com/user-attachments/assets/63fec1c9-232c-45f6-9150-daf8751ecf85" /> ## Solution This PR removes superfluous `RemovedComponents` iteration for `ViewVisibility` and `GlobalTransform`, ensuring that we only iterate over the most specific `RemovedComponents` relevant to the system (e.g., material components, mesh components). This is guaranteed to match what the system originally collected. ### Before (red) / After (yellow): <img width="838" alt="Screenshot 2025-02-21 at 10 46 17 AM" src="https://github.com/user-attachments/assets/0e06b06d-7e91-4da5-a919-b843eb442a72" /> Log plot to highlight the long tail that this PR is addressing.
1 parent 6fc4bc1 commit d40c5b5

File tree

4 files changed

+5
-19
lines changed

4 files changed

+5
-19
lines changed

crates/bevy_pbr/src/material.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,11 +746,11 @@ fn early_sweep_material_instances<M>(
746746
/// preparation for a new frame.
747747
pub(crate) fn late_sweep_material_instances(
748748
mut material_instances: ResMut<RenderMaterialInstances>,
749-
mut removed_visibilities_query: Extract<RemovedComponents<ViewVisibility>>,
749+
mut removed_meshes_query: Extract<RemovedComponents<Mesh3d>>,
750750
) {
751751
let last_change_tick = material_instances.current_change_tick;
752752

753-
for entity in removed_visibilities_query.read() {
753+
for entity in removed_meshes_query.read() {
754754
if let Entry::Occupied(occupied_entry) = material_instances.instances.entry(entity.into()) {
755755
// Only sweep the entry if it wasn't updated this frame. It's
756756
// possible that a `ViewVisibility` component was removed and

crates/bevy_pbr/src/render/mesh.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,8 +1452,6 @@ pub fn extract_meshes_for_gpu_building(
14521452
>,
14531453
>,
14541454
all_meshes_query: Extract<Query<GpuMeshExtractionQuery>>,
1455-
mut removed_visibilities_query: Extract<RemovedComponents<ViewVisibility>>,
1456-
mut removed_global_transforms_query: Extract<RemovedComponents<GlobalTransform>>,
14571455
mut removed_meshes_query: Extract<RemovedComponents<Mesh3d>>,
14581456
gpu_culling_query: Extract<Query<(), (With<Camera>, Without<NoIndirectDrawing>)>>,
14591457
meshes_to_reextract_next_frame: ResMut<MeshesToReextractNextFrame>,
@@ -1509,11 +1507,7 @@ pub fn extract_meshes_for_gpu_building(
15091507
}
15101508

15111509
// Also record info about each mesh that became invisible.
1512-
for entity in removed_visibilities_query
1513-
.read()
1514-
.chain(removed_global_transforms_query.read())
1515-
.chain(removed_meshes_query.read())
1516-
{
1510+
for entity in removed_meshes_query.read() {
15171511
// Only queue a mesh for removal if we didn't pick it up above.
15181512
// It's possible that a necessary component was removed and re-added in
15191513
// the same frame.

crates/bevy_pbr/src/render/skin.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,6 @@ pub fn extract_skins(
309309
skinned_mesh_inverse_bindposes: Extract<Res<Assets<SkinnedMeshInverseBindposes>>>,
310310
changed_transforms: Extract<Query<(Entity, &GlobalTransform), Changed<GlobalTransform>>>,
311311
joints: Extract<Query<&GlobalTransform>>,
312-
mut removed_visibilities_query: Extract<RemovedComponents<ViewVisibility>>,
313312
mut removed_skinned_meshes_query: Extract<RemovedComponents<SkinnedMesh>>,
314313
) {
315314
let skin_uniforms = skin_uniforms.into_inner();
@@ -335,10 +334,7 @@ pub fn extract_skins(
335334
);
336335

337336
// Delete skins that became invisible.
338-
for skinned_mesh_entity in removed_visibilities_query
339-
.read()
340-
.chain(removed_skinned_meshes_query.read())
341-
{
337+
for skinned_mesh_entity in removed_skinned_meshes_query.read() {
342338
// Only remove a skin if we didn't pick it up in `add_or_delete_skins`.
343339
// It's possible that a necessary component was removed and re-added in
344340
// the same frame.

crates/bevy_sprite/src/mesh2d/material.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,6 @@ pub fn extract_mesh_materials_2d<M: Material2d>(
331331
Or<(Changed<ViewVisibility>, Changed<MeshMaterial2d<M>>)>,
332332
>,
333333
>,
334-
mut removed_visibilities_query: Extract<RemovedComponents<ViewVisibility>>,
335334
mut removed_materials_query: Extract<RemovedComponents<MeshMaterial2d<M>>>,
336335
) {
337336
for (entity, view_visibility, material) in &changed_meshes_query {
@@ -342,10 +341,7 @@ pub fn extract_mesh_materials_2d<M: Material2d>(
342341
}
343342
}
344343

345-
for entity in removed_visibilities_query
346-
.read()
347-
.chain(removed_materials_query.read())
348-
{
344+
for entity in removed_materials_query.read() {
349345
// Only queue a mesh for removal if we didn't pick it up above.
350346
// It's possible that a necessary component was removed and re-added in
351347
// the same frame.

0 commit comments

Comments
 (0)