Closed Bug 1511433 Opened 6 years ago Closed 6 years ago

Artifacts and flickering when rendering gradients on webrender on android

Categories

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

Unspecified
Android
defect

Tracking

()

RESOLVED FIXED
mozilla68
Tracking Status
firefox65 --- wontfix
firefox66 --- wontfix
firefox67 --- wontfix
firefox68 --- fixed

People

(Reporter: jnicol, Assigned: jnicol)

References

(Blocks 1 open bug)

Details

Attachments

(2 files)

Attached image Screenshot_20181130-182622.png (deleted) —
As seen in bug 1499104, there were issues with gradients on webrender on android, noticable in the settings wheel on spiegel.de.

This appeared to be fixed by webrender #3352. However, it doesn't seem to have fully fixed them. Since that landed, I can no longer reproduce by visiting spiegel.de on a fresh app launch. But if I visit reddit.com an issue is visible (see vertical stripes next to padlock icon in attachment). And after visiting reddit, it is easy to reproduce back on spiegel or a simple gradient testcase.
In fact, even just reloading spiegel.de is enough to break the gradient again - no need to visit reddit. It does seem to flicker less crazily than before, but it's definitely still broken.
Blocks: wr-android
Summary: Flickering gradients on webrender on android (reddit.com) → Artifacts and flickering when rendering gradients on webrender on android
The issue occurs when attempting to read gradient stops from the gpu cache at row 32 or greater (ie address >= 2^15). This is because on GLES GLSL ints are 16 bit, so we overflow and read from the wrong location in the gpu cache.

If we use a highp int for the address that should fix this problem.
Priority: -- → P3

Assuming this happens on newer Adrenos as well since it sounds like a GLES thing.

Yes, it's a GLES spec thing rather than a device-specific driver bug. Affects most/all devices AFAIK, including the pixel 2.

I was wondering for a while why only gradients were affected and not other primitives, since they all need to fetch data from the gpu cache.

The reason is that linear and radial gradients are the only primitives which fetch data in the fragment shader, all others only do so in the vertex shader. For vertex shaders highp is the default, whereas mediump is the default for fragment shaders.

In GLES 3 GLSL, the default precision for ints is highp (32 bit) in
vertex shaders, but only mediump (16 bit) in fragment shaders.

To render linear and radial gradients the fragment shader must fetch
the gradient stops from the gpu cache, using an address variable. This
variable is a 16 bit int, so if the stops data is located at
too high an address (row 32 or greater) then this value will have
overflown and we fetch from the wrong location. This was resulting in
garbage being drawn instead of the correct gradients.

To fix this, any address used in a fragment shader must be marked as
highp. This includes the varying input which supplies the address, and
the arguments to any functions used for the fetch.

Pushed by jnicol@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/495ee696b110
Ensure address variables in fragment shaders are highp precision. r=gw
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla68
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: