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
15 changes: 8 additions & 7 deletions .github/workflows/build-test-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,16 @@ jobs:
actions: read # This is required for wait-for-job

env:
BUILD_C_SHARP: ${{ matrix.cxx_compiler == 'msvc-2026' && matrix.build_system == 'MSBuild' }}
# The C# bindings are generated and tested on the clang-cl jobs, which also produce the NuGet
# payload (the native DLLs, MRDotNet2.dll and its XML)
BUILD_C_SHARP: ${{ matrix.cxx_compiler == 'clang-cl' }}
PYTEST_C_SHARP_ARGS: --run-c-sharp-samples --csharp-sample-dir=..\source\${{ matrix.arch || 'x64' }}\${{ matrix.config }}
VCPKG_DEFAULT_TRIPLET: ${{ matrix.vcpkg_triplet || 'x64-windows-meshlib' }}
# Upload a developer distributive per Visual Studio toolchain and target
# architecture so update-win-version can repackage each into
# MeshLibDistVS{19,22,26}[-arm64].zip.
# VS2019/VS2022 ship the CMake build; VS2026 ships the MSBuild build
# (which also produces the C#/.NET components). VS_TAG keeps the archive
# names distinct.
# VS2019/VS2022 ship the CMake build; VS2026 ships the MSBuild build.
# VS_TAG keeps the archive names distinct.
job_upload_artifact: ${{ inputs.upload_artifacts && ( matrix.cxx_compiler == 'msvc-2026' && matrix.build_system == 'MSBuild' || matrix.cxx_compiler != 'msvc-2026' && matrix.cxx_compiler != 'clang-cl' && matrix.build_system == 'CMake' ) }}
# Only VS2026 has an arm64 leg, so the suffix separates it from the x64 VS26 archive
VS_TAG: ${{ format('{0}{1}', fromJSON('{"msvc-2019":"VS19","msvc-2022":"VS22"}')[matrix.cxx_compiler] || 'VS26', matrix.arch == 'arm64' && '-arm64' || '') }}
Expand Down Expand Up @@ -489,15 +490,15 @@ jobs:
compression-level: 0

- name: Create and fix fake Wheel for NuGet
if: ${{ inputs.nuget_build && matrix.cxx_compiler == 'msvc-2026' && matrix.config == 'Release' && env.BUILD_C_SHARP == 'true' }}
if: ${{ inputs.nuget_build && matrix.cxx_compiler == 'clang-cl' && matrix.config == 'Release' && env.BUILD_C_SHARP == 'true' }}
run: |
py -3 -m venv wheel_venv
wheel_venv\Scripts\Activate
py -3 -m pip install delvewheel
py -3 ./scripts/nuget_patch/patch_library_deps.py ./patched_content/ ./source/${{ env.MR_ARCH }}/Release/MeshLibC2.dll ./source/${{ env.MR_ARCH }}/Release/MeshLibC2Cuda.dll

- name: Upload NuGet files to Artifacts
if: ${{ inputs.nuget_build && matrix.cxx_compiler == 'msvc-2026' && matrix.config == 'Release' && env.BUILD_C_SHARP == 'true' }}
if: ${{ inputs.nuget_build && matrix.cxx_compiler == 'clang-cl' && matrix.config == 'Release' && env.BUILD_C_SHARP == 'true' }}
uses: actions/upload-artifact@v7
with:
name: DotNetPatchArchiveWindows-${{ env.MR_ARCH }}
Expand All @@ -508,7 +509,7 @@ jobs:
- name: Upload NuGet library DLL and XML to Artifacts
# These are netstandard2.0 and carry no architecture, so take them from the x64
# leg only; the arm64 one would only overwrite them with equivalent assemblies.
if: ${{ inputs.nuget_build && matrix.cxx_compiler == 'msvc-2026' && matrix.config == 'Release' && env.BUILD_C_SHARP == 'true' && matrix.arch != 'arm64' }}
if: ${{ inputs.nuget_build && matrix.cxx_compiler == 'clang-cl' && matrix.config == 'Release' && env.BUILD_C_SHARP == 'true' && matrix.arch != 'arm64' }}
uses: actions/upload-artifact@v7
with:
name: DotNetDllXml
Expand Down
49 changes: 29 additions & 20 deletions .github/workflows/pip-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -462,11 +462,12 @@ jobs:
matrix:
platform: [x64, arm64]
include:
# Both build with the image's clang-cl through CMake, as the clang-cl jobs of build-test-windows.yml:
# x64 on the 14.4 (VS2022) toolset, which CUDA 12 needs, arm64 on VS2026.
- platform: x64
runner: windows-2025
vcpkg-triplet: x64-windows-meshlib
msbuild-platform: x64
msbuild-architecture: x86
vcpkg-triplet: x64-windows-vs2022-meshlib
vcvars-ver: '14.4'
vs-dev-args: -arch=amd64 -host_arch=x86
plat-name: win-amd64
msys2-env: clang64
Expand All @@ -475,12 +476,10 @@ jobs:
cuda-version: '12.0.1'
cuda-major: '12'
cuda-minor: '0'
cuda-platform-toolset: v143
- platform: arm64
runner: windows-11-vs2026-arm
vcpkg-triplet: arm64-windows-meshlib
msbuild-platform: ARM64
msbuild-architecture: arm64
vcvars-ver: '14.5'
vs-dev-args: -arch=arm64 -host_arch=arm64
plat-name: win-arm64
msys2-env: clangarm64
Expand All @@ -489,7 +488,6 @@ jobs:
cuda-version: '13.4.1'
cuda-major: '13'
cuda-minor: '4'
cuda-platform-toolset: ''
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
Expand All @@ -499,9 +497,8 @@ jobs:
CUDA-MAJOR: ${{ matrix.cuda-major }}
CUDA-MINOR: ${{ matrix.cuda-minor }}
VCPKG_DEFAULT_TRIPLET: ${{ matrix.vcpkg-triplet }}
VCVARS_VER: '14.5'
PLATFORM_TOOLSET: v145
CUDA_PLATFORM_TOOLSET: ${{ matrix.cuda-platform-toolset }}
VCVARS_VER: ${{ matrix.vcvars-ver }}
CMAKE_COMPILER_ARGS: -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe" -DCMAKE_C_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe" -DCMAKE_LINKER_TYPE=LLD
MSYS2_ENV: ${{ matrix.msys2-env }}
steps:
- name: Checkout
Expand Down Expand Up @@ -543,16 +540,7 @@ jobs:
with:
cuda-major: ${{ env.CUDA-MAJOR }}
cuda-minor: ${{ env.CUDA-MINOR }}

- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3.0.0
with:
# an x86 MSBuild would make the VC props pick an x86 host compiler, whose address
# space is too small for our PCH when targeting ARM64
msbuild-architecture: ${{ matrix.msbuild-architecture }}

- name: Build
run: msbuild -m source\MeshLib.sln -p:Configuration=Release -p:Platform=${{ matrix.msbuild-platform }} -p:VcpkgTriplet=${{ env.VCPKG_DEFAULT_TRIPLET }} -p:PlatformToolset=${{ env.PLATFORM_TOOLSET }} -p:MRCudaPlatformToolset=${{ env.CUDA_PLATFORM_TOOLSET }} -p:MR_PCH_USE_EXTRA_HEADERS=ON -p:MRVOXELS_UNITY_BUILD=ON -p:MESHLIB_BUILD_MCP=OFF
install-vs-integration: false

- name: Install MSYS2 for MRBind
uses: ./.github/actions/install-msys2-mrbind
Expand All @@ -567,6 +555,27 @@ jobs:
extra-cache-key: ${{ hashFiles(format('scripts/mrbind/msys2_package_hashes{0}.txt', matrix.msys2-pkgs)) }}
msys2-env: ${{ matrix.msys2-env }}

- name: Build
shell: cmd
env:
GETTEXT_ROOT: C:\msys64\clang64
VCPKG_ROOT: C:\vcpkg
VCPKG_TARGET_TRIPLET: ${{ matrix.vcpkg-triplet }}
# The CMake branch of the Build step of build-test-windows.yml, Release only; see the notes there
# on `|| exit /b 1` and on the serial z-applocal pass. VsDevCmd.bat replaces VCPKG_ROOT with the
# VS-bundled vcpkg, whose path has a space, so the project's one is kept aside for the loop.
run: |
set "PROJ_VCPKG_ROOT=%VCPKG_ROOT%"
call "${{ env.VC_PATH }}\Common7\Tools\VsDevCmd.bat" ${{ matrix.vs-dev-args }} -vcvars_ver=${{ env.VCVARS_VER }} || exit /b 1
cmake --version || exit /b 1
cmake -B source\TempOutput -GNinja -DCMAKE_BUILD_TYPE=Release %CMAKE_COMPILER_ARGS% -DVCPKG_TARGET_TRIPLET=%VCPKG_TARGET_TRIPLET% -DVCPKG_APPLOCAL_DEPS=OFF -DMESHLIB_BUILD_GENERATED_C_BINDINGS=OFF -DMESHLIB_BUILD_MRCUDA=${{ matrix.cuda-version != '' && 'ON' || 'OFF' }} -DMESHLIB_BUILD_MCP=OFF -DMR_PCH_USE_EXTRA_HEADERS=ON -DMRVOXELS_UNITY_BUILD=ON || exit /b 1
cmake --build source\TempOutput -j || exit /b 1
for %%b in (source\TempOutput\bin\*.exe source\TempOutput\bin\*.dll) do (
"%PROJ_VCPKG_ROOT%\vcpkg.exe" z-applocal --target-binary="%%b" --installed-bin-dir="%PROJ_VCPKG_ROOT%\installed\%VCPKG_TARGET_TRIPLET%\bin" >nul || exit 1
)
if not exist source\${{ matrix.platform }} mkdir source\${{ matrix.platform }} || exit /b 1
xcopy source\TempOutput\bin\* source\${{ matrix.platform }}\Release\* /s /e /i /Y || exit /b 1

- name: Generate and build MRBind bindings
shell: cmd
env:
Expand Down
9 changes: 5 additions & 4 deletions source/MRDotNet2Test/src/ICPTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ public void TestMultiwayICP()
icp.setParams(iCPProperties);
icp.updateAllPointPairs();

Assert.That(icp.getNumActivePairs(), Is.EqualTo((nuint)1748));
Assert.That(icp.getNumSamples(), Is.EqualTo((nuint)1748));
// 1744 pairs with FMA instructions (clang-cl on arm64), 1748 without
Assert.That((long)icp.getNumActivePairs(), Is.InRange(1744, 1748));
Assert.That((long)icp.getNumSamples(), Is.InRange(1744, 1748));
Assert.That(icp.getMeanSqDistToPoint(), Is.EqualTo(0.00254).Within(1e-5));

Console.WriteLine("Calculating transformations...");
var xfs = icp.calculateTransformations();
Assert.That(icp.getNumActivePairs(), Is.EqualTo((nuint)1748));
Assert.That(icp.getNumSamples(), Is.EqualTo((nuint)1748));
Assert.That((long)icp.getNumActivePairs(), Is.InRange(1744, 1748));
Assert.That((long)icp.getNumSamples(), Is.InRange(1744, 1748));
Assert.That(icp.getMeanSqDistToPoint(), Is.EqualTo(0).Within(1e-5));
}

Expand Down
13 changes: 7 additions & 6 deletions source/MRDotNet2Test/src/MeshCollideTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,17 @@ public void TestMeshCollidePrecise()
else
edgeBTriACount++;
}
Assert.That(edgeATriBCount, Is.EqualTo(80));
Assert.That(edgeBTriACount, Is.EqualTo(72));
// the second values are with FMA instructions (clang-cl on arm64), as in the C++ test of MRMeshBooleanTests.cpp
Assert.That(edgeATriBCount, Is.EqualTo(80).Or.EqualTo(76));
Assert.That(edgeBTriACount, Is.EqualTo(72).Or.EqualTo(76));

var contours = orderIntersectionContours(meshA.topology, meshB.topology, intersections);

Assert.That(contours.size(), Is.EqualTo((nuint)4));
Assert.That(contours[0].size(), Is.EqualTo((nuint)71));
Assert.That(contours[1].size(), Is.EqualTo((nuint)7));
Assert.That(contours[2].size(), Is.EqualTo((nuint)69));
Assert.That(contours[3].size(), Is.EqualTo((nuint)9));
Assert.That(contours[0].size(), Is.EqualTo((nuint)71).Or.EqualTo((nuint)69));
Assert.That(contours[1].size(), Is.EqualTo((nuint)7).Or.EqualTo((nuint)9));
Assert.That(contours[2].size(), Is.EqualTo((nuint)69).Or.EqualTo((nuint)71));
Assert.That(contours[3].size(), Is.EqualTo((nuint)9).Or.EqualTo((nuint)7));
var aConts = new Std.Vector_MROneMeshContour();
getOneMeshIntersectionContours(meshA, meshB, contours, aConts, null, conv);
Assert.That(aConts.size(), Is.EqualTo((nuint)4));
Expand Down
16 changes: 10 additions & 6 deletions source/MRDotNet2Test/src/MeshTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,12 @@ public void TestProjection()
Assert.That(projRes.proj.point.y, Is.EqualTo(0.507).Within(1e-3));
Assert.That(projRes.proj.point.z, Is.EqualTo(0.803).Within(1e-3));

Assert.That(projRes.mtp.e.id, Is.EqualTo(1640));
Assert.That(projRes.mtp.bary.a, Is.EqualTo(0.053).Within(1e-3));
Assert.That(projRes.mtp.bary.b, Is.EqualTo(0.946).Within(1e-3));
// which edge of the triangle represents the point differs with FMA instructions (clang-cl on arm64)
Assert.That(mesh.topology.left(projRes.mtp.e).id, Is.EqualTo(904));
var mtpPoint = mesh.triPoint(projRes.mtp);
Assert.That(mtpPoint.x, Is.EqualTo(0.310).Within(1e-3));
Assert.That(mtpPoint.y, Is.EqualTo(0.507).Within(1e-3));
Assert.That(mtpPoint.z, Is.EqualTo(0.803).Within(1e-3));

var xf = AffineXf3f.translation(Vector3f.diagonal(1.0f));
projRes = findProjection(p, mesh, float.MaxValue, xf);
Expand All @@ -333,9 +336,10 @@ public void TestProjection()
Assert.That(projRes.proj.point.y, Is.EqualTo(1.439).Within(1e-3));
Assert.That(projRes.proj.point.z, Is.EqualTo(1.895).Within(1e-3));

Assert.That(projRes.mtp.e.id, Is.EqualTo(1898));
Assert.That(projRes.mtp.bary.a, Is.EqualTo(0.5).Within(1e-3));
Assert.That(projRes.mtp.bary.b, Is.EqualTo(0.0).Within(1e-3));
mtpPoint = mesh.triPoint(projRes.mtp); // in mesh space, before xf
Assert.That(mtpPoint.x, Is.EqualTo(0.000).Within(1e-3));
Assert.That(mtpPoint.y, Is.EqualTo(0.439).Within(1e-3));
Assert.That(mtpPoint.z, Is.EqualTo(0.895).Within(1e-3));
}

[Test]
Expand Down
2 changes: 1 addition & 1 deletion source/MRVoxels/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ ENDIF()

IF(NOT MRVOXELS_NO_DICOM)
find_package(GDCM CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE gdcmIOD gdcmDICT gdcmDSED gdcmMEXD gdcmMSFF)
target_link_libraries(${PROJECT_NAME} PRIVATE gdcmIOD gdcmDICT gdcmDSED gdcmMSFF)
ENDIF()

IF(MR_PCH)
Expand Down
Loading