servo / pathfinder

A fast, practical GPU rasterizer for fonts and vector graphics
Apache License 2.0
3.6k stars 201 forks source link

Artifact when rendering large numbers of overlapping paths #405

Open alec-deason opened 4 years ago

alec-deason commented 4 years ago

I'm seeing artifacts when rendering scenes with large numbers of paths that overlap. It looks like it's related to the renderer's tiles somehow but it isn't strictly a paths per tile issue (see the third image). Here's the roof from the canvas_minimal example drawn on top of itself thousands of times:

screenshot

Obviously that's a pathological case but the artifacts start to show up with a much smaller number of overlaps (30 in this case):

screenshot

I'm seeing it in real use as well where complex objects are drawn on top of other paths:

screenshot

The bottom half of the screen in that example should be solid black but instead has lines of sky color showing through. That also shows the artifact in tiles which don't actually contain a large number of paths, like the ground on the right edge where there should just be two paths overlapping, one for the sky and one for the ground.

The code I used to produce the top two images: https://gist.github.com/alec-deason/2518dfce805c8222ab96c7c336336555

The only issue I could find that looks similar is the lines shown here: https://github.com/servo/pathfinder/issues/284#issuecomment-597564528_

I'm seeing this in both the GL and WebGL renderers on an Intel GPU on Linux and latest commit to pathfinder.

alec-deason commented 4 years ago

Sorry, I mispoke in the description. The sky in the last picture is not a path, it's just the clear color. So what's showing through the ground is the clear color not another path. That seems like it might be an important distinction.

pcwalton commented 4 years ago

Yeah, the problem is that when overflow the mask texture the resizing is currently buggy for one frame (that's the first and third images).

alec-deason commented 4 years ago

Oh, lovely. If I render a second time the worst of the artifacts do indeed go away. I still see the faint vertical lines in the second example but that isn't actually a problem in my use case.

Is there a way to preallocate if I know what I'm going to need? Skimming through the code, I don't see anything obvious.

pcwalton commented 4 years ago

It's impossible to predict how big the textures are. We just need to fix the bug.

alec-deason commented 4 years ago

Ok, makes sense. Thanks.

pcwalton commented 4 years ago

This is the D3D11 mode, right?

alec-deason commented 4 years ago

I was requesting a GL3.0 context from surfman, which I think puts me in D3D10. I just tried it again requesting a GL4.0 context and see the same artifacts.

pcwalton commented 4 years ago

https://github.com/servo/pathfinder/pull/418 fixes the biggest problems here. 1-character fix :)

The remaining issue with the 1-pixel-wide vertical lines seems to be caused by accumulation of floating-point error. I had worried that it indicated a fundamental problem with the lookup table approach for area, but I don't think it does, because if it did it wouldn't be a vertical line and would manifest itself only with lines of a certain slope, rather than all lines. So it's probably some subtle bug, not something fundamental.

alec-deason commented 4 years ago

That's the best kind of fix. And it resolves the main issue for me. Thanks!