Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 30 additions & 9 deletions .github/workflows/continuous.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,40 +80,52 @@ jobs:
echo "CPU: $(grep -m1 '^model name' /proc/cpuinfo | cut -d: -f2-)"
echo "SIMD_ARGS=-DSIMD_CXX_FLAGS=-march=x86-64-v3" >> "$GITHUB_ENV"

- name: Cache Build
id: cache-build
uses: actions/cache@v5
# Cache entries are immutable, so a fixed key is saved once and never
# updated. We give each run its own key and restore the newest one by
# prefix instead. Only pushes to main save (see "Save ccache" below), and
# PRs restore from those.
- name: Restore ccache
uses: actions/cache/restore@v5
with:
path: ${{ env.CACHE_PATH }}
key: ${{ runner.os }}-${{ matrix.config }}-cache
key: ${{ runner.os }}-${{ matrix.config }}-ccache-${{ github.run_id }}
restore-keys: ${{ runner.os }}-${{ matrix.config }}-ccache-

- name: Prepare ccache
run: |
ccache --max-size=1.0G
ccache -V && ccache --show-config
ccache --show-stats && ccache --zero-stats

# Debug keeps the asserts (NDEBUG stays undefined) and -O0 but drops -g.
# Debug info made the Debug ccache about 20x larger than Release, and CI
# never reads it: assert and Catch2 messages carry __FILE__ and __LINE__.
# Debug keeps the asserts (NDEBUG stays undefined) but drops -g and builds
# at -O1. Debug info made the Debug ccache about 20x larger than Release,
# and CI never reads it: assert and Catch2 messages carry __FILE__ and
# __LINE__. At -O0 none of Eigen's small template functions get inlined,
# which made the Debug tests about 10x slower than Release. -O1 lets the
# compiler inline most of them, and every assert is still checked.
- name: Configure (Linux/macOS)
if: runner.os != 'Windows'
run: |
mkdir -p build
cd build
cmake .. \
-DIPC_TOOLKIT_BUILD_TESTS=ON \
-DCMAKE_C_FLAGS_DEBUG=-O0 \
-DCMAKE_CXX_FLAGS_DEBUG=-O0 \
-DCMAKE_C_FLAGS_DEBUG=-O1 \
-DCMAKE_CXX_FLAGS_DEBUG=-O1 \
$SIMD_ARGS \
-DCMAKE_BUILD_TYPE=${{ matrix.config }}

# MSVC's default Debug flags include /Zi, which writes debug info to a
# shared PDB that ccache cannot cache, so we drop it the same way the
# Linux/macOS configure drops -g.
- name: Configure (Windows)
if: runner.os == 'Windows'
shell: cmd
run: |
cmake -G Ninja ^
-DIPC_TOOLKIT_BUILD_TESTS=ON ^
-DCMAKE_C_FLAGS_DEBUG="/Od /Ob0 /RTC1" ^
-DCMAKE_CXX_FLAGS_DEBUG="/Od /Ob0 /RTC1" ^
-DCMAKE_BUILD_TYPE=${{ matrix.config }} ^
-B build ^
-S .
Expand All @@ -130,5 +142,14 @@ jobs:
run: |
cmake --build build -j ${{ steps.cpu-cores.outputs.count }} && ccache --show-stats

# We save after a failed build too, so the next run reuses what did
# compile.
- name: Save ccache
if: ${{ !cancelled() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
uses: actions/cache/save@v5
with:
path: ${{ env.CACHE_PATH }}
key: ${{ runner.os }}-${{ matrix.config }}-ccache-${{ github.run_id }}

- name: Tests
run: cd build; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }}
18 changes: 14 additions & 4 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,15 @@ jobs:
done
echo "CPU: $(grep -m1 '^model name' /proc/cpuinfo | cut -d: -f2-)"

- name: Cache Build
id: cache-build
uses: actions/cache@v5
# Cache entries are immutable, so a fixed key is saved once and never
# updated. We give each run its own key and restore the newest one by
# prefix instead. Only pushes to main save, and PRs restore from those.
- name: Restore ccache
uses: actions/cache/restore@v5
with:
path: ${{ env.CACHE_PATH }}
key: coverage-cache
key: coverage-ccache-${{ github.run_id }}
restore-keys: coverage-ccache-

- name: Prepare ccache
run: |
Expand All @@ -74,6 +77,13 @@ jobs:
cmake --build build -j ${{ steps.cpu-cores.outputs.count }}
ccache --show-stats

- name: Save ccache
if: ${{ !cancelled() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
uses: actions/cache/save@v5
with:
path: ${{ env.CACHE_PATH }}
key: coverage-ccache-${{ github.run_id }}

- name: Run Coverage
run: |
cd build
Expand Down
21 changes: 15 additions & 6 deletions .github/workflows/cuda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,16 @@ jobs:
echo "CPU: $(grep -m1 '^model name' /proc/cpuinfo | cut -d: -f2-)"

# The CUDA key gets its own prefix because continuous.yml uses the same
# <os>-<config> names, and cache entries are immutable. Whichever workflow
# saved first would otherwise own the entry for both builds.
- name: Cache Build
id: cache-build
uses: actions/cache@v5
# <os>-<config> names. Cache entries are immutable, so a fixed key is
# saved once and never updated. We give each run its own key and restore
# the newest one by prefix instead. Only pushes to main save, and PRs
# restore from those.
- name: Restore ccache
uses: actions/cache/restore@v5
with:
path: ${{ env.CACHE_PATH }}
key: cuda-${{ runner.os }}-${{ matrix.config }}-cache
key: cuda-${{ runner.os }}-${{ matrix.config }}-ccache-${{ github.run_id }}
restore-keys: cuda-${{ runner.os }}-${{ matrix.config }}-ccache-

- name: Prepare ccache
shell: bash
Expand Down Expand Up @@ -185,6 +187,13 @@ jobs:
cmake --build build -j ${{ steps.cpu-cores.outputs.count }}
ccache --show-stats

- name: Save ccache
if: ${{ !cancelled() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
uses: actions/cache/save@v5
with:
path: ${{ env.CACHE_PATH }}
key: cuda-${{ runner.os }}-${{ matrix.config }}-ccache-${{ github.run_id }}

# The GPU unit tests, minus the CCD and STQ ones on the cloth and puffer
# ball meshes, which take several minutes each on a simulated GPU.
- name: Tests
Expand Down
18 changes: 14 additions & 4 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,15 @@ jobs:
python -m pip install --upgrade pip
pip install -r docs/requirements.txt

- name: Cache Build
id: cache-build
uses: actions/cache@v5
# Cache entries are immutable, so a fixed key is saved once and never
# updated. We give each run its own key and restore the newest one by
# prefix instead.
- name: Restore ccache
uses: actions/cache/restore@v5
with:
path: ${{ env.CACHE_PATH }}
key: docs-ccache
key: docs-ccache-${{ github.run_id }}
restore-keys: docs-ccache-

- name: Prepare Ccache
run: |
Expand Down Expand Up @@ -120,6 +123,13 @@ jobs:
pip install --verbose .
ccache --show-stats

- name: Save ccache
if: ${{ !cancelled() }}
uses: actions/cache/save@v5
with:
path: ${{ env.CACHE_PATH }}
key: docs-ccache-${{ github.run_id }}

- name: Build docs
run: |
cd docs
Expand Down
33 changes: 29 additions & 4 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,21 @@ jobs:
choco install ccache
"CACHE_PATH=${env:LOCALAPPDATA}\ccache" | Out-File -FilePath $env:GITHUB_ENV -Append

# scikit-build-core picks the Visual Studio generator on Windows. That
# generator ignores CMAKE_<LANG>_COMPILER_LAUNCHER, so ccache never runs,
# and it compiles the files of each target one at a time. We use Ninja
# instead, which needs the MSVC environment set up first.
- name: Setup MSVC (Windows)
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64

- name: Use Ninja (Windows)
if: runner.os == 'Windows'
run: |
"CMAKE_GENERATOR=Ninja" | Out-File -FilePath $env:GITHUB_ENV -Append

# On Linux, explicitly build for x86-64-v3 instead of -march=native. This
# avoids issues with ccache restoring from a runner with a different ISA.
- name: Check x86-64-v3 support (Linux)
Expand All @@ -101,12 +116,15 @@ jobs:
done
echo "CPU: $(grep -m1 '^model name' /proc/cpuinfo | cut -d: -f2-)"

- name: Cache Build
id: cache-build
uses: actions/cache@v5
# Cache entries are immutable, so a fixed key is saved once and never
# updated. We give each run its own key and restore the newest one by
# prefix instead. Only pushes to main save, and PRs restore from those.
- name: Restore ccache
uses: actions/cache/restore@v5
with:
path: ${{ env.CACHE_PATH }}
key: ${{ runner.os }}-Python${{ matrix.python-version }}-cache
key: ${{ runner.os }}-Python${{ matrix.python-version }}-ccache-${{ github.run_id }}
restore-keys: ${{ runner.os }}-Python${{ matrix.python-version }}-ccache-

- name: Prepare Ccache
run: |
Expand All @@ -120,6 +138,13 @@ jobs:
run: |
pip install --verbose . && ccache --show-stats

- name: Save ccache
if: ${{ !cancelled() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
uses: actions/cache/save@v5
with:
path: ${{ env.CACHE_PATH }}
key: ${{ runner.os }}-Python${{ matrix.python-version }}-ccache-${{ github.run_id }}

- name: Tests
run: |
pip install -r python/tests/requirements.txt
Expand Down
27 changes: 17 additions & 10 deletions tests/src/tests/collisions/test_thickness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <ipc/ipc.hpp>
#include <ipc/barrier/adaptive_stiffness.hpp>
#include <ipc/ccd/tight_inclusion_ccd.hpp>
#include <ipc/candidates/candidates.hpp>
#include <ipc/collision_mesh.hpp>
#include <ipc/collisions/normal/normal_collisions.hpp>
Expand Down Expand Up @@ -242,13 +243,17 @@ TEST_CASE("Plane-vertex with a thickness", "[collisions][thickness][plane]")

TEST_CASE("CCD stops at the thickness", "[ccd][thickness]")
{
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(NDEBUG)
SKIP("'CCD stops at the thickness' test is skipped in debug mode");
#endif

const auto broad_phase = GENERATE(tests::BroadPhaseGenerator::create());
CAPTURE(broad_phase->name());

// Tight Inclusion slows down sharply as the minimum separation grows,
// because every point within the thickness counts as a root it has to
// refine. With a 0.2 separation and the default 1e-6 tolerance, this test
// took 30-100 s in Release and over 20 minutes in Debug. We only check the
// step to within 0.1, so a 1e-3 tolerance loses nothing and runs about
// 20x faster.
const TightInclusionCCD ccd(/*tolerance=*/1e-3);

Eigen::MatrixXd V0, V1;
Eigen::MatrixXi E, F;
two_triangles(/*gap=*/1, V0, E, F);
Expand All @@ -259,13 +264,13 @@ TEST_CASE("CCD stops at the thickness", "[ccd][thickness]")
const double thickness = 0.1; // per face, so a pair rests 0.2 apart

const double plain_step = compute_collision_free_stepsize(
mesh, V0, V1, /*min_distance=*/std::nullopt, broad_phase.get());
mesh, V0, V1, /*min_distance=*/std::nullopt, broad_phase.get(), ccd);
CHECK(plain_step <= 0.5);
CHECK(plain_step > 0.3);

mesh.set_face_thickness(Eigen::Vector2d::Constant(thickness));
const double step = compute_collision_free_stepsize(
mesh, V0, V1, /*min_distance=*/std::nullopt, broad_phase.get());
mesh, V0, V1, /*min_distance=*/std::nullopt, broad_phase.get(), ccd);
// Contact at a gap of 0.2, so z = 0.2 at t = 0.4.
CHECK(step <= 0.4);
CHECK(step > 0.3);
Expand All @@ -274,18 +279,20 @@ TEST_CASE("CCD stops at the thickness", "[ccd][thickness]")
// A min_distance (deprecated) overrides the thickness.
CHECK(
compute_collision_free_stepsize(
mesh, V0, V1, /*min_distance=*/0.0, broad_phase.get())
mesh, V0, V1, /*min_distance=*/0.0, broad_phase.get(), ccd)
== Catch::Approx(plain_step));

Eigen::MatrixXd V_close = V0;
V_close.bottomRows(3).col(2).setConstant(0.15);
CHECK(!is_step_collision_free(
mesh, V0, V_close, /*min_distance=*/std::nullopt, broad_phase.get()));
mesh, V0, V_close, /*min_distance=*/std::nullopt, broad_phase.get(),
ccd));
CHECK(is_step_collision_free(
mesh, V0, V_close, /*min_distance=*/0.0, broad_phase.get()));
mesh, V0, V_close, /*min_distance=*/0.0, broad_phase.get(), ccd));
mesh.clear_thickness();
CHECK(is_step_collision_free(
mesh, V0, V_close, /*min_distance=*/std::nullopt, broad_phase.get()));
mesh, V0, V_close, /*min_distance=*/std::nullopt, broad_phase.get(),
ccd));
}

TEST_CASE(
Expand Down
Loading