Unverified Commit f776cc19 authored by liyuqian's avatar liyuqian Committed by GitHub

Add convex path and non-AA paint to shader warm-up (#28614)

One of our important client's SKP shows that this could improve one of
their janky frame by 20ms. This also improves our
flutter_gallery__transition_perf's worst frame time by ~20ms.

On the other hand, 15ms has been added to the start-up latency. I guess
it's a little faster to compile the shader on the start-up because we're
compiling a lot of shaders there and the CPU cache must be hot.

## Related Issues

https://github.com/flutter/flutter/issues/813
parent 5aedf97e
......@@ -38,8 +38,8 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
/// shaders that are not covered by [DefaultShaderWarmUp], it may cause jank
/// in the middle of an animation or interaction. In that case, set
/// [shaderWarmUp] to a custom [ShaderWarmUp] before calling [initInstances]
/// (usually before [runApp] for normal flutter apps, and before
/// [enableFlutterDriverExtension] for flutter drive tests). Paint the scene
/// (usually before [runApp] for normal Flutter apps, and before
/// [enableFlutterDriverExtension] for Flutter drive tests). Paint the scene
/// in the custom [ShaderWarmUp] so Flutter can pre-compile and cache the
/// shaders during startup. The warm up is only costly (100ms-200ms,
/// depending on the shaders to compile) during the first run after the
......@@ -49,6 +49,10 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
/// Currently the warm-up happens synchronously on the GPU thread which means
/// the rendering of the first frame on the GPU thread will be postponed until
/// the warm-up is finished.
///
/// See also:
///
/// * [ShaderWarmUp], the interface of how this warm up works.
static ShaderWarmUp shaderWarmUp = const DefaultShaderWarmUp();
/// The singleton that implements the Flutter framework's image cache.
......
......@@ -9,26 +9,45 @@ import 'package:flutter/foundation.dart';
/// Interface for drawing an image to warm up Skia shader compilations.
///
/// When Skia first sees a certain type of draw operations on GPU, it needs to
/// compile the corresponding shader. The compilation can be slow (20ms-200ms).
/// Having that time as a startup latency is often better than having a jank in
/// the middle of an animation.
/// When Skia first sees a certain type of draw operation on the GPU, it needs
/// to compile the corresponding shader. The compilation can be slow (20ms-
/// 200ms). Having that time as startup latency is often better than having
/// jank in the middle of an animation.
///
/// Therefore, we use this during the [PaintingBinding.initInstances] call to
/// move common shader compilations from animation time to startup time. By
/// default, a [DefaultShaderWarmUp] is used. Create a custom [ShaderWarmUp]
/// subclass to replace [PaintingBinding.shaderWarmUp] before
/// [PaintingBinding.initInstances] is called. Usually, that can be done before
/// calling [runApp].
/// default, a [DefaultShaderWarmUp] is used. If needed, app developers can
/// create a custom [ShaderWarmUp] subclass and hand it to
/// [PaintingBinding.shaderWarmUp] (so it replaces [DefaultShaderWarmUp])
/// before [PaintingBinding.initInstances] is called. Usually, that can be
/// done before calling [runApp].
///
/// This warm up needs to be run on each individual device because the shader
/// To determine whether a draw operation is useful for warming up shaders,
/// check the difference in the `worst_frame_rasterizer_time_millis` benchmarks.
/// Also, tracing with `flutter run --profile --trace-skia` may reveal whether
/// there is shader-compilation-related jank. If there is such jank, some long
/// `GrGLProgramBuilder::finalize` calls would appear in the middle of an
/// animation. Their parent calls, which look like `XyzOp` (e.g., `FillRecOp`,
/// `CircularRRectOp`) would suggest Xyz draw operations are causing the shaders
/// to be compiled. A useful shader warm-up draw operation would eliminate such
/// long compilation calls in the animation. To double-check the warm-up, trace
/// with `flutter run --profile --trace-skia --start-paused`. The
/// `GrGLProgramBuilder` with the associated `XyzOp` should appear during
/// startup rather than in the middle of a later animation.
///
/// This warm-up needs to be run on each individual device because the shader
/// compilation depends on the specific GPU hardware and driver a device has. It
/// can't be pre-computed during the Flutter engine compilation as the engine is
/// device agnostic.
/// device-agnostic.
///
/// If no warm up is desired (e.g., when the startup latency is crucial), set
/// If no warm-up is desired (e.g., when the startup latency is crucial), set
/// [PaintingBinding.shaderWarmUp] either to a custom ShaderWarmUp with an empty
/// [warmUpOnCanvas] or null.
///
/// See also:
///
/// * [PaintingBinding.shaderWarmUp], the actual instance of [ShaderWarmUp]
/// that's used to warm up the shaders.
abstract class ShaderWarmUp {
/// Allow const constructors for subclasses.
const ShaderWarmUp();
......@@ -101,12 +120,27 @@ class DefaultShaderWarmUp extends ShaderWarmUp {
path.moveTo(60.0, 20.0);
path.quadraticBezierTo(60.0, 60.0, 20.0, 60.0);
final List<ui.Path> paths = <ui.Path>[rrectPath, circlePath, path];
final ui.Path convexPath = ui.Path();
convexPath.moveTo(20.0, 30.0);
convexPath.lineTo(40.0, 20.0);
convexPath.lineTo(60.0, 30.0);
convexPath.lineTo(60.0, 60.0);
convexPath.lineTo(20.0, 60.0);
convexPath.close();
// Skia uses different shaders based on the kinds of paths being drawn and
// the associated paint configurations. According to our experience and
// tracing, drawing the following paths/paints generates various of
// shaders that are commonly used.
final List<ui.Path> paths = <ui.Path>[rrectPath, circlePath, path, convexPath];
final List<ui.Paint> paints = <ui.Paint>[
ui.Paint()
..isAntiAlias = true
..style = ui.PaintingStyle.fill,
ui.Paint()
..isAntiAlias = false
..style = ui.PaintingStyle.fill,
ui.Paint()
..isAntiAlias = true
..style = ui.PaintingStyle.stroke
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment