From 48049f72569a9a29114cd69e6bb72f1904dc164e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 5 Feb 2025 09:35:19 -0800 Subject: [PATCH] Don't mark a previous mesh transform as changed if it didn't actually change. (#17688) This patch fixes a bug whereby we're re-extracting every mesh every frame. It's a regression from PR #17413. The code in question has actually been in the tree with this bug for quite a while; it's that just the code didn't actually run unless the renderer considered the previous view transforms necessary. Occlusion culling expanded the set of circumstances under which Bevy computes the previous view transforms, causing this bug to appear more often. This patch fixes the issue by checking to see if the previous transform of a mesh actually differs from the current transform before copying the current transform to the previous transform. --- crates/bevy_pbr/src/prepass/mod.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 3bc2dc51e3..b0bda94b8e 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -226,7 +226,7 @@ pub fn update_previous_view_data( } } -#[derive(Component, Default)] +#[derive(Component, PartialEq, Default)] pub struct PreviousGlobalTransform(pub Affine3A); #[cfg(not(feature = "meshlet"))] @@ -237,15 +237,19 @@ type PreviousMeshFilter = Or<(With, With)>; pub fn update_mesh_previous_global_transforms( mut commands: Commands, views: Query<&Camera, Or<(With, With)>>, - meshes: Query<(Entity, &GlobalTransform), PreviousMeshFilter>, + meshes: Query<(Entity, &GlobalTransform, Option<&PreviousGlobalTransform>), PreviousMeshFilter>, ) { let should_run = views.iter().any(|camera| camera.is_active); if should_run { - for (entity, transform) in &meshes { - commands - .entity(entity) - .try_insert(PreviousGlobalTransform(transform.affine())); + for (entity, transform, old_previous_transform) in &meshes { + let new_previous_transform = PreviousGlobalTransform(transform.affine()); + // Make sure not to trigger change detection on + // `PreviousGlobalTransform` if the previous transform hasn't + // changed. + if old_previous_transform != Some(&new_previous_transform) { + commands.entity(entity).try_insert(new_previous_transform); + } } } }