Skip to content

perf(rbd): performance improvements of the RBD solver - #45

Merged
sebcrozet merged 37 commits into
mainfrom
rbd-performance
Oct 10, 2026
Merged

sebcrozet merged 37 commits into
mainfrom
rbd-performance

Conversation

@sebcrozet

@sebcrozet sebcrozet commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

This PR significantly improves performances of the rigid-body solver, reaching up to 10x performance improvements in heavy scenes (like a 110K ring of cubes). Depending on the machine this makes Nexus attractive compared to, e.g., Rapier, when simulating more than ~8K objects in 3D (tested on an Apple M4 Max).

The optimizations are mainly gains from (1) better parallelism, especially for the broad-phase which had single-workgroup tasks, and (2) better memory access patterns by leveraging AoSoA in the solver (similar to rapier’s simd path). Loop-unrolling also brought some interesting speedups mainly because this mitigates an issue with how rust-gpu array accesses are compiled.
I also ported the twist friction model from rapier to nexus, resulting in an additional 20% performance improvements on heavy scenes.

List of optimizations:

  • Parallelize the LBVH refit with more than a single workgroup. This works by refitting independent subtrees (with, e.g., 256 leaves each) of the LBVH up to the node that are parent of subtrees handled by different workgroups. The remaining “top” of the LBVH is then refit by a single workgroup.
  • Reduce memory traffic for contact constraints by recomputing angular jacobians and target (rhs) in the constraints solve code directly. This is interesting as that same pattern actually was slower in rapier (CPU physics), but is better for Nexus on the gpu.
  • Switch to a stack-less LBVH traversal (by storing a “next depth-first node” pointer on each node).
  • When finding overlaps for each LBVH leaves against the whole LBVH (one thread per leaf), each pair is, in theory, visited twice. To avoid duplication we had an heuristic based only on indexing. Now we also take into account the node’s AABB size so we prefer traversing subtrees with AABBs that are bigger than the current leaf AABB (to prevent large leaf AABBs like the floor from traversing the whole tree single-threaded).
  • Compute the LBVH domain (the scene AABB) using a two-passes reduction (where the first pass uses multiple workgroups) instead of just one.
  • Some loop unrolling in hot paths (like box-box collision-detection).
  • Implement the same contact recycling strategy as Rapier. This lowers the needs for a full contact manifold calculation for barely moving objects, improving performances (less calculations) and stacking stability (better warmstarting).
  • Remove some branching through kernel specialization (using macros).
  • Implement mass-splinting to avoid degenerately large amount of colors ("Mass splitting for jitter-free parallel rigid body simulation”, Tonge et al. 2012)
  • Use the AoSoA pattern in the solver (where each constraint “tile” contains the data of a fixed set of constraints in a SoA format).

With these optimizations, we are reaching performances level that get almost as competitive as an AVBD solver (which we don’t support yet), despite remaining on our Soft-TGS solver. Both scenes below are inspired from the AVBD solver’s paper.

Pyramids made of 505K cubes total hit by two balls

Runs in 25ms/step on M4 Max, 14ms/step on an RTX 5080.

rigid_505k_pyramid_walls

A ring of 110K cubes hit by a ball, 11ms/step

Runs in 14ms/step on M4 Max, 8ms/step on an RTX 5080.

rigid_110k_brick_ring

@sebcrozet
sebcrozet merged commit 818974f into main Oct 10, 2026
5 checks passed
@sebcrozet
sebcrozet deleted the rbd-performance branch October 10, 2026 13:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant