Skip to content

Commit

Permalink
Allow raster caching any layer subtree (flutter#6442)
Browse files Browse the repository at this point in the history
We first test this with OpacityLayer. This test alone (without retained rendering) should have ~30% speedup as we'll have fewer render target switches by snapshoting in the Preroll instead of saveLayer in the Paint.

In my local flutter_gallery transition perf tests, the average frame time drops from ~16ms to ~12ms.

flutter/flutter#21756
  • Loading branch information
liyuqian authored Oct 11, 2018
1 parent 9cad7b6 commit 6447418
Show file tree
Hide file tree
Showing 15 changed files with 248 additions and 119 deletions.
2 changes: 1 addition & 1 deletion flow/compositor_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ CompositorContext::ScopedFrame::~ScopedFrame() {
bool CompositorContext::ScopedFrame::Raster(flow::LayerTree& layer_tree,
bool ignore_raster_cache) {
layer_tree.Preroll(*this, ignore_raster_cache);
layer_tree.Paint(*this);
layer_tree.Paint(*this, ignore_raster_cache);
return true;
}

Expand Down
10 changes: 5 additions & 5 deletions flow/debug_print.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ std::ostream& operator<<(std::ostream& os, const flow::MatrixDecomposition& m) {

std::ostream& operator<<(std::ostream& os, const SkMatrix& m) {
SkString string;
string.printf(
"[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
string.printf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
os << string.c_str();
return os;
}
Expand Down Expand Up @@ -72,8 +71,9 @@ std::ostream& operator<<(std::ostream& os, const SkPoint& r) {
return os;
}

std::ostream& operator<<(std::ostream& os, const flow::RasterCacheKey& k) {
os << "Picture: " << k.picture_id() << " matrix: " << k.matrix();
std::ostream& operator<<(std::ostream& os,
const flow::PictureRasterCacheKey& k) {
os << "Picture: " << k.id() << " matrix: " << k.matrix();
return os;
}

Expand Down
2 changes: 1 addition & 1 deletion flow/debug_print.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#define DEF_PRINTER(x) std::ostream& operator<<(std::ostream&, const x&);

DEF_PRINTER(flow::MatrixDecomposition);
DEF_PRINTER(flow::RasterCacheKey);
DEF_PRINTER(flow::PictureRasterCacheKey);
DEF_PRINTER(SkISize);
DEF_PRINTER(SkMatrix);
DEF_PRINTER(SkMatrix44);
Expand Down
21 changes: 14 additions & 7 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,34 @@ enum Clip { none, hardEdge, antiAlias, antiAliasWithSaveLayer };

class ContainerLayer;

struct PrerollContext {
RasterCache* raster_cache;
GrContext* gr_context;
SkColorSpace* dst_color_space;
SkRect child_paint_bounds;

// The following allows us to paint in the end of subtree preroll
const Stopwatch& frame_time;
const Stopwatch& engine_time;
TextureRegistry& texture_registry;
const bool checkerboard_offscreen_layers;
};

// Represents a single composited layer. Created on the UI thread but then
// subquently used on the Rasterizer thread.
class Layer {
public:
Layer();
virtual ~Layer();

struct PrerollContext {
RasterCache* raster_cache;
GrContext* gr_context;
SkColorSpace* dst_color_space;
SkRect child_paint_bounds;
};

virtual void Preroll(PrerollContext* context, const SkMatrix& matrix);

struct PaintContext {
SkCanvas& canvas;
const Stopwatch& frame_time;
const Stopwatch& engine_time;
TextureRegistry& texture_registry;
const RasterCache* raster_cache;
const bool checkerboard_offscreen_layers;
};

Expand Down
41 changes: 25 additions & 16 deletions flow/layers/layer_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ void LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
frame.canvas() ? frame.canvas()->imageInfo().colorSpace() : nullptr;
frame.context().raster_cache().SetCheckboardCacheImages(
checkerboard_raster_cache_images_);
Layer::PrerollContext context = {
PrerollContext context = {
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
frame.gr_context(),
color_space,
SkRect::MakeEmpty(),
};
frame.context().frame_time(),
frame.context().engine_time(),
frame.context().texture_registry(),
checkerboard_offscreen_layers_};

root_layer_->Preroll(&context, frame.root_surface_transformation());
}
Expand Down Expand Up @@ -60,15 +63,16 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
}
#endif

void LayerTree::Paint(CompositorContext::ScopedFrame& frame) const {
void LayerTree::Paint(CompositorContext::ScopedFrame& frame,
bool ignore_raster_cache) const {
TRACE_EVENT0("flutter", "LayerTree::Paint");
Layer::PaintContext context = {
*frame.canvas(), //
frame.context().frame_time(), //
frame.context().engine_time(), //
frame.context().texture_registry(), //
checkerboard_offscreen_layers_ //
};
*frame.canvas(),
frame.context().frame_time(),
frame.context().engine_time(),
frame.context().texture_registry(),
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
checkerboard_offscreen_layers_};

if (root_layer_->needs_painting())
root_layer_->Paint(context);
Expand All @@ -84,24 +88,29 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
return nullptr;
}

Layer::PrerollContext preroll_context{
nullptr, // raster_cache (don't consult the cache)
nullptr, // gr_context (used for the raster cache)
nullptr, // SkColorSpace* dst_color_space
SkRect::MakeEmpty(), // SkRect child_paint_bounds
};

const Stopwatch unused_stopwatch;
TextureRegistry unused_texture_registry;
SkMatrix root_surface_transformation;
// No root surface transformation. So assume identity.
root_surface_transformation.reset();

PrerollContext preroll_context{
nullptr, // raster_cache (don't consult the cache)
nullptr, // gr_context (used for the raster cache)
nullptr, // SkColorSpace* dst_color_space
SkRect::MakeEmpty(), // SkRect child_paint_bounds
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
false, // checkerboard_offscreen_layers
};

Layer::PaintContext paint_context = {
*canvas, // canvas
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
nullptr, // raster cache
false // checkerboard offscreen layers
};

Expand Down
3 changes: 2 additions & 1 deletion flow/layers/layer_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class LayerTree {
scenic::ContainerNode& container);
#endif

void Paint(CompositorContext::ScopedFrame& frame) const;
void Paint(CompositorContext::ScopedFrame& frame,
bool ignore_raster_cache = false) const;

sk_sp<SkPicture> Flatten(const SkRect& bounds);

Expand Down
30 changes: 29 additions & 1 deletion flow/layers/opacity_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,42 @@ OpacityLayer::OpacityLayer() = default;

OpacityLayer::~OpacityLayer() = default;

void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
ContainerLayer::Preroll(context, matrix);
if (context->raster_cache && layers().size() == 1) {
std::shared_ptr<Layer> child = layers()[0];
SkMatrix ctm = matrix;
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
ctm = RasterCache::GetIntegralTransCTM(ctm);
#endif
context->raster_cache->Prepare(context, child, ctm);
}
}

void OpacityLayer::Paint(PaintContext& context) const {
TRACE_EVENT0("flutter", "OpacityLayer::Paint");
FML_DCHECK(needs_painting());

SkPaint paint;
paint.setAlpha(alpha_);

Layer::AutoSaveLayer save =
SkAutoCanvasRestore save(&context.canvas, true);

#ifndef SUPPORT_FRACTIONAL_TRANSLATION
context.canvas.setMatrix(
RasterCache::GetIntegralTransCTM(context.canvas.getTotalMatrix()));
#endif

if (layers().size() == 1 && context.raster_cache) {
const SkMatrix& ctm = context.canvas.getTotalMatrix();
RasterCacheResult child_cache = context.raster_cache->Get(layers()[0], ctm);
if (child_cache.is_valid()) {
child_cache.draw(context.canvas, &paint);
return;
}
}

Layer::AutoSaveLayer save_layer =
Layer::AutoSaveLayer::Create(context, paint_bounds(), &paint);
PaintChildren(context);
}
Expand Down
2 changes: 2 additions & 0 deletions flow/layers/opacity_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class OpacityLayer : public ContainerLayer {

void set_alpha(int alpha) { alpha_ = alpha; }

void Preroll(PrerollContext* context, const SkMatrix& matrix) override;

void Paint(PaintContext& context) const override;

// TODO(chinmaygarde): Once MZ-139 is addressed, introduce a new node in the
Expand Down
19 changes: 10 additions & 9 deletions flow/layers/picture_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@ void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
ctm = RasterCache::GetIntegralTransCTM(ctm);
#endif
raster_cache_result_ = cache->GetPrerolledImage(
context->gr_context, sk_picture, ctm, context->dst_color_space,
is_complex_, will_change_);
} else {
raster_cache_result_ = RasterCacheResult();
cache->Prepare(context->gr_context, sk_picture, ctm,
context->dst_color_space, is_complex_, will_change_);
}

SkRect bounds = sk_picture->cullRect().makeOffset(offset_.x(), offset_.y());
Expand All @@ -44,11 +41,15 @@ void PictureLayer::Paint(PaintContext& context) const {
RasterCache::GetIntegralTransCTM(context.canvas.getTotalMatrix()));
#endif

if (raster_cache_result_.is_valid()) {
raster_cache_result_.draw(context.canvas);
} else {
context.canvas.drawPicture(picture());
if (context.raster_cache) {
const SkMatrix& ctm = context.canvas.getTotalMatrix();
RasterCacheResult result = context.raster_cache->Get(*picture(), ctm);
if (result.is_valid()) {
result.draw(context.canvas);
return;
}
}
context.canvas.drawPicture(picture());
}

} // namespace flow
1 change: 0 additions & 1 deletion flow/layers/picture_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class PictureLayer : public Layer {
SkiaGPUObject<SkPicture> picture_;
bool is_complex_ = false;
bool will_change_ = false;
RasterCacheResult raster_cache_result_;

FML_DISALLOW_COPY_AND_ASSIGN(PictureLayer);
};
Expand Down
Loading

0 comments on commit 6447418

Please sign in to comment.