Optimize transform systems to only run on change (#417)

Optimize transform systems to only run on change
This commit is contained in:
Tristan Pemble 2020-09-06 12:53:14 -07:00 committed by GitHub
parent 9eba19c8f0
commit 43463a7a06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 226 additions and 39 deletions

View File

@ -16,6 +16,7 @@ pub mod prelude {
Commands, IntoForEachSystem, IntoQuerySystem, IntoThreadLocalSystem, Query, System, Commands, IntoForEachSystem, IntoQuerySystem, IntoThreadLocalSystem, Query, System,
}, },
world::WorldBuilderSource, world::WorldBuilderSource,
Added, Bundle, Changed, Component, Entity, Mut, Mutated, Ref, RefMut, With, Without, World, Added, Bundle, Changed, Component, Entity, Mut, Mutated, Or, Ref, RefMut, With, Without,
World,
}; };
} }

View File

@ -7,7 +7,7 @@ pub fn local_transform_translation_system(
mut query: Query< mut query: Query<
Without< Without<
Rotation, Rotation,
Without<Scale, Without<NonUniformScale, (&mut LocalTransform, &Translation)>>, Without<Scale, Without<NonUniformScale, (&mut LocalTransform, Changed<Translation>)>>,
>, >,
>, >,
) { ) {
@ -20,7 +20,7 @@ pub fn local_transform_rotation_system(
mut query: Query< mut query: Query<
Without< Without<
Translation, Translation,
Without<Scale, Without<NonUniformScale, (&mut LocalTransform, &Rotation)>>, Without<Scale, Without<NonUniformScale, (&mut LocalTransform, Changed<Rotation>)>>,
>, >,
>, >,
) { ) {
@ -33,7 +33,7 @@ pub fn local_transform_scale_system(
mut query: Query< mut query: Query<
Without< Without<
Translation, Translation,
Without<Rotation, Without<NonUniformScale, (&mut LocalTransform, &Scale)>>, Without<Rotation, Without<NonUniformScale, (&mut LocalTransform, Changed<Scale>)>>,
>, >,
>, >,
) { ) {
@ -46,7 +46,7 @@ pub fn local_transform_non_uniform_scale_system(
mut query: Query< mut query: Query<
Without< Without<
Translation, Translation,
Without<Rotation, Without<Scale, (&mut LocalTransform, &NonUniformScale)>>, Without<Rotation, Without<Scale, (&mut LocalTransform, Changed<NonUniformScale>)>>,
>, >,
>, >,
) { ) {
@ -57,20 +57,38 @@ pub fn local_transform_non_uniform_scale_system(
pub fn local_transform_translation_rotation_system( pub fn local_transform_translation_rotation_system(
mut query: Query< mut query: Query<
Without<Scale, Without<NonUniformScale, (&mut LocalTransform, &Translation, &Rotation)>>, Without<
Scale,
Without<
NonUniformScale,
(
&mut LocalTransform,
Or<(Changed<Translation>, Changed<Rotation>)>,
),
>,
>,
>, >,
) { ) {
for (mut local, translation, rotation) in &mut query.iter() { for (mut local, (translation, rotation)) in &mut query.iter() {
*local = LocalTransform(Mat4::from_rotation_translation(rotation.0, translation.0)); *local = LocalTransform(Mat4::from_rotation_translation(rotation.0, translation.0));
} }
} }
pub fn local_transform_translation_scale_system( pub fn local_transform_translation_scale_system(
mut query: Query< mut query: Query<
Without<Rotation, Without<NonUniformScale, (&mut LocalTransform, &Translation, &Scale)>>, Without<
Rotation,
Without<
NonUniformScale,
(
&mut LocalTransform,
Or<(Changed<Translation>, Changed<Scale>)>,
),
>,
>,
>, >,
) { ) {
for (mut local, translation, scale) in &mut query.iter() { for (mut local, (translation, scale)) in &mut query.iter() {
*local = LocalTransform(Mat4::from_scale_rotation_translation( *local = LocalTransform(Mat4::from_scale_rotation_translation(
Vec3::new(scale.0, scale.0, scale.0), Vec3::new(scale.0, scale.0, scale.0),
Quat::default(), Quat::default(),
@ -81,10 +99,19 @@ pub fn local_transform_translation_scale_system(
pub fn local_transform_translation_non_uniform_scale_system( pub fn local_transform_translation_non_uniform_scale_system(
mut query: Query< mut query: Query<
Without<Rotation, Without<Scale, (&mut LocalTransform, &Translation, &NonUniformScale)>>, Without<
Rotation,
Without<
Scale,
(
&mut LocalTransform,
Or<(Changed<Translation>, Changed<NonUniformScale>)>,
),
>,
>,
>, >,
) { ) {
for (mut local, translation, non_uniform_scale) in &mut query.iter() { for (mut local, (translation, non_uniform_scale)) in &mut query.iter() {
*local = LocalTransform(Mat4::from_scale_rotation_translation( *local = LocalTransform(Mat4::from_scale_rotation_translation(
non_uniform_scale.0, non_uniform_scale.0,
Quat::default(), Quat::default(),
@ -95,10 +122,16 @@ pub fn local_transform_translation_non_uniform_scale_system(
pub fn local_transform_rotation_scale_system( pub fn local_transform_rotation_scale_system(
mut query: Query< mut query: Query<
Without<Translation, Without<NonUniformScale, (&mut LocalTransform, &Rotation, &Scale)>>, Without<
Translation,
Without<
NonUniformScale,
(&mut LocalTransform, Or<(Changed<Rotation>, Changed<Scale>)>),
>,
>,
>, >,
) { ) {
for (mut local, rotation, scale) in &mut query.iter() { for (mut local, (rotation, scale)) in &mut query.iter() {
*local = LocalTransform(Mat4::from_scale_rotation_translation( *local = LocalTransform(Mat4::from_scale_rotation_translation(
Vec3::new(scale.0, scale.0, scale.0), Vec3::new(scale.0, scale.0, scale.0),
rotation.0, rotation.0,
@ -109,10 +142,19 @@ pub fn local_transform_rotation_scale_system(
pub fn local_transform_rotation_non_uniform_scale_system( pub fn local_transform_rotation_non_uniform_scale_system(
mut query: Query< mut query: Query<
Without<Translation, Without<Scale, (&mut LocalTransform, &Rotation, &NonUniformScale)>>, Without<
Translation,
Without<
Scale,
(
&mut LocalTransform,
Or<(Changed<Rotation>, Changed<NonUniformScale>)>,
),
>,
>,
>, >,
) { ) {
for (mut local, rotation, non_uniform_scale) in &mut query.iter() { for (mut local, (rotation, non_uniform_scale)) in &mut query.iter() {
*local = LocalTransform(Mat4::from_scale_rotation_translation( *local = LocalTransform(Mat4::from_scale_rotation_translation(
non_uniform_scale.0, non_uniform_scale.0,
rotation.0, rotation.0,
@ -123,10 +165,16 @@ pub fn local_transform_rotation_non_uniform_scale_system(
pub fn local_transform_translation_rotation_scale_system( pub fn local_transform_translation_rotation_scale_system(
mut query: Query< mut query: Query<
Without<NonUniformScale, (&mut LocalTransform, &Translation, &Rotation, &Scale)>, Without<
NonUniformScale,
(
&mut LocalTransform,
Or<(Changed<Translation>, Changed<Rotation>, Changed<Scale>)>,
),
>,
>, >,
) { ) {
for (mut local, translation, rotation, scale) in &mut query.iter() { for (mut local, (translation, rotation, scale)) in &mut query.iter() {
*local = LocalTransform(Mat4::from_scale_rotation_translation( *local = LocalTransform(Mat4::from_scale_rotation_translation(
Vec3::new(scale.0, scale.0, scale.0), Vec3::new(scale.0, scale.0, scale.0),
rotation.0, rotation.0,
@ -141,14 +189,16 @@ pub fn local_transform_translation_rotation_non_uniform_scale_system(
Scale, Scale,
( (
&mut LocalTransform, &mut LocalTransform,
&Translation, Or<(
&Rotation, Changed<Translation>,
&NonUniformScale, Changed<Rotation>,
Changed<NonUniformScale>,
)>,
), ),
>, >,
>, >,
) { ) {
for (mut local, translation, rotation, non_uniform_scale) in &mut query.iter() { for (mut local, (translation, rotation, non_uniform_scale)) in &mut query.iter() {
*local = LocalTransform(Mat4::from_scale_rotation_translation( *local = LocalTransform(Mat4::from_scale_rotation_translation(
non_uniform_scale.0, non_uniform_scale.0,
rotation.0, rotation.0,
@ -270,4 +320,46 @@ mod test {
Mat4::from_scale_rotation_translation(nus.0, r.0, t.0) Mat4::from_scale_rotation_translation(nus.0, r.0, t.0)
); );
} }
#[test]
fn only_propagates_local_transform_on_change() {
let mut world = World::default();
let mut resources = Resources::default();
let mut schedule = Schedule::default();
schedule.add_stage("update");
for system in local_transform_systems() {
schedule.add_system_to_stage("update", system);
}
let local_transform = LocalTransform::identity();
let t = Translation::new(1.0, 2.0, 3.0);
let r = Rotation(Quat::from_rotation_ypr(1.0, 2.0, 3.0));
let s = Scale(2.0);
let nus = NonUniformScale::new(1.0, 2.0, 3.0);
// Add every combination of transform types.
world.spawn((local_transform, t));
world.spawn((local_transform, r));
world.spawn((local_transform, s));
world.spawn((local_transform, nus));
world.spawn((local_transform, t, r));
world.spawn((local_transform, t, s));
world.spawn((local_transform, t, nus));
world.spawn((local_transform, r, s));
world.spawn((local_transform, r, nus));
world.spawn((local_transform, t, r, s));
world.spawn((local_transform, t, r, nus));
// Run the system, local transforms should mutate since they are new
schedule.run(&mut world, &mut resources);
// Verify that the local transform is not mutated on the second frame
fn assert_no_local_transforms_changed_system(_: Changed<LocalTransform>) {
assert!(false)
}
schedule.add_system_to_stage("update", assert_no_local_transforms_changed_system.system());
schedule.run(&mut world, &mut resources);
}
} }

View File

@ -9,7 +9,7 @@ pub fn transform_translation_system(
LocalTransform, LocalTransform,
Without< Without<
Rotation, Rotation,
Without<Scale, Without<NonUniformScale, (&mut Transform, &Translation)>>, Without<Scale, Without<NonUniformScale, (&mut Transform, Changed<Translation>)>>,
>, >,
>, >,
>, >,
@ -29,7 +29,7 @@ pub fn transform_rotation_system(
LocalTransform, LocalTransform,
Without< Without<
Translation, Translation,
Without<Scale, Without<NonUniformScale, (&mut Transform, &Rotation)>>, Without<Scale, Without<NonUniformScale, (&mut Transform, Changed<Rotation>)>>,
>, >,
>, >,
>, >,
@ -49,7 +49,7 @@ pub fn transform_scale_system(
LocalTransform, LocalTransform,
Without< Without<
Translation, Translation,
Without<Rotation, Without<NonUniformScale, (&mut Transform, &Scale)>>, Without<Rotation, Without<NonUniformScale, (&mut Transform, Changed<Scale>)>>,
>, >,
>, >,
>, >,
@ -69,7 +69,7 @@ pub fn transform_non_uniform_scale_system(
LocalTransform, LocalTransform,
Without< Without<
Translation, Translation,
Without<Rotation, Without<Scale, (&mut Transform, &NonUniformScale)>>, Without<Rotation, Without<Scale, (&mut Transform, Changed<NonUniformScale>)>>,
>, >,
>, >,
>, >,
@ -87,11 +87,20 @@ pub fn transform_translation_rotation_system(
mut query: Query< mut query: Query<
Without< Without<
LocalTransform, LocalTransform,
Without<Scale, Without<NonUniformScale, (&mut Transform, &Translation, &Rotation)>>, Without<
Scale,
Without<
NonUniformScale,
(
&mut Transform,
Or<(Changed<Translation>, Changed<Rotation>)>,
),
>,
>,
>, >,
>, >,
) { ) {
for (mut transform, translation, rotation) in &mut query.iter() { for (mut transform, (translation, rotation)) in &mut query.iter() {
if !transform.sync { if !transform.sync {
continue; continue;
} }
@ -104,11 +113,17 @@ pub fn transform_translation_scale_system(
mut query: Query< mut query: Query<
Without< Without<
LocalTransform, LocalTransform,
Without<Rotation, Without<NonUniformScale, (&mut Transform, &Translation, &Scale)>>, Without<
Rotation,
Without<
NonUniformScale,
(&mut Transform, Or<(Changed<Translation>, Changed<Scale>)>),
>,
>,
>, >,
>, >,
) { ) {
for (mut transform, translation, scale) in &mut query.iter() { for (mut transform, (translation, scale)) in &mut query.iter() {
if !transform.sync { if !transform.sync {
continue; continue;
} }
@ -125,11 +140,20 @@ pub fn transform_translation_non_uniform_scale_system(
mut query: Query< mut query: Query<
Without< Without<
LocalTransform, LocalTransform,
Without<Rotation, Without<Scale, (&mut Transform, &Translation, &NonUniformScale)>>, Without<
Rotation,
Without<
Scale,
(
&mut Transform,
Or<(Changed<Translation>, Changed<NonUniformScale>)>,
),
>,
>,
>, >,
>, >,
) { ) {
for (mut transform, translation, non_uniform_scale) in &mut query.iter() { for (mut transform, (translation, non_uniform_scale)) in &mut query.iter() {
if !transform.sync { if !transform.sync {
continue; continue;
} }
@ -146,11 +170,14 @@ pub fn transform_rotation_scale_system(
mut query: Query< mut query: Query<
Without< Without<
LocalTransform, LocalTransform,
Without<Translation, Without<NonUniformScale, (&mut Transform, &Rotation, &Scale)>>, Without<
Translation,
Without<NonUniformScale, (&mut Transform, Or<(Changed<Rotation>, Changed<Scale>)>)>,
>,
>, >,
>, >,
) { ) {
for (mut transform, rotation, scale) in &mut query.iter() { for (mut transform, (rotation, scale)) in &mut query.iter() {
if !transform.sync { if !transform.sync {
continue; continue;
} }
@ -167,11 +194,20 @@ pub fn transform_rotation_non_uniform_scale_system(
mut query: Query< mut query: Query<
Without< Without<
LocalTransform, LocalTransform,
Without<Translation, Without<Scale, (&mut Transform, &Rotation, &NonUniformScale)>>, Without<
Translation,
Without<
Scale,
(
&mut Transform,
Or<(Changed<Rotation>, Changed<NonUniformScale>)>,
),
>,
>,
>, >,
>, >,
) { ) {
for (mut transform, rotation, non_uniform_scale) in &mut query.iter() { for (mut transform, (rotation, non_uniform_scale)) in &mut query.iter() {
if !transform.sync { if !transform.sync {
continue; continue;
} }
@ -188,11 +224,17 @@ pub fn transform_translation_rotation_scale_system(
mut query: Query< mut query: Query<
Without< Without<
LocalTransform, LocalTransform,
Without<NonUniformScale, (&mut Transform, &Translation, &Rotation, &Scale)>, Without<
NonUniformScale,
(
&mut Transform,
Or<(Changed<Translation>, Changed<Rotation>, Changed<Scale>)>,
),
>,
>, >,
>, >,
) { ) {
for (mut transform, translation, rotation, scale) in &mut query.iter() { for (mut transform, (translation, rotation, scale)) in &mut query.iter() {
if !transform.sync { if !transform.sync {
continue; continue;
} }
@ -209,11 +251,21 @@ pub fn transform_translation_rotation_non_uniform_scale_system(
mut query: Query< mut query: Query<
Without< Without<
LocalTransform, LocalTransform,
Without<Scale, (&mut Transform, &Translation, &Rotation, &NonUniformScale)>, Without<
Scale,
(
&mut Transform,
Or<(
Changed<Translation>,
Changed<Rotation>,
Changed<NonUniformScale>,
)>,
),
>,
>, >,
>, >,
) { ) {
for (mut transform, translation, rotation, non_uniform_scale) in &mut query.iter() { for (mut transform, (translation, rotation, non_uniform_scale)) in &mut query.iter() {
if !transform.sync { if !transform.sync {
continue; continue;
} }
@ -336,4 +388,46 @@ mod test {
Mat4::from_scale_rotation_translation(nus.0, r.0, t.0) Mat4::from_scale_rotation_translation(nus.0, r.0, t.0)
); );
} }
#[test]
fn only_propagates_transform_on_change() {
let mut world = World::default();
let mut resources = Resources::default();
let mut schedule = Schedule::default();
schedule.add_stage("update");
for system in transform_systems() {
schedule.add_system_to_stage("update", system);
}
let transform = Transform::identity();
let t = Translation::new(1.0, 2.0, 3.0);
let r = Rotation(Quat::from_rotation_ypr(1.0, 2.0, 3.0));
let s = Scale(2.0);
let nus = NonUniformScale::new(1.0, 2.0, 3.0);
// Add every combination of transform types.
world.spawn((transform, t));
world.spawn((transform, r));
world.spawn((transform, s));
world.spawn((transform, nus));
world.spawn((transform, t, r));
world.spawn((transform, t, s));
world.spawn((transform, t, nus));
world.spawn((transform, r, s));
world.spawn((transform, r, nus));
world.spawn((transform, t, r, s));
world.spawn((transform, t, r, nus));
// Run the system, transforms should mutate since they are new
schedule.run(&mut world, &mut resources);
// Verify that the transform is not mutated on the second frame
fn assert_no_transforms_changed_system(_: Changed<Transform>) {
assert!(false)
}
schedule.add_system_to_stage("update", assert_no_transforms_changed_system.system());
schedule.run(&mut world, &mut resources);
}
} }