Repository navigation
Handle linear and radial gradients in UberSDF - #190874
Conversation
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request adds support for linear and radial gradients in the UberSDF renderer by introducing helper sampling functions in shaders, populating gradient parameters from color sources, and binding gradient textures during rendering. The review feedback suggests guarding against division by zero in the shader gradient sampling functions when the length or radius is zero, adding an unreachable macro to prevent compiler warnings in ToShaderColorSourceType, and explicitly converting texture sizes to avoid implicit conversions and division by zero when calculating half-texel values.
There was a problem hiding this comment.
Code Review
This pull request adds support for rendering linear and radial gradients directly within UberSDF, avoiding the need to fall back to blending with a separate color source. It introduces helper functions in the gradient shader library, updates UberSDFParameters and UberSDFContents to handle gradient parameters and bind the gradient texture, and updates the uber_sdf fragment shader to sample from the gradient texture. Feedback suggests utilizing the GradientGenerator cache instead of creating a new texture every frame to prevent performance issues, and adding FML_UNREACHABLE() to avoid compiler warnings in ToShaderColorSourceType.
|
@gaaclarke I was planning on waiting for the golden tests to get back to see if this does anything weird before sending it out for review. But there are infra issues blocking CI, so the goldens aren't going to run any time soon. So I'm sending this out now, but if the goldens do eventually show weird stuff then I may change the PR back to draft while I investigate. |
gaaclarke
left a comment
There was a problem hiding this comment.
can you add the malioc change please?
|
Looking at the golden results so far: https://flutter-gold.skia.org/search?crs=github&issue=190874&patchsets=3 Most of the changes are subtly visible changes that are not worse (maybe even a little better looking), and are likely due to different rendering techniques. For example, CanRenderLinearGradientMirror_MetalSDF. But some of the changes are very off and likely incorrect. For example CanRenderLinearGradientDecalWithColorFilter_MetalSDF and CanRenderLinearGradientWithOverlappingStopsClamp_MetalSDF I'll change this back to a draft while I investigate. |
|
Updated malioc and addressed a bunch of issues revealed in the old goldens:
The goldens now all seem reasonable to me: https://flutter-gold.skia.org/search?issue=190874&crs=github&patchsets=9&corpus=flutter |
There was a problem hiding this comment.
Code Review
This pull request integrates support for linear and radial gradients directly into UberSDF rendering, refactoring gradient sampling helpers in shaders and updating UberSDFContents and Canvas to bind and pass gradient parameters. It also refactors gradient buffer generation to correctly handle overlapping or zero-delta stops. Feedback on these changes recommends using epsilon checks instead of direct comparisons to 0.0 in shader division operations to prevent potential division-by-zero or overflow, and implementing a caching mechanism for gradient textures to avoid performance bottlenecks from uploading textures on every frame.
| float t = start_to_end_squared == 0.0 | ||
| ? 0.0 | ||
| : dot(start_to_position, start_to_end) / start_to_end_squared; |
There was a problem hiding this comment.
To prevent potential division-by-zero or overflow issues on some GPUs when the start and end points of a linear gradient are extremely close (but not exactly identical), consider using a small epsilon check (e.g., 1e-6) instead of comparing start_to_end_squared directly to 0.0.
float t = start_to_end_squared < 1e-6
? 0.0
: dot(start_to_position, start_to_end) / start_to_end_squared;
| vec2 half_texel, | ||
| float tile_mode, | ||
| vec4 decal_border_color) { | ||
| float t = radius == 0.0 ? 0.0 : length(pos - center) / radius; |
| std::shared_ptr<Texture> texture = | ||
| CreateGradientTexture(gradient_data, renderer.GetContext()); | ||
| if (!texture) { |
There was a problem hiding this comment.
Creating and uploading a new gradient texture to the GPU on every frame during the rendering phase can be a significant performance bottleneck and may cause jank, especially for complex or animated scenes.
While the PR description mentions adding caching in a follow-up PR, it is highly recommended to implement a basic caching mechanism (similar to TextShadowCache or other texture caches in ContentContext) to reuse these gradient textures across frames.
gaaclarke
left a comment
There was a problem hiding this comment.
I looked over everything and it is looking good. The only big thing we need to address is the overflow of uniform registers. Hopefully sorting the declarations will remove padding and get us there. Once we move them around, docstrings will be more important to communicate what register is doing what a little more.
| "stack_spill_bytes": 0, | ||
| "thread_occupancy": 100, | ||
| "uniform_registers_used": 48, | ||
| "uniform_registers_used": 66, |
There was a problem hiding this comment.
This is problematic, the Mali-G78 only has 64 uniform registers. I think the first thing we should try is sorting the uniforms by size [vec4 -> vec2 -> float] to see if that removes enough padding to get us under 64.
There was a problem hiding this comment.
I reordered the fields as you suggested. This improved the cycle measurements a bit, but it did not reduce the uniform register usage: 228eebd
A lot of the uniform usage is specifically for rounded superellipses. If we want to keep uniform register size down, should we move rounded superellipses to its own fragment shader?
According to Gemini:
Why Mali-G78 Uniform Registers Remain at 66 in Vulkan SPIR-V
In uber_sdf.frag.vkspv, the Mali compiler allocates Uniform Registers (UGRs) for three things:
- Raw uniform data: (38 scalar floats)
- Vulkan UBO descriptor & base address pointers: (~4–6 UGRs in SPIR-V)
- Compiler-promoted invariant expressions:
- Because
uber_sdf.fragcontains code for 5 distinct shapes and 3 color sources, the Mali compiler hoists uniform-derived math across all branches (atan(),pow(),half_stroke = max(stroke_width, base_pixel_size) * 0.5, octant diagonal transitions, and gamma-correction constants) into uniform registers.
- Because
Even with zero struct padding, the sheer number of active branches in the unified Uber shader keeps the UGR pressure at 66.
There was a problem hiding this comment.
As mentioned in #190874 (comment) and the follow-up comments, we went with the approach of restricting UberSDF to only RSEs with identical corners and with corner rounding extents that are equal horizontally/vertically. This reduces the uniform_registers_used to 64.
| vec2 gradient_start; | ||
| vec2 gradient_end; | ||
| vec2 half_texel; | ||
| float tile_mode; | ||
| float color_source_type; |
There was a problem hiding this comment.
Let's start the norm of adding a docstring to these uniform fields.
| ASSERT_EQ(gradient.texture_size, 1024u); | ||
|
|
||
| std::vector<Color> expected_colors(1024); | ||
| for (size_t i = 0; i < 1024; i++) { |
There was a problem hiding this comment.
I missed this, what is this change about?
There was a problem hiding this comment.
Updated this unit test for the changes I made in gradient.cc. See my comment there for why it was changed.
| // size. | ||
| texture_size = std::min( | ||
| static_cast<uint32_t>(std::round(1.0 / minimum_delta)) + 1, 1024u); | ||
| texture_size = static_cast<uint32_t>(std::round(1.0 / minimum_delta)) + 1; |
There was a problem hiding this comment.
Why aren't we clamping anymore?
There was a problem hiding this comment.
This is one of the fixes mentioned in my comment at #190874 (comment). In particular, this is about:
- Make CreateGradientBuffer compatible with overlapping color stops
- For issues like this where overlapping color stops weren't being respected
In the original code, very close together stops (including overlapping 0-delta stops) are ignored when calculating the gradient texture size. This ends up ignoring sharp transitions that are specified as duplicate or very close together stops, and ends up rendering the wrong thing.
See the example golden result before this fix. The stops are: [0.0, 0.5, 0.5, 1.0] with the colors [red, red, blue, blue]. So it's supposed to render pure red for the first half, then sharply switch to pure blue.
With the original code, we end up with a texture of size 3 here: minimum_delta is 0.5 (for the 0.0 to 0.5 stop interval, or for the 0.5 to 1.0 stop interval. The 0.5 to 0.5 stop interval is ignored). So texture size is ((1.0 / 0.5) + 1) = 3). And it gets populated as [red, red, blue] below. This ends up being rendered as pure red for the first half, then a gradient from red to blue for the second half, as seen in the golden screenshot. This is a real bug that is present in the current *_gradient_fill.frag shaders, when used with very close together stops. But I think it doesn't show up very much because those shaders are only used as fallbacks when *_gradient_ssbo_fill.frag and *_gradient_uniform_fill.frag can't be used.
With the new code, the 0.5 to 0.5 stop interval is not ignored. Instead, it sets minimum_delta to minimum_allowable_delta, to create a texture of the maximum size (1024). Then below, this gets populated as all red for index 0 through 511 of the texture and all blue for index 512 through 1023. The result is this, which is much closer to correct. Note that it still ends up with a blended color at the boundary between the red and the blue, because those pixels are sampling the texture between index 511 and 512.
| auto mixed_color = Color::Lerp(previous_color, next_color, t); | ||
|
|
||
| AppendColor(mixed_color, &data); | ||
| i--; |
There was a problem hiding this comment.
Why did this have to be changed?
There was a problem hiding this comment.
See the above comment for more context.
This particular change to the loop lets it populate the colors of close-together stops properly. When scaled_i advances to the next stop, this updates the previous_color and next_color interval without appending a color, then reruns the loop iteration with the same scaled_i. This repeats multiple times if the next stop(s) are duplicate or very close to the current stop, until reaching a stop that is different enough that scaled_i >= next_stop and the loop iteration appends another color.
With the original code, when scaled_i advances to the next stop, it appends a color based on the immediate next stop, which is not the correct thing to do when the next stop is very close to the previous stop.
There was a problem hiding this comment.
no action required: it would be better if we put the fixes in another pr
There was a problem hiding this comment.
Acknowledged. I'll keep this in mind for future PRs.
|
Do we already have a benchmark for this? Probably. Maybe it isn't running on windows? |
|
Reason for revert: Breaks Mac_arm64 wide_gamut_macos https://ci.chromium.org/ui/p/flutter/builders/prod/Mac_arm64%20wide_gamut_macos/1682/overview |
|
Successfully created revert PR: #191913 |
Reverts: [Handle linear and radial gradients in UberSDF](flutter#190874) 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 flutter#190401. Results from the demo app in flutter#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 - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. 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](https://developers.google.com/gemini-code-assist/docs/review-github-code). 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. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [AI contribution guidelines]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Roll Flutter from 15d8908addf6 to e8dca90ec9e0 (58 revisions) flutter/flutter@15d8908...e8dca90 2026-08-27 15619084+vashworth@users.noreply.github.com Terminate existing process before launching with devicectl (flutter/flutter#191885) 2026-08-27 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from qjOQi-zAgu_tADorh... to dDxH8G5cDBP602eyG... (flutter/flutter#191889) 2026-08-27 bkonyi@google.com [flutter_tools] Verify native assets tree-shaking during linking (flutter/flutter#191637) 2026-08-27 30870216+gaaclarke@users.noreply.github.com Denylists b-series powervr from vulkan (flutter/flutter#191808) 2026-08-27 97480502+b-luk@users.noreply.github.com Handle linear and radial gradients in UberSDF (flutter/flutter#190874) 2026-08-27 engine-flutter-autoroll@skia.org Roll Packages from 740f093 to bd3cbc1 (7 revisions) (flutter/flutter#191886) 2026-08-27 jason-simmons@users.noreply.github.com Disable more Windows tests that have been causing CI flakes (flutter/flutter#191822) 2026-08-27 engine-flutter-autoroll@skia.org Roll Skia from d32721369bd8 to 82e972ea84b1 (2 revisions) (flutter/flutter#191880) 2026-08-27 engine-flutter-autoroll@skia.org Roll Skia from 3640b8edd16c to d32721369bd8 (10 revisions) (flutter/flutter#191858) 2026-08-27 154381524+flutteractionsbot@users.noreply.github.com Revert: [AGP 9] Update remaining tests to AGP 9 (flutter/flutter#191863) 2026-08-27 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from 0iCv10IlKfiilEBOU... to 6SXRz6wsA2Zm_rAqP... (flutter/flutter#191852) 2026-08-27 137456488+flutter-pub-roller-bot@users.noreply.github.com Roll pub packages (flutter/flutter#191851) 2026-08-27 46920873+gabrimatic@users.noreply.github.com Refactor FormField build wrappers (flutter/flutter#185795) 2026-08-27 50643541+Mairramer@users.noreply.github.com Make ScrollPhysics reactive by introducing shouldUpdate (flutter/flutter#189664) 2026-08-27 chris@bracken.jp macOS: Fix crash on out-of-bounds text input ranges (flutter/flutter#191780) 2026-08-27 34871572+gmackall@users.noreply.github.com Add HCPP feature flag, and turn it on by default in beta/master (flutter/flutter#190623) 2026-08-27 bkonyi@google.com [tool] Migrate CleanCommand to modular dependency injection (flutter/flutter#190742) 2026-08-26 katelovett@google.com Update triage docs for ecosystem and codelab changes (flutter/flutter#191809) 2026-08-26 jesswon@google.com [AGP 9] Update remaining tests to AGP 9 (flutter/flutter#191824) 2026-08-26 louisehsu@google.com [UIScene] Migrate dev/benchmarks/complex_layout to UIScene lifecycle (flutter/flutter#191619) 2026-08-26 57765714+Vi-debug@users.noreply.github.com Add SliverAppBar showOnScreen semantics test coverage (flutter/flutter#190410) 2026-08-26 95318996+shawnridgeway-google@users.noreply.github.com Add prompt_suggestion icon to list of RTL mirroring icons. (flutter/flutter#191741) 2026-08-26 okorohelijah@google.com Remove bringup for batch 3 (flutter/flutter#191750) 2026-08-26 engine-flutter-autoroll@skia.org Roll Skia from b5465d7b0b77 to 3640b8edd16c (6 revisions) (flutter/flutter#191835) 2026-08-26 louisehsu@google.com Uiscene migrate custom channels views (flutter/flutter#191817) 2026-08-26 matt.boetger@gmail.com Support --[no-]adb-log-filtering CLI option (flutter/flutter#187252) 2026-08-26 engine-flutter-autoroll@skia.org Roll Dart SDK from cb8a4e1a0fbb to cb4c39d067f3 (2 revisions) (flutter/flutter#191825) 2026-08-26 nate.w5687@gmail.com Fix `Navigator.pushNamed<T>()` type checking (flutter/flutter#188148) 2026-08-26 robert.ancell@canonical.com Handle the case where a window doesn't have a title set (flutter/flutter#191767) 2026-08-26 github@alexv525.com [Android] Remove old `InputType` constructor from embedding (flutter/flutter#191244) 2026-08-26 engine-flutter-autoroll@skia.org Roll Skia from 244a6a0f8f92 to b5465d7b0b77 (19 revisions) (flutter/flutter#191810) 2026-08-26 46920873+gabrimatic@users.noreply.github.com Tolerate floating-point rounding in paintImage centerSlice assertion (flutter/flutter#185789) 2026-08-26 30870216+gaaclarke@users.noreply.github.com Fixes translated bounded blurs (flutter/flutter#191615) 2026-08-26 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from MstTWE1RDOT-RnrtH... to qjOQi-zAgu_tADorh... (flutter/flutter#191769) 2026-08-26 136096126+glitchfl@users.noreply.github.com Lerp HSVColor and HSLColor hue along the shortest arc (flutter/flutter#191186) 2026-08-26 116356835+AbdeMohlbi@users.noreply.github.com Fix enum instances comparison to use `equality ==` since dart has the correct behavior now (flutter/flutter#191537) 2026-08-26 30870216+gaaclarke@users.noreply.github.com Switches windows to opengles 3 (flutter/flutter#191516) 2026-08-26 engine-flutter-autoroll@skia.org Roll Dart SDK from 7739e8602bc1 to cb8a4e1a0fbb (1 revision) (flutter/flutter#191784) 2026-08-26 chris@bracken.jp iOS,macOS: Check viewType before creating a platform view (flutter/flutter#191777) 2026-08-26 154381524+flutteractionsbot@users.noreply.github.com Revert: [tool_tests] Remove bringup from Windows tool_tests_commands_2_2 (flutter/flutter#191793) 2026-08-26 kevmoo@users.noreply.github.com refactor(flutter_tools): clean up dead unreferenced declarations (flutter/flutter#191163) 2026-08-26 engine-flutter-autoroll@skia.org Roll Fuchsia GN SDK from a87CbQSWEjkPUK1ZY... to ZsxUUK2SfA-TrNvb8... (flutter/flutter#191763) 2026-08-26 bkonyi@google.com [tool_tests] Remove bringup from Windows tool_tests_commands_2_2 (flutter/flutter#191732) 2026-08-25 36861262+QuncCccccc@users.noreply.github.com Remove legacy gen_defaults analyze checks (flutter/flutter#191629) 2026-08-25 52160996+FMorschel@users.noreply.github.com Refactors `try` to avoid `unawaited_return_in_try_block` case (flutter/flutter#191129) 2026-08-25 engine-flutter-autoroll@skia.org Roll Dart SDK from 8996935d3d0a to 7739e8602bc1 (1 revision) (flutter/flutter#191754) ...
Two fixes for texture-backed gradients: 1. Fix incorrect ending coord check in IPSampleLinearWithTileMode for decal mode. This fixes an issue where decal gradients end a pixel early. 2. Make CreateGradientBuffer compatible with overlapping color stops Related: flutter#190401 This re-implements part of flutter#190874. That PR was reverted because it didn't handle wide gamut colors properly. I will re-implement a fixed version of it in multiple parts. In the original reviews for that PR, it was suggested that these self-contained gradient fixes could be put in their own separate PR. Now that the PR is reverted, we get our chance to put these fixes in their own PR. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. 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](https://developers.google.com/gemini-code-assist/docs/review-github-code). 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. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [AI contribution guidelines]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…re (flutter#191980) This is a prerequisite to re-implementing flutter#190874. This addresses the unsupported wide gamut issue which was originally present in that PR and which caused it to be reverted. Related: flutter#190401 ### Previously: - `CreateGradientBuffer` converts a gradient's colors and stops to an interpolated list of colors. This interpolated list of colors is converted to bytes with `ToR8G8B8A8()` and is returned in a `GradientData`. - The `R8G8B8A8` `GradientData` is passed to `CreateGradientTexture`, which allocates a `PixelFormat::kR8G8B8A8UNormInt` texture. Wide gamut colors can't be converted to `R8G8B8A8`, so they end up getting clamped. ### Now: - `CreateGradientBuffer` converts a gradient's colors and stops to an interpolated list of colors (same as before). But now no conversion to bytes happens here. The interpolated list of colors is directly returned in a `GradientData`. - The `Color`-based `GradientData` is passed to `CreateGradientTexture`. `CreateGradientTexture` now handles the conversion to bytes. If there are wide gamut colors, it converts to `kR32G32B32A32Float`. Otherwise it does the old behavior of converting to `PixelFormat::kR8G8B8A8UNormInt`. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. 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](https://developers.google.com/gemini-code-assist/docs/review-github-code). 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. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [AI contribution guidelines]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
flutter#192124) This re-implements flutter#190874, after landing: flutter#191925 - Separated out some of the fixes from the original PR flutter#191980 - Add support for wide gamut colors. This re-implements the rest of the original PR. This is the same exact code as the original PR, minus the changes that have already been merged in flutter#191925. Verified locally that the wide gamut test passes. Related: flutter#190401 Original PR description: ---- 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 flutter#190401. Results from the demo app in flutter#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 - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ ] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant in-code documentation (doc comments with `///`). - [ ] If this PR introduces a new feature or capability, I created and linked a website documentation issue or PR in [flutter/website] (or verified none is needed). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. 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](https://developers.google.com/gemini-code-assist/docs/review-github-code). 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. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [AI contribution guidelines]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [flutter/website]: https://github.com/flutter/website [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…r#12660) Roll Flutter from 15d8908addf6 to e8dca90ec9e0 (58 revisions) flutter/flutter@15d8908...e8dca90 2026-08-27 15619084+vashworth@users.noreply.github.com Terminate existing process before launching with devicectl (flutter/flutter#191885) 2026-08-27 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from qjOQi-zAgu_tADorh... to dDxH8G5cDBP602eyG... (flutter/flutter#191889) 2026-08-27 bkonyi@google.com [flutter_tools] Verify native assets tree-shaking during linking (flutter/flutter#191637) 2026-08-27 30870216+gaaclarke@users.noreply.github.com Denylists b-series powervr from vulkan (flutter/flutter#191808) 2026-08-27 97480502+b-luk@users.noreply.github.com Handle linear and radial gradients in UberSDF (flutter/flutter#190874) 2026-08-27 engine-flutter-autoroll@skia.org Roll Packages from 740f093 to bd3cbc1 (7 revisions) (flutter/flutter#191886) 2026-08-27 jason-simmons@users.noreply.github.com Disable more Windows tests that have been causing CI flakes (flutter/flutter#191822) 2026-08-27 engine-flutter-autoroll@skia.org Roll Skia from d32721369bd8 to 82e972ea84b1 (2 revisions) (flutter/flutter#191880) 2026-08-27 engine-flutter-autoroll@skia.org Roll Skia from 3640b8edd16c to d32721369bd8 (10 revisions) (flutter/flutter#191858) 2026-08-27 154381524+flutteractionsbot@users.noreply.github.com Revert: [AGP 9] Update remaining tests to AGP 9 (flutter/flutter#191863) 2026-08-27 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from 0iCv10IlKfiilEBOU... to 6SXRz6wsA2Zm_rAqP... (flutter/flutter#191852) 2026-08-27 137456488+flutter-pub-roller-bot@users.noreply.github.com Roll pub packages (flutter/flutter#191851) 2026-08-27 46920873+gabrimatic@users.noreply.github.com Refactor FormField build wrappers (flutter/flutter#185795) 2026-08-27 50643541+Mairramer@users.noreply.github.com Make ScrollPhysics reactive by introducing shouldUpdate (flutter/flutter#189664) 2026-08-27 chris@bracken.jp macOS: Fix crash on out-of-bounds text input ranges (flutter/flutter#191780) 2026-08-27 34871572+gmackall@users.noreply.github.com Add HCPP feature flag, and turn it on by default in beta/master (flutter/flutter#190623) 2026-08-27 bkonyi@google.com [tool] Migrate CleanCommand to modular dependency injection (flutter/flutter#190742) 2026-08-26 katelovett@google.com Update triage docs for ecosystem and codelab changes (flutter/flutter#191809) 2026-08-26 jesswon@google.com [AGP 9] Update remaining tests to AGP 9 (flutter/flutter#191824) 2026-08-26 louisehsu@google.com [UIScene] Migrate dev/benchmarks/complex_layout to UIScene lifecycle (flutter/flutter#191619) 2026-08-26 57765714+Vi-debug@users.noreply.github.com Add SliverAppBar showOnScreen semantics test coverage (flutter/flutter#190410) 2026-08-26 95318996+shawnridgeway-google@users.noreply.github.com Add prompt_suggestion icon to list of RTL mirroring icons. (flutter/flutter#191741) 2026-08-26 okorohelijah@google.com Remove bringup for batch 3 (flutter/flutter#191750) 2026-08-26 engine-flutter-autoroll@skia.org Roll Skia from b5465d7b0b77 to 3640b8edd16c (6 revisions) (flutter/flutter#191835) 2026-08-26 louisehsu@google.com Uiscene migrate custom channels views (flutter/flutter#191817) 2026-08-26 matt.boetger@gmail.com Support --[no-]adb-log-filtering CLI option (flutter/flutter#187252) 2026-08-26 engine-flutter-autoroll@skia.org Roll Dart SDK from cb8a4e1a0fbb to cb4c39d067f3 (2 revisions) (flutter/flutter#191825) 2026-08-26 nate.w5687@gmail.com Fix `Navigator.pushNamed<T>()` type checking (flutter/flutter#188148) 2026-08-26 robert.ancell@canonical.com Handle the case where a window doesn't have a title set (flutter/flutter#191767) 2026-08-26 github@alexv525.com [Android] Remove old `InputType` constructor from embedding (flutter/flutter#191244) 2026-08-26 engine-flutter-autoroll@skia.org Roll Skia from 244a6a0f8f92 to b5465d7b0b77 (19 revisions) (flutter/flutter#191810) 2026-08-26 46920873+gabrimatic@users.noreply.github.com Tolerate floating-point rounding in paintImage centerSlice assertion (flutter/flutter#185789) 2026-08-26 30870216+gaaclarke@users.noreply.github.com Fixes translated bounded blurs (flutter/flutter#191615) 2026-08-26 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from MstTWE1RDOT-RnrtH... to qjOQi-zAgu_tADorh... (flutter/flutter#191769) 2026-08-26 136096126+glitchfl@users.noreply.github.com Lerp HSVColor and HSLColor hue along the shortest arc (flutter/flutter#191186) 2026-08-26 116356835+AbdeMohlbi@users.noreply.github.com Fix enum instances comparison to use `equality ==` since dart has the correct behavior now (flutter/flutter#191537) 2026-08-26 30870216+gaaclarke@users.noreply.github.com Switches windows to opengles 3 (flutter/flutter#191516) 2026-08-26 engine-flutter-autoroll@skia.org Roll Dart SDK from 7739e8602bc1 to cb8a4e1a0fbb (1 revision) (flutter/flutter#191784) 2026-08-26 chris@bracken.jp iOS,macOS: Check viewType before creating a platform view (flutter/flutter#191777) 2026-08-26 154381524+flutteractionsbot@users.noreply.github.com Revert: [tool_tests] Remove bringup from Windows tool_tests_commands_2_2 (flutter/flutter#191793) 2026-08-26 kevmoo@users.noreply.github.com refactor(flutter_tools): clean up dead unreferenced declarations (flutter/flutter#191163) 2026-08-26 engine-flutter-autoroll@skia.org Roll Fuchsia GN SDK from a87CbQSWEjkPUK1ZY... to ZsxUUK2SfA-TrNvb8... (flutter/flutter#191763) 2026-08-26 bkonyi@google.com [tool_tests] Remove bringup from Windows tool_tests_commands_2_2 (flutter/flutter#191732) 2026-08-25 36861262+QuncCccccc@users.noreply.github.com Remove legacy gen_defaults analyze checks (flutter/flutter#191629) 2026-08-25 52160996+FMorschel@users.noreply.github.com Refactors `try` to avoid `unawaited_return_in_try_block` case (flutter/flutter#191129) 2026-08-25 engine-flutter-autoroll@skia.org Roll Dart SDK from 8996935d3d0a to 7739e8602bc1 (1 revision) (flutter/flutter#191754) ...
…r#12660) Roll Flutter from 15d8908addf6 to e8dca90ec9e0 (58 revisions) flutter/flutter@15d8908...e8dca90 2026-08-27 15619084+vashworth@users.noreply.github.com Terminate existing process before launching with devicectl (flutter/flutter#191885) 2026-08-27 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from qjOQi-zAgu_tADorh... to dDxH8G5cDBP602eyG... (flutter/flutter#191889) 2026-08-27 bkonyi@google.com [flutter_tools] Verify native assets tree-shaking during linking (flutter/flutter#191637) 2026-08-27 30870216+gaaclarke@users.noreply.github.com Denylists b-series powervr from vulkan (flutter/flutter#191808) 2026-08-27 97480502+b-luk@users.noreply.github.com Handle linear and radial gradients in UberSDF (flutter/flutter#190874) 2026-08-27 engine-flutter-autoroll@skia.org Roll Packages from 740f093 to bd3cbc1 (7 revisions) (flutter/flutter#191886) 2026-08-27 jason-simmons@users.noreply.github.com Disable more Windows tests that have been causing CI flakes (flutter/flutter#191822) 2026-08-27 engine-flutter-autoroll@skia.org Roll Skia from d32721369bd8 to 82e972ea84b1 (2 revisions) (flutter/flutter#191880) 2026-08-27 engine-flutter-autoroll@skia.org Roll Skia from 3640b8edd16c to d32721369bd8 (10 revisions) (flutter/flutter#191858) 2026-08-27 154381524+flutteractionsbot@users.noreply.github.com Revert: [AGP 9] Update remaining tests to AGP 9 (flutter/flutter#191863) 2026-08-27 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from 0iCv10IlKfiilEBOU... to 6SXRz6wsA2Zm_rAqP... (flutter/flutter#191852) 2026-08-27 137456488+flutter-pub-roller-bot@users.noreply.github.com Roll pub packages (flutter/flutter#191851) 2026-08-27 46920873+gabrimatic@users.noreply.github.com Refactor FormField build wrappers (flutter/flutter#185795) 2026-08-27 50643541+Mairramer@users.noreply.github.com Make ScrollPhysics reactive by introducing shouldUpdate (flutter/flutter#189664) 2026-08-27 chris@bracken.jp macOS: Fix crash on out-of-bounds text input ranges (flutter/flutter#191780) 2026-08-27 34871572+gmackall@users.noreply.github.com Add HCPP feature flag, and turn it on by default in beta/master (flutter/flutter#190623) 2026-08-27 bkonyi@google.com [tool] Migrate CleanCommand to modular dependency injection (flutter/flutter#190742) 2026-08-26 katelovett@google.com Update triage docs for ecosystem and codelab changes (flutter/flutter#191809) 2026-08-26 jesswon@google.com [AGP 9] Update remaining tests to AGP 9 (flutter/flutter#191824) 2026-08-26 louisehsu@google.com [UIScene] Migrate dev/benchmarks/complex_layout to UIScene lifecycle (flutter/flutter#191619) 2026-08-26 57765714+Vi-debug@users.noreply.github.com Add SliverAppBar showOnScreen semantics test coverage (flutter/flutter#190410) 2026-08-26 95318996+shawnridgeway-google@users.noreply.github.com Add prompt_suggestion icon to list of RTL mirroring icons. (flutter/flutter#191741) 2026-08-26 okorohelijah@google.com Remove bringup for batch 3 (flutter/flutter#191750) 2026-08-26 engine-flutter-autoroll@skia.org Roll Skia from b5465d7b0b77 to 3640b8edd16c (6 revisions) (flutter/flutter#191835) 2026-08-26 louisehsu@google.com Uiscene migrate custom channels views (flutter/flutter#191817) 2026-08-26 matt.boetger@gmail.com Support --[no-]adb-log-filtering CLI option (flutter/flutter#187252) 2026-08-26 engine-flutter-autoroll@skia.org Roll Dart SDK from cb8a4e1a0fbb to cb4c39d067f3 (2 revisions) (flutter/flutter#191825) 2026-08-26 nate.w5687@gmail.com Fix `Navigator.pushNamed<T>()` type checking (flutter/flutter#188148) 2026-08-26 robert.ancell@canonical.com Handle the case where a window doesn't have a title set (flutter/flutter#191767) 2026-08-26 github@alexv525.com [Android] Remove old `InputType` constructor from embedding (flutter/flutter#191244) 2026-08-26 engine-flutter-autoroll@skia.org Roll Skia from 244a6a0f8f92 to b5465d7b0b77 (19 revisions) (flutter/flutter#191810) 2026-08-26 46920873+gabrimatic@users.noreply.github.com Tolerate floating-point rounding in paintImage centerSlice assertion (flutter/flutter#185789) 2026-08-26 30870216+gaaclarke@users.noreply.github.com Fixes translated bounded blurs (flutter/flutter#191615) 2026-08-26 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from MstTWE1RDOT-RnrtH... to qjOQi-zAgu_tADorh... (flutter/flutter#191769) 2026-08-26 136096126+glitchfl@users.noreply.github.com Lerp HSVColor and HSLColor hue along the shortest arc (flutter/flutter#191186) 2026-08-26 116356835+AbdeMohlbi@users.noreply.github.com Fix enum instances comparison to use `equality ==` since dart has the correct behavior now (flutter/flutter#191537) 2026-08-26 30870216+gaaclarke@users.noreply.github.com Switches windows to opengles 3 (flutter/flutter#191516) 2026-08-26 engine-flutter-autoroll@skia.org Roll Dart SDK from 7739e8602bc1 to cb8a4e1a0fbb (1 revision) (flutter/flutter#191784) 2026-08-26 chris@bracken.jp iOS,macOS: Check viewType before creating a platform view (flutter/flutter#191777) 2026-08-26 154381524+flutteractionsbot@users.noreply.github.com Revert: [tool_tests] Remove bringup from Windows tool_tests_commands_2_2 (flutter/flutter#191793) 2026-08-26 kevmoo@users.noreply.github.com refactor(flutter_tools): clean up dead unreferenced declarations (flutter/flutter#191163) 2026-08-26 engine-flutter-autoroll@skia.org Roll Fuchsia GN SDK from a87CbQSWEjkPUK1ZY... to ZsxUUK2SfA-TrNvb8... (flutter/flutter#191763) 2026-08-26 bkonyi@google.com [tool_tests] Remove bringup from Windows tool_tests_commands_2_2 (flutter/flutter#191732) 2026-08-25 36861262+QuncCccccc@users.noreply.github.com Remove legacy gen_defaults analyze checks (flutter/flutter#191629) 2026-08-25 52160996+FMorschel@users.noreply.github.com Refactors `try` to avoid `unawaited_return_in_try_block` case (flutter/flutter#191129) 2026-08-25 engine-flutter-autoroll@skia.org Roll Dart SDK from 8996935d3d0a to 7739e8602bc1 (1 revision) (flutter/flutter#191754) ...
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.
linear_gradient_fill.fragandradial_gradient_fill.fragthat samples a texture to get a color for linear and radial gradients. This logic is moved to functions ingradient.glsl, to share withuber_sdf.frag.Canvas::AddRenderSDFEntityToCurrentPassto fill in the gradient texture and gradient related properties whenpaint.color_sourceis 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:
after:
Skia:
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-assistbot 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.