diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index 3471f9ff80dac..f268b1275df7a 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -178,8 +178,8 @@ std::unique_ptr RasterCache::RasterizeDisplayList( void RasterCache::Prepare(PrerollContext* context, Layer* layer, const SkMatrix& ctm) { - LayerRasterCacheKey cache_key(layer->unique_id(), ctm); - Entry& entry = layer_cache_[cache_key]; + RasterCacheKey cache_key(layer->unique_id(), RasterCacheKeyType::kLayer, ctm); + Entry& entry = cache_[cache_key]; entry.access_count++; entry.used_this_frame = true; if (!entry.image) { @@ -242,10 +242,11 @@ bool RasterCache::Prepare(PrerollContext* context, return false; } - PictureRasterCacheKey cache_key(picture->uniqueID(), transformation_matrix); + RasterCacheKey cache_key(picture->uniqueID(), RasterCacheKeyType::kPicture, + transformation_matrix); // Creates an entry, if not present prior. - Entry& entry = picture_cache_[cache_key]; + Entry& entry = cache_[cache_key]; if (entry.access_count < access_threshold_) { // Frame threshold has not yet been reached. return false; @@ -295,11 +296,12 @@ bool RasterCache::Prepare(PrerollContext* context, return false; } - DisplayListRasterCacheKey cache_key(display_list->unique_id(), - transformation_matrix); + RasterCacheKey cache_key(display_list->unique_id(), + RasterCacheKeyType::kDisplayList, + transformation_matrix); // Creates an entry, if not present prior. - Entry& entry = display_list_cache_[cache_key]; + Entry& entry = cache_[cache_key]; if (entry.access_count < access_threshold_) { // Frame threshold has not yet been reached. return false; @@ -321,30 +323,28 @@ bool RasterCache::Prepare(PrerollContext* context, } void RasterCache::Touch(Layer* layer, const SkMatrix& ctm) { - LayerRasterCacheKey cache_key(layer->unique_id(), ctm); - auto it = layer_cache_.find(cache_key); - if (it != layer_cache_.end()) { - it->second.used_this_frame = true; - it->second.access_count++; - } + RasterCacheKey cache_key(layer->unique_id(), RasterCacheKeyType::kLayer, ctm); + Touch(cache_key); } void RasterCache::Touch(SkPicture* picture, const SkMatrix& transformation_matrix) { - PictureRasterCacheKey cache_key(picture->uniqueID(), transformation_matrix); - auto it = picture_cache_.find(cache_key); - if (it != picture_cache_.end()) { - it->second.used_this_frame = true; - it->second.access_count++; - } + RasterCacheKey cache_key(picture->uniqueID(), RasterCacheKeyType::kPicture, + transformation_matrix); + Touch(cache_key); } void RasterCache::Touch(DisplayList* display_list, const SkMatrix& transformation_matrix) { - DisplayListRasterCacheKey cache_key(display_list->unique_id(), - transformation_matrix); - auto it = display_list_cache_.find(cache_key); - if (it != display_list_cache_.end()) { + RasterCacheKey cache_key(display_list->unique_id(), + RasterCacheKeyType::kDisplayList, + transformation_matrix); + Touch(cache_key); +} + +void RasterCache::Touch(const RasterCacheKey& cache_key) { + auto it = cache_.find(cache_key); + if (it != cache_.end()) { it->second.used_this_frame = true; it->second.access_count++; } @@ -353,52 +353,33 @@ void RasterCache::Touch(DisplayList* display_list, bool RasterCache::Draw(const SkPicture& picture, SkCanvas& canvas, const SkPaint* paint) const { - PictureRasterCacheKey cache_key(picture.uniqueID(), canvas.getTotalMatrix()); - auto it = picture_cache_.find(cache_key); - if (it == picture_cache_.end()) { - return false; - } - - Entry& entry = it->second; - entry.access_count++; - entry.used_this_frame = true; - - if (entry.image) { - entry.image->draw(canvas, paint); - return true; - } - - return false; + RasterCacheKey cache_key(picture.uniqueID(), RasterCacheKeyType::kPicture, + canvas.getTotalMatrix()); + return Draw(cache_key, canvas, paint); } bool RasterCache::Draw(const DisplayList& display_list, SkCanvas& canvas, const SkPaint* paint) const { - DisplayListRasterCacheKey cache_key(display_list.unique_id(), - canvas.getTotalMatrix()); - auto it = display_list_cache_.find(cache_key); - if (it == display_list_cache_.end()) { - return false; - } - - Entry& entry = it->second; - entry.access_count++; - entry.used_this_frame = true; - - if (entry.image) { - entry.image->draw(canvas, paint); - return true; - } - - return false; + RasterCacheKey cache_key(display_list.unique_id(), + RasterCacheKeyType::kDisplayList, + canvas.getTotalMatrix()); + return Draw(cache_key, canvas, paint); } bool RasterCache::Draw(const Layer* layer, SkCanvas& canvas, const SkPaint* paint) const { - LayerRasterCacheKey cache_key(layer->unique_id(), canvas.getTotalMatrix()); - auto it = layer_cache_.find(cache_key); - if (it == layer_cache_.end()) { + RasterCacheKey cache_key(layer->unique_id(), RasterCacheKeyType::kLayer, + canvas.getTotalMatrix()); + return Draw(cache_key, canvas, paint); +} + +bool RasterCache::Draw(const RasterCacheKey& cache_key, + SkCanvas& canvas, + const SkPaint* paint) const { + auto it = cache_.find(cache_key); + if (it == cache_.end()) { return false; } @@ -419,37 +400,88 @@ void RasterCache::PrepareNewFrame() { display_list_cached_this_frame_ = 0; } +void RasterCache::SweepOneCacheAfterFrame(RasterCacheKey::Map& cache, + RasterCacheMetrics& picture_metrics, + RasterCacheMetrics& layer_metrics) { + std::vector::iterator> dead; + + for (auto it = cache.begin(); it != cache.end(); ++it) { + Entry& entry = it->second; + + if (!entry.used_this_frame) { + dead.push_back(it); + } else if (entry.image) { + RasterCacheKeyKind kind = it->first.kind(); + switch (kind) { + case RasterCacheKeyKind::kPictureMetrics: + picture_metrics.in_use_count++; + picture_metrics.in_use_bytes += entry.image->image_bytes(); + break; + case RasterCacheKeyKind::kLayerMetrics: + layer_metrics.in_use_count++; + layer_metrics.in_use_bytes += entry.image->image_bytes(); + break; + } + } + entry.used_this_frame = false; + } + + for (auto it : dead) { + if (it->second.image) { + RasterCacheKeyKind kind = it->first.kind(); + switch (kind) { + case RasterCacheKeyKind::kPictureMetrics: + picture_metrics.eviction_count++; + picture_metrics.eviction_bytes += it->second.image->image_bytes(); + break; + case RasterCacheKeyKind::kLayerMetrics: + layer_metrics.eviction_count++; + layer_metrics.eviction_bytes += it->second.image->image_bytes(); + break; + } + } + cache.erase(it); + } +} + void RasterCache::CleanupAfterFrame() { picture_metrics_ = {}; layer_metrics_ = {}; { TRACE_EVENT0("flutter", "RasterCache::SweepCaches"); - SweepOneCacheAfterFrame(picture_cache_, picture_metrics_); - SweepOneCacheAfterFrame(display_list_cache_, picture_metrics_); - SweepOneCacheAfterFrame(layer_cache_, layer_metrics_); + SweepOneCacheAfterFrame(cache_, picture_metrics_, layer_metrics_); } TraceStatsToTimeline(); } void RasterCache::Clear() { - picture_cache_.clear(); - display_list_cache_.clear(); - layer_cache_.clear(); + cache_.clear(); picture_metrics_ = {}; layer_metrics_ = {}; } size_t RasterCache::GetCachedEntriesCount() const { - return layer_cache_.size() + picture_cache_.size() + - display_list_cache_.size(); + return cache_.size(); } size_t RasterCache::GetLayerCachedEntriesCount() const { - return layer_cache_.size(); + size_t layer_cached_entries_count = 0; + for (const auto& item : cache_) { + if (item.first.kind() == RasterCacheKeyKind::kLayerMetrics) { + layer_cached_entries_count++; + } + } + return layer_cached_entries_count; } size_t RasterCache::GetPictureCachedEntriesCount() const { - return picture_cache_.size() + display_list_cache_.size(); + size_t picture_cached_entries_count = 0; + for (const auto& item : cache_) { + if (item.first.kind() == RasterCacheKeyKind::kPictureMetrics) { + picture_cached_entries_count++; + } + } + return picture_cached_entries_count; } void RasterCache::SetCheckboardCacheImages(bool checkerboard) { @@ -479,8 +511,9 @@ void RasterCache::TraceStatsToTimeline() const { size_t RasterCache::EstimateLayerCacheByteSize() const { size_t layer_cache_bytes = 0; - for (const auto& item : layer_cache_) { - if (item.second.image) { + for (const auto& item : cache_) { + if (item.first.kind() == RasterCacheKeyKind::kLayerMetrics && + item.second.image) { layer_cache_bytes += item.second.image->image_bytes(); } } @@ -489,13 +522,9 @@ size_t RasterCache::EstimateLayerCacheByteSize() const { size_t RasterCache::EstimatePictureCacheByteSize() const { size_t picture_cache_bytes = 0; - for (const auto& item : picture_cache_) { - if (item.second.image) { - picture_cache_bytes += item.second.image->image_bytes(); - } - } - for (const auto& item : display_list_cache_) { - if (item.second.image) { + for (const auto& item : cache_) { + if (item.first.kind() == RasterCacheKeyKind::kPictureMetrics && + item.second.image) { picture_cache_bytes += item.second.image->image_bytes(); } } diff --git a/flow/raster_cache.h b/flow/raster_cache.h index 5edbec51a8332..bf5b39e92a751 100644 --- a/flow/raster_cache.h +++ b/flow/raster_cache.h @@ -43,6 +43,7 @@ class RasterCacheResult { fml::tracing::TraceFlow flow_; }; +class Layer; struct PrerollContext; struct RasterCacheMetrics { @@ -290,30 +291,15 @@ class RasterCache { std::unique_ptr image; }; - template - static void SweepOneCacheAfterFrame(Cache& cache, - RasterCacheMetrics& metrics) { - std::vector dead; - - for (auto it = cache.begin(); it != cache.end(); ++it) { - Entry& entry = it->second; - if (!entry.used_this_frame) { - dead.push_back(it); - } else if (entry.image) { - metrics.in_use_count++; - metrics.in_use_bytes += entry.image->image_bytes(); - } - entry.used_this_frame = false; - } + void Touch(const RasterCacheKey& cache_key); - for (auto it : dead) { - if (it->second.image) { - metrics.eviction_count++; - metrics.eviction_bytes += it->second.image->image_bytes(); - } - cache.erase(it); - } - } + bool Draw(const RasterCacheKey& cache_key, + SkCanvas& canvas, + const SkPaint* paint) const; + + void SweepOneCacheAfterFrame(RasterCacheKey::Map& cache, + RasterCacheMetrics& picture_metrics, + RasterCacheMetrics& layer_metrics); bool GenerateNewCacheInThisFrame() const { // Disabling caching when access_threshold is zero is historic behavior. @@ -328,9 +314,7 @@ class RasterCache { size_t display_list_cached_this_frame_ = 0; RasterCacheMetrics layer_metrics_; RasterCacheMetrics picture_metrics_; - mutable PictureRasterCacheKey::Map picture_cache_; - mutable DisplayListRasterCacheKey::Map display_list_cache_; - mutable LayerRasterCacheKey::Map layer_cache_; + mutable RasterCacheKey::Map cache_; bool checkerboard_images_; void TraceStatsToTimeline() const; diff --git a/flow/raster_cache_key.h b/flow/raster_cache_key.h index 2b71ca748545b..3c146221253c2 100644 --- a/flow/raster_cache_key.h +++ b/flow/raster_cache_key.h @@ -7,32 +7,49 @@ #include +#include "flutter/fml/hash_combine.h" #include "flutter/fml/logging.h" #include "third_party/skia/include/core/SkMatrix.h" namespace flutter { -template +enum class RasterCacheKeyType { kLayer, kPicture, kDisplayList }; + +enum class RasterCacheKeyKind { kLayerMetrics, kPictureMetrics }; + class RasterCacheKey { public: - RasterCacheKey(ID id, const SkMatrix& ctm) : id_(id), matrix_(ctm) { + RasterCacheKey(uint64_t id, RasterCacheKeyType type, const SkMatrix& ctm) + : id_(id), type_(type), matrix_(ctm) { matrix_[SkMatrix::kMTransX] = 0; matrix_[SkMatrix::kMTransY] = 0; } - ID id() const { return id_; } + uint64_t id() const { return id_; } + RasterCacheKeyType type() const { return type_; } const SkMatrix& matrix() const { return matrix_; } + RasterCacheKeyKind kind() const { + switch (type_) { + case RasterCacheKeyType::kPicture: + case RasterCacheKeyType::kDisplayList: + return RasterCacheKeyKind::kPictureMetrics; + case RasterCacheKeyType::kLayer: + return RasterCacheKeyKind::kLayerMetrics; + } + } + struct Hash { - uint32_t operator()(RasterCacheKey const& key) const { - return std::hash()(key.id_); + std::size_t operator()(RasterCacheKey const& key) const { + return fml::HashCombine(key.id_, key.type_); } }; struct Equal { constexpr bool operator()(const RasterCacheKey& lhs, const RasterCacheKey& rhs) const { - return lhs.id_ == rhs.id_ && lhs.matrix_ == rhs.matrix_; + return lhs.id_ == rhs.id_ && lhs.type_ == rhs.type_ && + lhs.matrix_ == rhs.matrix_; } }; @@ -40,7 +57,9 @@ class RasterCacheKey { using Map = std::unordered_map; private: - ID id_; + uint64_t id_; + + RasterCacheKeyType type_; // ctm where only fractional (0-1) translations are preserved: // matrix_ = ctm; @@ -49,17 +68,6 @@ class RasterCacheKey { SkMatrix matrix_; }; -// The ID is the uint32_t picture uniqueID -using PictureRasterCacheKey = RasterCacheKey; - -// The ID is the uint32_t DisplayList uniqueID -using DisplayListRasterCacheKey = RasterCacheKey; - -class Layer; - -// The ID is the uint64_t layer unique_id -using LayerRasterCacheKey = RasterCacheKey; - } // namespace flutter #endif // FLUTTER_FLOW_RASTER_CACHE_KEY_H_ diff --git a/flow/raster_cache_unittests.cc b/flow/raster_cache_unittests.cc index 8d99cb38d93c7..ed2be3feb4a8a 100644 --- a/flow/raster_cache_unittests.cc +++ b/flow/raster_cache_unittests.cc @@ -605,6 +605,81 @@ TEST(RasterCache, DisplayListWithSingularMatrixIsNotCached) { } } +TEST(RasterCache, RasterCacheKeyHashFunction) { + RasterCacheKey::Map map; + auto hash_function = map.hash_function(); + SkMatrix matrix = SkMatrix::I(); + uint64_t id = 5; + RasterCacheKey layer_key(id, RasterCacheKeyType::kLayer, matrix); + RasterCacheKey picture_key(id, RasterCacheKeyType::kPicture, matrix); + RasterCacheKey display_list_key(id, RasterCacheKeyType::kDisplayList, matrix); + + auto layer_hash_code = hash_function(layer_key); + ASSERT_EQ(layer_hash_code, fml::HashCombine(id, RasterCacheKeyType::kLayer)); + + auto picture_hash_code = hash_function(picture_key); + ASSERT_EQ(picture_hash_code, + fml::HashCombine(id, RasterCacheKeyType::kPicture)); + + auto display_list_hash_code = hash_function(display_list_key); + ASSERT_EQ(display_list_hash_code, + fml::HashCombine(id, RasterCacheKeyType::kDisplayList)); +} + +TEST(RasterCache, RasterCacheKeySameID) { + RasterCacheKey::Map map; + SkMatrix matrix = SkMatrix::I(); + uint64_t id = 5; + RasterCacheKey layer_key(id, RasterCacheKeyType::kLayer, matrix); + RasterCacheKey picture_key(id, RasterCacheKeyType::kPicture, matrix); + RasterCacheKey display_list_key(id, RasterCacheKeyType::kDisplayList, matrix); + map[layer_key] = 100; + map[picture_key] = 200; + map[display_list_key] = 300; + + ASSERT_EQ(map[layer_key], 100); + ASSERT_EQ(map[picture_key], 200); + ASSERT_EQ(map[display_list_key], 300); +} + +TEST(RasterCache, RasterCacheKeySameType) { + RasterCacheKey::Map map; + SkMatrix matrix = SkMatrix::I(); + + RasterCacheKeyType type = RasterCacheKeyType::kLayer; + RasterCacheKey layer_first_key(5, type, matrix); + RasterCacheKey layer_second_key(10, type, matrix); + RasterCacheKey layer_third_key(15, type, matrix); + map[layer_first_key] = 50; + map[layer_second_key] = 100; + map[layer_third_key] = 150; + ASSERT_EQ(map[layer_first_key], 50); + ASSERT_EQ(map[layer_second_key], 100); + ASSERT_EQ(map[layer_third_key], 150); + + type = RasterCacheKeyType::kPicture; + RasterCacheKey picture_first_key(20, type, matrix); + RasterCacheKey picture_second_key(25, type, matrix); + RasterCacheKey picture_third_key(30, type, matrix); + map[picture_first_key] = 200; + map[picture_second_key] = 250; + map[picture_third_key] = 300; + ASSERT_EQ(map[picture_first_key], 200); + ASSERT_EQ(map[picture_second_key], 250); + ASSERT_EQ(map[picture_third_key], 300); + + type = RasterCacheKeyType::kDisplayList; + RasterCacheKey display_list_first_key(35, type, matrix); + RasterCacheKey display_list_second_key(40, type, matrix); + RasterCacheKey display_list_third_key(45, type, matrix); + map[display_list_first_key] = 350; + map[display_list_second_key] = 400; + map[display_list_third_key] = 450; + ASSERT_EQ(map[display_list_first_key], 350); + ASSERT_EQ(map[display_list_second_key], 400); + ASSERT_EQ(map[display_list_third_key], 450); +} + } // namespace testing } // namespace flutter