Misaligned ABI when using JPH_DOUBLE_PRECISION causes a problem on the VirtualCharacter #1072
-
Hello, I'm integrating Jolt into UE5 and while integrating the After a bunch of tests I've noticed that JPH::CharacterVirtualSettings Settings;
[...]
JPH::CharacterVirtual *CharacterVirtual = new JPH::CharacterVirtual(
&Settings,
Position,
Quat,
JWorld->World_GetPhysicsSystem());
const JPH::RVec3 FetchPosition = CharacterVirtual->GetPosition();
const JPH::Quat FetchQuat = CharacterVirtual->GetRotation();
check(FetchPosition == Position);
check(FetchQuat == Quat); The above checks are not satisfied. I suspected an ABI misalignment. I've then found that compiling the library with double precision disabled ( Consider that on the app side I've defined |
Beta Was this translation helpful? Give feedback.
Replies: 16 comments 3 replies
-
The only thing I can think of is that you have a mismatch in the JPH_DOUBLE_PRECISION define between the two projects. The CharacterVirtual constructor literally just puts the position and rotation as a member and GetPosition/Rotation returns that member. By stepping through the disassembly you can see if both sides use 256 bit registers and if the offsets where it stores/gets the values are the same. |
Beta Was this translation helpful? Give feedback.
-
I wrote |
Beta Was this translation helpful? Give feedback.
-
Check this out, the |
Beta Was this translation helpful? Give feedback.
-
I would say this is a typical symptom of a mismatch in preprocessor defines, but maybe there are other compiler flags that affect the class layout. |
Beta Was this translation helpful? Give feedback.
-
And have you done the same in the Jolt code to verify that it too is being compiled with JPH_DOUBLE_PRECISION? |
Beta Was this translation helpful? Give feedback.
-
Yeah, I totally agree. I think
Yes, I just tested it again. I've added the following static function, inside the CharacterVirtual.cpp, and it returns true, when called from UnrealEngine. This is the command I use to compile jolt:
I wonder, is it possible to get the list of all the preprocessor-defines defined by CMake? |
Beta Was this translation helpful? Give feedback.
-
It looks like you're generating a visual studio project, so wouldn't right clicking the project, Properties, C++, Command Line tell you the exact command line that is used (including all preprocessor defines)? |
Beta Was this translation helpful? Give feedback.
-
This is the command line defines:
This is the check on the Unreal Engine side.
I assume these are the only "external" defines which are required to have on the Unreal Engine side too. Everything seems correct till this point. I wonder if the library linking is broken instead, somehow. |
Beta Was this translation helpful? Give feedback.
-
@jrouwe using this function:
Then, I've duplicated that function inside a jolt lib CPP file and compared the two strings:
As you can notice, even if jolt is compiled using Anyway, I've removed the extra and not used preprocessor define |
Beta Was this translation helpful? Give feedback.
-
The |
Beta Was this translation helpful? Give feedback.
-
If I run cmake with your options (with I use a MSVC plugin called Struct Layout to display the layout of the class and this agrees: However in MSVC 17.9 they added a tool called 'Memory Layout' which agrees with your measurement: The difference is in the beginning of the class, Struct Layout aligns the base class RefTarget<...> to 16 bytes: While Memory Layout does not: If I add Switching to MSVC 2019 or a MSVC Clang-17 build gives me the same trace output. Running the same code on Linux with clang however gives me It appears that MSVC aligns the first member of the class to the largest alignment of any of the members of the class which doesn't really make sense to me, but a simple experiment in godbolt confirms it. If you switch from MSVC to clang x64 18 and suppress a warning
Running either clang++.exe or clang-cl.exe on Windows don't trigger this error, so it must be how the windows ABI is defined. I have no idea what Unreal does to negate this, but you could try the test code in Unreal to see what it does and you could try finding out what |
Beta Was this translation helpful? Give feedback.
-
Thanks a lot for the detailed answer. The misalignment starts from
I think the problem can be fixed by using the same toolchain that unreal is using to compile Jolt. I just need to figure out how, now. |
Beta Was this translation helpful? Give feedback.
-
Ok, in the mean time I reported the problem with the Memory Layout tool to Microsoft here. Converting this to a discussion as I don't think there's a bug in Jolt. |
Beta Was this translation helpful? Give feedback.
-
I've fully refactored my CMake integration and now I'm using this Unreal Engine Plugin to build it. In this way I'm 100% that the Unreal Engine Toolchain is used. The bug is still there. Something else I'm trying to experiment is to instruct CMake to use C++20 (instead of C++17) which is what unreal uses. Maybe the fact that the standard library is different is causing this issue. Is there any specific flag that I've to specify in order to compile Jolt using C++20? |
Beta Was this translation helpful? Give feedback.
-
The problem seems caused by unreal which enforces 4 bytes alignment. Doc It's possible to disable it for third-party libraries. The problem is partially solved, now it crashes only in Packaged build. |
Beta Was this translation helpful? Give feedback.
-
No it defaults to 17 at the moment here: Line 2 in 04ef2e1 and right now there's no way to override it (I'm also not aware of any difference this may cause). |
Beta Was this translation helpful? Give feedback.
The problem seems caused by unreal which enforces 4 bytes alignment. Doc
It's possible to disable it for third-party libraries. The problem is partially solved, now it crashes only in Packaged build.