-
Notifications
You must be signed in to change notification settings - Fork 143
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
Rendering glitches on path filling #23
Comments
Heh, I'm not parsing the transform properly; the The font glitches are a known issue, some numerical robustness issues I haven't gotten around to fixing yet. Thanks for your interest! |
Just discovered How where the benchmarks from the blog post performed? Merely run the CLI tool without any additional options? Given the tiger svg from this repo, my old RX 470 seems to be faster than a 1060, which seems odd. |
Yes, by running the cli tool. This tends not to trigger a "boost" mode, I've notice it run about 20% faster running with continuous presentation. Regarding relative performance, the code uses shared memory (LDS) extensively, which is considerably faster (relative to other metrics) on AMD than other cards. I think between those two things is probably explains it, though you always learn things when you explore deeply into performance measurement. |
Would you like to keep this issue open as source of information for others or rather close it? |
I'd like to work on this. If you have pointers to where the issues are, I'd appreciate it. |
This is a good starter issue - it probably won't require a lot of code to fix (and that will be likely localized to path_coarse.comp), but it does require some insight and understanding. The source of the glitch is a numerical inconsistency between two "orientation problems". One is to detect where the path segment crosses the top edge of a tile (that's "xray" on line 215 of current master), and the other is where it crosses the left edge ("y_edge" on line 234). The answer is reworking the slope calculation so that these two test are always consistent with each other. Obviously one thing that makes it a little tricky is that the segment can be vertical or horizontal, in which case the slope is infinite. I suggest taking a look at the Pathfinder codebase, as Patrick has changed it to use a similar algorithm (also inspired by RAVG) and has addressed the numerical robustness issues. Patrick might be able to point you to the relevant commit in the code if you don't easily find it yourself. Best of luck! |
I have some progress on this. The diff below empirically fixes all visible glitches from a setup where I carefully watch a slowly rotating tiger. The approach is sound in that the changes steer the intersection decisions away from inconsistencies. Unfortunately, the code is complicated enough that deficiencies are no longer obvious; I'm going to attempt a rewrite of the algorithm to tackle that.
|
Eliminates the precision loss of the subtraction in the sign(end.x - start.x) expression in kernel4. That's important for the next change that avoids inconsistent line intersections in path_coarse. Updates linebender#23 Signed-off-by: Elias Naur <[email protected]>
The previous attempt to fix inconsistent intersections because of floating point inaccuracy[0], missed two cases. The first case is that for top intersections with the very first row would fail the test tag == PathSeg_FillCubic && y > y0 && xbackdrop < bbox.z, specifically y is not larger than y0 when y0 has been clipped to 0. Fix that by re-introducing the min(p0.y, p1.y) < tile_y0 check that does work and is just as consistent. The second case is that the tracking left intersections in the [xray, next_xray] range of tiles may fail when next_xray is forced to last_xray, the final xray value. Fix that case by computing next_xray explicitly, before looping over the x tiles. The code is now much simpler. Updates linebender#23 [0] linebender@29cfb8b Signed-off-by: Elias Naur <[email protected]>
The previous attempt to fix inconsistent intersections because of floating point inaccuracy[0] missed two cases. The first case is that for top intersections with the very first row would fail the test tag == PathSeg_FillCubic && y > y0 && xbackdrop < bbox.z, specifically y is not larger than y0 when y0 has been clipped to 0. Fix that by re-introducing the min(p0.y, p1.y) < tile_y0 check that does work and is just as consistent. The second case is that the tracking left intersections in the [xray, next_xray] range of tiles may fail when next_xray is forced to last_xray, the final xray value. Fix that case by computing next_xray explicitly, before looping over the x tiles. The code is now much simpler. Updates linebender#23 [0] linebender@29cfb8b Signed-off-by: Elias Naur <[email protected]>
The previous attempt to fix inconsistent intersections because of floating point inaccuracy[0] missed two cases. The first case is that for top intersections with the very first row would fail the test tag == PathSeg_FillCubic && y > y0 && xbackdrop < bbox.z In particular, y is not larger than y0 when y0 has been clipped to 0. Fix that by re-introducing the min(p0.y, p1.y) < tile_y0 check that does work and is just as consistent. The second case is that the tracking left intersections in the [xray, next_xray] range of tiles may fail when next_xray is forced to last_xray, the final xray value. Fix that case by computing next_xray explicitly, before looping over the x tiles. The code is now much simpler. Updates linebender#23 [0] linebender@29cfb8b Signed-off-by: Elias Naur <[email protected]>
The previous attempt to fix inconsistent intersections because of floating point inaccuracy[0] missed two cases. The first case is that for top intersections with the very first row would fail the test tag == PathSeg_FillCubic && y > y0 && xbackdrop < bbox.z In particular, y is not larger than y0 when y0 has been clipped to 0. Fix that by re-introducing the min(p0.y, p1.y) < tile_y0 check that does work and is just as consistent. The second case is that the tracking left intersections in the [xray, next_xray] range of tiles may fail when next_xray is forced to last_xray, the final xray value. Fix that case by computing next_xray explicitly, before looping over the x tiles. The code is now much simpler. Updates linebender#23 [0] linebender@29cfb8b Signed-off-by: Elias Naur <[email protected]>
The previous attempt to fix inconsistent intersections because of floating point inaccuracy[0] missed two cases. The first case is that for top intersections with the very first row would fail the test tag == PathSeg_FillCubic && y > y0 && xbackdrop < bbox.z In particular, y is not larger than y0 when y0 has been clipped to 0. Fix that by re-introducing the min(p0.y, p1.y) < tile_y0 check that does work and is just as consistent. The second case is that the tracking left intersections in the [xray, next_xray] range of tiles may fail when next_xray is forced to last_xray, the final xray value. Fix that case by computing next_xray explicitly, before looping over the x tiles. The code is now much simpler. Finally, ensure that xx0 and xx1 doesn't overflow the allocated number of tiles by clamping them *after* setting them. Adjust xx0 to include xray, just as xx1 is adjusted; I haven't seen corruption without it, but it's not obvious xx0 always includes xray. While here, replace a "+=" on a guaranteed zero value to just "=". Updates linebender#23 [0] linebender@29cfb8b Signed-off-by: Elias Naur <[email protected]>
The previous attempt to fix inconsistent intersections because of floating point inaccuracy[0] missed two cases. The first case is that for top intersections with the very first row would fail the test tag == PathSeg_FillCubic && y > y0 && xbackdrop < bbox.z In particular, y is not larger than y0 when y0 has been clipped to 0. Fix that by re-introducing the min(p0.y, p1.y) < tile_y0 check that does work and is just as consistent. Add similar check, min(p0.x, p1.x) < tile_x0, for deciding when to clip the segment to the left edge (but keep consistent xray check for deciding left edge *intersections*). The second case is that the tracking left intersections in the [xray, next_xray] range of tiles may fail when next_xray is forced to last_xray, the final xray value. Fix that case by computing next_xray explicitly, before looping over the x tiles. The code is now much simpler. Finally, ensure that xx0 and xx1 doesn't overflow the allocated number of tiles by clamping them *after* setting them. Adjust xx0 to include xray, just as xx1 is adjusted; I haven't seen corruption without it, but it's not obvious xx0 always includes xray. While here, replace a "+=" on a guaranteed zero value to just "=". Updates linebender#23 [0] linebender@29cfb8b Signed-off-by: Elias Naur <[email protected]>
The previous attempt to fix inconsistent intersections because of floating point inaccuracy[0] missed two cases. The first case is that for top intersections with the very first row would fail the test tag == PathSeg_FillCubic && y > y0 && xbackdrop < bbox.z In particular, y is not larger than y0 when y0 has been clipped to 0. Fix that by re-introducing the min(p0.y, p1.y) < tile_y0 check that does work and is just as consistent. Add similar check, min(p0.x, p1.x) < tile_x0, for deciding when to clip the segment to the left edge (but keep consistent xray check for deciding left edge *intersections*). The second case is that the tracking left intersections in the [xray, next_xray] range of tiles may fail when next_xray is forced to last_xray, the final xray value. Fix that case by computing next_xray explicitly, before looping over the x tiles. The code is now much simpler. Finally, ensure that xx0 and xx1 doesn't overflow the allocated number of tiles by clamping them *after* setting them. Adjust xx0 to include xray, just as xx1 is adjusted; I haven't seen corruption without it, but it's not obvious xx0 always includes xray. While here, replace a "+=" on a guaranteed zero value to just "=". Updates linebender#23 [0] linebender@29cfb8b Signed-off-by: Elias Naur <[email protected]>
The previous attempt to fix inconsistent intersections because of floating point inaccuracy[0] missed two cases. The first case is that for top intersections with the very first row would fail the test tag == PathSeg_FillCubic && y > y0 && xbackdrop < bbox.z In particular, y is not larger than y0 when y0 has been clipped to 0. Fix that by re-introducing the min(p0.y, p1.y) < tile_y0 check that does work and is just as consistent. Add similar check, min(p0.x, p1.x) < tile_x0, for deciding when to clip the segment to the left edge (but keep consistent xray check for deciding left edge *intersections*). The second case is that the tracking left intersections in the [xray, next_xray] range of tiles may fail when next_xray is forced to last_xray, the final xray value. Fix that case by computing next_xray explicitly, before looping over the x tiles. The code is now much simpler. Finally, ensure that xx0 and xx1 doesn't overflow the allocated number of tiles by clamping them *after* setting them. Adjust xx0 to include xray, just as xx1 is adjusted; I haven't seen corruption without it, but it's not obvious xx0 always includes xray. While here, replace a "+=" on a guaranteed zero value to just "=". Updates linebender#23 [0] linebender@29cfb8b Signed-off-by: Elias Naur <[email protected]>
The previous attempt to fix inconsistent intersections because of floating point inaccuracy[0] missed two cases. The first case is that for top intersections with the very first row would fail the test tag == PathSeg_FillCubic && y > y0 && xbackdrop < bbox.z In particular, y is not larger than y0 when y0 has been clipped to 0. Fix that by re-introducing the min(p0.y, p1.y) < tile_y0 check that does work and is just as consistent. Add similar check, min(p0.x, p1.x) < tile_x0, for deciding when to clip the segment to the left edge (but keep consistent xray check for deciding left edge *intersections*). The second case is that the tracking left intersections in the [xray, next_xray] range of tiles may fail when next_xray is forced to last_xray, the final xray value. Fix that case by computing next_xray explicitly, before looping over the x tiles. The code is now much simpler. Finally, ensure that xx0 and xx1 doesn't overflow the allocated number of tiles by clamping them *after* setting them. Adjust xx0 to include xray, just as xx1 is adjusted; I haven't seen corruption without it, but it's not obvious xx0 always includes xray. While here, replace a "+=" on a guaranteed zero value to just "=". Updates linebender#23 [0] linebender@29cfb8b Signed-off-by: Elias Naur <[email protected]>
With great interest, I read your blog post on the new code in
piet-gpu
and gave it a try on my Radeon RX 470 GPU:I got the example images from:
[1] http://w3.impa.br/~diego/projects/GanEtAl14/
It would seem there are a few rendering glitches, most notably:
Please note, I used the default
radav
driver on ArchLinux. There is an experimental new shader backend, which is faster, but has the same output (or at least I didn't notice any difference). It can be activated by exportingexport RADV_PERFTEST=aco
.Also, there is another vulkan driver for AMD, namely
amdvlk
. That seems to be a little slower for most operations, but the output seems to be the same as well.How where the benchmarks from the blog post performed? Merely run the CLI tool without any additional options? Given the tiger svg from this repo, my old RX 470 seems to be faster than a 1060, which seems odd.
paper-1
At scale=2
tiger
The tiger from [1], however, is upside-down as well.
paris-30k
At scale=2
The text was updated successfully, but these errors were encountered: