Repository navigation
Open
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listc: renderingUI glitches reported at the engine/skia or impeller rendering levelUI glitches reported at the engine/skia or impeller rendering levele: impellerImpeller rendering backend issues and features requestsImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.found in release: 3.32Found to occur in 3.32Found to occur in 3.32found in release: 3.33Found to occur in 3.33Found to occur in 3.33has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onplatform-androidAndroid applications specificallyAndroid applications specificallyteam-engineOwned by Engine teamOwned by Engine teamtriaged-engineTriaged by Engine teamTriaged by Engine team
Description
Steps to reproduce
- Run the following sample shader on Android with Impeller. You can also play this on Chrome or macOS for expected behavior
- Then disable Android Impeller by adding
<meta-data android:name="io.flutter.embedding.android.EnableImpeller" android:value="false" />and running again
Expected results
This is expected result
skia.mp4
Actual results
And this is what I can see with Impeller
impeller.mp4
Code sample
Code sample
- Go to repository https://github.com/orestesgaolin/shaders_gallery
- Affected shader is called
CRT
// Original shader: https://www.shadertoy.com/view/lt3yz7 by @tommclaughlan
// Modified to display a glitch effect at a specific time and to compile for Flutter
#version 460 core
precision mediump float;
#include <flutter/runtime_effect.glsl>
uniform vec2 iResolution;
uniform float iTime;
uniform sampler2D iChannel0;
out vec4 fragColor;
float rand(float seed){
return fract(sin(dot(vec2(seed) ,vec2(12.9898,78.233))) * 43758.5453);
}
vec2 displace(vec2 co, float seed, float seed2) {
vec2 shift = vec2(0);
if (rand(seed) > 0.5) {
shift += 0.05 * vec2(2. * (0.5 - rand(seed2)));
}
if (rand(seed2) > 0.6) {
if (co.y > 0.5) {
shift.x *= rand(seed2 * seed);
shift.y *= rand(seed2 * seed);
}
}
return shift;
}
vec4 interlace(vec2 co, vec4 col) {
if (mod(int(co.y), 3) == 0) {
return col * ((sin(iTime * 4.0) * 0.1) + 0.75) + (rand(iTime) * 0.05);
}
return col;
}
void main()
{
vec2 fragCoord = FlutterFragCoord().xy;
vec2 uv = fragCoord/iResolution.xy;
vec2 rDisplace = vec2(0);
vec2 gDisplace = vec2(0);
vec2 bDisplace = vec2(0);
if (iTime == 0.0)
{
fragColor = texture(iChannel0,uv);
return;
}
if (iTime >= 0.55) {
rDisplace = displace(uv, iTime * 2., 2. + iTime);
gDisplace = displace(uv, iTime * 3., 3. + iTime);
bDisplace = displace(uv, iTime * 2., 1. + iTime);
}
rDisplace.x += 0.005 * (0.5 - rand(iTime * 37. * uv.y));
gDisplace.x += 0.007 * (0.5 - rand(iTime * 41. * uv.y));
bDisplace.x += 0.0011 * (0.5 - rand(iTime * 53. * uv.y));
rDisplace.y += 0.001 * (0.5 - rand(iTime * 37. * uv.x));
gDisplace.y += 0.001 * (0.5 - rand(iTime * 41. * uv.x));
bDisplace.y += 0.001 * (0.5 - rand(iTime * 53. * uv.x));
// Output to screen
float rcolor = texture(iChannel0, uv.xy + rDisplace).r;
float gcolor = texture(iChannel0, uv.xy + gDisplace).g;
float bcolor = texture(iChannel0, uv.xy + bDisplace).b;
fragColor = interlace(fragCoord, vec4(rcolor, gcolor, bcolor, 1));
}
Screenshots or Video
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
n/a
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.32.8, on macOS 15.5 24F74 darwin-arm64, locale pl-PL) [454ms]
• Flutter version 3.32.8 on channel stable at /Users/dominik/fvm/versions/stable
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision edada7c56e (3 days ago), 2025-07-25 14:08:03 +0000
• Engine revision ef0cd00091
• Dart version 3.8.1
• DevTools version 2.45.1
[!] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [456ms]
• Android SDK at /Users/dominik/Library/Android/sdk
✗ cmdline-tools component is missing.
Try installing or updating Android Studio.
Alternatively, download the tools from https://developer.android.com/studio#command-line-tools-only and make sure to set the ANDROID_HOME environment variable.
See https://developer.android.com/studio/command-line for more details.
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/to/macos-android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 16.4) [1 145ms]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 16F6
• CocoaPods version 1.16.2
[✓] Chrome - develop for the web [11ms]
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2024.3) [10ms]
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.5+-13047016-b750.29)
[✓] VS Code (version 1.102.2) [9ms]
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.114.0
[✓] Connected device (5 available) [6,2s]
• SM G991B (mobile) • R5CR617G51T • android-arm64 • Android 15 (API 35)
• iPhone 12 mini (mobile) • 00008101-0001510C3CF0001E • ios • iOS 18.5 22F76
• iPhone 16 (mobile) • A842F0B4-B420-4FF4-AC01-9C30D5531144 • ios • com.apple.CoreSimulator.SimRuntime.iOS-18-4 (simulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 15.5 24F74 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 138.0.7204.169
[✓] Network resources [294ms]
• All expected network resources are available.
! Doctor found issues in 1 category.Reacted by Daniel Saier
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listc: renderingUI glitches reported at the engine/skia or impeller rendering levelUI glitches reported at the engine/skia or impeller rendering levele: impellerImpeller rendering backend issues and features requestsImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.found in release: 3.32Found to occur in 3.32Found to occur in 3.32found in release: 3.33Found to occur in 3.33Found to occur in 3.33has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onplatform-androidAndroid applications specificallyAndroid applications specificallyteam-engineOwned by Engine teamOwned by Engine teamtriaged-engineTriaged by Engine teamTriaged by Engine team
Activity
tirth-patel-nc commentedon Jul 28, 2025
Thanks for the report. Seeing the same behaviour with latest SDK versions with Impeller Enabled on Android. Tested on Pixel 6a.
chinmaygarde commentedon Jul 28, 2025
From Triage: Thanks for the reproduction. We are attempting to get to the bottom of this.
We are most interesting in the precision of the uniform and
impellercapplying it inconsistently across backends. Especially of the iTime uniform which is used in thesinfunction. Besides that, this shader is pretty plain vanilla.chinmaygarde commentedon Jul 28, 2025
Ok, as suspected,
precision mediump float;is the culprit. Specifically, on theiTimeuniform.In the Skia backend, SKSL ignores the precision modifiers and always assumes
highprecision forfloats andmediumprecision forhalfs (lowpis always unsupported). With Impeller, it is specific to whatever the backend can support.Does
precision mediump float;serve a specific purpose? It may be common for shader code to copied from different sources and perhaps we should always ignore precision modifiers in the code. But we have used them selectively in internal shaders for performance. It stands to reason that third-party shaders might want to do the same and we shouldn't lock them out of this opportunity.But from a developer experience standpoint this behavior is unexpected and there may be reasonable expectation that Flutter should abstract away this detail as much as possible.
As an aside but still relevant in your case, since you are sampling from the texture, please don't forget to account for the Y-flip in OpenGL.
[-]Fragment shader looks vastly different on Android with Impeller than with Skia[/-][+]Shader precision is handled inconsistently between rendering backends.[/+]chinmaygarde commentedon Jul 28, 2025
Unless @orestesgaolin has a reason for adding the
mediumpprecision, my vote would be to ignore all precision modifiers in runtime stages so users don't run into unexpected issues.orestesgaolin commentedon Jul 28, 2025
Thanks for the thorough explanation. I copied the source code from the shadertoy with minimal adjustements for Flutter, so my expectation would be to have the same experience as on macOS/iOS where this looks the same as on Android with Skia.
I don't have any particular reason to use
mediumpprecision.