Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try to fix the RasterCache benchmark gone down problems #34455

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 35 additions & 21 deletions flow/layers/display_list_raster_cache_item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "flutter/flow/raster_cache_key.h"
#include "flutter/flow/raster_cache_util.h"
#include "flutter/flow/skia_gpu_object.h"
#include "flutter/fml/logging.h"

namespace flutter {

Expand Down Expand Up @@ -52,7 +53,7 @@ DisplayListRasterCacheItem::DisplayListRasterCacheItem(
bool will_change)
: RasterCacheItem(RasterCacheKeyID(display_list->unique_id(),
RasterCacheKeyType::kDisplayList),
CacheState::kCurrent),
CacheState::kNone),
display_list_(display_list),
offset_(offset),
is_complex_(is_complex),
Expand All @@ -70,6 +71,9 @@ std::unique_ptr<DisplayListRasterCacheItem> DisplayListRasterCacheItem::Make(
void DisplayListRasterCacheItem::PrerollSetup(PrerollContext* context,
const SkMatrix& matrix) {
cache_state_ = CacheState::kNone;
if (!context->raster_cache->GenerateNewCacheInThisFrame()) {
return;
}
DisplayListComplexityCalculator* complexity_calculator =
context->gr_context ? DisplayListComplexityCalculator::GetForBackend(
context->gr_context->backend())
Expand All @@ -81,18 +85,15 @@ void DisplayListRasterCacheItem::PrerollSetup(PrerollContext* context,
return;
}

matrix_ = matrix;
transformation_matrix_ = matrix;
transformation_matrix_.preTranslate(offset_.x(), offset_.y());

if (!transformation_matrix_.invert(nullptr)) {
// The matrix was singular. No point in going further.
return;
}

if (context->raster_cached_entries && context->raster_cache) {
context->raster_cached_entries->push_back(this);
cache_state_ = CacheState::kCurrent;
}
cache_state_ = CacheState::kCurrent;
return;
}

Expand All @@ -108,17 +109,34 @@ void DisplayListRasterCacheItem::PrerollFinalize(PrerollContext* context,
// if the rect is intersect we will get the entry access_count to confirm if
// it great than the threshold. Otherwise we only increase the entry
// access_count.
cache_state_ = CacheState::kNone;
if (context->cull_rect.intersect(bounds)) {
if (raster_cache->MarkSeen(key_id_, transformation_matrix_) <
// Thought MarkDisplayListSeen we only get the access cout or create entry.
// Don't increase the access_count or use_this_frame = true.
if (raster_cache->MarkDisplayListSeen(key_id_, transformation_matrix_) <
raster_cache->access_threshold()) {
cache_state_ = CacheState::kNone;
return;
}
// We need to make sure that we create a maximum of three images per frame.
// This display_list can be cached and current entry doesn't create image,
// so we should increate the cache count.
if (!raster_cache->HasCached(key_id_, transformation_matrix_)) {
context->raster_cache->IncreaseDisplayListCacheCount();
cache_state_ = CacheState::kCurrent;
} else {
// Current DL has generator a image and in here it may be used in this
// frame, so we need to touch it.
raster_cache->Touch(key_id_, matrix);
}
context->subtree_can_inherit_opacity = true;
cache_state_ = CacheState::kCurrent;
} else {
// if the bounds with the cull rect is not intersect, we only touch the
// cache entry. And should not cache the display list
raster_cache->Touch(key_id_, matrix);
return;
}
// If the display_list can be cached we will add it to cache_entries.
context->raster_cached_entries->push_back(this);
return;
}

Expand All @@ -133,13 +151,8 @@ bool DisplayListRasterCacheItem::Draw(const PaintContext& context,
if (!context.raster_cache || !canvas) {
return false;
}
if (cache_state_ == CacheState::kCurrent) {
return context.raster_cache->Draw(key_id_, *canvas, paint);
}
// This display_list doesn't cache itself, this only increase the entry
// access_count;
context.raster_cache->Touch(key_id_, canvas->getTotalMatrix());
return false;

return context.raster_cache->Draw(key_id_, *canvas, paint);
}

static const auto* flow_type = "RasterCacheFlow::DisplayList";
Expand All @@ -153,11 +166,12 @@ bool DisplayListRasterCacheItem::TryToPrepareRasterCache(
// display_list or picture_list to calculate the memory they used, we
// shouldn't cache the current node if the memory is more significant than the
// limit.
if (cache_state_ == kNone || !context.raster_cache || parent_cached ||
!context.raster_cache->GenerateNewCacheInThisFrame()) {
if (cache_state_ == CacheState::kNone || !context.raster_cache ||
parent_cached) {
return false;
}
SkRect bounds = display_list_->bounds().makeOffset(offset_.x(), offset_.y());

SkRect bounds = display_list_->bounds();
RasterCache::Context r_context = {
// clang-format off
.gr_context = context.gr_context,
Expand All @@ -169,9 +183,9 @@ bool DisplayListRasterCacheItem::TryToPrepareRasterCache(
// clang-format on
};
return context.raster_cache->UpdateCacheEntry(
GetId().value(), r_context,
[display_list = display_list_](SkCanvas* canvas) {
key_id_, r_context, [display_list = display_list_](SkCanvas* canvas) {
display_list->RenderTo(canvas);
return true;
});
}
} // namespace flutter
2 changes: 1 addition & 1 deletion flow/layers/display_list_raster_cache_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class DisplayListRasterCacheItem : public RasterCacheItem {
const SkPaint* paint) const override;

bool TryToPrepareRasterCache(const PaintContext& context,
bool parent_cached = false) const override;
bool parent_cached) const override;

void ModifyMatrix(SkPoint offset) const {
matrix_ = matrix_.preTranslate(offset.x(), offset.y());
Expand Down
58 changes: 31 additions & 27 deletions flow/layers/layer_raster_cache_item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,11 @@ void LayerRasterCacheItem::PrerollFinalize(PrerollContext* context,
if (!context->raster_cache || !context->raster_cached_entries) {
return;
}
// We've marked the cache entry that we would like to cache so it stays
// alive, but if the following conditions apply then we need to set our
// state back to kDoNotCache so that we don't populate the entry later.
if (context->has_platform_view || context->has_texture_layer ||
!SkRect::Intersects(context->cull_rect, layer_->paint_bounds())) {
return;
}
child_items_ = context->raster_cached_entries->size() - child_items_;
// Determine cache current layer or cache children.
if (num_cache_attempts_ >= layer_cached_threshold_) {
// the layer can be cached
cache_state_ = CacheState::kCurrent;
context->raster_cache->MarkSeen(key_id_, matrix_);
} else {
num_cache_attempts_++;
// access current layer
Expand All @@ -67,9 +60,25 @@ void LayerRasterCacheItem::PrerollFinalize(PrerollContext* context,
RasterCacheKeyType::kLayerChildren);
}
cache_state_ = CacheState::kChildren;
context->raster_cache->MarkSeen(layer_children_id_.value(), matrix_);
}
}
// We've marked the cache entry that we would like to cache so it stays
// alive, but if the following conditions apply then we need to set our
// state back to kDoNotCache so that we don't populate the entry later.
if (context->has_platform_view || context->has_texture_layer ||
!SkRect::Intersects(context->cull_rect, layer_->paint_bounds())) {
if (cache_state_ != CacheState::kNone) {
// Only touch the entry, do not to cache the layer or children.
context->raster_cache->Touch(GetId().value(), matrix_);
cache_state_ = CacheState::kNone;
}
return;
}
// The layer can be cache, so we should create a entry.
if (cache_state_ != CacheState::kNone) {
// Create Cache entry
context->raster_cache->MarkSeen(GetId().value(), matrix_);
}
}

std::optional<RasterCacheKeyID> LayerRasterCacheItem::GetId() const {
Expand Down Expand Up @@ -111,19 +120,20 @@ bool Rasterize(RasterCacheItem::CacheState cache_state,
.leaf_nodes_canvas = canvas,
.gr_context = paint_context.gr_context,
.dst_color_space = paint_context.dst_color_space,
.view_embedder = paint_context.view_embedder,
.view_embedder = nullptr,
.raster_time = paint_context.raster_time,
.ui_time = paint_context.ui_time,
.texture_registry = paint_context.texture_registry,
.raster_cache = paint_context.raster_cache,
.raster_cache = layer->subtree_has_platform_view() ? nullptr: paint_context.raster_cache,
.checkerboard_offscreen_layers = paint_context.checkerboard_offscreen_layers,
.frame_device_pixel_ratio = paint_context.frame_device_pixel_ratio,
// clang-format on
};

switch (cache_state) {
case RasterCacheItem::CacheState::kCurrent:
FML_DCHECK(layer->needs_painting(context));
if (!layer->needs_painting(context)) {
return false;
}
layer->Paint(context);
break;
case RasterCacheItem::CacheState::kChildren:
Expand All @@ -140,7 +150,11 @@ static const auto* flow_type = "RasterCacheFlow::Layer";

bool LayerRasterCacheItem::TryToPrepareRasterCache(const PaintContext& context,
bool parent_cached) const {
if (!context.raster_cache || parent_cached) {
if (!context.raster_cache) {
return false;
}
if (parent_cached) {
context.raster_cache->Touch(GetId().value(), matrix_);
return false;
}
if (cache_state_ != kNone) {
Expand All @@ -159,7 +173,7 @@ bool LayerRasterCacheItem::TryToPrepareRasterCache(const PaintContext& context,
GetId().value(), r_context,
[ctx = context, cache_state = cache_state_,
layer = layer_](SkCanvas* canvas) {
Rasterize(cache_state, layer, ctx, canvas);
return Rasterize(cache_state, layer, ctx, canvas);
});
}
}
Expand All @@ -174,20 +188,10 @@ bool LayerRasterCacheItem::Draw(const PaintContext& context,
bool LayerRasterCacheItem::Draw(const PaintContext& context,
SkCanvas* canvas,
const SkPaint* paint) const {
if (!context.raster_cache || !canvas) {
if (!context.raster_cache || !canvas || cache_state_ == CacheState::kNone) {
return false;
}
switch (cache_state_) {
case RasterCacheItem::kNone:
return false;
case RasterCacheItem::kCurrent: {
return context.raster_cache->Draw(key_id_, *canvas, paint);
}
case RasterCacheItem::kChildren: {
return context.raster_cache->Draw(layer_children_id_.value(), *canvas,
paint);
}
}
return context.raster_cache->Draw(GetId().value(), *canvas, paint);
}

} // namespace flutter
2 changes: 1 addition & 1 deletion flow/layers/layer_raster_cache_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class LayerRasterCacheItem : public RasterCacheItem {
const SkPaint* paint) const override;

bool TryToPrepareRasterCache(const PaintContext& context,
bool parent_cached = false) const override;
bool parent_cached) const override;

void MarkCacheChildren() { can_cache_children_ = true; }

Expand Down
5 changes: 3 additions & 2 deletions flow/layers/opacity_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
SkMatrix child_matrix = matrix;
child_matrix.preTranslate(offset_.fX, offset_.fY);

AutoCache auto_cache =
AutoCache(layer_raster_cache_item_.get(), context, child_matrix);

// Similar to what's done in TransformLayer::Preroll, we have to apply the
// reverse transformation to the cull rect to properly cull child layers.
context->cull_rect = context->cull_rect.makeOffset(-offset_.fX, -offset_.fY);
Expand All @@ -46,8 +49,6 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
SkMatrix::Translate(offset_.fX, offset_.fY));
context->mutators_stack.PushOpacity(alpha_);

AutoCache auto_cache =
AutoCache(layer_raster_cache_item_.get(), context, matrix);
Layer::AutoPrerollSaveLayerState save =
Layer::AutoPrerollSaveLayerState::Create(context);

Expand Down
40 changes: 24 additions & 16 deletions flow/raster_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "flutter/flow/layers/container_layer.h"
#include "flutter/flow/layers/layer.h"
#include "flutter/flow/paint_utils.h"
#include "flutter/flow/raster_cache_key.h"
#include "flutter/flow/raster_cache_util.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
Expand Down Expand Up @@ -51,7 +52,7 @@ RasterCache::RasterCache(size_t access_threshold,
/// @note Procedure doesn't copy all closures.
std::unique_ptr<RasterCacheResult> RasterCache::Rasterize(
const RasterCache::Context& context,
const std::function<void(SkCanvas*)>& draw_function) {
const std::function<bool(SkCanvas*)>& draw_function) {
TRACE_EVENT0("flutter", "RasterCachePopulate");

SkRect dest_rect =
Expand All @@ -76,7 +77,10 @@ std::unique_ptr<RasterCacheResult> RasterCache::Rasterize(
canvas->clear(SK_ColorTRANSPARENT);
canvas->translate(-dest_rect.left(), -dest_rect.top());
canvas->concat(context.matrix);
draw_function(canvas);

if (!draw_function(canvas)) {
return nullptr;
}

if (context.checkerboard) {
DrawCheckerboard(canvas, context.logical_rect);
Expand All @@ -89,23 +93,12 @@ std::unique_ptr<RasterCacheResult> RasterCache::Rasterize(
bool RasterCache::UpdateCacheEntry(
const RasterCacheKeyID& id,
const Context& raster_cache_context,
const std::function<void(SkCanvas*)>& render_function) const {
const std::function<bool(SkCanvas*)>& render_function) const {
RasterCacheKey key = RasterCacheKey(id, raster_cache_context.matrix);
Entry& entry = cache_[key];
entry.used_this_frame = true;
if (!entry.image) {
entry.image = Rasterize(raster_cache_context, render_function);
if (entry.image != nullptr) {
switch (id.type()) {
case RasterCacheKeyType::kDisplayList: {
display_list_cached_this_frame_++;
break;
}
default:
break;
}
return true;
}
}
return entry.image != nullptr;
}
Expand All @@ -115,7 +108,6 @@ bool RasterCache::Touch(const RasterCacheKeyID& id,
RasterCacheKey cache_key = RasterCacheKey(id, matrix);
auto it = cache_.find(cache_key);
if (it != cache_.end()) {
it->second.access_count++;
it->second.used_this_frame = true;
return true;
}
Expand All @@ -126,7 +118,13 @@ int RasterCache::MarkSeen(const RasterCacheKeyID& id,
const SkMatrix& matrix) const {
RasterCacheKey key = RasterCacheKey(id, matrix);
Entry& entry = cache_[key];
entry.used_this_frame = true;
return entry.access_count;
}

int RasterCache::MarkDisplayListSeen(const RasterCacheKeyID& id,
const SkMatrix& matrix) const {
RasterCacheKey key = RasterCacheKey(id, matrix);
Entry& entry = cache_[key];
return entry.access_count;
}

Expand All @@ -139,6 +137,16 @@ bool RasterCache::HasEntry(const RasterCacheKeyID& id,
return false;
}

bool RasterCache::HasCached(const RasterCacheKeyID& id,
const SkMatrix& matrix) const {
RasterCacheKey key = RasterCacheKey(id, matrix);
auto it = cache_.find(key);
if (it != cache_.end()) {
return it->second.image != nullptr;
}
return false;
}

bool RasterCache::Draw(const RasterCacheKeyID& id,
SkCanvas& canvas,
const SkPaint* paint) const {
Expand Down
Loading