Skip to content

Commit

Permalink
raster cache process analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
JsouLiang committed Jul 6, 2022
1 parent 5d1fddc commit 4157626
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 83 deletions.
55 changes: 33 additions & 22 deletions flow/layers/display_list_raster_cache_item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,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 +70,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 +84,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 +108,32 @@ 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;
}
context->subtree_can_inherit_opacity = true;
cache_state_ = CacheState::kCurrent;
} else {
raster_cache->Touch(key_id_, matrix);
// if the bounds with the cull rect is not intersect, we only touch the
// cache entry. And should not cache the display list
if (!raster_cache->HasCached(key_id_, transformation_matrix_)) {
raster_cache->Touch(key_id_, transformation_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 +148,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 +163,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 +180,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
37 changes: 23 additions & 14 deletions flow/raster_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,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 +76,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 +92,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 @@ -130,6 +122,13 @@ int RasterCache::MarkSeen(const RasterCacheKeyID& id,
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;
}

bool RasterCache::HasEntry(const RasterCacheKeyID& id,
const SkMatrix& matrix) const {
RasterCacheKey key = RasterCacheKey(id, matrix);
Expand All @@ -139,6 +138,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
10 changes: 8 additions & 2 deletions flow/raster_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class RasterCache {

static std::unique_ptr<RasterCacheResult> Rasterize(
const RasterCache::Context& context,
const std::function<void(SkCanvas*)>& draw_function);
const std::function<bool(SkCanvas*)>& draw_function);

explicit RasterCache(
size_t access_threshold = 3,
Expand All @@ -123,6 +123,8 @@ class RasterCache {
SkCanvas& canvas,
const SkPaint* paint) const;

void IncreaseDisplayListCacheCount() { display_list_cached_this_frame_++; }

bool Touch(const RasterCacheKeyID& id, const SkMatrix& matrix) const;

bool HasEntry(const RasterCacheKeyID& id, const SkMatrix&) const;
Expand Down Expand Up @@ -198,11 +200,15 @@ class RasterCache {
* a new entry that will be 1.
*/
int MarkSeen(const RasterCacheKeyID& id, const SkMatrix& matrix) const;
int MarkDisplayListSeen(const RasterCacheKeyID& id,
const SkMatrix& matrix) const;

bool HasCached(const RasterCacheKeyID& id, const SkMatrix& matrix) const;

bool 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;

private:
struct Entry {
Expand Down
2 changes: 1 addition & 1 deletion flow/raster_cache_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class RasterCacheItem {
virtual std::optional<RasterCacheKeyID> GetId() const { return key_id_; }

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

unsigned child_items() const { return child_items_; }

Expand Down
2 changes: 1 addition & 1 deletion flow/raster_cache_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class RasterCacheKeyID {
RasterCacheKeyID(uint16_t id, RasterCacheKeyType type)
: ids_({id}), type_(type) {}

RasterCacheKeyID(const std::vector<uint64_t> ids, RasterCacheKeyType type)
RasterCacheKeyID(const std::vector<uint64_t>& ids, RasterCacheKeyType type)
: ids_(ids), type_(type) {}

const std::vector<uint64_t>& ids() const { return ids_; }
Expand Down
1 change: 0 additions & 1 deletion flow/raster_cache_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ TEST(RasterCache, AccessThresholdOfZeroDisablesCachingForSkPicture) {
SkMatrix matrix = SkMatrix::I();

auto display_list = GetSampleDisplayList();
;

SkCanvas dummy_canvas;
SkPaint paint;
Expand Down
Loading

0 comments on commit 4157626

Please sign in to comment.