Closed aleksa2808 closed 6 months ago
Merging #94 first would make fixing this a bit simpler, because then it's just one place to change the hasher.
@aleksa2808 Thanks for the detailed write-up. Do you want to contribute this as a PR (casting to u64 and replacing with SeaHash or another portable hasher)?
Sure, I can make this a PR. I'm just not sure what to do with SeaHash
as I'm currently using my own fork of it where I intentionally panic when trying to hash usize
/isize
values since this would lead to desyncs on different architectures. I could use the original, non-panicky version, but I feel like users could easily make the mistake of hashing some .len()
value for example and in this case I think it is good to error out (or better yet prevent compilation if possible). Do you have any ideas regarding this?
We don't necessarily have to do everything in one go. We could do it like this:
usize
in internal checksumsaHash
to SeaHash
or something elseHey @johanhelsing, sorry for the late reply. I created a PR for this now with both changes included as they are both essential to calculate checksums in a portable manner.
Additionally, regarding the mentioned SeaHash
fork, in this PR I used the regular, crates.io
provided version. This means that users will still be able to use usize
/isize
types in their code which would break portability, so it is a good idea to have this mentioned in a gotcha.
Describe the bug
When running
bevy_ggrs
on two different architectures (in my case these were 64bit x86 and 32bit WASM) false desyncs can occur because the checksum code is not portable. Several reasons contribute to this:bevy::utils::FixedState
is used for calculating checksums which uses the non-portableaHash
crate, meaning that two machines can give two different checksums from the same number. Quoting theaHash
crate repo:usize
, for example the return of a.len()
call. Even with a portable hasher, from the same sourceusize
number you would get different hashes on 32bit and 64bit machines, as this type is 32 bit and 64 bit wide, respectively.I resolved these issues (or at least up to what my game needed) in a fork branch. Here, I did the following:
usize
/isize
variables, as a prevention measure.usize
/isize
types inbevy_ggrs
, usually by using or casting tou64
.Expected behavior
I expect the checksums to be the same across architectures. I'm not yet sure what would be the best solution for
usize
/isize
variables.Desktop (please complete the following information):