Open Bug 1579977 Opened 5 years ago Updated 2 years ago

Poor scrolling performance on Apple Music Beta

Categories

(Core :: Graphics: WebRender, defect, P3)

defect

Tracking

()

People

(Reporter: mstange, Assigned: nical)

References

(Depends on 1 open bug, Blocks 2 open bugs, )

Details

(Whiteboard: [sci-exclude])

I get 27fps scrolling on https://beta.music.apple.com/us/browse.
(Non-WebRender is also bad.)

Profile: https://perfht.ml/2ZOlWFk

There's a bunch of blob rasterization drawing gradients. This seems to be a mask-image gradient, from the .shelf-grid__list elements. This gradient mask is applied to all the horizontal "paging" boxes with arrows on the sides - when those arrow buttons are clicked, during the horizontal slide animation, the gradient mask makes the sides of the contents fade out. In the stationary case, the mask does not have a visible effect.

Blocks: wr-perf

Nical - can you take a look at this?

Flags: needinfo?(nical.bugzilla)
Priority: -- → P3
Assignee: nobody → nical.bugzilla
Flags: needinfo?(nical.bugzilla)

On the GPU side, the slowness is caused by the mask: linear-gradient properties applied to the shelf-grid__list elements (the rows of playlists in the main panel), forcing them to be rasterized in an intermediate pass. A lot of the time GPU is then spent clearing and rendering these elements.
If I remove these masks from the dev tools the overdraw is massively reduced.

The gradient: linear-gradient(90deg,transparent 0,#000 15px,#000 calc(100% - 15px),transparent 100%)

It's basically a horizontal gradient that starts transparent on the left side, then opaque at 15 pixels, then still opaque all the way to the right side minus 15 pixels and fades back to transparent at the end.
The majority of the gradient is opaque and as far as I can see, all of the items only overlap with the opaque part, but we don't currently have a way to segment gradients and handle solid portions.

Two approaches come to mind:

  • One way to address this could be to cache the masked pictures from frame to frame. In this case They are reasonably sized so we don't need to tile them. I think that it would make sense to do that for expensive stacking contexts (for some definition of expensive) that need to be rendered off-screen, just like our compositor backends have non-scrollable layers. Ideally we would bake the mask in that cached picture.

  • Another approach could be to segment gradient masks like we segment rounded rects, and see if we can remove the opaque part (perhaps only attempt that for gradient masks that cover a lot of pixels).

It's also possible to do both, especially if baking the mask in the cached picture turns out to be complicated.

Depends on: 1583545
Whiteboard: [sci-exclude]
Blocks: wr-caching
Blocks: blob-perf
No longer blocks: wr-perf
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.