Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix aliasing issue in framework #300

Merged
merged 1 commit into from
Oct 4, 2024

Conversation

Lamakaio
Copy link
Contributor

A proposal for a fix of aliasing issues in framework, using some memcpy calls. They should be optimized away because the compiler is smart.

bit_cast also exists, but apparently it cannot be used to cast between arrays with elements of different size.

I bundled a small fix for jolt that was still pending, because I don't want to make a whole pull request for 1 line.

@Lamakaio
Copy link
Contributor Author

Lamakaio commented Sep 27, 2024

It looks like a problem with the way I compute the sizes of intermediate array, which triggers static analysis somehow. Not sure what to do about it. nvm it was a dumb mistake, I rewrote the commits.

Copy link
Contributor

@Capital-Asterisk Capital-Asterisk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old code with the funny comment worked because it worked with an unsigned char array first, then used it to initialize a struct afterwards.

This memcpy approach looks a little cleaner.

About bit_cast, an alternative approach may be to use arrays of PipelineDefBlank_t that are bit_casted at the end with return { .pl = std::bit_cast<typename FI_T::Pipelines>(...) ... };. (bit_casting an array to a struct of the same size)

PipelineDefBlank_t plMembers[members_size] ;
std::memcpy(plMembers, &out.pl, sizeof(typename FI_T::Pipelines));
//auto const plMembers = arrayCast<PipelineDefBlank_t>( arrayCast<std::byte>( arrayView(&out.pl, 1) ) );
for (std::size_t i = 0; i < members_size; ++i)
{
plMembers[i].m_value = rInterface.pipelines[i];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not memcpy directly with a pointer to plMembers[i].m_value instead of needing an intermediate array? wouldn't these assignments (including diMembers[i] = rInterface.data[i]; below) be the only lines that needs to be changed?

Assuming auto const plMembers was mistaken for an array? It's actually an ArrayView (pointer and size), not an array.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could test it.
I thought the cast to ArrayView was the problem. The compiler might understand a memcpy of size 4 exactly the same way it does a simple assignment.

What makes it work here for me is that the cast from opaque struct to array is done through memcpy and not ArrayView ?

auto const plMembers = arrayCast<PipelineDefBlank_t>( arrayCast<std::byte>( arrayView(&out.pl, 1) ) );
for (std::size_t i = 0; i < plMembers.size(); ++i)
constexpr size_t members_size = sizeof(typename FI_T::Pipelines)/sizeof(PipelineDefBlank_t);
PipelineDefBlank_t plMembers[members_size] ;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: I mentioned this intermediate array is likely not needed, though C-style arrays are generally avoided.

if constexpr ( ! std::is_empty_v<typename FI_T::Pipelines> )
{
auto const plMembers = arrayCast<PipelineDefBlank_t>( arrayCast<std::byte>( arrayView(&out.pl, 1) ) );
for (std::size_t i = 0; i < plMembers.size(); ++i)
constexpr size_t members_size = sizeof(typename FI_T::Pipelines)/sizeof(PipelineDefBlank_t);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

camelCase (though this variable may not be needed)

@@ -623,7 +623,7 @@ static void rocket_thrust_force(BodyId const bodyId, ACtxJoltWorld const& rJolt,

JPH::BodyID joltBodyId = BToJolt(bodyId);
Quaternion const rot = QuatJoltToMagnum(bodyInterface.GetRotation(joltBodyId));
RVec3 joltCOM = bodyInterface.GetCenterOfMassPosition(joltBodyId) - bodyInterface.GetPosition(joltBodyId);
RVec3 joltCOM = bodyInterface.GetPosition(joltBodyId) - bodyInterface.GetCenterOfMassPosition(joltBodyId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the pendulum effect the rockets are having?

The issue here is that GetCenterOfMassPosition takes (world) rotation in account when it shouldn't. I worked this out on Capital-Asterisk@463fe6e , part of the commit I sent on the gdextension pull request. This can just be cherry-picked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh well perfect then.

constexpr size_t members_size = sizeof(typename FI_T::Pipelines)/sizeof(PipelineDefBlank_t);
PipelineDefBlank_t plMembers[members_size] ;
std::memcpy(plMembers, &out.pl, sizeof(typename FI_T::Pipelines));
//auto const plMembers = arrayCast<PipelineDefBlank_t>( arrayCast<std::byte>( arrayView(&out.pl, 1) ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to keep commented out code

@Lamakaio
Copy link
Contributor Author

I changed the memcpy to just replace the array assignement. Is this what you suggested @Capital-Asterisk ?

If that looks good I'll rewrite the commit history to remove the Jolt stuff and get a single commit.

Copy link
Contributor

@Capital-Asterisk Capital-Asterisk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this what you suggested @Capital-Asterisk ?

looks good!

}
}

if constexpr ( ! std::is_empty_v<typename FI_T::DataIds> )
{
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very minor: excess spacing

if constexpr ( ! std::is_empty_v<typename FI_T::Pipelines> )
{
auto const plMembers = arrayCast<PipelineDefBlank_t>( arrayCast<std::byte>( arrayView(&out.pl, 1) ) );
for (std::size_t i = 0; i < plMembers.size(); ++i)
{
plMembers[i].m_value = rInterface.pipelines[i];
memcpy(&plMembers[i].m_value, &rInterface.pipelines[i], sizeof(PipelineId));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: std::memcpy. iirc, this is C's memcpy from <string.h>, instead of <cstring>

@Lamakaio
Copy link
Contributor Author

Should be good !

@Capital-Asterisk Capital-Asterisk self-requested a review September 28, 2024 18:15
@Capital-Asterisk Capital-Asterisk merged commit b67b90b into TheOpenSpaceProgram:master Oct 4, 2024
22 checks passed
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.

2 participants