Skip to content

sapien: Add version 3.0.3 - #3277

Draft
luhenry wants to merge 2 commits into
mainfrom
port/sapien
Draft

luhenry wants to merge 2 commits into
mainfrom
port/sapien

Conversation

@luhenry

@luhenry luhenry commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Compiles SAPIEN's C++ core (libsapien), the bundled sapien-vulkan-2 renderer and PhysX into one wheel per interpreter. Upstream publishes no riscv64 wheel.

Mirrors upstream's scripts/build_aarch64.sh two-stage --sapien-only/--pybind-only shape, driving manylinux_2_39_riscv64 directly instead of cibuildwheel.

Differs from upstream

  • PhysX is built from source (sapien-sim/PhysX@105.1-physx-5.3.1.patch0, exactly the fork+tag SAPIEN pins) - no riscv64 precompiled archive exists, fed back in via new SAPIEN_PHYSX5_DIR setup.py plumbing.
  • GPU PhysX, CUDA and OpenImageDenoise are off (no CUDA_PATH) - aarch64's own wheel builds them in via the Jetson/Grace sbsa toolkit, which riscv64 has no equivalent of.
  • Installs the same forked auditwheel (fbxiang/auditwheel@fe61bcd) both Linux Dockerfiles already use - it adds a --internal flag so grafted libsapien.so/libsvulkan2.so keep their exact names, independent of architecture.

Matrix: cp312/cp313/cp314/cp314t, built once (not per interpreter) and looped for the pybind step, to avoid rebuilding PhysX and the ~11 sapien-vulkan-2 FetchContent deps four times.

Testing

  • Physics-only smoke test (sapien.Scene + physx_system, no renderer) - no GPU/Vulkan driver on these runners. Upstream's own Linux CI (build.yml) runs no test at all on the wheels it builds.

License: Wheel bundles PhysX (BSD-3) and sapien-vulkan-2's vendored deps (glm/assimp/spdlog/glfw/KTX/Vulkan-Headers/glslang/SPIRV-Cross/imgui/OpenEXR/openvr, mixed BSD/MIT/Apache); unchanged from how upstream's own wheel already ships them.

Patches

  • 0001/0002/0003 (PhysX) - To upstream, not yet submitted. 0001/0002 fix real #error compile blockers (unknown-architecture, unknown-binary-platform); 0003 extends an aarch64-only -Werror relaxation to riscv64. All riscv64-only.
  • 0004/0005/0006 (SAPIEN) - To upstream, not yet submitted. Skip CMake's CUDA language on riscv64 (like macOS), add a bin/linux.riscv64 library path, and thread SAPIEN_PHYSX5_DIR through setup.py. All riscv64-only.
  • 0007 (sapien-vulkan-2/openvr) - Inappropriate, riscv64 build-infra detail. Fixes a mislabeled arch branch in a vendored fork; low-risk either way since openvr_api is never exercised without VR hardware.

Draft: first CI run in progress, a multi-hour heavy C++ build (PhysX from source plus sapien-vulkan-2's FetchContent world) with no prior riscv64 compile to validate against.

Adds build-sapien.yml, docs/packages/sapien.yaml and the patches/sapien/3.0.3
patch set porting SAPIEN 3.0.3 to riscv64.

PhysX is built from source from sapien-sim/PhysX (the exact fork + tag
105.1-physx-5.3.1.patch0 SAPIEN pins, not raw NVIDIA-Omniverse/PhysX; no
riscv64 precompiled archive exists) and fed back in via the new
SAPIEN_PHYSX5_DIR plumbing in setup.py. Six concrete PhysX/SAPIEN sites
needed patching:

- PxPreprocessor.h: new PX_RISCV64 define, folded into PX_P64_FAMILY only
  (not PX_ARM_FAMILY/PX_INTEL_FAMILY). COMPILE_VECTOR_INTRINSICS is gated on
  PX_INTEL_FAMILY||PX_SWITCH only, so riscv64 automatically lands on
  PxVecMathAoSScalar.h -- the same scalar fallback aarch64's own
  precompiled Linux build already ships in production.
- SnSerialUtils.cpp: a tenth binary-platform-tag table entry
  (SN_NUM_BINARY_PLATFORMS 9->10).
- source/compiler/cmake/linux/CMakeLists.txt: extend the aarch64-only
  -Werror relaxation to riscv64 too, rather than exposing a brand new GCC
  target to an x86_64-tuned -Werror exclude list untested.
- Root CMakeLists.txt: skip CMake's CUDA language on riscv64 like macOS
  (project() enables it unconditionally on every non-Apple platform,
  independent of the runtime SAPIEN_CUDA option).
- cmake/physx5.cmake: a dedicated bin/linux.riscv64/release path instead of
  silently reusing the x86_64-labeled bin/linux.clang bucket.
- setup.py: thread --physx5-dir/SAPIEN_PHYSX5_DIR into both cmake
  invocations (there was no CLI/env plumbing for it at all).

Verified directly against sapien-sim/PhysX@105.1-physx-5.3.1.patch0 and
haosulab/SAPIEN@3.0.3 source (sparse sibling clones, not committed here):
PxUnixFPU.h's SIMDGuard #error, flagged by the prior triage as a 6th
compile blocker, turns out to be unreachable on riscv64 -- PxFPU.h only
ever includes it when PX_LINUX&&PX_SSE2, so riscv64 (PX_SSE2=0) already
takes PxFPU.h's own generic no-op ctor/dtor fallback without it. No patch
needed there.

A 7th patch adds an explicit riscv64 branch to the sapien-vulkan-2
submodule's cmake/openvr.cmake (via a FetchContent PATCH_COMMAND against
the comoco-xiao/openvr fork's own CMakeLists.txt, since that source isn't
vendored here): it currently silently takes the x86_64-labeled -DLINUX64
branch instead of -DLINUXARM64's riscv64 equivalent. Low-risk either way
(openvr_api is linked but never exercised without VR hardware) but fixed
for correctness.

build-sapien.yml builds PhysX and SAPIEN's --sapien-only core once (not
per interpreter) inside manylinux_2_39_riscv64, then loops --pybind-only
+ auditwheel repair over cp312/cp313/cp314/cp314t, matching upstream's own
scripts/build.sh/build_aarch64.sh shape. sapien-vulkan-2's 11 FetchContent
deps (glm/assimp-fork/spdlog/glfw/ktx/Vulkan-Headers/glslang/SPIRV-Cross/
imgui/openexr/openvr-fork) are left to CMake's own FetchContent machinery
inside the build step -- this repo's build-openexr.yml/build-glfw.yml/
build-cmeel-zlib.yml/build-cmeel-assimp.yml already prove OpenEXR/glfw/
zlib/assimp source-compile cleanly on manylinux_2_39_riscv64, but that's
signal, not proof, for this different FetchContent-vs-pip-wheel
consumption path; KTX-Software's Basis Universal transcoder was the
remaining worry, but BASISU_SUPPORT_SSE turns out to be a
CMAKE_DEPENDENT_OPTION keyed on CPU_ARCHITECTURE STREQUAL x86_64/x86, so
it already resolves OFF on riscv64 without a patch.

The docker/arm.Dockerfile "forked auditwheel" (fbxiang/auditwheel@fe61bcd)
mystery is resolved: diffed against stock pypa/auditwheel 6.2.0 (its
CHANGELOG base), the fork is a single ~20-line, architecture-independent
`--internal <soname>` flag that skips auditwheel's usual hash-renaming for
named libraries. SAPIEN needs it so the grafted libsapien.so/libsvulkan2.so
keep their exact names (pysapien loads them by fixed filename); x86_64 and
aarch64 Dockerfiles both already carry it. This repo's stock auditwheel
does not support --internal, so the riscv64 build installs the same fork,
not a workaround.

No GPU/Vulkan driver exists on the riscv64 runners, so the wheel test is
physics-only (sapien.Scene + physx_system, no renderer). The
SwiftShader/lavapipe software-Vulkan fallback was not investigated this
pass.

Nothing here has been compiled on riscv64 yet -- there is no riscv64
toolchain available to validate the C++ patches locally, so correctness
of the PhysX cmake invocation (output library layout especially) and the
sapien-vulkan-2 FetchContent compile are unproven until CI actually runs
this workflow.
luhenry added a commit that referenced this pull request Oct 15, 2026
…BIN_DIR

PhysX's NvidiaBuildOptions.cmake hard-requires PX_OUTPUT_LIB_DIR and
PX_OUTPUT_BIN_DIR to be defined (its GameWorks output structure), else
it fails with a CMake FATAL_ERROR before configuration completes. The
riscv64 PhysX cmake invocation was missing both, causing the build job
to fail immediately during PhysX configure.

Upstream's own buildtools/cmake_generate_projects.py always passes
both, pointed at PHYSX_ROOT_DIR, so the find/cp step right after that
expects libraries under /physx-src/physx/bin/... works as intended.

This branch has not been deployed

No deployments
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