[Impeller] Add filterQuality support to ImageFilter.shader by ahyangnb · Pull Request #188544 · flutter/flutter · GitHub
Skip to content

[Impeller] Add filterQuality support to ImageFilter.shader#188544

Open
ahyangnb wants to merge 2 commits into
flutter:masterfrom
ahyangnb:master
Open

[Impeller] Add filterQuality support to ImageFilter.shader#188544
ahyangnb wants to merge 2 commits into
flutter:masterfrom
ahyangnb:master

Conversation

@ahyangnb

@ahyangnb ahyangnb commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Adds a filterQuality argument to ImageFilter.shader so the implicitly bound image-filter input sampler can be configured instead of always using nearest-neighbor sampling.

This threads the requested sampling quality through dart:ui, DisplayList runtime-effect image filters, and Impeller’s runtime-effect texture input setup. The default remains FilterQuality.none to preserve existing behavior.

This also adds regression coverage with a fractional-texel shader to verify that BackdropFilter + ImageFilter.shader honors FilterQuality, plus equality coverage for shader image filters that differ only by input sampling.

Fixes #188365

No changes were required in the flutter/tests repo.

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.

@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. platform-web Web applications specifically e: impeller Impeller rendering backend issues and features requests team-web Owned by Web platform team labels Jun 25, 2026

@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 adds support for specifying FilterQuality when creating an ImageFilter from a custom fragment shader, propagating the sampling configuration through the Dart API, native bindings, and Impeller backend. Feedback on the changes highlights a missing initialization of the u_size uniform in the test shader, which could cause undefined behavior, and suggests refactoring the sampler loop in image_filter.cc to use a boolean flag instead of an index counter for simpler logic.

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.

high

The fragment shader filter_shader_fractional_texel.frag declares a uniform vec2 u_size which is used to normalize the texture coordinates. However, in backdropShaderWithFilterQuality, the u_size uniform is never initialized on the shader object. This will result in a division by zero (or uninitialized garbage values) in the shader, leading to undefined behavior and potential test flakiness across different GPUs/backends.

Please set the u_size uniform using shader.setFloat before using it.

    final FragmentShader shader = program.fragmentShader();
    shader.setFloat(0, widthAsDouble);
    shader.setFloat(1, heightAsDouble);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't agree with it, because for ImageFilter.shader, the first vec2 uniform is intentionally engine-managed. The API doc says the first uniform is set by the engine to the bound texture size in painting.dart. The actual Impeller render path does it in runtime_effect_filter_contents.cc.

Comment on lines 120 to 130
size_t index = 0;
for (const std::shared_ptr<flutter::DlColorSource>& sampler :
runtime_filter->samplers()) {
if (index == 0 && sampler == nullptr) {
// Insert placeholder for filter.
if (index == 0) {
// The first sampler is always the image filter input.
texture_inputs.push_back(
{.sampler_descriptor = skia_conversions::ToSamplerDescriptor({}),
{.sampler_descriptor = skia_conversions::ToSamplerDescriptor(
runtime_filter->input_sampling()),
.texture = nullptr});
index++;
continue;

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

Using a bool is_first flag instead of an index counter simplifies the loop logic and makes it less error-prone, as we don't need to manually increment the index in multiple branches.

Suggested change
size_t index = 0;
for (const std::shared_ptr<flutter::DlColorSource>& sampler :
runtime_filter->samplers()) {
if (index == 0 && sampler == nullptr) {
// Insert placeholder for filter.
if (index == 0) {
// The first sampler is always the image filter input.
texture_inputs.push_back(
{.sampler_descriptor = skia_conversions::ToSamplerDescriptor({}),
{.sampler_descriptor = skia_conversions::ToSamplerDescriptor(
runtime_filter->input_sampling()),
.texture = nullptr});
index++;
continue;
bool is_first = true;
for (const std::shared_ptr<flutter::DlColorSource>& sampler :
runtime_filter->samplers()) {
if (is_first) {
is_first = false;
// The first sampler is always the image filter input.
texture_inputs.push_back(
{.sampler_descriptor = skia_conversions::ToSamplerDescriptor(
runtime_filter->input_sampling()),
.texture = nullptr});
continue;
}

Comment on lines 142 to +147
texture_inputs.push_back({
.sampler_descriptor =
skia_conversions::ToSamplerDescriptor(image->sampling()),
.texture = std::move(texture),
});
index++;

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

Remove the index++ increment since we are now using the is_first boolean flag to identify the first sampler.

Suggested change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

e: impeller Impeller rendering backend issues and features requests engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Impeller] ImageFilter.shader implicit backdrop sampler cannot be configured with FilterQuality

1 participant