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

Defer decisions about RasterCache actions until after Preroll is complete #31892

Conversation

JsouLiang
Copy link
Contributor

@JsouLiang JsouLiang commented Mar 8, 2022

  1. I use the AutoGatherLayers (from knopp) to collection the Layer which need to RasterCache
  2. Add a level property which mean the layer level in the LayerTree, when we have collection the need RasterCache layer from preroll method and the we will Raster Cache Layer according the level that mean we will do Raster Cache layer from top to bottom .
  3. In the new RasterCache(PrerollContext*, matrix) method the layer not do raster cache if the ancestor layer has raster cache

TODO:

  • Layer is can do raster cache in current version
    • ImageFilterLayer
    • ColorFilterLayer
    • DisplayListLayer
    • OpacityLayer
    • SkPictureLayer
    • ShaderMaskLayer
  • check displayList layer and picture layer can do raster cache
    • RasterCacheableEntry need to differentiate: Layer, DisplayList, SkPicture
  • raster cache displayList layer and picture layer

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat (don't just cc him here, he won't see it! He's on Discord!).

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

flow/layers/layer_tree.cc Outdated Show resolved Hide resolved
Copy link
Contributor

@flar flar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I like about this mechanism is that it essentially breaks the caching out into a separate pass as per flutter/flutter#91923

I think the mechanism should be much simpler as explained in the review comments. Also, it would be nice to include picture and display caching in the list of cacheable items.

Finally, we could prune the dead cache entries (see the SweepOneCache method) before we add new ones in the caching pass. This would require the preroll items to "touch" or "mark" their existing cache items as having been seen so we don't de-cache anything used in the current frame. This advanced pruning could be a follow on PR, or it could be rolled into this mechanism.

flow/layers/container_layer.cc Outdated Show resolved Hide resolved
flow/layers/container_layer.cc Outdated Show resolved Hide resolved
flow/layers/layer_tree.cc Outdated Show resolved Hide resolved
@JsouLiang JsouLiang force-pushed the Collection-Need-RasterCache-Layer-In-Preroll branch from 36d70fd to 3ea7e25 Compare March 9, 2022 06:57
@JsouLiang
Copy link
Contributor Author

JsouLiang commented Mar 9, 2022

@flar hey bro, According your suggest I have change the RasterCache method. And also has some thing need to do, may be you can review the current logic to see if it is correct. Thanks
Current I only change the ImageFilterLayer::Preroll logic. If the ImageFilterLayer::Preroll logic is correct,I will modify other categories layers of the as well

@ColdPaleLight
Copy link
Member

ColdPaleLight commented Mar 9, 2022

@flar @JsouLiang
In general, caching entries from top to bottom according to the level of the layer is a generally correct algorithm, but I think there may be a bad case here. I filed a PR #31925 to try to resolve flutter/flutter#87827 and flutter/flutter#87826 . If these two issues are finally resolved, it means that for particularly complex pictures, they should be cached the first time they are used, and will continue to be kept for a few frames when they are unused. Then if there is such a particularly complex Layer in a descendant of OpaqueLayer or ImageFilterLayer, I guess we should cache this particularly complex Layer instead of OpaqueLayer or ImageFilterLayer.

@wangying3426
Copy link
Contributor

wangying3426 commented Mar 15, 2022

Fine...
It seems to be a right idea which like a "Mark-Cache" algorithm , then we can more flexibly to decide the layers which need to be cached from the perspective of global optimum at each frame.

flow/layers/layer.h Outdated Show resolved Hide resolved
flow/layers/layer.h Outdated Show resolved Hide resolved
flow/layers/layer.h Outdated Show resolved Hide resolved
flow/layers/display_list_layer.cc Outdated Show resolved Hide resolved
flow/layers/display_list_layer.cc Outdated Show resolved Hide resolved
flow/layers/display_list_layer.h Outdated Show resolved Hide resolved
flow/layers/image_filter_layer.cc Outdated Show resolved Hide resolved
flow/layers/image_filter_layer.cc Outdated Show resolved Hide resolved
flow/layers/image_filter_layer.cc Outdated Show resolved Hide resolved
flow/layers/layer_tree.cc Outdated Show resolved Hide resolved
@JsouLiang JsouLiang force-pushed the Collection-Need-RasterCache-Layer-In-Preroll branch 2 times, most recently from 1658c1a to 3d0731a Compare March 16, 2022 13:47
@JsouLiang JsouLiang force-pushed the Collection-Need-RasterCache-Layer-In-Preroll branch from 3d0731a to 9b054f5 Compare March 16, 2022 15:11
@JsouLiang JsouLiang force-pushed the Collection-Need-RasterCache-Layer-In-Preroll branch from 9b054f5 to 5b927b4 Compare March 17, 2022 04:26
flow/layers/image_filter_layer.cc Outdated Show resolved Hide resolved
flow/layers/image_filter_layer.cc Outdated Show resolved Hide resolved
flow/layers/cacheable_layer.h Outdated Show resolved Hide resolved
flow/layers/container_layer.cc Outdated Show resolved Hide resolved
flow/layers/layer.h Outdated Show resolved Hide resolved
flow/layers/layer.h Outdated Show resolved Hide resolved
SkRect cull_rect;
SkColorSpace* color_space;

bool surface_needs_readback;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally this value is only used during Preroll and will not be needed in the caching methods. You can delete this field and just provide a dummy value when creating the Context used when processing the caching queue.

flow/layers/layer_tree.cc Outdated Show resolved Hide resolved
flow/layers/layer_tree.cc Outdated Show resolved Hide resolved
flow/layers/display_list_layer.cc Outdated Show resolved Hide resolved
@chinmaygarde chinmaygarde added Work in progress (WIP) Not ready (yet) for review! and removed Work in progress (WIP) Not ready (yet) for review! labels Mar 24, 2022
@JsouLiang JsouLiang force-pushed the Collection-Need-RasterCache-Layer-In-Preroll branch from 5b927b4 to aefa7c6 Compare March 31, 2022 05:26
@flar flar changed the title [WIP] Collection Need RasterCache Layer in Preroll [WIP] Defer decisions about RasterCache actions until after Preroll is complete Mar 31, 2022
@JsouLiang JsouLiang force-pushed the Collection-Need-RasterCache-Layer-In-Preroll branch 2 times, most recently from 463110e to fe86bd1 Compare April 3, 2022 06:48
Copy link
Contributor

@flar flar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, I'm not entirely happy with the way the classes break down and inherit methods. I originally suggested creating a CacheableLayer type of class so that only the exact layers that want to perform caching would inherit from it and none of the methods to implement the caching mechanism would exist in Layer or ContainerLayer, but that doesn't seem to be the way that this is going. Every ContainerLayer implements CacheableLayer whether or not its sub class wants to consider caching, and only a portipon of them actually try to cache themselves or their children. If this subclass can't isolate the cacheable methods out of Layer and ContainerLayer, then let's just get rid of it.

Second, we are seeing an issue with the opacity inheritance flags. These were originally implemented as part of Preroll and the children would indicate their ability to inherit the opacity based on a few conditions:

  • They were planning to do their own saveLayer in the Paint method and so they could add the opacity as an attribute to the saveLayer "for free" to avoid OpacityLayer having to do its own saveLayer
  • They were planning to just drawImage an image to the screen so they could add the opacity to the SkPaint used in the call to drawImage. This applied mainly to TextureLayer and the Picture/DisplayListLayers in the case where they were being drawn from the cache.
  • Some layers could pass the opacity through to their child(ren) since their function involved no rendering at all (Transform/ClipLayers).
  • Finally some DisplayList objects could inherit the opacity even if they weren't cached.

Most of those cases can be statically determined during preroll except for one - whether or not a Picture or DisplayList is cached. We now don't really know that until after Preroll is done.

In most cases you set it after ShouldBeCached which is a far cry from when it actually should be set. ShouldBeCached simply says that the Picture or DisplayList is eligible based on a static assessment, but there is still a countdown before caching it. It used to be set only after the countdown of pre-cache draws was exceeded and then the picture/DL was cached. You are setting the flag way prematurely (3 entire frames prematurely).

Even if it "ShouldBeCached" and the countdown happens and this is the frame where it gets into the cache, it may not end up being cached because we only cache a maximum of N items per frame and this one may be beyond that limit, or we could simply fail to cache it because it exceeded the maximum allocation size for a texture - we won't know until the cache evaluation phase for much of that.

flow/raster_cacheable_entry.h Outdated Show resolved Hide resolved
flow/layers/container_layer.h Outdated Show resolved Hide resolved
flow/raster_cacheable_entry.cc Outdated Show resolved Hide resolved
flow/layers/display_list_layer.cc Outdated Show resolved Hide resolved
@JsouLiang JsouLiang force-pushed the Collection-Need-RasterCache-Layer-In-Preroll branch from fe86bd1 to d728981 Compare April 8, 2022 02:52
@JsouLiang
Copy link
Contributor Author

@flar Hi bro, according to your suggestion, I change the CacheableLayer to an interface, that the ColorFilterLayer, ImageFilterLayer implement the interface that mean they can try to raster cache;
About the check DisplayList should be raster cache, I add the access_threshold_ to limit it.

@JsouLiang JsouLiang force-pushed the Collection-Need-RasterCache-Layer-In-Preroll branch from 0c52ffe to 0e2f476 Compare April 8, 2022 09:55
@JsouLiang JsouLiang requested a review from flar June 29, 2022 06:40
@JsouLiang JsouLiang force-pushed the Collection-Need-RasterCache-Layer-In-Preroll branch from 3cb79e4 to 9b68847 Compare June 29, 2022 09:36
Copy link
Contributor

@flar flar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@flar
Copy link
Contributor

flar commented Jun 29, 2022

@ColdPaleLight @dnfield any final review comments?

@flar
Copy link
Contributor

flar commented Jun 29, 2022

The corresponding benchmark to demonstrate the elimination of the "double caching" issue is in the framework tree and collecting data. Depending on how busy the trees are, it will hopefully collect a good dozen or so results before this PR can be rolled in.

See: https://flutter-dashboard.appspot.com/#/build?taskFilter=cache_use&authorFilter&messageFilter&hashFilter&showMac=true&showWindows=true&showiOS=true&showLinux=true&showAndroid=true&showStaging=false&repo=flutter&branch=master

context->raster_cached_entries->push_back(this);
cache_state_ = CacheState::kCurrent;
}
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove it

Copy link
Member

@ColdPaleLight ColdPaleLight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with nit

@dnfield
Copy link
Contributor

dnfield commented Jun 30, 2022

I would really like to see the captures in the two places that are using [=] just explicitly capture what's needed - this can be a source of runtime issues by capturing and then using things that aren't actually safe to use.

That said, It doesn't have to block landing this change and it'd be fine to follow on in a separate PR.

@dnfield
Copy link
Contributor

dnfield commented Jun 30, 2022

My other review comments were less important nits or appear to have been addressed.

@JsouLiang JsouLiang added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Jun 30, 2022
@fluttergithubbot fluttergithubbot merged commit 557655b into flutter:main Jun 30, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 30, 2022
@flar
Copy link
Contributor

flar commented Jun 30, 2022

I would really like to see the captures in the two places that are using [=] just explicitly capture what's needed - this can be a source of runtime issues by capturing and then using things that aren't actually safe to use.

That said, It doesn't have to block landing this change and it'd be fine to follow on in a separate PR.

Good point. flutter/flutter#106892

// 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.
if (context->cull_rect.intersect(bounds)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be "intersects"? Is this a bug? I'm curious why it never showed up anywhere. Perhaps because we don't use this cull_rect for much during preroll?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land.
Projects
None yet
7 participants