Skip to content

BackdropFilter renders offscreen even if not repainted. #27677

Closed

Description

@ctrl-shift

Issue:

Bad performance with lots of blur BackdropFilters even if background below them is always the same.

Steps to Reproduce

  1. Add BackdropFilter anywhere in the app. (with visible child like text/etc)
  2. Repaint any other part of screen.
  3. Notice that BackdropFilter is rendered offscreen on every frame (via checkerboardOffscreenLayers and 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)

Activity

  1. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    engineflutter/engine related. See also e: labels.
    c: performanceRelates to speed or footprint issues (see "perf:" labels)
    on Feb 8, 2019
  2. added this to the milestone on Feb 8, 2019
  3. chinmaygarde commented on Feb 11, 2019

    @chinmaygarde
    Contributor

    cc @liyuqian: Can we consider bumping up the priority of such layers for participation in the raster cache?

  4. liyuqian commented on Feb 14, 2019

    @liyuqian
    Contributor

    Yes, I have started working on adding options to RepaintBoundary to allow developers to explicitly enable raster cache. It should be useful for rotation (#24627), Opacity, and in this case BackdropFilter.

    The work is currently postponed because of other higher priority issues. My estimation of finishing the work is Q2.

  5. flar commented on Jun 19, 2019

    @flar
    Contributor

    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.)

  6. flar commented on Jun 19, 2019

    @flar
    Contributor

    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"...?

  7. ctrl-shift commented on Jun 19, 2019

    @ctrl-shift
    Author

    At the time issue was filled BackdropFilter was affecting only the area behind it, so assume implicit ClipRect around BackdropFilter in 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 BackdropFilter is the only one affecting widgets below it, due to SceneBuilder.pushBackdropFilter accepting only ImageFilter and no way to create those from flutter side at the moment.

  8. flar commented on Jun 20, 2019

    @flar
    Contributor

    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.

  9. ctrl-shift commented on Jun 21, 2019

    @ctrl-shift
    Author

    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".

  10. added a commit that references this issue on Jun 25, 2019
  11. added a commit that references this issue on Jul 30, 2019
  12. added
    P2Important issues not at the top of the work list
    on May 29, 2020
  13. removed this from the milestone on Aug 17, 2020
  14. darshankawar commented on Aug 26, 2020

    @darshankawar
    Member

    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 backdropfilter rendering offscreen.

    27677.mp4.zip

  15. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Aug 26, 2020
  16. darshankawar commented on Sep 16, 2020

    @darshankawar
    Member

    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.

  17. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Dec 30, 2020
  18. github-actions commented on Aug 7, 2021

    @github-actions

    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 -v and a minimal reproduction of the issue.

  19. locked as resolved and limited conversation to collaborators on Aug 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: performanceRelates to speed or footprint issues (see "perf:" labels)engineflutter/engine related. See also e: labels.frameworkflutter/packages/flutter repository. See also f: labels.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions