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

Skip clip masks where the inner rect encloses the primitive rect. #1649

Merged
merged 1 commit into from Sep 5, 2017

Conversation

@glennw
Copy link
Member

glennw commented Aug 31, 2017

This fixes some performance issues in the Motionmark images demo.


This change is Reviewable

@glennw
Copy link
Member Author

glennw commented Aug 31, 2017

I'll run the Servo and Gecko tests against this before merging, but it seems like it should be a safe optimization.

r? @kvark

@glennw
Copy link
Member Author

glennw commented Sep 1, 2017

Copy link
Member

kvark left a comment

Thanks for tracking this down, @glennw !
I'm not fully convinced this hack is worth submitting. Another approach proposed in the comment.

// encloses the screen rect of the primitive, it can't
// possibly affect the result, so remove it during
// this filtering pass.
if inner.device_rect.contains_rect(&prim_rect) {

This comment has been minimized.

@kvark

kvark Sep 1, 2017

Member

There is only one case where task_rect is larger than prim_rect: when we are processing clips specified for parent stacking contexts, while the primitive itself doesn't have a specific clip.

But in this case it should be desirable to have this task even if the particular primitive rect is not affected, because the generated mask is to be re-used for multiple primitives inside this stacking context.

I think we need to sort this out at a higher level: have a heuristic for a stacking context to share it's mask with children primitives. The heuristic can be as follows:

  1. compute the bounding box of all primitives inside this stacking context that don't have specific clips already
  2. compute the sum of bounding box squares of all the same primitives
  3. if the sum is smaller than the bounding box of all, then pass None here for clip_id and prim_rect for task_rect
  4. if the sum is larger, then do what we are doing now

As you can see, with this approach we'll not need a hack inside new_mask, and we'll not pass the primitive rectangle in here (just the task rectangle).

This comment has been minimized.

@glennw

glennw Sep 1, 2017

Author Member

That does sound a bit more elegant conceptually, but I think the implementation may be a bit complicated.

We'd have to either scan the primitive list inside a stacking context first to get the sum, and know which path to choose when generating the masks, or we'd have to keep track of the primitives that need a clip mask and then revisit them to set up the appropriate clip mask, wouldn't we? It's possible I'm over-thinking this :)

I think we could land this first, since it's a simple win, and then revisit the heuristic above as a possible follow up. What do you think?

This comment has been minimized.

@glennw

glennw Sep 1, 2017

Author Member

Huh, I have an idea that might fix this and drastically simplify the way we manage shared masks. Will need some more thought and prototyping to see if it works though. @jrmuizel Do you want an urgent fix for that performance issue, or is it fine to hold off for a few days and work out the best long term solution?

@jrmuizel
Copy link
Contributor

jrmuizel commented Sep 1, 2017

@glennw
Copy link
Member Author

glennw commented Sep 1, 2017

@kvark I wrote up what I've been thinking about for clip masks - https://github.com/servo/webrender/wiki/Improved-clipping.

When you have time available, it'd be great to hear any feedback or issues you can think of related to it. It seems like it should just work, but it's quite likely there's something subtle I haven't thought though...

@kvark
Copy link
Member

kvark commented Sep 1, 2017

@glennw Thank you! I moved the discussion to #1656

This fixes some performance issues in the Motionmark images demo.
@glennw glennw force-pushed the glennw:clip-opt-2 branch from ad4b151 to c85571c Sep 3, 2017
@glennw
Copy link
Member Author

glennw commented Sep 3, 2017

@kvark In terms of this PR / optimization - I realized a simpler way to achieve it. The patch now just skips creating a mask altogether if the final inner rect contains the primitive rect.

This removes any hacks regarding modifying the cache key, and still fixes up the performance of this benchmark.

Tests run OK in Servo, and Gecko try run here looks good:

https://hg.mozilla.org/try/rev/23927113bc7051c5779d3ed5c5dd5a0e16f2e689
https://treeherder.mozilla.org/#/jobs?repo=try&revision=23927113bc7051c5779d3ed5c5dd5a0e16f2e689

(Also rebased).

@kvark
kvark approved these changes Sep 4, 2017
if let Some(inner_rect) = inner_rect {
// If the inner rect completely contains the primitive
// rect, then this mask can't affect the primitive.
if inner_rect.contains_rect(&prim_rect) {

This comment has been minimized.

@kvark

kvark Sep 4, 2017

Member

hmm, so now of all the primitives sharing the same task, some will just cop out by returning None here and others will process as usual? seems logically correct to me

This comment has been minimized.

@glennw

glennw Sep 5, 2017

Author Member

Yup, that's right :)

@kvark
Copy link
Member

kvark commented Sep 4, 2017

@bors-servo
Copy link
Contributor

bors-servo commented Sep 4, 2017

📌 Commit c85571c has been approved by kvark

bors-servo added a commit that referenced this pull request Sep 4, 2017
Skip clip masks where the inner rect encloses the primitive rect.

This fixes some performance issues in the Motionmark images demo.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1649)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Sep 4, 2017

Testing commit c85571c with merge e5485fb...

@bors-servo
Copy link
Contributor

bors-servo commented Sep 5, 2017

☀️ Test successful - status-travis
Approved by: kvark
Pushing e5485fb to master...

@bors-servo bors-servo merged commit c85571c into servo:master Sep 5, 2017
3 checks passed
3 checks passed
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

5 participants
You can’t perform that action at this time.