-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Add unit structs for each ease function #18739
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
base: main
Are you sure you want to change the base?
Conversation
…moothStep` directly instead of `EaseFunction::SmoothStep`.
…ingCurve`. Doesn't make sense for one to be broader. Also updated docs and added a TODO to the main `EasingCurve` docs.
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 is pretty much exactly what I've been hoping for. Thanks for doing it!
As for the extra API surface, this is 100% worth it. It gives significant performance wins in my noise lib, basically for free. Also note that not all easing functions are zero-sized, differentiable, etc. We could build on this with enums like SmallEaseFunction
, DifferentiableEaseFunction
, and SmoothEaseFunction
(where the derivative is 0 at t=0 and t=1). That's what I'd use ultimately for my noise lib to allow users to change the ease at runtime. It would also open up the possibility for a Smooth
trait (WIP name).
So the API surface is not only worth it, but it's a blocker for these tools.
As for the docs, for now, I see no problem duplicating it. But if we add the other 3 enums above, this would become annoying. It doesn't have to be this pr, but I would either have the enum docs point back to the unit struct docs, or create a macro for each function that expands to the desired docs. Or just dump it all in module docs and refer to that. I've seen other crates do that sometimes.
Anyway, that's my thoughts. Excited to see this land!
}); | ||
} | ||
|
||
#[test] | ||
fn unit_structs_match_function() { |
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 isn't a bad thing to have, but all the functions just call each other, so I don't really see the need for this.
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 added it to defend against copy and paste errors, although in retrospect the test was vulnerable to the same error.
I've updated with a macro based test that should be less vulnerable. Also open to removing it if there's a consensus that it's unnecessary.
Objective
When a user wants a specific ease function, make it less verbose and more efficient.
Background
EaseFunction
is a flexible and data-driven way to apply easing. But that has a price when a user only wants a specific ease function:This is a little bit verbose, but the main problem is efficiency - it calls the general
EaseFunction::eval
, which won't be inlined. That means an unnecessary branch insideeval
, and can increase code size since it pulls in all ease functions even though the user might only require one. As far as I can tell this is true even withopt-level = 3
andlto = "fat"
.Solution
The PR adds unit structs that implement
Curve<f32>
for each ease function. This is less verbose, and the compiler can make accurate predictions about inlining.In a microbenchmark this is around 4x faster, but could be less in real code. If inlining permits auto-vectorization then it's 20-50x faster, but that's a niche case.
Adding unit structs is also a small boost to discoverability - the unit struct can be found in VS Code via "Go To Symbol" -> "smoothstep", which doesn't find
EaseFunction::SmoothStep
.Concerns
EasingCurve
, which requiresEaseFunction
.EasingCurve::new(a, b, SmoothStep)
.EasingCurve::new(a, b, EaseFunction::SmoothStep)
.EasingCurve
could be changed to support anyCurve<f32>
or a more limited trait.EaseFunction
.EaseFunction
.Testing