Skip to content

Conversation

@zfergus
Copy link
Member

@zfergus zfergus commented Sep 2, 2025

Description

This pull request introduces a new broad phase collision detection method (LBVH), adds a performance profiling utility, and performs significant memory optimizations on the AABB structure. It also updates the build system and Python bindings.

Type of change

  • Enhancement (non-breaking change which improves existing functionality)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

🚀 New Features

  • LBVH Broad Phase:

    • Implemented LBVH class in src/ipc/broad_phase/lbvh.hpp, providing a Linear Bounding Volume Hierarchy method for broad phase collision detection.
    • Fully parallel build and traversal routines using Intel TBB.
    • SIMD optimizations for AABB overlap tests.
      • Limited to Apple devices for now (using <simd/simd.h> library).
    • Faster than the existing BVH method and all other broad phase methods in IPC Toolkit for large scenes.
      • More than 3x faster to build.
      • Up to 1.5x faster for candidate detection.
      • Detailed performance charts available below.
    • Added python/examples/lbvh.py to demonstrate usage and visualization.
  • Performance Profiling:

    • Added a (optional) profiler utility (src/ipc/utils/profiler.hpp) to measure/record metrics with CSV output support.
    • Added Nlohmann JSON as a dependency for profiler storage.
    • Use IPC_TOOLKIT_WITH_PROFILER CMake option to enable/disable profiling.
benchmark_broadphase_build_mac

Construction Performance. `LBVH` construction is more than 3x faster than `BVH`.
Benchmarked on Apple M2 Max with 12 cores.

benchmark_broadphase_mac

Broad Phase Benchmark (Mac). LBVH total performance is approximately 1.5x faster than the fastest available method.
Benchmarked on Apple M2 Max (12 Cores) CPU and 96 GB RAM. LBVH utilizes SIMD for AABB overlap tests on Apple devices.

benchmark_broadphase_linux

Broad Phase Benchmark (Linux). LBVH total performance is approximately 1.5x faster than the fastest available method.
Benchmarked on Linux with Intel Ultra 9 285K (24 Cores) CPU, NVIDIA GeForce RTX 5080 GPU, and 64 GB RAM. LBVH well exceeds the performance of STQ, which is implemented in CUDA, while LBVH is CPU-only.

⚡ Enhancements

  • Performance Optimizations:
    • Added DefaultInitAllocator to reduce overhead when allocating large arrays of POD types.
    • Replaced std::vector<AABB> with std::vector<AABB, DefaultInitAllocator<AABB>>.
  • Memory Optimization:
    • Switched AABB::min and AABB::max from ArrayMax3d to Eigen::Array3d.
    • Result: Reduces sizeof(AABB) from 76 to 64 bytes, allowing AABB to fit into a single cache line (assuming 64-byte lines).
  • Accuracy & Code Health:
    • Replaced hardware rounding in AABB::conservative_inflation with software rounding using std::nextafter.
    • Removed warnings -Wgnu-anonymous-struct and -Wnested-anon-types.
    • Updated Python CI: Added Python 3.14 testing; dropped Python 3.9 testing.
    • Updated test data with new simulation scenes.

💥 Breaking Changes

  • API & Structural Changes:
    • Moved dimension variable: Removed dim from AABB and moved it to BroadPhase to handle 2D/3D data more cleanly. dim is now set in BroadPhase::build.
    • Handle 2D data by setting AABB's z-components to zero.
    • Constructor Removal: Removed the AABB default constructor and the initialization of AABB::vertex_ids.
    • Type Change: Changed to_3D in ipc/utils/eigen_ext.hpp to operate on Eigen::Array types instead of Eigen::Vector.
  • Deprecations:
    • Deprecated BVH class in favor of the new LBVH class for better performance on large scenes.

How Has This Been Tested?

  • New and existing broad phase tests
  • New scene files

Test Configuration:

  • OS and Version: macOS Tahoe 26.2
  • Compiler and Version: Apple clang version 17.0.0

Checklist

  • I have followed the project style guide
  • My code follows the clang-format style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

…ing support

- Introduced LBVH class for efficient broad phase collision detection.
- Implemented LBVH node structure with AABB intersection checks.
- Added methods for detecting vertex-vertex, edge-vertex, edge-edge, face-vertex, edge-face, and face-face candidates.
- Integrated profiling functionality with IPC_TOOLKIT_WITH_PROFILER flag.
- Updated CMakeLists to include new LBVH test files and source files.
- Added tests for LBVH construction and candidate detection.
- Included Python bindings for LBVH and example usage scripts.
- Enhanced configuration options in config.hpp for profiling support.
@codecov
Copy link

codecov bot commented Sep 2, 2025

Codecov Report

❌ Patch coverage is 96.23016% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.34%. Comparing base (f6ee986) to head (91ff457).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/ipc/broad_phase/lbvh.cpp 95.43% 14 Missing ⚠️
src/ipc/broad_phase/spatial_hash.cpp 81.25% 3 Missing ⚠️
src/ipc/utils/default_init_allocator.hpp 71.42% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #188      +/-   ##
==========================================
- Coverage   97.37%   97.34%   -0.03%     
==========================================
  Files         157      161       +4     
  Lines       24240    24664     +424     
  Branches      843      877      +34     
==========================================
+ Hits        23604    24010     +406     
- Misses        636      654      +18     
Flag Coverage Δ
unittests 97.34% <96.23%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@zfergus zfergus added the enhancement New feature or request label Oct 1, 2025
Copilot AI review requested due to automatic review settings January 16, 2026 14:54
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a parallel CPU implementation of Linear Bounding Volume Hierarchy (LBVH) for broad-phase collision detection and adds performance profiling capabilities. The LBVH uses Morton codes for efficient spatial sorting and parallel construction.

Changes:

  • Implemented LBVH broad-phase collision detection method with parallel construction using TBB
  • Added profiler utility with CSV export and optional compilation via CMake flag
  • Integrated profiling blocks into BVH and LBVH implementations

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/ipc/broad_phase/lbvh.hpp Defines LBVH class with Node structure and detection methods
src/ipc/broad_phase/lbvh.cpp Implements LBVH construction using Morton codes and parallel traversal
src/ipc/utils/profiler.hpp Profiler header with timing macros and data structures
src/ipc/utils/profiler.cpp Profiler implementation with CSV export functionality
tests/src/tests/broad_phase/test_lbvh.cpp Test cases for LBVH construction and candidate detection
python/examples/lbvh.py Python example demonstrating LBVH visualization
CMakeLists.txt Adds profiler option and nlohmann/json dependency
.github/workflows/python.yml Updates Python version to 3.14
.clang-format Removes Language and RemoveEmptyLinesInUnwrappedLines options

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Updated the LBVH Node structure to use Eigen::Array3f for AABB representation, improving compactness of Nodes.
- Introduced a union in the Node structure to efficiently manage leaf and internal node data, reducing memory usage and cache misses.
- Added functions for calculating 2D and 3D Morton codes in a new morton.hpp file, enhancing spatial indexing capabilities.
- Modified the test suite for LBVH to include checks for candidate presence rather than exact size matches, improving robustness of collision detection tests.
- Updated CMakeLists.txt to include the new morton.hpp file.
- Adjusted utility functions to maintain consistency with the new data types and structures.
- Updated test data with new simulation scenes
Updated bit-shift constants in morton_2D and morton_3D to use 1ULL instead of 1ul or 1, ensuring explicit 64-bit unsigned long long type. This improves type safety and portability across platforms with differing type sizes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 16 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +48
void Profiler::start(const std::string& name)
{
current_scope.push_back(name);
if (!m_data.contains(current_scope)) {
m_data[current_scope] = {
{ "time_ms", 0 },
{ "count", 0 },
};
}
}

void Profiler::stop(const double time_ms)
{
const static std::string log_fmt_text = fmt::format(
"[{}] {{}} {{:.6f}} ms",
fmt::format(fmt::fg(fmt::terminal_color::magenta), "timing"));

logger().trace(
fmt::runtime(log_fmt_text), current_scope.to_string(), time_ms);

assert(m_data.contains(current_scope));
assert(m_data.at(current_scope).contains("time_ms"));
assert(m_data.at(current_scope).contains("count"));
m_data[current_scope]["time_ms"] =
m_data[current_scope]["time_ms"].get<double>() + time_ms;
m_data[current_scope]["count"] =
m_data[current_scope]["count"].get<size_t>() + 1;
current_scope.pop_back();
}
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The m_data JSON object is being modified concurrently from multiple threads without synchronization (lines 23-28, 43-46). Multiple threads can call start() and stop() simultaneously, leading to data races when reading/writing the JSON object. This needs proper synchronization with mutexes or atomic operations.

Copilot uses AI. Check for mistakes.
zfergus and others added 6 commits January 20, 2026 12:21
- Store dimension of the scene inside the BroadPhase class.
- Updated broad phase classes (HashGrid, LBVH, SpatialHash, SweepAndPrune, STQ) to replace custom array types with Eigen's Array3i and Array3d for better performance and consistency.
- Introduced DefaultInitAllocator to avoid unnecessary initialization overhead in vectors used in LBVH.
- Modified build methods across various classes to accept AABBs instead of std::vector<AABB>, ensuring compatibility with the new data structures.
- Enhanced parallel processing in LBVH and SpatialHash for copying vertex IDs and building BVH structures.
- Updated tests to reflect changes in data types and method signatures, ensuring all tests pass with the new implementations.
@zfergus zfergus added this to the v1.5.0 milestone Jan 26, 2026
Mark BVH enum/class as deprecated in favor of LBVH.

Adjust LBVH parallel traversal batching: reduce SIMD grain
size on Apple, fix task range and indexing to correctly handle
SIMD tails and avoid out-of-range leaf accesses.

Rewrite merge_thread_local helpers to allow stealing and
clearing per-thread buffers, add a fast memcpy path for
trivially-copyable types, move remaining items for non-trivial
types, and add profiling hooks.
@zfergus zfergus merged commit 935e8af into main Jan 26, 2026
21 checks passed
@zfergus zfergus deleted the lbvh branch January 26, 2026 02:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants