Repository navigation
Open
Labels
P1High-priority issues at the top of the work listHigh-priority issues 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.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onteam-engineOwned by Engine teamOwned by Engine teamtriaged-engineTriaged by Engine teamTriaged by Engine team
Description
Issue
When Impeller enabled, rendering a gradient abruptly changes color instead of transitioning smoothly. The shader’s dot product overflows the FP16 exponent range on llvmpipe before normalization. Using highp fixes the output.
Reproduction
Issue verified using Fedora 44 Linux and Flutter 3.50.0-1.0.pre-209 • channel master
flutter-shader-compare-gradient-fix.zip
Extract the attached reproduction and run:
./setup.sh
./compile.sh
python3 render.py compare
This compiles the original and fixed Flutter shaders using impellerc, then compares their rendered output. Verified on Mesa llvmpipe; and AMD GPU.
For the integrated Flutter regression test and proposed fix, see #195036.
or try this
import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(
home: Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Linear'),
SizedBox(
width: 400,
height: 100,
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [Colors.red, Colors.blue],
),
),
),
),
SizedBox(height: 24),
Text('Radial'),
SizedBox(
width: 1100,
height: 100,
child: DecoratedBox(
decoration: BoxDecoration(
gradient: RadialGradient(
center: Alignment.centerLeft,
// Radius is relative to the shortest side:
// 10 × 100 = 1000 logical pixels.
radius: 10,
colors: [Colors.red, Colors.blue],
),
),
),
),
],
),
),
),
),
),
));Proposed fix
References
GLSL ES precision guarantees. mediump does not guarantee 32-bit arithmetic.
Metadata
Metadata
Assignees
Labels
P1High-priority issues at the top of the work listHigh-priority issues 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.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onteam-engineOwned by Engine teamOwned by Engine teamtriaged-engineTriaged by Engine teamTriaged by Engine team
Activity
richyo-codes commentedon Oct 23, 2026
I am wondering if only noticing this now because Impeller started on Android / mobile with smaller screens that may not have triggered or been noticable. Now with Desktop impeller enabled in Flutter easier to render bigger gradients.
mbcorona commentedon Oct 23, 2026
Hi @richyo-codes, thanks for the analysis and the PR.
Related to the broader precision inconsistency tracked in #172846, and your fix is up as a draft in #195036 with a regression test.
Routing to team-engine.
richyo-codes commentedon Oct 26, 2026
According to my research Impeller + Vulkan rendering is the main problem with the inconsistent precision. Because with mediump the Vulkan driver can decide on 16bit or 32bit float. I've been working on GTK4 support which defaults to Vulkan rendering, so that might be why I am noticing this issue sooner than others. There is also a GTK3 branch working on merging a Vulkan renderer for Impeller.
Regardless of the precision inconsistency ticket you mention. If mediump sometimes fails with gradient due to lack of precision. Then I think my Draft PR changing gradient shaders to explicitly use highp is correct because it will always work.
I will note that precision inconsistency issue #172846 was reported using a external demo shader toy, where as the shaders I am reporting are built into flutter. So can't be corrected / worked around without framework fix.