From 18db417ded3fef2fc3c86a34d48e17f2653bcc42 Mon Sep 17 00:00:00 2001 From: "SOLIDOR\\emper" Date: Fri, 8 May 2026 13:04:07 -0700 Subject: [PATCH] Match JPH per-arch VECTOR alignment so 32-bit ARM links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JPH defines `JPH_VECTOR_ALIGNMENT = 8` on 32-bit ARM (per `JoltPhysics/Jolt/Core/Core.h`: "32-bit ARM does not support aligning on the stack on 16 byte boundaries"), but the JoltC C-side typedefs hardcode `alignas(16)` for `JPC_Vec3` / `Vec4` / `Quat` / `Mat44` (and `alignas(32)` for `JPC_DVec3` / `DMat44`). The mismatch propagates: every settings struct that contains a vector field — `JPC_ShapeCastSettings`, `JPC_CollideShapeSettings`, `JPC_BodyManager_DrawSettings`, `JPC_ContactPoints`, `JPC_ContactManifold` — fails the `LAYOUT_COMPATIBLE` static_assert in `JoltCImpl/JoltC.cpp` with `align of JPC_ did not match align of JPH:: (16 == 8)`. Fix: introduce `JPC_VECTOR_ALIGNMENT` / `JPC_DVECTOR_ALIGNMENT` macros at the top of `JoltC/Functions.h` mirroring JPH's per-architecture branches (x86 / x86_64 / aarch64 / WASM / E2K get 16/32; 32-bit ARM gets 8/8; RISC-V splits on `__riscv_xlen`; PowerPC + LoongArch get 16/8). Replace the six load-bearing `alignas` literals on the vector / matrix typedefs with the macros; the value matches the original on every 64-bit target, so this is a no-op except on the 32-bit ARM path that previously failed the build. Verified locally: - x86_64-pc-windows-msvc host build: passes (no behaviour change) - aarch64-linux-android cross-compile via cargo-ndk r26d: passes - armv7-linux-androideabi cross-compile via cargo-ndk r26d: passes (previously failed at LAYOUT_COMPATIBLE static_assert) --- JoltC/Functions.h | 52 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/JoltC/Functions.h b/JoltC/Functions.h index 500106d..95bf036 100644 --- a/JoltC/Functions.h +++ b/JoltC/Functions.h @@ -11,6 +11,46 @@ #define JPC_API #endif +// Mirror JPH's per-arch VECTOR / DVECTOR alignment logic from +// `JoltPhysics/Jolt/Core/Core.h`. These two values MUST match what JPH +// computes, otherwise the LAYOUT_COMPATIBLE static_asserts in +// `JoltCImpl/JoltC.cpp` fail at build time. +// +// The load-bearing case is 32-bit ARM (e.g. armv7 Android, armv7 Linux): +// JPH falls back to 8-byte alignment because 32-bit ARM cannot stack-align +// to 16 bytes. Without mirroring that fallback here, the C-side `alignas(16)` +// over-constrains `JPC_Vec3` / `Vec4` / `Quat` / `Mat44` / `DVec3` / `DMat44` +// (and every higher-level struct that embeds them: `JPC_ShapeCastSettings`, +// `JPC_CollideShapeSettings`, `JPC_BodyManager_DrawSettings`, +// `JPC_ContactPoints`, `JPC_ContactManifold`, …) and the LAYOUT_COMPATIBLE +// static_assert fires for every settings struct that contains a vector +// field — `align of JPC_ did not match align of JPH:: (16 == 8)`. +#if defined(__aarch64__) || defined(_M_ARM64) || \ + defined(__x86_64__) || defined(_M_X64) || \ + defined(__i386__) || defined(_M_IX86) || \ + defined(__wasm__) || defined(__e2k__) + #define JPC_VECTOR_ALIGNMENT 16 + #define JPC_DVECTOR_ALIGNMENT 32 +#elif defined(__arm__) || defined(_M_ARM) + // 32-bit ARM (the aarch64 case above takes precedence on 64-bit). + #define JPC_VECTOR_ALIGNMENT 8 + #define JPC_DVECTOR_ALIGNMENT 8 +#elif defined(__riscv) + #define JPC_VECTOR_ALIGNMENT 16 + #if __riscv_xlen == 64 + #define JPC_DVECTOR_ALIGNMENT 32 + #else + #define JPC_DVECTOR_ALIGNMENT 8 + #endif +#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__loongarch__) + #define JPC_VECTOR_ALIGNMENT 16 + #define JPC_DVECTOR_ALIGNMENT 8 +#else + // Conservative fallback: assume the common 64-bit shape. + #define JPC_VECTOR_ALIGNMENT 16 + #define JPC_DVECTOR_ALIGNMENT 32 +#endif + static float JPC_PI = 3.14159265358979323846f; // C-compatible typedefs that match Jolt's internal primitive typedefs. @@ -46,7 +86,7 @@ typedef struct JPC_Vec2 { ENSURE_SIZE_ALIGN(JPC_Vec2, JPH::Vector<2>) typedef struct JPC_Vec3 { - alignas(16) float x; + alignas(JPC_VECTOR_ALIGNMENT) float x; float y; float z; float _w; @@ -55,7 +95,7 @@ typedef struct JPC_Vec3 { ENSURE_SIZE_ALIGN(JPC_Vec3, JPH::Vec3) typedef struct JPC_Vec4 { - alignas(16) float x; + alignas(JPC_VECTOR_ALIGNMENT) float x; float y; float z; float w; @@ -64,7 +104,7 @@ typedef struct JPC_Vec4 { ENSURE_SIZE_ALIGN(JPC_Vec4, JPH::Vec4) typedef struct JPC_DVec3 { - alignas(32) double x; + alignas(JPC_DVECTOR_ALIGNMENT) double x; double y; double z; double _w; @@ -73,7 +113,7 @@ typedef struct JPC_DVec3 { ENSURE_SIZE_ALIGN(JPC_DVec3, JPH::DVec3) typedef struct JPC_Quat { - alignas(16) float x; + alignas(JPC_VECTOR_ALIGNMENT) float x; float y; float z; float w; @@ -82,14 +122,14 @@ typedef struct JPC_Quat { ENSURE_SIZE_ALIGN(JPC_Quat, JPH::Quat) typedef struct JPC_Mat44 { - alignas(16) JPC_Vec4 col[3]; + alignas(JPC_VECTOR_ALIGNMENT) JPC_Vec4 col[3]; JPC_Vec3 col3; } JPC_Mat44; ENSURE_SIZE_ALIGN(JPC_Mat44, JPH::Mat44) typedef struct JPC_DMat44 { - alignas(32) JPC_Vec4 col[3]; + alignas(JPC_DVECTOR_ALIGNMENT) JPC_Vec4 col[3]; JPC_DVec3 col3; } JPC_DMat44;