-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
On lower-end devices two small blurs tend to perform much worse than one large blur because of the extra render pass. But with wide-gamut, this is now an issue on high-end devices too.
Consider the following example:
code
import 'dart:ui';
import 'package:flutter/material.dart';
void main() {
runApp(const MainApp());
}
const kSigma = 1.0;
const kNumberOfBlurs = 6;
class _Blur extends StatelessWidget {
const _Blur();
@override
Widget build(BuildContext context) {
return ClipRRect(
child: BackdropFilter(
blendMode: BlendMode.srcIn,
filter: ImageFilter.blur(
sigmaX: kSigma,
sigmaY: kSigma,
),
child: Container(
color: Colors.red.withAlpha(30),
child: const Text('Blur'),
),
),
);
}
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Stack(
children: [
ListView.builder(
itemBuilder: (context, index) {
return Container(
padding: const EdgeInsets.all(10),
child: Text('Item $index'),
);
},
itemCount: 1000),
for (var i = 0; i < kNumberOfBlurs; ++i) ...[
Positioned(
left: 0,
right: 0,
top: i * 150,
height: 60,
child: const _Blur(),
),
]
],
),
),
);
}
}With 6 backdrop this currently requires 7 passes to render. With wide gamut the cost of each pass can get quite high: #131567.
In this particular case all backdrops can be rendered in second pass, because for each backdrop nothing rendered before it in the second pass affects the area where the backdrop samples from.
Performance on iPhone 13 Pro (A15) with 7 passes:

Performance with all backdrops rendered in second pass:

I think something along "if this is not the first pass and nothing in this pass has rendered where the backdrop is sampling from don't end the pass" might be a significant improvement for common cases such as blurred header and tabbar.
