Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
5652351d
Unverified
Commit
5652351d
authored
Feb 12, 2021
by
Ian Hickson
Committed by
GitHub
Feb 12, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clean up some documentation around shader warm-up. (#75863)
parent
cd324657
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
69 additions
and
44 deletions
+69
-44
binding.dart
packages/flutter/lib/src/painting/binding.dart
+18
-10
shader_warm_up.dart
packages/flutter/lib/src/painting/shader_warm_up.dart
+51
-34
No files found.
packages/flutter/lib/src/painting/binding.dart
View file @
5652351d
...
...
@@ -29,27 +29,35 @@ mixin PaintingBinding on BindingBase, ServicesBinding {
static
PaintingBinding
?
get
instance
=>
_instance
;
static
PaintingBinding
?
_instance
;
/// [ShaderWarmUp] to be executed during [initInstances].
/// [ShaderWarmUp] instance to be executed during [initInstances].
///
/// Defaults to an instance of [DefaultShaderWarmUp].
///
/// If the application has scenes that require the compilation of complex
/// 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 c
alling [initInstances]
/// in the middle of an animation or interaction. In that case, set
ting
/// [shaderWarmUp] to a custom [ShaderWarmUp] before c
reating the binding
/// (usually before [runApp] for normal Flutter apps, and before
/// [enableFlutterDriverExtension] for Flutter driver 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
/// installation or a data wipe. The warm up does not block the main thread
/// so there should be no "Application Not Responding" warning.
/// [enableFlutterDriverExtension] for Flutter driver tests) may help if that
/// object paints the difficult scene in its [ShaderWarmUp.warmUpOnCanvas]
/// method, as this allows Flutter to pre-compile and cache the required
/// shaders during startup.
///
/// Currently the warm-up happens synchronously on the raster thread which
/// means the rendering of the first frame on the raster thread will be
/// postponed until the warm-up is finished.
///
/// The warm up is only costly (100ms-200ms, depending on the shaders to
/// compile) during the first run after the installation or a data wipe. The
/// warm up does not block the platform thread so there should be no
/// "Application Not Responding" warning.
///
/// If this is null, no shader warm-up is executed.
///
/// See also:
///
/// * [ShaderWarmUp], the interface of how this warm up works.
/// * [ShaderWarmUp], the interface for implementing custom warm-up scenes.
/// * <https://flutter.dev/docs/perf/rendering/shader>
static
ShaderWarmUp
?
shaderWarmUp
=
const
DefaultShaderWarmUp
();
/// The singleton that implements the Flutter framework's image cache.
...
...
packages/flutter/lib/src/painting/shader_warm_up.dart
View file @
5652351d
...
...
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:developer'
;
import
'dart:ui'
as
ui
;
...
...
@@ -25,18 +24,16 @@ import 'package:flutter/foundation.dart';
///
/// To determine whether a draw operation is useful for warming up shaders,
/// check whether it improves the slowest frame rasterization time. Also,
/// tracing with `flutter run --profile --trace-skia` may reveal whether
///
there
is shader-compilation-related jank. If there is such jank, some long
/// 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.
/// `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
...
...
@@ -51,8 +48,10 @@ import 'package:flutter/foundation.dart';
///
/// * [PaintingBinding.shaderWarmUp], the actual instance of [ShaderWarmUp]
/// that's used to warm up the shaders.
/// * <https://flutter.dev/docs/perf/rendering/shader>
abstract
class
ShaderWarmUp
{
/// Allow const constructors for subclasses.
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
const
ShaderWarmUp
();
/// The size of the warm up image.
...
...
@@ -68,32 +67,33 @@ abstract class ShaderWarmUp {
/// compilation cache.
///
/// To decide which draw operations to be added to your custom warm up
/// process, try capture an skp using
/// `flutter screenshot --observatory-uri=<uri> --type=skia`
/// and analyze it with https://debugger.skia.org.
/// Alternatively, one may run the app with `flutter run --trace-skia` and
/// then examine the raster thread in the observatory timeline to see which
/// Skia draw operations are commonly used, and which shader compilations
/// are causing jank.
/// process, consider capturing an skp using `flutter screenshot
/// --observatory-uri=<uri> --type=skia` and analyzing it with
/// <https://debugger.skia.org/>. Alternatively, one may run the app with
/// `flutter run --trace-skia` and then examine the raster thread in the
/// observatory timeline to see which Skia draw operations are commonly used,
/// and which shader compilations are causing jank.
@protected
Future
<
void
>
warmUpOnCanvas
(
ui
.
Canvas
canvas
);
/// Construct an offscreen image of [size], and execute [warmUpOnCanvas] on a
/// canvas associated with that image.
///
/// Currently, this has no effect when [kIsWeb] is true.
Future
<
void
>
execute
()
async
{
final
ui
.
PictureRecorder
recorder
=
ui
.
PictureRecorder
();
final
ui
.
Canvas
canvas
=
ui
.
Canvas
(
recorder
);
await
warmUpOnCanvas
(
canvas
);
final
ui
.
Picture
picture
=
recorder
.
endRecording
();
final
TimelineTask
shaderWarmUpTask
=
TimelineTask
();
shaderWarmUpTask
.
start
(
'Warm-up shader'
);
// Picture.toImage is not yet implemented on the web.
if
(!
kIsWeb
)
{
await
picture
.
toImage
(
size
.
width
.
ceil
(),
size
.
height
.
ceil
());
if
(!
kIsWeb
)
{
// Picture.toImage is not yet implemented on the web.
final
TimelineTask
shaderWarmUpTask
=
TimelineTask
();
shaderWarmUpTask
.
start
(
'Warm-up shader'
);
try
{
await
picture
.
toImage
(
size
.
width
.
ceil
(),
size
.
height
.
ceil
());
}
finally
{
shaderWarmUpTask
.
finish
();
}
}
shaderWarmUpTask
.
finish
();
}
}
...
...
@@ -102,19 +102,37 @@ abstract class ShaderWarmUp {
/// The draw operations being warmed up here are decided according to Flutter
/// engineers' observation and experience based on the apps and the performance
/// issues seen so far.
///
/// This is used for the default value of [PaintingBinding.shaderWarmUp].
/// Consider setting that static property to a different value before the
/// binding is initialized to change the warm-up sequence.
///
/// See also:
///
/// * [ShaderWarmUp], the base class for shader warm-up objects.
/// * <https://flutter.dev/docs/perf/rendering/shader>
class
DefaultShaderWarmUp
extends
ShaderWarmUp
{
/// Allow [DefaultShaderWarmUp] to be used as the default value of parameters.
/// Create an instance of the default shader warm-up logic.
///
/// Since this constructor is `const`, [DefaultShaderWarmUp] can be used as
/// the default value of parameters.
const
DefaultShaderWarmUp
({
this
.
drawCallSpacing
=
0.0
,
this
.
canvasSize
=
const
ui
.
Size
(
100.0
,
100.0
),
});
/// Constant that can be used to space out draw calls for visualizing the draws
/// for debugging purposes (example: 80.0). Be sure to also change your canvas
/// size.
/// Distance to place between draw calls for visualizing the draws for
/// debugging purposes (e.g. 80.0).
///
/// Defaults to 0.0.
///
/// When changing this value, the [canvasSize] must also be changed to
/// accomodate the bigger canvas.
final
double
drawCallSpacing
;
/// Value that returned by this.size to control canvas size where draws happen.
/// The [size] of the canvas required to paint the shapes in [warmUpOnCanvas].
///
/// When [drawCallSpacing] is 0.0, this should be at least 100.0 by 100.0.
final
ui
.
Size
canvasSize
;
@override
...
...
@@ -126,9 +144,8 @@ class DefaultShaderWarmUp extends ShaderWarmUp {
Future
<
void
>
warmUpOnCanvas
(
ui
.
Canvas
canvas
)
async
{
const
ui
.
RRect
rrect
=
ui
.
RRect
.
fromLTRBXY
(
20.0
,
20.0
,
60.0
,
60.0
,
10.0
,
10.0
);
final
ui
.
Path
rrectPath
=
ui
.
Path
()..
addRRect
(
rrect
);
final
ui
.
Path
circlePath
=
ui
.
Path
()..
addOval
(
ui
.
Rect
.
fromCircle
(
center:
const
ui
.
Offset
(
40.0
,
40.0
),
radius:
20.0
)
ui
.
Rect
.
fromCircle
(
center:
const
ui
.
Offset
(
40.0
,
40.0
),
radius:
20.0
)
);
// The following path is based on
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment