Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit df619c6

Browse files
authored
Lazily allocate RasterCacheItems only when caching is enabled (#45211)
Fixes flutter/flutter#133377 The default allocation of RasterCacheItems in the layer tree was showing up in profiles of apps running on Impeller which don't actually use the raster cache. In order to eliminate the overhead of those allocations, RasterCacheItems are now lazily allocated only when the layers encounter an actual raster_cache during the Preroll phase.
1 parent 20865fb commit df619c6

22 files changed

+567
-200
lines changed

flow/layers/cacheable_layer.cc

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,39 @@
66

77
namespace flutter {
88

9-
AutoCache::AutoCache(RasterCacheItem* raster_cache_item,
9+
AutoCache::AutoCache(CacheableLayer& cacheable_layer,
1010
PrerollContext* context,
11-
const SkMatrix& matrix)
12-
: raster_cache_item_(raster_cache_item),
13-
context_(context),
14-
matrix_(matrix) {
15-
if (IsCacheEnabled()) {
16-
raster_cache_item->PrerollSetup(context, matrix);
11+
bool caching_enabled) {
12+
if (context->raster_cache && caching_enabled) {
13+
raster_cache_item_ = cacheable_layer.realize_raster_cache_item();
14+
if (raster_cache_item_) {
15+
context_ = context;
16+
matrix_ = context->state_stack.transform_3x3();
17+
raster_cache_item_->PrerollSetup(context_, matrix_);
18+
}
19+
} else {
20+
cacheable_layer.disable_raster_cache_item();
1721
}
1822
}
1923

20-
bool AutoCache::IsCacheEnabled() {
21-
return raster_cache_item_ && context_ && context_->raster_cache;
22-
}
23-
2424
AutoCache::~AutoCache() {
25-
if (IsCacheEnabled()) {
25+
if (raster_cache_item_) {
2626
raster_cache_item_->PrerollFinalize(context_, matrix_);
2727
}
2828
}
2929

30-
CacheableContainerLayer::CacheableContainerLayer(int layer_cached_threshold,
31-
bool can_cache_children) {
32-
layer_raster_cache_item_ = LayerRasterCacheItem::Make(
33-
this, layer_cached_threshold, can_cache_children);
30+
RasterCacheItem* CacheableContainerLayer::realize_raster_cache_item() {
31+
if (!layer_raster_cache_item_) {
32+
layer_raster_cache_item_ = LayerRasterCacheItem::Make(
33+
this, layer_cache_threshold_, can_cache_children_);
34+
}
35+
return layer_raster_cache_item_.get();
36+
}
37+
38+
void CacheableContainerLayer::disable_raster_cache_item() {
39+
if (layer_raster_cache_item_) {
40+
layer_raster_cache_item_->reset_cache_state();
41+
}
3442
}
3543

3644
} // namespace flutter

flow/layers/cacheable_layer.h

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,62 @@
99

1010
#include "flutter/flow/layers/container_layer.h"
1111
#include "flutter/flow/layers/layer_raster_cache_item.h"
12+
#include "flutter/flow/raster_cache_util.h"
1213

1314
namespace flutter {
1415

16+
class CacheableLayer {
17+
protected:
18+
virtual RasterCacheItem* realize_raster_cache_item() = 0;
19+
virtual void disable_raster_cache_item() = 0;
20+
21+
friend class AutoCache;
22+
};
23+
1524
class AutoCache {
1625
public:
17-
AutoCache(RasterCacheItem* raster_cache_item,
26+
AutoCache(CacheableLayer& item_provider,
1827
PrerollContext* context,
19-
const SkMatrix& matrix);
28+
bool caching_enabled = true);
2029

2130
void ShouldNotBeCached() { raster_cache_item_ = nullptr; }
2231

2332
~AutoCache();
2433

2534
private:
26-
inline bool IsCacheEnabled();
2735
RasterCacheItem* raster_cache_item_ = nullptr;
2836
PrerollContext* context_ = nullptr;
29-
const SkMatrix matrix_;
37+
SkMatrix matrix_;
38+
39+
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(AutoCache);
3040
};
3141

32-
class CacheableContainerLayer : public ContainerLayer {
42+
class CacheableContainerLayer : public ContainerLayer, public CacheableLayer {
3343
public:
3444
explicit CacheableContainerLayer(
3545
int layer_cached_threshold =
3646
RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer,
37-
bool can_cache_children = false);
47+
bool can_cache_children = false)
48+
: layer_cache_threshold_(layer_cached_threshold),
49+
can_cache_children_(can_cache_children) {}
3850

3951
const LayerRasterCacheItem* raster_cache_item() const {
4052
return layer_raster_cache_item_.get();
4153
}
4254

55+
void MarkCanCacheChildren(bool can_cache_children) {
56+
if (layer_raster_cache_item_) {
57+
layer_raster_cache_item_->MarkCanCacheChildren(can_cache_children);
58+
}
59+
}
60+
4361
protected:
62+
RasterCacheItem* realize_raster_cache_item() override;
63+
virtual void disable_raster_cache_item() override;
4464
std::unique_ptr<LayerRasterCacheItem> layer_raster_cache_item_;
65+
66+
int layer_cache_threshold_;
67+
bool can_cache_children_;
4568
};
4669

4770
} // namespace flutter

flow/layers/clip_path_layer_unittests.cc

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -519,31 +519,74 @@ TEST_F(ClipPathLayerTest, LayerCached) {
519519
use_mock_raster_cache();
520520
preroll_context()->state_stack.set_preroll_delegate(initial_transform);
521521

522-
const auto* clip_cache_item = layer->raster_cache_item();
523-
524522
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
523+
EXPECT_EQ(layer->raster_cache_item(), nullptr);
525524

526525
layer->Preroll(preroll_context());
526+
EXPECT_NE(layer->raster_cache_item(), nullptr);
527527
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
528528

529529
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
530-
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
530+
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
531+
RasterCacheItem::CacheState::kNone);
531532

532533
layer->Preroll(preroll_context());
533534
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
534535
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
535-
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
536+
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
537+
RasterCacheItem::CacheState::kNone);
536538

537539
layer->Preroll(preroll_context());
538540
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
539541
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1);
540-
EXPECT_EQ(clip_cache_item->cache_state(),
542+
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
541543
RasterCacheItem::CacheState::kCurrent);
542544
DlPaint paint;
543-
EXPECT_TRUE(raster_cache()->Draw(clip_cache_item->GetId().value(),
545+
EXPECT_TRUE(raster_cache()->Draw(layer->raster_cache_item()->GetId().value(),
544546
cache_canvas, &paint));
545547
}
546548

549+
TEST_F(ClipPathLayerTest, NullRasterCacheResetsRasterCacheItem) {
550+
auto path1 = SkPath().addRect({10, 10, 30, 30});
551+
auto mock1 = MockLayer::MakeOpacityCompatible(path1);
552+
auto layer_clip = SkPath()
553+
.addRect(SkRect::MakeLTRB(5, 5, 25, 25))
554+
.addOval(SkRect::MakeLTRB(20, 20, 40, 50));
555+
auto layer =
556+
std::make_shared<ClipPathLayer>(layer_clip, Clip::antiAliasWithSaveLayer);
557+
layer->Add(mock1);
558+
559+
ASSERT_EQ(layer->raster_cache_item(), nullptr);
560+
561+
layer->Preroll(preroll_context());
562+
ASSERT_EQ(layer->raster_cache_item(), nullptr);
563+
564+
use_mock_raster_cache();
565+
566+
int limit = RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer;
567+
for (int i = 1; i < limit; i++) {
568+
layer->Preroll(preroll_context());
569+
ASSERT_NE(layer->raster_cache_item(), nullptr);
570+
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
571+
RasterCacheItem::kNone);
572+
ASSERT_FALSE(
573+
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));
574+
}
575+
576+
layer->Preroll(preroll_context());
577+
ASSERT_NE(layer->raster_cache_item(), nullptr);
578+
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
579+
RasterCacheItem::kCurrent);
580+
ASSERT_TRUE(
581+
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));
582+
583+
use_null_raster_cache();
584+
585+
layer->Preroll(preroll_context());
586+
ASSERT_NE(layer->raster_cache_item(), nullptr);
587+
ASSERT_EQ(layer->raster_cache_item()->cache_state(), RasterCacheItem::kNone);
588+
}
589+
547590
TEST_F(ClipPathLayerTest, EmptyClipDoesNotCullPlatformView) {
548591
const SkPoint view_offset = SkPoint::Make(0.0f, 0.0f);
549592
const SkSize view_size = SkSize::Make(8.0f, 8.0f);

flow/layers/clip_rect_layer_unittests.cc

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -499,30 +499,71 @@ TEST_F(ClipRectLayerTest, LayerCached) {
499499

500500
use_mock_raster_cache();
501501
preroll_context()->state_stack.set_preroll_delegate(initial_transform);
502-
503-
const auto* clip_cache_item = layer->raster_cache_item();
502+
EXPECT_EQ(layer->raster_cache_item(), nullptr);
504503

505504
layer->Preroll(preroll_context());
505+
EXPECT_NE(layer->raster_cache_item(), nullptr);
506506
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
507507

508508
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
509-
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
509+
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
510+
RasterCacheItem::CacheState::kNone);
510511

511512
layer->Preroll(preroll_context());
512513
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
513514
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
514-
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
515+
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
516+
RasterCacheItem::CacheState::kNone);
515517

516518
layer->Preroll(preroll_context());
517519
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
518520
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1);
519-
EXPECT_EQ(clip_cache_item->cache_state(),
521+
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
520522
RasterCacheItem::CacheState::kCurrent);
521523
DlPaint paint;
522-
EXPECT_TRUE(raster_cache()->Draw(clip_cache_item->GetId().value(),
524+
EXPECT_TRUE(raster_cache()->Draw(layer->raster_cache_item()->GetId().value(),
523525
cache_canvas, &paint));
524526
}
525527

528+
TEST_F(ClipRectLayerTest, NullRasterCacheResetsRasterCacheItem) {
529+
auto path1 = SkPath().addRect({10, 10, 30, 30});
530+
auto mock1 = MockLayer::MakeOpacityCompatible(path1);
531+
SkRect clip_rect = SkRect::MakeWH(500, 500);
532+
auto layer =
533+
std::make_shared<ClipRectLayer>(clip_rect, Clip::antiAliasWithSaveLayer);
534+
layer->Add(mock1);
535+
536+
ASSERT_EQ(layer->raster_cache_item(), nullptr);
537+
538+
layer->Preroll(preroll_context());
539+
ASSERT_EQ(layer->raster_cache_item(), nullptr);
540+
541+
use_mock_raster_cache();
542+
543+
int limit = RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer;
544+
for (int i = 1; i < limit; i++) {
545+
layer->Preroll(preroll_context());
546+
ASSERT_NE(layer->raster_cache_item(), nullptr);
547+
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
548+
RasterCacheItem::kNone);
549+
ASSERT_FALSE(
550+
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));
551+
}
552+
553+
layer->Preroll(preroll_context());
554+
ASSERT_NE(layer->raster_cache_item(), nullptr);
555+
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
556+
RasterCacheItem::kCurrent);
557+
ASSERT_TRUE(
558+
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));
559+
560+
use_null_raster_cache();
561+
562+
layer->Preroll(preroll_context());
563+
ASSERT_NE(layer->raster_cache_item(), nullptr);
564+
ASSERT_EQ(layer->raster_cache_item()->cache_state(), RasterCacheItem::kNone);
565+
}
566+
526567
TEST_F(ClipRectLayerTest, EmptyClipDoesNotCullPlatformView) {
527568
const SkPoint view_offset = SkPoint::Make(0.0f, 0.0f);
528569
const SkSize view_size = SkSize::Make(8.0f, 8.0f);

flow/layers/clip_rrect_layer_unittests.cc

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -512,29 +512,72 @@ TEST_F(ClipRRectLayerTest, LayerCached) {
512512

513513
use_mock_raster_cache();
514514
preroll_context()->state_stack.set_preroll_delegate(initial_transform);
515-
516-
const auto* clip_cache_item = layer->raster_cache_item();
515+
EXPECT_EQ(layer->raster_cache_item(), nullptr);
517516

518517
layer->Preroll(preroll_context());
518+
EXPECT_NE(layer->raster_cache_item(), nullptr);
519519
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
520520

521521
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
522-
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
522+
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
523+
RasterCacheItem::CacheState::kNone);
523524

524525
layer->Preroll(preroll_context());
525526
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
526527
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
527-
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
528+
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
529+
RasterCacheItem::CacheState::kNone);
528530

529531
layer->Preroll(preroll_context());
530532
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
531533
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1);
532-
EXPECT_EQ(clip_cache_item->cache_state(),
534+
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
533535
RasterCacheItem::CacheState::kCurrent);
534-
EXPECT_TRUE(raster_cache()->Draw(clip_cache_item->GetId().value(),
536+
EXPECT_TRUE(raster_cache()->Draw(layer->raster_cache_item()->GetId().value(),
535537
cache_canvas, &paint));
536538
}
537539

540+
TEST_F(ClipRRectLayerTest, NullRasterCacheResetsRasterCacheItem) {
541+
auto path1 = SkPath().addRect({10, 10, 30, 30});
542+
DlPaint paint = DlPaint();
543+
auto mock1 = MockLayer::MakeOpacityCompatible(path1);
544+
SkRect clip_rect = SkRect::MakeWH(500, 500);
545+
SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 20, 20);
546+
auto layer = std::make_shared<ClipRRectLayer>(clip_rrect,
547+
Clip::antiAliasWithSaveLayer);
548+
layer->Add(mock1);
549+
550+
ASSERT_EQ(layer->raster_cache_item(), nullptr);
551+
552+
layer->Preroll(preroll_context());
553+
ASSERT_EQ(layer->raster_cache_item(), nullptr);
554+
555+
use_mock_raster_cache();
556+
557+
int limit = RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer;
558+
for (int i = 1; i < limit; i++) {
559+
layer->Preroll(preroll_context());
560+
ASSERT_NE(layer->raster_cache_item(), nullptr);
561+
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
562+
RasterCacheItem::kNone);
563+
ASSERT_FALSE(
564+
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));
565+
}
566+
567+
layer->Preroll(preroll_context());
568+
ASSERT_NE(layer->raster_cache_item(), nullptr);
569+
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
570+
RasterCacheItem::kCurrent);
571+
ASSERT_TRUE(
572+
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));
573+
574+
use_null_raster_cache();
575+
576+
layer->Preroll(preroll_context());
577+
ASSERT_NE(layer->raster_cache_item(), nullptr);
578+
ASSERT_EQ(layer->raster_cache_item()->cache_state(), RasterCacheItem::kNone);
579+
}
580+
538581
TEST_F(ClipRRectLayerTest, NoSaveLayerShouldNotCache) {
539582
auto path1 = SkPath().addRect({10, 10, 30, 30});
540583

@@ -551,24 +594,23 @@ TEST_F(ClipRRectLayerTest, NoSaveLayerShouldNotCache) {
551594

552595
use_mock_raster_cache();
553596
preroll_context()->state_stack.set_preroll_delegate(initial_transform);
554-
555-
const auto* clip_cache_item = layer->raster_cache_item();
597+
EXPECT_EQ(layer->raster_cache_item(), nullptr);
556598

557599
layer->Preroll(preroll_context());
558600
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
559601

560602
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
561-
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
603+
EXPECT_EQ(layer->raster_cache_item(), nullptr);
562604

563605
layer->Preroll(preroll_context());
564606
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
565607
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
566-
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
608+
EXPECT_EQ(layer->raster_cache_item(), nullptr);
567609

568610
layer->Preroll(preroll_context());
569611
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
570612
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
571-
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
613+
EXPECT_EQ(layer->raster_cache_item(), nullptr);
572614
}
573615

574616
TEST_F(ClipRRectLayerTest, EmptyClipDoesNotCullPlatformView) {

0 commit comments

Comments
 (0)