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

First round of optimizations for box shadows. #1954

Merged
merged 3 commits into from Oct 30, 2017
Merged

Conversation

@glennw
Copy link
Member

glennw commented Oct 27, 2017

This applies two optimizations to outset box shadows:

  • If border radii are uniform, render only the top left corner
    of the box shadow, and mirror that across the primitive.
  • If border radii are non-uniform, render a minimal mask
    rect and stretch that across the primitive.

There are several remaining box shadow / clip related optimizations
to come, but this provides some large immediate wins on large
outset box shadows.

Fixes #1571.


This change is Reviewable

@glennw
Copy link
Member Author

glennw commented Oct 27, 2017

r? @kvark

@glennw
Copy link
Member Author

glennw commented Oct 27, 2017

@jrmuizel This provides a large performance win on https://bugzilla.mozilla.org/show_bug.cgi?id=1408612.

In the profile bars below, the pink segments are blurs for box shadows. They are an almost negligible amount of time with this optimization.

profile

On my HD4600, this drops the GPU time on bugzilla from ~20ms to ~8ms. The performance with this fix is reasonable now, but there's three major issues outstanding:

  • No z-buffer wins (known issue being worked on in WR, due to Gecko not using local clips).
  • Way too many clip masks being drawn (still nearly 3 2048x2048 A8 targets being filled per frame - the purple bars). Need to investigate this more - probably some issues in both Gecko and WR here.
  • High number of draw calls / bad batching. Needs a bit of investigation - it's worse than I'd expect. Will be resolved anyway as we unify more shaders to brush types.

Follow ups:

  • Optimize inset shadows.
  • Specifiy render task cache key for blurs - this will save doing the same blur on different primitives.
@glennw
Copy link
Member Author

glennw commented Oct 27, 2017

Servo WPT sanity tests pass, I need to do a full run through.

@kvark
Copy link
Member

kvark commented Oct 27, 2017

Amazing work 👍 ! I just got a few concerns to address.


Reviewed 15 of 15 files at r1.
Review status: all files reviewed at latest revision, 7 unresolved discussions.


webrender/res/brush_image.glsl, line 90 at r1 (raw file):

        }
        case BRUSH_IMAGE_NINEPATCH: {
            uv = clamp(vUv.xy, vec2(0.0), vParams.xy);

this seems incorrect, given that vParams.xy == vec2(0.5) at this point


webrender/res/brush_image.glsl, line 98 at r1 (raw file):

            // Mirror and stretch the box shadow corner over the entire
            // primitives.
            uv = vParams.xy - abs(vUv.xy - vParams.xy);

given that vParams.xy is half-size of the local rect, this would produce uv between the local rect origin and it's half-size. It doesn't appear to be desired?


webrender/res/brush_mask_rounded_rect.glsl, line 72 at r1 (raw file):

    // be made much faster.

    // NOTE: The AA range must be computed outside the if statement,

I think we should rather move the AA stuff out of rounded_rect (than call rounded_rect all the time), so that we can avoid some work here if we are outside of the clip region.


webrender/src/box_shadow.rs, line 20 at r1 (raw file):

// mask. This ensures that we get a few pixels past the corner that can be
// blurred without being affected by the border radius.
pub const MASK_CORNER_PADDING: f32 = 4.0;

hmm, should this depend on the border radius then?


webrender/src/picture.rs, line 41 at r1 (raw file):

        blur_regions: Vec<LayerRect>,
        clip_mode: BoxShadowClipMode,
        has_uniform_radii: bool,

would be nice to have it as an enum for better calling semantics


webrender/src/picture.rs, line 142 at r1 (raw file):

            PictureKind::BoxShadow { blur_radius, clip_mode, has_uniform_radii, .. } => {
                // We need to inflate the content rect if outset.
                if clip_mode == BoxShadowClipMode::Outset {

nit: match would be more clear


webrender/src/prim_store.rs, line 190 at r1 (raw file):

    fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
        match self.kind {
            BrushKind::Mask { clip_mode, ref kind } => {

nit: given the paths are so different, might as well match BrushMaskKind in place here, i.e. BrushKind::Mask { clip_mode, kind: BrushMaskKind::Corner(radius) } => {...}


Comments from Reviewable

gw3583 added 2 commits Oct 27, 2017
This applies two optimizations to outset box shadows:

* If border radii are uniform, render only the top left corner
  of the box shadow, and mirror that across the primitive.
* If border radii are non-uniform, render a minimal mask
  rect and stretch that across the primitive.

There are several remaining box shadow / clip related optimizations
to come, but this provides some large immediate wins on large
outset box shadows.

Fixes #1571.
@glennw glennw force-pushed the glennw:bs-opts-tidy branch from 2c9b414 to 52379bf Oct 29, 2017
@glennw
Copy link
Member Author

glennw commented Oct 29, 2017

Review status: 9 of 17 files reviewed at latest revision, 7 unresolved discussions.


webrender/res/brush_image.glsl, line 90 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

this seems incorrect, given that vParams.xy == vec2(0.5) at this point

The UV coords passed are divided by the size of the patch, so 0.5 is the UV when we reach half of the source patch.


webrender/res/brush_image.glsl, line 98 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

given that vParams.xy is half-size of the local rect, this would produce uv between the local rect origin and it's half-size. It doesn't appear to be desired?

Same as above - the UV space is local_rect_size / patch_size.


webrender/res/brush_mask_rounded_rect.glsl, line 72 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

I think we should rather move the AA stuff out of rounded_rect (than call rounded_rect all the time), so that we can avoid some work here if we are outside of the clip region.

Done.


webrender/src/box_shadow.rs, line 20 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

hmm, should this depend on the border radius then?

It's added as padding in addition to the border radii sizes below.


webrender/src/picture.rs, line 41 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

would be nice to have it as an enum for better calling semantics

Done.


webrender/src/picture.rs, line 142 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

nit: match would be more clear

Done.


webrender/src/prim_store.rs, line 190 at r1 (raw file):

Previously, kvark (Dzmitry Malyshau) wrote…

nit: given the paths are so different, might as well match BrushMaskKind in place here, i.e. BrushKind::Mask { clip_mode, kind: BrushMaskKind::Corner(radius) } => {...}

Done.


Comments from Reviewable

@glennw
Copy link
Member Author

glennw commented Oct 29, 2017

@kvark Thanks! All comments addressed, I think.

This is ready for re-review, but I still need to do a gecko try run to see what the differences are and if they are within expected fuzziness tolerance.

@glennw
Copy link
Member Author

glennw commented Oct 29, 2017

Looks like there are a few failures in a gecko try run - will investigate those today.

@glennw
Copy link
Member Author

glennw commented Oct 29, 2017

This is the try run:

https://treeherder.mozilla.org/#/jobs?repo=try&revision=c5f8f1ac6a590d976ba59e3ca8e5be9315509528&selectedJob=140569327

It has 1 new PASS and 3 new FAILs.

Unfortunately those fails seem to pass locally on my machine. Still investigating...

@glennw glennw force-pushed the glennw:bs-opts-tidy branch from 1d1f780 to 931a42d Oct 30, 2017
@glennw
Copy link
Member Author

glennw commented Oct 30, 2017

There is a 3rd commit which fixes / works around some of the Gecko try failures above. Specifically:

  • Handle the case of an inset shadow rect becoming invalid and skip trying to draw it.
  • Add a temporary workaround for cases where the inset box shadow is computed to be a fractional number of device pixels. We'll need a proper fix for this as a follow up.

With those changes, we have:

https://treeherder.mozilla.org/#/jobs?repo=try&revision=ecc653837134cedc319859af3de8f01040d102dd&selectedJob=140625740

The a11y and mda2 failures are unrelated.

Two new PASS in R3 and R4:

boxshadow-large-border-radius.html
box-decoration-break-with-inset-box-shadow-1.html

One new FAIL in R3:

boxshadow-skiprect.html - In this test, we clip one extra vertical line of pixels than it should be. This appears to be a bug in the clipping code, so technically unrelated to the box shadow code. I'm also unable to reproduce this locally - I get pixel-perfect results both running under OSMesa or on Intel GPU.

With @staktrace 's blessing, I think we should add some fuzziness to boxshadow-skiprect.html and get these changes re-reviewed and merged - they provide a really significant performance improvement on a lot of sites.

r? @kvark

@glennw
Copy link
Member Author

glennw commented Oct 30, 2017

(or @nical for the last 2 commits, if @kvark is on PTO this week?)

@staktrace
Copy link
Contributor

staktrace commented Oct 30, 2017

/me blesses

@nical
Copy link
Collaborator

nical commented Oct 30, 2017

@bors-servo
Copy link
Contributor

bors-servo commented Oct 30, 2017

📌 Commit 931a42d has been approved by nical

@bors-servo
Copy link
Contributor

bors-servo commented Oct 30, 2017

Testing commit 931a42d with merge a7bc0d2...

bors-servo added a commit that referenced this pull request Oct 30, 2017
First round of optimizations for box shadows.

This applies two optimizations to outset box shadows:

* If border radii are uniform, render only the top left corner
  of the box shadow, and mirror that across the primitive.
* If border radii are non-uniform, render a minimal mask
  rect and stretch that across the primitive.

There are several remaining box shadow / clip related optimizations
to come, but this provides some large immediate wins on large
outset box shadows.

Fixes #1571.

<!-- 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/1954)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Oct 30, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: nical
Pushing a7bc0d2 to master...

@bors-servo bors-servo merged commit 931a42d into servo:master Oct 30, 2017
4 of 5 checks passed
4 of 5 checks passed
code-review/reviewable 13 files, 7 discussions left (kvark)
Details
Taskcluster (pull_request) TaskGroup: success
Details
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

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