bevy_transform: Use Changed in the query for much faster transform_propagate_system (#4180)

# Objective

- Improve transform propagation performance

## Solution

- Use `Changed<Transform>` as part of the `root_query` and `transform_query` to avoid the indirection of having to look up the `Entity` in the `changed_transform_query`
- Get rid of the `changed_transform_query` entirely
- `transform_propagate_system` execution time for `many_cubes -- sphere` dropped from 1.07ms to 0.159ms, an 85% reduction for this system. Frame rate increased from ~42fps to ~44fps
This commit is contained in:
Robert Swain 2022-03-29 03:05:01 +00:00
parent f16768d868
commit 54d2e86afc

View file

@ -1,7 +1,8 @@
use crate::components::{GlobalTransform, Transform}; use crate::components::{GlobalTransform, Transform};
use bevy_ecs::{ use bevy_ecs::{
entity::Entity, entity::Entity,
query::{Changed, With, Without}, prelude::Changed,
query::{With, Without},
system::Query, system::Query,
}; };
use bevy_hierarchy::{Children, Parent}; use bevy_hierarchy::{Children, Parent};
@ -10,16 +11,23 @@ use bevy_hierarchy::{Children, Parent};
/// [`Transform`] component. /// [`Transform`] component.
pub fn transform_propagate_system( pub fn transform_propagate_system(
mut root_query: Query< mut root_query: Query<
(Entity, Option<&Children>, &Transform, &mut GlobalTransform), (
Option<&Children>,
&Transform,
Changed<Transform>,
&mut GlobalTransform,
),
Without<Parent>, Without<Parent>,
>, >,
mut transform_query: Query<(&Transform, &mut GlobalTransform), With<Parent>>, mut transform_query: Query<
changed_transform_query: Query<Entity, Changed<Transform>>, (&Transform, Changed<Transform>, &mut GlobalTransform),
With<Parent>,
>,
children_query: Query<Option<&Children>, (With<Parent>, With<GlobalTransform>)>, children_query: Query<Option<&Children>, (With<Parent>, With<GlobalTransform>)>,
) { ) {
for (entity, children, transform, mut global_transform) in root_query.iter_mut() { for (children, transform, transform_changed, mut global_transform) in root_query.iter_mut() {
let mut changed = false; let mut changed = false;
if changed_transform_query.get(entity).is_ok() { if transform_changed {
*global_transform = GlobalTransform::from(*transform); *global_transform = GlobalTransform::from(*transform);
changed = true; changed = true;
} }
@ -28,7 +36,6 @@ pub fn transform_propagate_system(
for child in children.iter() { for child in children.iter() {
propagate_recursive( propagate_recursive(
&global_transform, &global_transform,
&changed_transform_query,
&mut transform_query, &mut transform_query,
&children_query, &children_query,
*child, *child,
@ -41,16 +48,19 @@ pub fn transform_propagate_system(
fn propagate_recursive( fn propagate_recursive(
parent: &GlobalTransform, parent: &GlobalTransform,
changed_transform_query: &Query<Entity, Changed<Transform>>, transform_query: &mut Query<
transform_query: &mut Query<(&Transform, &mut GlobalTransform), With<Parent>>, (&Transform, Changed<Transform>, &mut GlobalTransform),
With<Parent>,
>,
children_query: &Query<Option<&Children>, (With<Parent>, With<GlobalTransform>)>, children_query: &Query<Option<&Children>, (With<Parent>, With<GlobalTransform>)>,
entity: Entity, entity: Entity,
mut changed: bool, mut changed: bool,
) { ) {
changed |= changed_transform_query.get(entity).is_ok();
let global_matrix = { let global_matrix = {
if let Ok((transform, mut global_transform)) = transform_query.get_mut(entity) { if let Ok((transform, transform_changed, mut global_transform)) =
transform_query.get_mut(entity)
{
changed |= transform_changed;
if changed { if changed {
*global_transform = parent.mul_transform(*transform); *global_transform = parent.mul_transform(*transform);
} }
@ -64,7 +74,6 @@ fn propagate_recursive(
for child in children.iter() { for child in children.iter() {
propagate_recursive( propagate_recursive(
&global_matrix, &global_matrix,
changed_transform_query,
transform_query, transform_query,
children_query, children_query,
*child, *child,