Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Avoid implicit conversions to floats in dart:ui #40098

Merged
merged 7 commits into from
Mar 24, 2023

Conversation

dnfield
Copy link
Contributor

@dnfield dnfield commented Mar 6, 2023

Dart has a built in double type. We currently sometimes let Dart's FFI mechanisms automatically truncate this to float (like in the path API), and sometimes implicitly convert Dart doubles to C++ floats (aka SkScalar and impeller:Scalar). We also do implicit conversions when dealing with Float64List data, especially w.r.t. matrices. This causes problems when applications use very large double values which then get silently truncated to infinity, especially in matrices and values that end up being used in matrix concatenation.

This is solved by the following.

  • Enable -Wimplicit-float-conversion for dart:ui's C++ sources.
  • Add a bunch of fs to C++ literals.
  • Create a utility method for truncating doubles to floats in a well defined manner, avoiding truncation from a finite double value to an infinite float value.
  • Delete Tonic's converters from double to float, since these silently truncate to infinity before the engine C++ code even touches them.

Fixes flutter/flutter#121299

dnfield added 2 commits March 6, 2023 14:08
Dart has a built in `double` type. We currently sometimes let
Dart's FFI mechanisms automatically truncate this to float (like in
the path API), and sometimes implicitly convert Dart doubles to
C++ floats (aka SkScalar and impeller:Scalar). We also do implicit
conversions when dealing with `Float64List` data, especially w.r.t.
matrices. This causes problems when applications use very large
double values which then get silently truncated to infinity, especially
in matrices and values that end up being used in matrix concatenation.

This is solved by the following.

  - Enable `-Wimplicit-float-conversion` for dart:ui's C++
    sources.
  - Add a bunch of `f`s to C++ literals.
  - Create a utility method for truncating doubles to floats
    in a well defined manner, avoiding truncation from a
    finite double value to an infinite float value.
  - Delete Tonic's converters from double to float, since
    these silently truncate to infinity before the engine C++ code
    even touches them.

Fixes flutter/flutter#121299
Comment on lines 20 to 22
return std::max(
std::numeric_limits<float>::lowest(),
std::min(std::numeric_limits<float>::max(), static_cast<float>(value)));
Copy link
Member

Choose a reason for hiding this comment

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

I think std::clamp can be used here for potentially faster code and easier to maintain.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@dnfield
Copy link
Contributor Author

dnfield commented Mar 7, 2023

In some offline conversation with @flar:

We may want to push the narrowing down til after DL has done its thing (and after the layer tree code has done its thing) to avoid premature precision loss. But that only really makes sense if we can get those types to use doubles as well, particularly around their matrix code (which today uses SkMatrix/SkM44, which are both float based).

@dnfield
Copy link
Contributor Author

dnfield commented Mar 9, 2023

(I'm going to hold off on updating merge conflicts until I get more feedback)

@chinmaygarde
Copy link
Member

chinmaygarde commented Mar 9, 2023

Neither FLT_MAX or INFINITY is what the user expects. Using one or the other hardly matters. An assertion ought to be added earlier (closer to the user) where this sort of error may occur. I am not sure if this is an improvement.

@dnfield
Copy link
Contributor Author

dnfield commented Mar 11, 2023

Neither FLT_MAX or INFINITY is what the user expects. Using one or the other hardly matters. An assertion ought to be added earlier (closer to the user) where this sort of error may occur. I am not sure if this is an improvement.

Part of how I got to this point was trying to add that assertion. But what does it tell the user to do? Clamp to FLT_MAX? Something else entirely?

@chinmaygarde
Copy link
Member

From the latest conversation in triage, I think a case can be made that this is less surprising than the current state of things. I'd really like the application author to be in control of the precision and how its clamped but I don't think that is feasible even in the medium to long term.

I think we should cleanup this patch and land this.

@dnfield dnfield added the autosubmit Merge PR when tree becomes green via auto submit App label Mar 24, 2023
@auto-submit auto-submit bot merged commit 6c2dafe into flutter:main Mar 24, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 24, 2023
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Mar 24, 2023
…gine#40098) (#123433)

Roll Flutter Engine from 608d5b214faa to 6c2dafed5077 (1 revision)
sourcegraph-bot pushed a commit to sgtest/megarepo that referenced this pull request Mar 24, 2023
…lutter/engine#40098) (#123433)

Commit: da5dc9dbed7e40bcb9b99b2c880c2483cf748e8a
@tvolkert
Copy link
Contributor

FYI, it looks like this may have introduced tiny differences in the AA pixel values -- check out the cluster around coordinates x=732, y=154 in this Skia Gold diff.

I approved the diff since it was not perceptible.

@tvolkert
Copy link
Contributor

Note that if this did indeed cause those small differences, we're likely to see a bunch of Scuba failures when this rolls into g3 as well.

@dnfield
Copy link
Contributor Author

dnfield commented Mar 27, 2023

Frob filed a bug against this PR that said it caused some minor scuba differences in google3.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
autosubmit Merge PR when tree becomes green via auto submit App
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Truncate large doubles to FLT_MAX instead of infinity (or instead of relying on UB)
4 participants