Repository navigation
BackdropFilter renders offscreen even if not repainted. #27677
Copy link
Copy link
Closed
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listc: performanceRelates to speed or footprint issues (see "perf:" labels)Relates to speed or footprint issues (see "perf:" labels)engineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.
Description
Issue:
Bad performance with lots of blur BackdropFilters even if background below them is always the same.
Steps to Reproduce
- Add
BackdropFilteranywhere in the app. (with visible child like text/etc) - Repaint any other part of screen.
- Notice that
BackdropFilteris rendered offscreen on every frame (viacheckerboardOffscreenLayersand performance overlay).
Is this behavior intended?
If yes, is it possible to somehow cache the output to prevent offscreen re-rendering?
Minimal reproducing code
Should be fine to just drop into new flutter project main.dart
Code below tries to animate a small rectangle with background color and lags a lot due to GPU thread being completely filled with BackdropFilters rendering offscreen.
Note that they are not repainted and RepaintBoundary is not helping with the issue. Animation is not required, absolutely anything that causes frame to paint has the issue (like scrolling scrollview in some other part of screen)
import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
checkerboardOffscreenLayers: true,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
AnimationController animation;
@override
void initState() {
super.initState();
animation = AnimationController(vsync: this, duration: Duration(seconds: 1));
_startAnimation();
}
Future _startAnimation() async {
try {
await animation
.repeat()
.orCancel;
} on TickerCanceled {}
}
@override
Widget build(BuildContext context) {
Widget text() {
return ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: Column(
children: <Widget>[
Container(padding: EdgeInsets.all(5), child: Text("txt")),
],
)),
);
}
Widget col() {
return Column(children: List.generate(17, (i) => text()));
}
return Scaffold(
backgroundColor: Colors.grey,
body: Container(
child: Column(
children: [
Expanded(
child: RepaintBoundary(
child: Center(
child: AnimatedBuilder(
animation: animation,
builder: (c, w) {
final val = (animation.value * 255).round();
return Container(
width: 50,
height: 50,
color: Color.fromARGB(255, val, val, val));
}),
)),
),
SizedBox(height: 50),
RepaintBoundary(
child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate(5, (i) => col())),
),
SizedBox(height: 50),
],
),
),
);
}
}Logs
flutter doctor -v:
[√] Flutter (Channel dev, v1.2.0, on Microsoft Windows [Version 10.0.17763.292], locale en-US)
• Flutter version 1.2.0 at D:\programs\flutter
• Framework revision 06b979c4d5 (2 weeks ago), 2019-01-25 14:27:35 -0500
• Engine revision 36acd02c94
• Dart version 2.1.1 (build 2.1.1-dev.3.2 f4afaee422)
[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
• Android SDK at D:\programs\androidsdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-28, build-tools 28.0.3
• ANDROID_HOME = D:\programs\androidsdk
• ANDROID_SDK_ROOT = D:\programs\androidsdk
• Java binary at: D:\programs\android-studio\jre\bin\java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
• All Android licenses accepted.
[√] Android Studio (version 3.3)
• Android Studio at D:\programs\android-studio
• Flutter plugin version 32.0.1
• Dart plugin version 182.5124
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
[!] VS Code, 64-bit edition (version 1.25.0)
• VS Code at C:\Program Files\Microsoft VS Code
X Flutter extension not installed; install from
https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[√] Connected device (1 available)
• Mi A2 Lite • 192.168.0.161:5555 • android-arm64 • Android 9 (API 28)
! Doctor found issues in 1 category.
Flutter analyze output
Analyzing flutter_bug_test...
No issues found! (ran in 2.0s)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listc: performanceRelates to speed or footprint issues (see "perf:" labels)Relates to speed or footprint issues (see "perf:" labels)engineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.
Activity
chinmaygarde commentedon Feb 11, 2019
cc @liyuqian: Can we consider bumping up the priority of such layers for participation in the raster cache?
liyuqian commentedon Feb 14, 2019
Yes, I have started working on adding options to
RepaintBoundaryto allow developers to explicitly enable raster cache. It should be useful for rotation (#24627),Opacity, and in this caseBackdropFilter.The work is currently postponed because of other higher priority issues. My estimation of finishing the work is Q2.
flar commentedon Jun 19, 2019
Just to be clear, the BackdropFilter blurs the entire screen by default so the animated rectangle is in the background of the text items. As written, the test case can never optimize out the repaint of the blurred text widgets because technically their pixels depend on the animating pixels in the color-changing rectangle.
(It may be possible to avoid redrawing the actual text item in the last child since it is on top of everything that might change, but repainting it is not a performance issue here. And even with such an optimization, all of the other text objects in the grid contribute to the blurred background of the last text item and so they do need to be rerendered in order to provide the raw pixels for the blur operation of the final text item.)
flar commentedon Jun 19, 2019
I am curious what the goal was for the test case - what was it trying to achieve? The BackdropFilter technically does include the entire screen as a background and so it is not possible to optimize out its repaints as suggested - in that way it is "working as the Widget intended" - but perhaps there is a different way to use it or a different Widget that will work "as the developer wants/intends"...?
ctrl-shift commentedon Jun 19, 2019
At the time issue was filled
BackdropFilterwas affecting only the area behind it, so assume implicitClipRectaroundBackdropFilterin the original code. I updated the code in the first post so it works on new flutter version.So in the example blurred background for text shouldn't paint outside.
It would be good if there was another widget but so far
BackdropFilteris the only one affecting widgets below it, due toSceneBuilder.pushBackdropFilteraccepting onlyImageFilterand no way to create those from flutter side at the moment.flar commentedon Jun 20, 2019
Thanks for the update, the test case makes a lot more sense now.
I'll be looking into RepaintBoundary objects and other layer (in)dependence issues as part of issue #32662 linked above.
The only other question is whether a grid of 17x5 text items all with an individually blurred backgrounds is a necessary aspect of the original design or if that duplication is in the test case to demonstrate the cumulative performance impact.
ctrl-shift commentedon Jun 21, 2019
Duplication is in the test case.
The original design where I encountered a problem had about 2*6 rounded rect "tiles" with pictures/text on them blurring background image behind. It was causing noticeable hiccup once they appeared (and on any view update afterwards) even when built with "--release".
Add test case for Flutter Issue #27677 as a benchmark. (#34870)
Add test case for Flutter Issue flutter#27677 as a benchmark. (flutte…
darshankawar commentedon Aug 26, 2020
Hi @ctrl-shift,
Can you confirm if this still happens on latest stable or master ?
I tried your code on latest stable and didn't notice
backdropfilterrendering offscreen.27677.mp4.zip
darshankawar commentedon Sep 16, 2020
Without additional information, we are unfortunately not sure how to resolve this issue.
We are therefore reluctantly going to close this bug for now.
Please don't hesitate to comment on the bug if you have any more information for us; we will reopen it right away!
Thanks for your contribution.
Could everyone who still has this problem please file a new issue with the exact description of what happens, logs, and the output of
flutter doctor -v.All system setups can be slightly different, so it's always better to open new issues and reference related issues.
github-actions commentedon Aug 7, 2021
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.