Sitelet https://github.com/flutter/flutter/pull/191913
Skip to content

Revert: Handle linear and radial gradients in UberSDF - #191913

Merged
jtmcdole merged 1 commit into
flutter:masterfrom
flutteractionsbot:revert-190874-1787864128
Aug 27, 2026
Merged

jtmcdole merged 1 commit into
flutter:masterfrom
flutteractionsbot:revert-190874-1787864128

Conversation

@flutteractionsbot

@flutteractionsbot flutteractionsbot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Reverts: Handle linear and radial gradients in UberSDF

Initiated by: @b-luk

Reason for reverting: Breaks Mac_arm64 wide_gamut_macos https://ci.chromium.org/ui/p/flutter/builders/prod/Mac_arm64%20wide_gamut_macos/1682/overview

Original PR Author: @b-luk

Reviewed By: @gaaclarke

The original PR description is provided below:

Adds direct support for linear and radial gradient color sources to UberSDF, enabling single-pass rendering of these gradients without the multi-pass blending that is currently used.

  • Adds a color_source_sampler input to UberSDF, which is used to sample a texture representing the gradient color ramp for a linear or radial gradient. This sampler may also be extended in the future for image-based color sources, but that is outside the scope of this PR.
  • Adds properties to UberSDFParameters and to UberSDF's FragInfo for specifying gradient properties.
  • Factors out code in linear_gradient_fill.frag and radial_gradient_fill.frag that samples a texture to get a color for linear and radial gradients. This logic is moved to functions in gradient.glsl, to share with uber_sdf.frag.
  • Updates Canvas::AddRenderSDFEntityToCurrentPass to fill in the gradient texture and gradient related properties when paint.color_source is a gradient supported by UberSDF.

This supports only linear and radial gradients. It does not support conical and sweep gradients. According to Gemini, linear and radial gradients make up more than 99% of gradient usage. Supporting conical and sweep gradients would require additional complexity to UberSDF, so it may not be worth it. We can revisit optimizing these other gradients in the future if we see performance related to them in real world use cases.

This change by itself speeds up gradient rendering significantly, according to the results below. This can be further improved in a follow up PR by adding caching for gradient textures, similar to TextShadowCache in ContentContext.

Addresses #190401.

Results from the demo app in #190401, run on my Windows VM.
Note that my Windows VM may not necessarily reflect real-world performance, but these numbers still show significant improvements with this PR. Also, my Windows VM reports a refresh rate of 500 hz, so almost all frame render times are considered "over budget". So ignore the "over budget" percentages and just look at the raw timing numbers.

before:

=== Windows linear-gradient comparison ===
mode=profile speed=1400px/s
Solid color | frames=953 fps=238.00 | ui p50/p95=0.669/1.231ms | raster p50/p90/p95/p99/max=4.131/5.154/5.519/6.192/6.830ms | raster_over_budget=949/953 (99.6%)
Linear gradient | frames=204 fps=50.75 | ui p50/p95=1.231/1.658ms | raster p50/p90/p95/p99/max=19.094/23.040/23.982/26.812/32.019ms | raster_over_budget=204/204 (100.0%)
================================================

after:

=== Windows linear-gradient comparison ===
mode=profile speed=1400px/s
Solid color | frames=833 fps=208.00 | ui p50/p95=0.635/1.033ms | raster p50/p90/p95/p99/max=4.752/5.570/5.732/6.134/7.504ms | raster_over_budget=833/833 (100.0%)
Linear gradient | frames=687 fps=171.50 | ui p50/p95=1.187/1.804ms | raster p50/p90/p95/p99/max=5.665/7.414/7.925/8.951/12.153ms | raster_over_budget=687/687 (100.0%)
================================================

Skia:

=== Windows linear-gradient comparison ===
mode=profile speed=1400px/s
Solid color | frames=1375 fps=343.50 | ui p50/p95=0.495/0.845ms | raster p50/p90/p95/p99/max=2.679/3.514/3.851/4.631/5.777ms | raster_over_budget=1160/1375 (84.4%)
Linear gradient | frames=1234 fps=308.25 | ui p50/p95=1.087/1.645ms | raster p50/p90/p95/p99/max=1.731/2.251/2.445/2.960/3.903ms | raster_over_budget=319/1234 (25.9%)
================================================

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors UberSDF to remove direct gradient rendering, instead rendering a solid white mask and blending it with the color source contents using a source-in blend mode. It also simplifies gradient shaders by removing dedicated linear and radial gradient sampling functions in favor of direct tile-mode sampling, and refactors the gradient buffer generation logic. Feedback on these changes highlights a critical variable shadowing bug in gradient.cc that prevents the gradient stop interval from advancing, a GLSL compatibility issue in texture.glsl where floats are compared to integer literals, and potential division-by-zero vulnerabilities in both the linear and radial gradient fragment shaders when the gradient length or radius is zero.

Comment on lines +86 to +87
next_color = colors[previous_color_index + 1];
auto next_stop = stops[previous_color_index + 1];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

The variable next_stop is declared with auto inside the else block, which shadows the outer next_stop variable. As a result, the outer next_stop is never updated when advancing to the next stop interval. In subsequent iterations, the loop condition scaled_i < next_stop will use the stale value of next_stop, leading to incorrect gradient generation and potential out-of-bounds reads on colors and stops as previous_color_index continues to increment.

Suggested change
next_color = colors[previous_color_index + 1];
auto next_stop = stops[previous_color_index + 1];
next_color = colors[previous_color_index + 1];
next_stop = stops[previous_color_index + 1];

Comment on lines +101 to +102
if (x_tile_mode == kTileModeDecal && (coords.x < 0 || coords.x >= 1) ||
y_tile_mode == kTileModeDecal && (coords.y < 0 || coords.y >= 1)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

In GLSL, comparing floating-point values (coords.x and coords.y) directly with integer literals (0 and 1) can cause compilation errors or warnings on stricter OpenGL ES / WebGL drivers. It is safer and more portable to use floating-point literals (0.0 and 1.0).

  if (x_tile_mode == kTileModeDecal && (coords.x < 0.0 || coords.x >= 1.0) ||
      y_tile_mode == kTileModeDecal && (coords.y < 0.0 || coords.y >= 1.0)) {

Comment on lines +30 to +31
float t =
dot(start_to_position, start_to_end) / dot(start_to_end, start_to_end);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

If start_point and end_point are identical, dot(start_to_end, start_to_end) will be 0.0, resulting in a division by zero. This can cause rendering artifacts (such as flickering or solid black/white shapes) on some GPUs. Guarding against division by zero improves shader robustness.

  float start_to_end_squared = dot(start_to_end, start_to_end);
  float t = start_to_end_squared == 0.0
                ? 0.0
                : dot(start_to_position, start_to_end) / start_to_end_squared;

texture_sampler, frag_info.center, frag_info.radius, v_position,
frag_info.half_texel, frag_info.tile_mode, frag_info.decal_border_color);
float len = length(v_position - frag_info.center);
float t = len / frag_info.radius;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

If frag_info.radius is 0.0, dividing len by radius results in a division by zero, which can cause rendering artifacts on some GPUs. Adding a guard for radius == 0.0 ensures robust rendering.

  float t = frag_info.radius == 0.0 ? 0.0 : len / frag_info.radius;

@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. e: impeller Impeller rendering backend issues and features requests labels Aug 27, 2026
@b-luk b-luk added the emergency Jump the queue; land PR in front of all others; only use for emergencies label Aug 27, 2026
@flutter-dashboard

Copy link
Copy Markdown

Detected the emergency label.

If you add the autosubmit label, the bot will wait until all presubmits pass but ignore the tree status, allowing fixes for tree breakages while still validating that they don't break any existing presubmits.

The "Merge" button is also unlocked. To bypass presubmits as well as the tree status, press the GitHub "Add to Merge Queue".

@b-luk
b-luk enabled auto-merge August 27, 2026 21:03
@jtmcdole jtmcdole added the autosubmit Merge PR when tree becomes green via auto submit App label Aug 27, 2026
@jtmcdole
jtmcdole disabled auto-merge August 27, 2026 21:12
@jtmcdole
jtmcdole enabled auto-merge August 27, 2026 21:12
@b-luk b-luk added emergency Jump the queue; land PR in front of all others; only use for emergencies and removed emergency Jump the queue; land PR in front of all others; only use for emergencies labels Aug 27, 2026
@jtmcdole
jtmcdole added this pull request to the merge queue Aug 27, 2026
Merged via the queue into flutter:master with commit a61a65d Aug 27, 2026
36 of 40 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Aug 27, 2026
@flutteractionsbot
flutteractionsbot deleted the revert-190874-1787864128 branch August 27, 2026 22:36
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Aug 28, 2026
flutter/flutter@e8dca90...8d8c1aa

2026-08-28 engine-flutter-autoroll@skia.org Roll Packages from bd3cbc1 to cd4cdd0 (15 revisions) (flutter/flutter#191965)
2026-08-28 matthiasngeo@gmail.com Bump customer testing version to pick up forui tests (flutter/flutter#191931)
2026-08-28 victorsanniay@gmail.com Use leading scroll offset instead of infinite offset to reveal pinned slivers (flutter/flutter#191329)
2026-08-28 engine-flutter-autoroll@skia.org Roll Skia from 21f71051e749 to fe0b9a5261f9 (1 revision) (flutter/flutter#191960)
2026-08-28 robert.ancell@canonical.com Share the common Linux window controller code in mixins (flutter/flutter#191930)
2026-08-28 engine-flutter-autoroll@skia.org Roll Dart SDK from 2cf2f69fd9f0 to ae63a6eca3f1 (1 revision) (flutter/flutter#191953)
2026-08-28 engine-flutter-autoroll@skia.org Roll Skia from 11e3a7cb0fd0 to 21f71051e749 (3 revisions) (flutter/flutter#191942)
2026-08-28 engine-flutter-autoroll@skia.org Roll Dart SDK from e030e77d5413 to 2cf2f69fd9f0 (2 revisions) (flutter/flutter#191934)
2026-08-28 32538273+ValentinVignal@users.noreply.github.com Remove no-shuffle in flutter tools overall experience test (flutter/flutter#191861)
2026-08-28 bkonyi@google.com [flutter_tools] Gracefully handle Windows Application Control and security policy execution blocks (flutter/flutter#191912)
2026-08-28 bkonyi@google.com [tool] Migrate ConfigCommand to modular dependency injection (flutter/flutter#190743)
2026-08-28 engine-flutter-autoroll@skia.org Roll Skia from 37459da0a755 to 11e3a7cb0fd0 (9 revisions) (flutter/flutter#191929)
2026-08-28 robert.ancell@canonical.com Connect to moved-to-rect after the window is realized (flutter/flutter#191773)
2026-08-28 chris@bracken.jp macOS: Compare accessibility strings as NSStrings in tests (flutter/flutter#191853)
2026-08-28 chris@bracken.jp macOS: Record test accessibility notifications in a dictionary (flutter/flutter#191854)
2026-08-28 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from 6SXRz6wsA2Zm_rAqP... to u_fSMsPU22VvUsvSo... (flutter/flutter#191927)
2026-08-28 engine-flutter-autoroll@skia.org Roll Dart SDK from cb4c39d067f3 to e030e77d5413 (3 revisions) (flutter/flutter#191923)
2026-08-27 okorohelijah@google.com Migrate ios driver tests batch 2 to simulators (flutter/flutter#190930)
2026-08-27 bkonyi@google.com [flutter_test] Ensure LiveTestWidgetsFlutterBinding executes frame and pointer callbacks in the test zone (flutter/flutter#191595)
2026-08-27 36861262+QuncCccccc@users.noreply.github.com Deprecate legacy gen_defaults tool (flutter/flutter#191911)
2026-08-27 robert.ancell@canonical.com Fix black window in the subsurface view renderer (flutter/flutter#191850)
2026-08-27 engine-flutter-autoroll@skia.org Roll Skia from 82e972ea84b1 to 37459da0a755 (10 revisions) (flutter/flutter#191906)
2026-08-27 chris@bracken.jp iOS: Key the platform view factory registries by NSString (flutter/flutter#191855)
2026-08-27 154381524+flutteractionsbot@users.noreply.github.com Sync CHANGELOG.md from stable (flutter/flutter#191895)
2026-08-27 bkonyi@google.com [flutter_tools] Honor configured build-dir across flutter project and build targets (flutter/flutter#191592)
2026-08-27 154381524+flutteractionsbot@users.noreply.github.com Revert: Handle linear and radial gradients in UberSDF (flutter/flutter#191913)
2026-08-27 34871572+gmackall@users.noreply.github.com Explicitly disable HCPP in hybrid_android_views integration test (flutter/flutter#191894)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC bmparr@google.com,stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
victorsanni pushed a commit to victorsanni/packages that referenced this pull request Sep 9, 2026
…r#12679)

flutter/flutter@e8dca90...8d8c1aa

2026-08-28 engine-flutter-autoroll@skia.org Roll Packages from bd3cbc1 to cd4cdd0 (15 revisions) (flutter/flutter#191965)
2026-08-28 matthiasngeo@gmail.com Bump customer testing version to pick up forui tests (flutter/flutter#191931)
2026-08-28 victorsanniay@gmail.com Use leading scroll offset instead of infinite offset to reveal pinned slivers (flutter/flutter#191329)
2026-08-28 engine-flutter-autoroll@skia.org Roll Skia from 21f71051e749 to fe0b9a5261f9 (1 revision) (flutter/flutter#191960)
2026-08-28 robert.ancell@canonical.com Share the common Linux window controller code in mixins (flutter/flutter#191930)
2026-08-28 engine-flutter-autoroll@skia.org Roll Dart SDK from 2cf2f69fd9f0 to ae63a6eca3f1 (1 revision) (flutter/flutter#191953)
2026-08-28 engine-flutter-autoroll@skia.org Roll Skia from 11e3a7cb0fd0 to 21f71051e749 (3 revisions) (flutter/flutter#191942)
2026-08-28 engine-flutter-autoroll@skia.org Roll Dart SDK from e030e77d5413 to 2cf2f69fd9f0 (2 revisions) (flutter/flutter#191934)
2026-08-28 32538273+ValentinVignal@users.noreply.github.com Remove no-shuffle in flutter tools overall experience test (flutter/flutter#191861)
2026-08-28 bkonyi@google.com [flutter_tools] Gracefully handle Windows Application Control and security policy execution blocks (flutter/flutter#191912)
2026-08-28 bkonyi@google.com [tool] Migrate ConfigCommand to modular dependency injection (flutter/flutter#190743)
2026-08-28 engine-flutter-autoroll@skia.org Roll Skia from 37459da0a755 to 11e3a7cb0fd0 (9 revisions) (flutter/flutter#191929)
2026-08-28 robert.ancell@canonical.com Connect to moved-to-rect after the window is realized (flutter/flutter#191773)
2026-08-28 chris@bracken.jp macOS: Compare accessibility strings as NSStrings in tests (flutter/flutter#191853)
2026-08-28 chris@bracken.jp macOS: Record test accessibility notifications in a dictionary (flutter/flutter#191854)
2026-08-28 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from 6SXRz6wsA2Zm_rAqP... to u_fSMsPU22VvUsvSo... (flutter/flutter#191927)
2026-08-28 engine-flutter-autoroll@skia.org Roll Dart SDK from cb4c39d067f3 to e030e77d5413 (3 revisions) (flutter/flutter#191923)
2026-08-27 okorohelijah@google.com Migrate ios driver tests batch 2 to simulators (flutter/flutter#190930)
2026-08-27 bkonyi@google.com [flutter_test] Ensure LiveTestWidgetsFlutterBinding executes frame and pointer callbacks in the test zone (flutter/flutter#191595)
2026-08-27 36861262+QuncCccccc@users.noreply.github.com Deprecate legacy gen_defaults tool (flutter/flutter#191911)
2026-08-27 robert.ancell@canonical.com Fix black window in the subsurface view renderer (flutter/flutter#191850)
2026-08-27 engine-flutter-autoroll@skia.org Roll Skia from 82e972ea84b1 to 37459da0a755 (10 revisions) (flutter/flutter#191906)
2026-08-27 chris@bracken.jp iOS: Key the platform view factory registries by NSString (flutter/flutter#191855)
2026-08-27 154381524+flutteractionsbot@users.noreply.github.com Sync CHANGELOG.md from stable (flutter/flutter#191895)
2026-08-27 bkonyi@google.com [flutter_tools] Honor configured build-dir across flutter project and build targets (flutter/flutter#191592)
2026-08-27 154381524+flutteractionsbot@users.noreply.github.com Revert: Handle linear and radial gradients in UberSDF (flutter/flutter#191913)
2026-08-27 34871572+gmackall@users.noreply.github.com Explicitly disable HCPP in hybrid_android_views integration test (flutter/flutter#191894)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC bmparr@google.com,stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
victorsanni pushed a commit to victorsanni/packages that referenced this pull request Sep 9, 2026
…r#12679)

flutter/flutter@e8dca90...8d8c1aa

2026-08-28 engine-flutter-autoroll@skia.org Roll Packages from bd3cbc1 to cd4cdd0 (15 revisions) (flutter/flutter#191965)
2026-08-28 matthiasngeo@gmail.com Bump customer testing version to pick up forui tests (flutter/flutter#191931)
2026-08-28 victorsanniay@gmail.com Use leading scroll offset instead of infinite offset to reveal pinned slivers (flutter/flutter#191329)
2026-08-28 engine-flutter-autoroll@skia.org Roll Skia from 21f71051e749 to fe0b9a5261f9 (1 revision) (flutter/flutter#191960)
2026-08-28 robert.ancell@canonical.com Share the common Linux window controller code in mixins (flutter/flutter#191930)
2026-08-28 engine-flutter-autoroll@skia.org Roll Dart SDK from 2cf2f69fd9f0 to ae63a6eca3f1 (1 revision) (flutter/flutter#191953)
2026-08-28 engine-flutter-autoroll@skia.org Roll Skia from 11e3a7cb0fd0 to 21f71051e749 (3 revisions) (flutter/flutter#191942)
2026-08-28 engine-flutter-autoroll@skia.org Roll Dart SDK from e030e77d5413 to 2cf2f69fd9f0 (2 revisions) (flutter/flutter#191934)
2026-08-28 32538273+ValentinVignal@users.noreply.github.com Remove no-shuffle in flutter tools overall experience test (flutter/flutter#191861)
2026-08-28 bkonyi@google.com [flutter_tools] Gracefully handle Windows Application Control and security policy execution blocks (flutter/flutter#191912)
2026-08-28 bkonyi@google.com [tool] Migrate ConfigCommand to modular dependency injection (flutter/flutter#190743)
2026-08-28 engine-flutter-autoroll@skia.org Roll Skia from 37459da0a755 to 11e3a7cb0fd0 (9 revisions) (flutter/flutter#191929)
2026-08-28 robert.ancell@canonical.com Connect to moved-to-rect after the window is realized (flutter/flutter#191773)
2026-08-28 chris@bracken.jp macOS: Compare accessibility strings as NSStrings in tests (flutter/flutter#191853)
2026-08-28 chris@bracken.jp macOS: Record test accessibility notifications in a dictionary (flutter/flutter#191854)
2026-08-28 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from 6SXRz6wsA2Zm_rAqP... to u_fSMsPU22VvUsvSo... (flutter/flutter#191927)
2026-08-28 engine-flutter-autoroll@skia.org Roll Dart SDK from cb4c39d067f3 to e030e77d5413 (3 revisions) (flutter/flutter#191923)
2026-08-27 okorohelijah@google.com Migrate ios driver tests batch 2 to simulators (flutter/flutter#190930)
2026-08-27 bkonyi@google.com [flutter_test] Ensure LiveTestWidgetsFlutterBinding executes frame and pointer callbacks in the test zone (flutter/flutter#191595)
2026-08-27 36861262+QuncCccccc@users.noreply.github.com Deprecate legacy gen_defaults tool (flutter/flutter#191911)
2026-08-27 robert.ancell@canonical.com Fix black window in the subsurface view renderer (flutter/flutter#191850)
2026-08-27 engine-flutter-autoroll@skia.org Roll Skia from 82e972ea84b1 to 37459da0a755 (10 revisions) (flutter/flutter#191906)
2026-08-27 chris@bracken.jp iOS: Key the platform view factory registries by NSString (flutter/flutter#191855)
2026-08-27 154381524+flutteractionsbot@users.noreply.github.com Sync CHANGELOG.md from stable (flutter/flutter#191895)
2026-08-27 bkonyi@google.com [flutter_tools] Honor configured build-dir across flutter project and build targets (flutter/flutter#191592)
2026-08-27 154381524+flutteractionsbot@users.noreply.github.com Revert: Handle linear and radial gradients in UberSDF (flutter/flutter#191913)
2026-08-27 34871572+gmackall@users.noreply.github.com Explicitly disable HCPP in hybrid_android_views integration test (flutter/flutter#191894)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC bmparr@google.com,stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD e: impeller Impeller rendering backend issues and features requests emergency Jump the queue; land PR in front of all others; only use for emergencies engine flutter/engine related. See also e: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants