-
-
Notifications
You must be signed in to change notification settings - Fork 212
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
Add support for precision=double
builds of godot
#149
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for this feature! 👍
precision-double
sounds weird somehow. I see where it's coming from (precision=double
argument), but I would probably name the feature double-precision
. What do you think?
Sorry for merge conflicts, I renamed binary-filename
into godot-binary
on master.
.github/workflows/full-ci.yml
Outdated
|
||
# Don't use latest Ubuntu (22.04) as it breaks lots of ecosystem compatibility. | ||
# If ever moving to ubuntu-latest, need to manually install libtinfo5 for LLVM. | ||
- name: linux | ||
os: ubuntu-20.04 | ||
rust-toolchain: stable | ||
godot-binary: godot.linuxbsd.editor.dev.x86_64 | ||
with-llvm: false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far, the convention was to only provide arguments which don't have a default value (empty in this case).
@@ -9,12 +9,14 @@ | |||
// | |||
// Nice: | |||
// self.glam2(&with, |a, b| a.dot(b)) | |||
// self.glam2(&with, glam::f32::Quat::dot) | |||
// self.glam2(&with, glam::Real::Quat::dot) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
search&replace mistake?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh yeah, i spotted a couple earlier, missed this one
// Clippy complains that this is an `as_*` function but it takes a `self` | ||
// however, since this uses `as` internally it makes much more sense for | ||
// it to be named `as_f32` rather than `to_f32`. | ||
#[allow(clippy::wrong_self_convention)] | ||
fn as_f32(self) -> f32; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Rust, as_
functions almost always return a reference or raw pointer by convention.
They express: "return a different representation of this very object", i.e. similar to a transmute, and not a copy.
On the other hand, to_
suggests that a different type is returned (a conversion takes place), but here this is only true in half the cases. So maybe not ideal either.
I'm not very sure about this, more opinions on this matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it does look more similar to the code the user wants to write, i.e
r as f64
vs
r.as_f64()
godot-core/src/builtin/mod.rs
Outdated
/// A glam [`Vec2`](glam::Vec2) with floating-point format compatible | ||
/// with [`real`]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you use a single line for these comments?
In general you use very short line widths, while screens are super wide 😉 probably a matter of taste, but you could easily use 1.5x your current width in my opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fair, it'd be nice if there was a standard line width in the project tho
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is, as long as there is no tooling to enforce it, such a convention will just be ignored in every PR, and I can spend the rest of my free time bikeshedding line breaks 😉
rustfmt nightly has max_width
, which may be a start -- but it seems like it only breaks longer lines, and doesn't extend shorter ones -- which would make it rather useless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can at least say that i would follow it if there was one
godot-core/src/builtin/mod.rs
Outdated
|
||
/// Floating point type used for many structs and functions in Godot. | ||
/// | ||
/// This is not the `float` type in gdscript, that type is always 64-bits. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Capitalization: "GDScript"
and maybe semicolon after it
godot-core/src/builtin/projection.rs
Outdated
pub fn fov(&self) -> f64 { | ||
self.as_inner().get_fov() | ||
pub fn fov(&self) -> real { | ||
self.as_inner().get_fov() as real |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably use real::from_f64
, no?
godot-core/src/builtin/quaternion.rs
Outdated
// pub fn spherical_cubic_interpolate(self, b: Self, pre_a: Self, post_b: Self, weight: f32) -> Self {} | ||
// pub fn spherical_cubic_interpolate(self, b: Self, pre_a: Self, post_b: Self, weight: Real) -> Self {} | ||
// TODO: Implement godot's function in rust | ||
/* | ||
pub fn spherical_cubic_interpolate_in_time( | ||
self, | ||
b: Self, | ||
pre_a: Self, | ||
post_b: Self, | ||
weight: f32, | ||
b_t: f32, | ||
pre_a_t: f32, | ||
post_b_t: f32, | ||
weight: Real, | ||
b_t: Real, | ||
pre_a_t: Real, | ||
post_b_t: Real, | ||
) -> Self { | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leftover capitals 🙂
godot-core/src/builtin/vector2.rs
Outdated
@@ -42,8 +42,8 @@ impl Vector2 { | |||
/// Vector with all components set to `1.0`. | |||
pub const ONE: Self = Self::splat(1.0); | |||
|
|||
/// Vector with all components set to `f32::INFINITY`. | |||
pub const INF: Self = Self::splat(f32::INFINITY); | |||
/// Vector with all components set to `Real::INFINITY`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
more capital 💰
@@ -167,7 +167,7 @@ macro_rules! impl_vector_operators { | |||
( | |||
// Name of the vector type to be implemented, for example `Vector2`. | |||
$Vector:ty, | |||
// Type of each individual component, for example `f32`. | |||
// Type of each individual component, for example `Real`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
capitals again
itest/rust/src/basis_test.rs
Outdated
@@ -143,7 +143,7 @@ fn basis_equiv() { | |||
assert_eq_approx!( | |||
inner, | |||
outer, | |||
|a, b| is_equal_approx(a as f32, b), | |||
|a, b| is_equal_approx(a as real, b), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
real::from_*
?
// As this is a scalar value, we will use a non-standard type name. | ||
#[allow(non_camel_case_types)] | ||
pub type real = f64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about that, shouldn't it be Real
? Even if it's an alias for a primitive, it's still an alias. It feels weird to me to name it using the convention that's normally reserved for built-in primitives (and modules! causing you a naming conflict here).
I don't know of any prior art in std
, but there's some in the Rust By Example book.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's upon my request, see Discord discussion 🙂
@SayakS Could you add |
Like, explicitly? it already is in the prelude because of the |
Ah true, it's already re-exported. No, in that case not 🙂 |
Maybe some general points regarding
Overall, usage of I feel a bit sorry for the effort that went into building this complex bash functionality; I hope it can be useful somewhere else. To avoid this, we could maybe quickly discuss these things beforehand 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks very good by now! Maybe revert the check.sh
to the previous revision (with --double
instead of --features double-precision
), other than that only minor things left!
.github/workflows/full-ci.yml
Outdated
@@ -98,6 +124,13 @@ jobs: | |||
rust-toolchain: stable | |||
rust-special: -minimal-deps | |||
godot-binary: godot.linuxbsd.editor.dev.x86_64 | |||
with-llvm: false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could remove this
Contributing.md
Outdated
To run the testing suite with `double-precision` enabled you may add `--features double-precision` to a `check.sh` invocation: | ||
``` | ||
$ check.sh -- --features double-precision | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would become a simple check.sh --double
, see above
#[cfg(not(feature = "double-precision"))] | ||
assert_eq_approx!( | ||
lerp_angle(0.0, PI + 3.0 * TAU, 0.5), | ||
FRAC_PI_2, | ||
is_angle_equal_approx | ||
); | ||
#[cfg(feature = "double-precision")] | ||
assert_eq_approx!( | ||
lerp_angle(0.0, PI + 3.0 * TAU, 0.5), | ||
-FRAC_PI_2, | ||
is_angle_equal_approx | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this pi / 2
for floats, but -pi / 2
for doubles?
Rounding errors?
Could you please add a TODO so we write a more robust angle comparison function later (outside of scope for this PR, let's not delay further 🙂)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's documented higher up that it can be unpredictable which way lerp goes when lerping towards multiples of PI, so this is just showing off that. and it kinda unsurprisingly is just different for f32 and f64
besides its a bit hard to know what would be the right thing to do when lerping towards a multiple of PI anyway, and I'm skeptical that it's like technically possible to write a completely consistent one just because of float inaccuracies
there was never a version that had just nightly is mainly cause it's useful to run it with nightly locally sometimes even if the CI doesn't run witb nightly. cause it can spot issues stable cant that'd be useful to fix anyway even if stable wont complain about them. the intent isn't to make it super flexible but just an easy way to do the things that I've noticed myself wanting:
|
My wording was a bit imprecise, the "with" was meant as "additionally". I fully agree that you shouldn't do a full revert 🙂
Out of curiosity, do you remember some of the issues that nightly could find? |
i think mainly that the new itest macro impl has some unnecessary returns, i can double check later |
also dont feel sorry about the effort i put in for the check script lol i just did it cause it came naturally to me and im not super attached to my code in that sense. either way i know bash better :p and like i know that when adding some feature that i havent discussed with anyone it's a risk that it wont be accepted |
I think the "allow any configuration to be passed in" is a kind of symptom fighting. Having limited options has the advantage that people either work with the available API, or are incentivized to add concrete flags/switches that help their workflows. In practice, this would mean:
Doing so would also benefit everyone, not just one developer who has figured out "the one true configuration" 😎 I think we should give it some time though, definitely not in this PR 🙂 |
I kept some things that are strictly speaking unneccessary in the And also just cause it was easier to just keep the code mostly the same as before but just hardcode in the values, since it already worked pretty well. Also since |
Does this also work if someone explicitly installs a Rust version like Also, this still doesn't guarantee that they run the same toolchain as CI. They may have updated their stable channel a year ago.
Not specifying |
I can check
Well yeah, but someone running on a recently updated version of rust will never use the same toolchain as CI if they're using nightly. Stable at least is the right one for most common configurations.
Which was part of my issue, i ran identical commands and got different outcomes. That is Hiding this from the user would've lead to more confusion. Because then i would run Not to mention that until we have a better solution (and making a bigger more complicated solution to figure this out should probably not be in this PR), then we'll just end up with the |
It seems that if a toolchain is missing, cargo will error. So if someone has manually installed a rust version that is not a stable version of rust and has no other stable version of rust, this could cause an error. But at least until we do a better solution than this, we're more likely to see people having their check.sh fail because they're using nightly, than we are to see someone having their check.sh fail because they dont have a stable toolchain installed. |
In that case, what do you think about this?
The big advantage I see, is that it ensures that the toolchain is configured properly for the whole directory, not just inside Otherwise, someone runs |
Have we considered adding a |
Toolchain files are quite cool! 🙂 Although I'm not sure they would help a lot here -- I don't think we should pin our project to a specific Rust and/or toolchain version. What matters is:
Why not leave developers some freedom? It's up to everyone to use nightly version if that helps them in some ways, or to use an older compiler if it's within MSRV bounds. In the end, CI makes the judgement call, and I'd encourage everyone to commit/push regularly in their forks, not only after 3 days of work. I also think there are limits regarding how much tooling we should provide in the repo itself. I spent quite a bit of effort on an elaborate CI infrastructure, and have no plans replicating more of it locally, let alone maintaining both in sync. Yes, it may help some users to find discrepancies between local and upstream setups, but it may as well limit others that have a perfectly valid configuration, so I'm not convinced being overly strict would cause a net decrease in support cases. Furthermore, every piece of infrastructure in existence is something that needs to be maintained, updated, can break and cause problems. I find time is more meaningfully spent on the library than on |
add transform2d/3d-itests back Add --double to check.sh Make check.sh run in the stable toolchain, since that's what the CI does
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for bringing this to a polished state! 👍
As discussed on Discord: there are now quite a lot of CI runs. Maybe some (like unit-tests) don't need to be run for both single and double configuration. Even if vectors etc. contain real
, this would likely only affect us if we specifically test for floating-point inaccuracies; as such, the engine/integration tests may be more interesting. But it's good for now, let's see how it goes!
bors r+
Build succeeded:
|
Add a feature
precision-double
which when enabled will make the various structs that usereal_t
in godot havef64
values instead off32
values.Add a type
real
which is an alias forf32
orf64
depending on the aboveAdd the ability to pass
--features features
tocheck.sh
, so we can easily runcheck.sh
withprecision-double
enabledAdd double-builds in the full-ci
Add double-build in the minimal-ci for clippy
One question:
Should we maintain the
glam::Vec2
convention somehow? maybe make a moduleglam_real
and doglam_real::RVec2
?Resolves #135