Closed Bug 1687977 Opened 3 years ago Closed 3 years ago

Render radial and conic gradients as cached images

Categories

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

enhancement

Tracking

()

RESOLVED FIXED
88 Branch
Tracking Status
firefox88 --- fixed

People

(Reporter: nical, Assigned: nical)

References

(Regressed 1 open bug)

Details

Attachments

(13 files)

48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review

Currently gradients are rendered:

  • conic or radial gradients: as a brush in the main pass
  • linear: under some conditions they are pre-rendered in a cached render task and composited with the image brush shader (fast path), otherwise rendered directly using the linear gradient brush shader. The conditions are:
    • The gradient covers the entire primitive
    • It must be vertical or horizontal
    • it must not have segments

The goal is for all gradients to be pre-rendered as a cached render task in all situation. The motivations for this are:

  • performance: it is faster to cache the rendered gradients once and composite a simple image every frame, than to run the gradient shaders every frame, in particular for swgl
  • simplify the rendering code by reducing the number of brush shader types. (Ideally we want to converge towards having only image and solid brushes in the main pass).

Potential solution:

Render in 3 steps:

  • 1: Render the gradient stops (whatever the type) as a horizontal line in a first pass, so that the second pass doesn't have to deal with gradient stops.
  • 2: in a second pass, a gradient shader samples this line to generate the image (a shader per gradient type: linear/radial/conic)
  • 3: the image brush shader is used to composite the image in the main pass.

If the gradient is linear and axis aligned, we can skip step 2 (today's fast path) and stretch the gradient line from step 1 direcly when compositing.

I'm not sure how hard we need hard gradient stops to be: If there is a hard stop, is it ok to render it in step 1 and that step 2 potentially samples in between (that would creat a sort of anti-aliased transition at the hard stop)? If this is not OK, then we have to combine step 1 and 2 and have the gradient shaders deal with hard stops. The advantage of not doing that is that we can avoid requiring a variable amount of inputs in the cached render tasks even with many gradient stops: each transition between two colors can be rendered with a separate quad.

I don't see a particular reason why this would not work with segmented primitives. I suspect that the linear gradient fast path currently does not support them to avoid duplicating code but that needs to be refactored.

It is the cs_* shader used to cache linear gradients in the simple/fast path (more complex linear gradients are rendered with a brush shader. The goal of this patch series is to move all gradients to cached render tasks that will be composited with brush_image, so there will be a cs_linear_gradient introduced in a followup to cover the general case as well as cs_radial_gradient and cs_conic_gradient to replace the brush equivalents.

Assignee: nobody → nical.bugzilla
Status: NEW → ASSIGNED

prim_store/gradient.rs is large enough that splitting it up will make things a bit clearer. The new organization is:

  • prim_store/gradient/mod.rs: shared/gradient-agnostic code.
  • prim_store/gradient/<linear|radial|conic>.rs: specific gradient code.

In addition, various gradient-specific data structures currently living in other modules will move into the proper gradient modules as part of this patch series.

For convenience, all specific public symbols are reexported in prim_store::gradient.

Depends on D107640

Historically WebRender's code has used 'gradient' as a shorthand for 'linear gradient' and often more specifically for 'the fast path for linear gradients'. This patch makes the naming less ambiguous in particular in places where we'll see more types of gradients sid by side introduced by upcoming patches in this series.

Depends on D107641

In the spirit of keeping primitive-specific logic mostly in the same place, this moves the linear gradient render task and the code to convert it into a gpu-visible instance into linear.rs.

I'm planning to give all specific render task structures/logic the same treatment eventually.

Depends on D107642

Pushed by nsilva@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/9f140075b49f
Part 1 - Rename cs_gradient into cs_fast_linear_gradient. r=gw
https://hg.mozilla.org/integration/autoland/rev/e5e58b10664a
Part 2 - Split prim_store/gradient.rs into sub-modules. r=gw
https://hg.mozilla.org/integration/autoland/rev/0b2d5a01cba8
Part 3 - rename gradient into fast_linear_gradient in various places. r=gw
https://hg.mozilla.org/integration/autoland/rev/ac798a0fe9e0
Part 4 - Move FastLinearGradientTask into gradient/linear.rs r=gw
Keywords: leave-open

The parts stay in gradient_shared.glsl are specific to the gradient brushes, dont build without outside of the brsuh infrastructure and will be removed along with the brush gradients. The parts that go into gradient.glsl will be shared between the different gradient render task shaders.

Depends on D108464

There was a lot of trial and error in the process of making this patch, so unfortunately I didn't manage to plan it out in smaller independent steps.

This patch introduces a new cs_radial_gradient shader to use instead of the brush radial gradient shader. The gradient is produced by a cached render task and composited via the image brush.

As a bonus, tiled radial gradients now get a chance to be in the opaque pass (the previous logic was overly conservative).

Depends on D108465

Depends on D108469

Attachment #9209162 - Attachment description: Bug 1687977 - Part 7 - Gracefully handle hug radial gradients. r=gw → Bug 1687977 - Part 7 - Gracefully handle huge radial gradients. r=gw
Pushed by nsilva@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/3842ded5b2c1
Part 5 - More Gradient/FastLienarGradient renaming. r=gw
https://hg.mozilla.org/integration/autoland/rev/9200289b567e
Part 6 - Split gradient_shared.glsl. r=gw
Attachment #9209424 - Attachment description: Bug 1687977 - WIP optimize large radial gradients. → Bug 1687977 - Optimize large radial gradients.
Attachment #9209161 - Attachment description: Bug 1687977 - Part 6 - Remove brush_radial_gradient. r=gw → Bug 1687977 - Part 8 - Remove brush_radial_gradient. r=gw
Attachment #9209162 - Attachment description: Bug 1687977 - Part 7 - Gracefully handle huge radial gradients. r=gw → Bug 1687977 - Part 9 - Gracefully handle huge radial gradients. r=gw
Attachment #9209424 - Attachment description: Bug 1687977 - Optimize large radial gradients. → Bug 1687977 - Part 10 - Optimize large radial gradients. r=gw
Attachment #9209163 - Attachment description: Bug 1687977 - Part 8 - Adjust reftest references. r=gw → Bug 1687977 - Part 11 - Adjust reftest references. r=gw
Attachment #9209423 - Attachment description: Bug 1687977 - Part 9 - Render conic gradients using render tasks. → Bug 1687977 - Part 12 - Render conic gradients using render tasks. r=gw
Attachment #9209772 - Attachment description: Bug 1687977 - Part 13 - Remove brusg_conic_gradient. r=gw" → Bug 1687977 - Part 13 - Remove brush_conic_gradient. r=gw"
Pushed by nsilva@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/2865e8332baa
Part 7 - Render radial gradients using render tasks. r=gw
https://hg.mozilla.org/integration/autoland/rev/2f392cb56f71
Part 8 - Remove brush_radial_gradient. r=gw
https://hg.mozilla.org/integration/autoland/rev/526d512c6cf9
Part 9 - Gracefully handle huge radial gradients. r=gw
https://hg.mozilla.org/integration/autoland/rev/ddceb031f73b
Part 10 - Optimize large radial gradients. r=jrmuizel,gw
https://hg.mozilla.org/integration/autoland/rev/72bcd469b597
Part 11 - Adjust reftest references. r=gw
https://hg.mozilla.org/integration/autoland/rev/56ef057fc29c
Part 12 - Render conic gradients using render tasks. r=gw
https://hg.mozilla.org/integration/autoland/rev/47f20111056a
Part 13 - Remove brush_conic_gradient. r=gw"
Pushed by nsilva@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/bc70dc8ad3a7
Part 7 - Render radial gradients using render tasks. r=gw
https://hg.mozilla.org/integration/autoland/rev/b88325347b88
Part 8 - Remove brush_radial_gradient. r=gw
https://hg.mozilla.org/integration/autoland/rev/0d96a981a333
Part 9 - Gracefully handle huge radial gradients. r=gw
https://hg.mozilla.org/integration/autoland/rev/ca611e922f49
Part 10 - Optimize large radial gradients. r=jrmuizel,gw
https://hg.mozilla.org/integration/autoland/rev/cd256e69c920
Part 11 - Adjust reftest references. r=gw
https://hg.mozilla.org/integration/autoland/rev/edd376ea0b95
Part 12 - Render conic gradients using render tasks. r=gw
https://hg.mozilla.org/integration/autoland/rev/4575418fa949
Part 13 - Remove brush_conic_gradient. r=gw"
Flags: needinfo?(nical.bugzilla)
Depends on: 1699884
Regressions: 1699884

== Change summary for alert #29391 (as of Tue, 23 Mar 2021 08:08:58 GMT) ==

Improvements:

Ratio Suite Test Platform Options Absolute values (old vs new)
7% microsoft PerceptualSpeedIndex windows10-64-shippable-qr cold nocondprof webrender 605.46 -> 562.33
6% microsoft FirstVisualChange windows10-64-shippable-qr cold nocondprof webrender 597.83 -> 564.92
5% microsoft SpeedIndex windows10-64-shippable-qr cold nocondprof webrender 599.29 -> 566.92
5% microsoft ContentfulSpeedIndex windows10-64-shippable-qr cold nocondprof webrender 601.29 -> 569.58
5% microsoft PerceptualSpeedIndex windows10-64-shippable-qr cold nocondprof webrender 601.12 -> 569.58
5% reddit loadtime linux1804-64-shippable-qr nocondprof warm webrender 2,171.25 -> 2,071.21
3% wikipedia fcp linux1804-64-shippable cold nocondprof 1,637.44 -> 1,586.42

For up to date results, see: https://treeherder.mozilla.org/perfherder/alerts?id=29391

Nicolas, is more work needed on this bug or can it be closed now?

Flags: needinfo?(nical.bugzilla)

I did conic and radial gradients, there's still linear gradients but it's more complicated (surprisingly) and I'm focusing on other things right now. I'll change the bug title so that we can close this one.

Flags: needinfo?(nical.bugzilla)
Status: ASSIGNED → RESOLVED
Closed: 3 years ago
Resolution: --- → FIXED
Summary: Render all gradients as cached images → Render radial and conic gradients as cached images
See Also: → 1702228
Target Milestone: --- → 88 Branch
Regressions: 1702638
Regressions: 1707624
Regressions: 1708122
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: