blur: expand partial render region by one pixel - #3114
Conversation
|
I wonder whether the issue won't be fixed if we use floating-point regions here (and convert to integers right before scissoring). Do you think that could fix the issue? |
|
I had already tried variations of this direction during the initial I repeated the test more directly now by keeping the blur damage as The scale 1.6 / kawase_degrade 10 case is still bad. The magenta edge This is consistent with the earlier diagnostics. The issue is not just Expanding the partial render region by one pixel does. I also have a separate, larger rendering regression involving |
|
@dmrlsn I am not sure I understand though why the expand by 1 fixes the issue (or what the issue actually is). The current algorithm already assumes that the region outside of the damaged region is black / invalid colors - this is why we add padding, blur a larger region (where we know the parts near the edges will be wrong) and then replace the 'wrong' parts with the old contents (see blur.cpp). |
|
That is not to say that we don't have to expand the region, I am simply trying to understand why the current compensation mechanism is failing and we need more workarounds. |
|
I think the compensation in The code in What I am seeing happens inside the intermediate blur pass chain. In the failing case I measured an intermediate buffer of256x162, A following blur pass can still sample row 0 while producing pixels I tested this directly by modifying that omitted row. If I fill it So the problem is not that pixels outside the padded scene region are The one-pixel expansion makes that intermediate texel get written |
| GL_CALL(glBindTexture(GL_TEXTURE_2D, tex_id)); | ||
|
|
||
| blur_region.expand_edges(1); | ||
| blur_region &= wlr_box{0, 0, width, height}; |
There was a problem hiding this comment.
Does it work if this code is gated with a conditional that is only executed if degrade != 0?
There was a problem hiding this comment.
'degrade' cannot be zero here - all blur degrade options have a
minimum value of 1, and it is also used as a divisor when preparing
the blur buffer
if you meant degrade != 1, I don't think that would be appropriate
either.A degrade value of 1 only disables the initial downscaling. The
intermediate blur passes still run and can sample outside the area
written by the prvious pass.
Since the expansion is done inside render_iteration(), it already
only applies when an intermediate blur pass is actually rendered.
Blur passes can sample one pixel outside the partial render region, leaving intermediate buffer contents undefined at the edge. Expand the region by one pixel and clip it to the target buffer. Fixes WayfireWM#3113
43adc2e to
bd7508d
Compare
|
I think this is another example of what types of bugs might crop up if using a 'bad' output scale value. @ammen99 I thought the plan was to snap to 'good' output scale values to sidestep off-by-one issues like these? |
|
Yes, scale 1.6 is one of the alignments which exposes the problem, but For example, with the same setup:
So changing either the output scale or the degradation factor can move More importantly, I tested the omitted intermediate row Snapping to a different scale may avoid a particular alignment, but it |
|
I will spin the CI on this since the change here isn't really computationally expensive and a potential improvement. @ammen99 ultimately has the decision though. |
|
I recorded a short direct capture to make the intermediate-buffer This is one continuous recording from the apple M2/asahi system Stock shows the magenta edge. Filling the omitted intermediate pixels In the failing run the intermediate target is 256x162 and the partial Since this happens in wayfire's intermediate blur rendering rather wayfire-blur-partial-repaint-asahi-m2.mp4 |
|
@dmrlsn Since you are able to reproduce this issue, I am curious to know if adjusting |
Very unlikely, this is about the internal blur algorithm, not how blur interacts with transparent areas. |
|
@dmrlsn I think I am starting to understand the issue. I assume it is because of these samples here: wayfire/plugins/blur/kawase.cpp Lines 29 to 32 in 4c34a7b This makes me wonder whether expanding by 1 pixel would be enough if you had Also, is this bug limited to the kawase algorithm? If so, we could expand the damage before calling |
|
I tested alpha_threshold=0.25 with the same 2560x1664 /scale 1.6 / I also tested the larger kawase offset you suggested: kawase_degrade=10, kawase_iterations= 2, kawase_offset=3.0 Stock still reproduces the artifact and the one-pixel guard still The issue is not limited to kawase either. I can reproduce the same gaussian_degrade=3, gaussian_iterations=10, gaussian_offset=2.0 and with: box_degrade=3, box_iterations=10, box_offset= 2.0 In both cases stock shows the magenta edge and the +1 guard removes so moving the expansion into kawase.cpp would not cover the gaussian For the current reproducer, +1 is also sufficient with kawase_offset= |
ammen99
left a comment
There was a problem hiding this comment.
Well, I am still not quite certain why the other suggestions didn't work out but I believe that this is a genuine issue, if this really improves blur then I don't see why we shouldn't merge it. And we have provided enough context in this PR so that if other people have similar issues in the future, they know where to look at. Thanks for the explanations and for this PR!
Fixes #3113.
Partial blur rendering only writes the current
blur_regioninto theintermediate buffer. A following blur pass can sample one pixel outside
that region, leaving the edge dependent on previous or undefined buffer
contents.
Expand the region by one pixel before scissoring and clip it to the
intermediate buffer size.
Tested on current master (
4c34a7bf) on an Apple M2 with Asahi/Mesa26.1.6. The magenta edge described in #3113 disappears with this change.
Also tested with Kawase, Gaussian and Box blur.