Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor and speed up transform propagation and hierarchies further #380

Merged
merged 5 commits into from
Jun 21, 2024

Conversation

Jondolf
Copy link
Owner

@Jondolf Jondolf commented Jun 21, 2024

Objective

#377 refactored collider hierarchy logic and extracted it into a ColliderHierarchyPlugin<C: ScalableCollider>, along with significantly speeding up ColliderTransform propagation using a ColliderAncestor marker component to ignore trees that don't have colliders.

However, a similar marker component approach can also be used to speed up the many copies of transform propagation that the engine has. By limiting the propagation runs to physics entities, we could drastically reduce the overhead for scenes with lots of non-physics entities, further addressing #356.

Solution

  • Extract the ancestor marker logic from ColliderHierarchyPlugin into an AncestorMarkerPlugin<C: Component> that adds an AncestorMarker<C> component for all ancestors of entities with the given component C. The logic was also refactored to be more robust and fix some edge cases and fully support hierarchy changes, along with adding more tests.
  • Use this plugin in SyncPlugin to mark rigid body ancestors.
  • Define custom transform propagation systems that only traverse trees that have physics entities (rigid bodies or colliders). See the comments in sync.rs above the propagation systems to see how this works.
  • To support custom collision backends without having to add generics to all the propagation systems, and to avoid needing to unnecessarily duplicate systems, the ColliderBackendPlugin now adds a general, automatically managed ColliderMarker component for all colliders, which allows filtering collider entities without knowing the collider type. This lets us get rid of the generics on ColliderHierarchyPlugin!
  • I also changed some scheduling and system sets in the PrepareSet to account for some changes and to be more logical.

Results

Test scene: 12 substeps, 1 root entity, 100,000 child entities. All entities have just a SpatialBundle, and one child entity also has a Collider.

  • Before #377: ~22 FPS
  • After #377: ~200 FPS
  • After this PR: ~490 FPS

Of course, this scene is not very representative of an actual game scene, but it does show just how much of an impact the transform propagation was having. A lot of games (probably most of them) do have many more non-physics entities than physics entities, and the overhead added by the marker components and new checks should be very minimal in comparison.


Migration Guide

Some PrepareSet system sets have changed order.

Before:

  1. PreInit
  2. PropagateTransforms
  3. InitRigidBodies
  4. InitMassProperties
  5. InitColliders
  6. InitTransforms
  7. Finalize

After:

  1. PreInit
  2. InitRigidBodies
  3. InitColliders
  4. PropagateTransforms
  5. InitMassProperties
  6. InitTransforms
  7. Finalize

Additionally, the ColliderHierarchyPlugin added in #377 no longer needs generics. The plugin is new anyway however, so this isn't really a breaking change.

@Jondolf Jondolf added performance Improvements or questions related to performance breaking change This change removes or changes behavior or APIs, requiring users to adapt. labels Jun 21, 2024
@Jondolf Jondolf merged commit 7975464 into bevy-0.14 Jun 21, 2024
4 checks passed
@Jondolf Jondolf deleted the reduce-unnecessary-propagation-further branch June 21, 2024 21:08
Jondolf added a commit that referenced this pull request Jul 2, 2024
…dren (#392)

# Objective

#380 significantly sped up transform propagation by reducing unnecessary work with physics entity ancestor markers. However, it also seems to have caused a severe bug: `GlobalTransform` is not updated for rigid bodies that have children that all are *not* physics entities.

The problem lies in `propagate_transforms_physics`, which *only* iterates through entities that are marked as ancestors of rigid bodies or colliders. Rigid bodies that have children but no physics entity descendants are just skipped.

## Solution

In `sync_simple_transforms_physics`, don't only iterate through rigid bodies with no children, but also through rigid bodies that have children but are *not* ancestors of other physics entities.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change This change removes or changes behavior or APIs, requiring users to adapt. performance Improvements or questions related to performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant