Gray line separating tab and chrome with DirectComposition turned on
Categories
(Core :: Graphics: WebRender, defect, P2)
Tracking
()
People
(Reporter: jrmuizel, Unassigned)
References
(Blocks 2 open bugs)
Details
(Whiteboard: wr-planning)
Attachments
(2 files)
I only see this at 1080p. It does not show up at higher resolutions even with the same scaling. The artifact does not show up in screenshots. I've reproduced on two different machines with Intel and AMD graphics respectively.
Reporter | ||
Comment 1•5 years ago
|
||
It looks like it actually happens at any non-native resolution.
Reporter | ||
Comment 2•5 years ago
|
||
So there's definitely something funky going on in the DWM/driver. If set up a laptop at its native resolution of 1366x768 and duplicate the display to a monitor with a different native resolution the weird line only shows up on the non-native resolution screen.
Comment 3•5 years ago
|
||
I've tried this on an Nvidia and Intel GPU where the native resolution is 3840 x 2160. I tried at various different resolutions from 1366 x 768 up to native resolution, and didn't notice anything obviously wrong.
Reporter | ||
Comment 4•5 years ago
|
||
Here's a video: https://photos.app.goo.gl/859rpK5r9QmpRweE6
Comment 5•5 years ago
|
||
Updated•5 years ago
|
Updated•5 years ago
|
Reporter | ||
Comment 6•5 years ago
|
||
I tried this again on some more GPUs and could so far only reproduce on an AMD R7 200 an 0x22b1 Intel HD Graphics. I could not reproduce on a GTX 950, GTX 1080, Intel 530.
Glenn, can you point out the max_update_rects change you wanted to me to try again?
Reporter | ||
Updated•5 years ago
|
Comment 7•5 years ago
|
||
Ensuring the condition in [1] evaluates to false should be enough to test it. Alternatively, you can change it in the RendererOptions
I think.
Reporter | ||
Comment 8•5 years ago
|
||
I wonder if the difference could be caused by whether the GPU has supports scaling outputs or not. It looks like they may have added scaler support in Skylake.
Reporter | ||
Comment 9•5 years ago
|
||
Did some more investigation. Confirmed that Windows has a separate "Desktop resolution" and "Active signal resolution". "Active signal resolution" is the resolution that is sent to the monitor. If the "Desktop resolution" and "Active signal resolution" don't match then Windows seems to take one of two paths.
- If the GPU supports scaled output the framebuffer will be in "Desktop resolution" and the GPU will scale during output
- Otherwise, the framebuffer will be in "Active signal resolution" and the DWM will scale up the scene to the higher resolution. This causes a variety of different artifacts. i.e. window edges are always sharp, Device manager has a line between the title bar and the menu bar, this bug etc.
Reporter | ||
Comment 10•5 years ago
|
||
I also confirmed that
diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs
index 18edf5d958ed..60127af510f3 100644
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -1301,7 +1301,7 @@ impl Tile {
(true, true)
}
CompositorKind::Native { max_update_rects, .. } => {
- (max_update_rects > 0, false)
+ (max_update_rects > 0 && false, false)
}
};
doesn't improve things.
Updated•5 years ago
|
Comment 11•5 years ago
|
||
I confirmed a few things that Jeff had already mentioned:
- Changing
max_update_rects
has no effect. - Any use of the screenshot or magnifier tools makes the artifact disappear.
I tweaked the shaders to make the brush_image
shader draw a magenta color. This color shows up as the artifact. So this confirms that the color of the artifact is from the picture cache slice being composited behind the tab strip.
I also found that I could control whether the artifact is present by making the window as small as possible, and carefully moving the mouse up and down on the right hand side of the window, between the window close button and the hamburger menu.
As the mouse crosses that horizontal boundary, the display list being sent changes in such a way that:
- When on close button, the URL bar and the tab strip get drawn into a single picture cache slice.
- When on hamburger button, the tab strip gets drawn into its own picture cache slice.
Once that was established, I tried changing the DC visual border mode between soft / hard, but that made no difference.
It's not clear to me why the display list changes in such a way that the picture caching slice configuration changes, I would expect there to be a single slice in both these cases.
It seems likely that if we can fix the behavior of the slice generation (or the Gecko display list, depending on where the issue is) to create a single slice in both these cases, we won't see the artifact.
This would be an unsatisfying fix, in that it is working around the root issue, but it might be our best option. Given the weirdness of the bug, and the conditions required to reproduce it, I think it's an underlying bug in DC / driver, which we're unlikely to be able to fix directly.
Reporter | ||
Updated•5 years ago
|
Comment 12•5 years ago
|
||
I think I can see what's happening. Ideally, this could be changed in the Gecko DL generation / frontend code, although I'm not sure how feasible that is.
The display list for the parent that WR receives looks roughly like:
[x primitives] [iframe pointing to content] [y primitives]
However, changing the mouse position as mentioned in comment 11 changes this to:
[(x-1) primitives] [iframe pointing to content] [(y+1 primitives]
Moving 1 or more primitives from before to after the iframe content changes the bounding rect of each of those UI slices, which is what seems to result in this apparent DC bug.
Having no idea how that code works above the WR level, it seems like what we would want to be doing is either:
(a) All of those display items either come before or after the iframe (would solve this issue and remove one picture cache slice).
(b) Have the display items stay in the same before / after position relative to the iframe (would solve this issue, by keeping the bounds the same).
How do we find out what's causing that change in display list, and whether it's feasible to change that in Gecko / frontend code?
Comment 13•5 years ago
|
||
I'm planning to make that happen in bug 1606631, once I get back to it. Can you try out the patch there and see if it fixes it?
Do you have reasons to believe that regular web content will not run into this problem?
Comment 14•5 years ago
|
||
That patch fixes it 99% of the time, so it seems my theory on the cause is correct.
I still see an occasional flicker of that line as I focus the megabar and it animates in, but it fixes the issue where it's persistent and occurs all the other times.
I don't believe regular web content will hit this problem, or at least, it would be extremely rare. This is because the size of the valid tiles and the picture cache slicing configuration in web content doesn't generally change for a given web page - generally there is a full background rectangle enforcing a full valid rect, and then in some cases an overlay tile or two for status bar, fixed dialogs etc (in addition to this only occurring on older Intel hardware without scaler support, and a non-native resolution).
It certainly seems possible to craft a web page which might show this bug, but I don't think it will show up in real world content.
Unfortunately, I'm not sure how else to resolve this bug, but I'm going to keep investigating today and looking further into the details - maybe there is something we're doing "wrong" that I missed, or maybe there is another way to work around it, if it is a DC bug.
Comment 15•5 years ago
|
||
The repro I am using has the following:
Display Resolution: 2048 x 1152
Desktop Resolution: 3840 x 2160
Active Signal Resolution: 3840 x 2160
I confirmed with logging in WR that the size of the framebuffer for a full-screen Gecko window is 2048 x 1120 (sounds about as expected, minus the taskbar at the bottom).
It seems inevitable that when DWM has to do GPU upscaling of that content, there will always be the possibility of scaling artifacts showing up in some form between tiles, at least in cases like this where the bounds are changing.
Could we consider disabling DC when running in a non-native resolution (+/- no native scaler), if we can detect that? I don't know, but I suspect that running in non-native resolution is quite rare, and there is already the GPU performance hit of the upscale, so that might be the simplest option? Also, WR compositing will be cheaper, since we're compositing into a framebuffer that is smaller than the native resolution?
Comment 16•5 years ago
•
|
||
Sotaro, do you know if it's possible to detect if the user is running a non-native resolution? If we can detect that, we could consider blocklisting DC on GPUs that we know don't have a hardware scaler and the user is running non-native?
Comment 17•5 years ago
|
||
Assigning to Sotaro for now, since this will be fixed by https://bugzilla.mozilla.org/show_bug.cgi?id=1620491.
Sotaro, please let me know if you need any help with this one (we'll want to either get it fixed before beta merge tomorrow, or make sure it's uplifted after that).
Reporter | ||
Comment 18•5 years ago
|
||
FWIW, the current backup plan is only enable DirectComposition when CheckHardwareCompositionSupport() return true. This should prevent us from running on systems that would show the gray line.
Updated•5 years ago
|
Reporter | ||
Comment 20•5 years ago
|
||
No, we still need a better long term solution. I've unblocked 75 though.
Comment 21•5 years ago
|
||
(In reply to Jeff Muizelaar [:jrmuizel] from comment #20)
No, we still need a better long term solution. I've unblocked 75 though.
OK
Updated•5 years ago
|
Updated•5 years ago
|
Reporter | ||
Updated•5 years ago
|
Updated•5 years ago
|
Reporter | ||
Updated•5 years ago
|
Reporter | ||
Updated•5 years ago
|
Updated•4 years ago
|
Comment 22•4 years ago
|
||
I am facing this issue on Mac from last 4 5 releases, never knew it was a bug.
Comment 23•2 years ago
|
||
(In reply to Glenn Watson [:gw] from comment #15)
It seems inevitable that when DWM has to do GPU upscaling of that content, there will always be the possibility of scaling artifacts showing up in some form between tiles, at least in cases like this where the bounds are changing.
I think contrary to this, it's not that we expect scaling artifacts to show up between tiles (that share an edge), but rather at edges of overlapped tiles.
We'd expect rounding for the same coord to happen the same way if we had two surfaces rect_a.y=[0-51] and rect_b.y=[51,1080].
However, in the stacked/overlapping case rect_top.y=[0-51] and rect_bottom.y=[0,1080], if 51*scale rounds down, we might manage to sample from the overlapped rect_bottom underneath, instead of the edge of the overlapping rect_top on top. This might filter between a white or magenta 'unpainted' texel in rect_bottom and the the actual valid rect_bottom texels that are (just barely) outside the bounds of rect_top.
E.g. we might sample:
y_scaled = y * scale;
y_scaled_floor = floor(y_scaled)
out = sample(y_scaled) = lerp( fetch(y_scaled_floor),
fetch(y_scaled_floor+1)
y_scaled - y_scaled_floor );
Comment 24•2 years ago
|
||
Elsewhere in layout code, we've long snapped bounding rects to "device pixels", but these "device pixels" are actually "desktop pixels", not "signal pixels".
If we snap instead to signal pixels (as our real, actual "device pixels"), then we shouldn't have this problem I think.
This does require that we have only one signal resolution. I think gw mentioned display mirroring and seeing artifacts only on one of the two paired/mirrored displays. If there's no one singular signal resolution, I think there's nothing we can reliably do, and we just need to fall back to single-surface compositing.
Updated•2 years ago
|
Updated•8 months ago
|
Updated•8 months ago
|
Description
•