- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 105
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
Might get significantly better performance using scanx instead of image/vector #334
Comments
Thank you for your extensive work and benchmarks, and thanks for raising the issue here. I'm always looking for improving the performance of My first instinct would be to check if you reuse the rasterizer object to reuse its memory. Secondly, stroking involves "fixing" the resulting path using Thirdly, maybe you should compare lines only since all other path commands are flattened to that, unless your benchmark notices slow performance for those operations? Fourthly, maybe the tolerance/precision for flattening is tuned for more accuracy in one of the benchmarks, which creates significantly more line segments. It would be nice to see if we're comparing apples to apples by checking if the input paths are the exact same number of commands. You might checkout I'm sure you've already ruled out various problems as the benchmarks looked sophisticated, but would be nice to get your perspective before diving in. Regarding the float32 point, I agree that removing the struct would be better. I was looking at improving the way that paths are stored and have an idea that would save about ~50% of memory for storage. A second idea could be using generics to set the underlying type to float64 or float32 and save another ~50% of memory for low-precision applications. I'm not sure what the implications are with the many algorithms, some of which are tricky regarding floating point accuracy, but worth looking into. And regarding text use, I believe the current implementation is quite complete. The only thing lacking is handling fall-back fonts for missing glyphs. Is that what you're looking for, or do you believe something else is missing? Thanks again for the great work! EDIT: perhaps we should create a |
yep we reuse.
adding a
Our goal was to test "real world" rendering for our GUI, so this is that. It really is just a ton of calls to the RoundedRect which is just lines and arcs for the corners. We implement shadows using alpha blended versions of these rects. There may be something entirely perverse from a rasterizing perspective for how that works.
I had those at default levels: .1 for tolerance. I did play around with those and didn't see much diff.
The tricky thing with generics would be requiring a fully generic math library, and presumably then forgoing the ASM optimizations that are in place for those, which I assume are specific to 32 vs 64. All your existing tests pass OK with float32, but I did have to lower the testing tolerances a bit. But if Skia can get away with float32, then it seems like it might be reasonable enough overall. Regarding the basic issues with We set the clip boundaries for each render path to contain the thing being rendered, but all of the time seems to be in the profile_canvas_scanx.pdf |
You're right, I'm seeing a significant speedup for a test case while generating the exact same result (see commits above). In fact, running various resulting image sizes it looks that This is really surprising, given that EDIT: it would've been nice if there was a paper it was based on or some other reference... |
…see #334
I've added the |
I've switched to the scanx rasterizer. In the future we should improve its implementation and integrate better with |
Great! SIMD versions would be amazing! BTW, at some point I will also try to implement rasterization for WebGPU, which is our GPU backend in Cogent Core, perhaps going so far as to implement this framework in Go: https://github.com/linebender/vello I'll let you know when we get to it, so you can perhaps port it back to canvas as another backend. |
Great, vello in Go would be an amazing addition! I had done some preliminary work on this some years ago. What is needed is a tessellator to divide up the filled regions in triangles. Should not be too hard to do? I also wanted to merge signed-field shaders for quadratic/cubic beziers to make fonts look great at any size, this may be somewhat more difficult I imagine. Happy to know any progress you have! |
I did some benchmarks of a modified version of your rasterizer and found that, for our GUI-based workload with lots of rounded rectangles for buttons, that the https://pkg.go.dev/golang.org/x/image/vector that you use was 500 to 1000 times(!) slower than https://github.com/srwiley/scanx I replicated this using srwiley's ScanGV as well. I don't know if there is something fundamentally wrong in how we're using that rasterizer but it really was surprising how bad the performance is.
Full details are here: cogentcore/core#1453 (comment)
FWIW my impl of the scanx rasterizer is here: https://github.com/cogentcore/core/blob/87b8f776975cbc126dcbbd2922eb82083c0cebc1/paint/renderers/_canvasrast/rasterizer.go
Meanwhile, thank you for all the amazing work you've done on this package and Go graphics more generally! We are refactoring our rendering framework for the Cogent Core GUI to try to get better performance on the web and mobile devices, and somehow only recently came across this package. We have translated your extensive and impressive path library into
float32
and ourmath32
library link, and plan on adapting the other back ends and some of the text formatting code as well. Our need for math32 and other differences make it impossible to directly use your packages but we give you full credit in the relevant code! One thing I found useful was just making the Path type a[]float32
directly, instead of having it be a struct wrapper around that.The text was updated successfully, but these errors were encountered: