Inefficient SVG pattern rendering |
|
Issue descriptionTest case lifted from issue 832482 . On my workstation it renders at 2.5fps SW, and waaaay < 1fps with Ganesh. The general structure is - 4 simple patterns - 10000 small rects referencing the patterns - random floating/animating circle to trigger invals/repaint Ideally: - we instantiate/cache 4 picture shaders for the 4 patterns - we pass those down to Skia, which only gets to see 4 stable picture shaders referenced in 10000 drawRect calls - the patterns and picture shaders don't change inter-frame What appears to happen: - Blink or CC breaks the stable reference chain and instantiates 10000 picture shaders (one for each reference), *for each frame* - Skia sees 10000 drawRect calls with 10000 different picture shaders per frame and completely thrashes the picture shader tile cache - this thrashing appears to disproportionately affect Ganesh (I see most time being spent in the NV driver, presumably shuffling textures around)
,
Apr 19 2018
At least part of the issue is related to instantiating the SVG group with <use>: if I instantiate directly (see attached), the inter-frame thrashing goes away (still seeing 10000 picture shaders, but they no longer change inter-frame). new sw fps: ~50 new gpu fps: ~2
,
Apr 23 2018
Yes, the structure of this thing doesn't interact well with <use> invalidation (change to target subtree -> rebuild instance), so every time the <circle> is updated the <use> is rebuilt, meaning we get new elements. New elements mean new layout objects, meaning the pattern keys change. The solution to that would be a "partial instance update / (re)clone", which undoubtedly involves a lot of hair. Sharing pattern instances would seem like it would be easier (payoff/effort is greater.)
,
Apr 23 2018
Agreed, it should be easier, and I actually started on sharing cached resources with the easy/obvious candidate -- gradients: https://chromium-review.googlesource.com/c/chromium/src/+/1020600 ... and ran straight into issue 835110 :( TBH I'm not sure if that's enough to block work in this area, because resource layout is rotten to the core and there are other cases where it breaks down. But that change does regress a class of cases where both the resource and the client are relative-sized and supposed to inval on container size changes.
,
Apr 23 2018
Yes, not great... I'll need to do some code archeology to see what exactly that was fixing.
,
Apr 23 2018
(I think it was me, but not 100% sure, long time ago) IIRC the bug had to do with forced layout causing invalidations outside the layout scope. Resources are a DAG, so forced inval during layout can dirty the rest of the tree arbitrarily. Worst case is not even within the same SVG root. So the workaround was to disable forced layout/inval for resources, rely on relative-length descendent tracking instead, and dirty resources at the view level -- when we're not constrained to a narrow layout scope. Problem is this is only hooked for LayoutView, and other containers don't trigger resource inval when their size changes.
,
Apr 23 2018
Looks like it was c80d2b59c2357c6cae1dee9baef6fbaecb3c8136 that touched it last. And the triggering case(s) there (specifically) seems to be descendants of resources (which can have "layoutable" descendants) in turn laying out their resources. I have some plans for removing all these "indirect resource layouts", and if that works out we ought to be able to reinstate the forced layout (or maybe even better selective mark objects for layout based on the tracking set.)
,
Apr 23 2018
See also https://chromiumcodereview.appspot.com/23785014 for when we starting digging this particular hole. |
|
►
Sign in to add a comment |
|
Comment 1 by fmalita@chromium.org
, Apr 19 2018