Skip to content

perf: add Canvas.drawVertices render pathway for PolygonLayer & fix bundled drawing#1800

Merged
JaffaKetchup merged 28 commits intomasterfrom
polygon-draw-vertices
Feb 13, 2024
Merged

perf: add Canvas.drawVertices render pathway for PolygonLayer & fix bundled drawing#1800
JaffaKetchup merged 28 commits intomasterfrom
polygon-draw-vertices

Conversation

@JaffaKetchup
Copy link
Copy Markdown
Member

@JaffaKetchup JaffaKetchup commented Jan 15, 2024

Canvas.drawVertices is a low level, very performant, canvas method. See https://www.youtube.com/watch?v=pD38Yyz7N2E for more info.

Will use https://pub.dev/packages/dart_earcut, and based roughly off 22b6cd3.


See documentation at https://docs.fleaflet.dev/v/v7-beta/layers/polygon-layer#performant-rendering-with-drawvertices-internal-disabled.

I've seen mixed results in terms of performance. It seems to generally greatly increase (up to 2x) performance on the GeoJson example (which I've also updated in this PR), with simplification enabled. However, with simplification disabled, performance has tanked - the triangulation algorithm simply isn't fast enough for all 138k points.

For this reason, and also the other considerations (mentioned within docstrings and on the docs site), I've disabled it by default.

Interestingly, from some limited testing on my budget Android device, the Impeller engine seems to not break things - and in fact, improves it a fair amount! We'll wait and see how well it works when it's finished. I'm in fact wondering whether the improvements Impeller gives dwarfs the improvements here, but more testing at another point is needed to determine that - and it wouldn't necessarily be a bad thing :D.

@JaffaKetchup JaffaKetchup changed the title perf: improve PolygonLayer performance using [Canvas.drawVertices](https://www.youtube.com/watch?v=pD38Yyz7N2E) perf: improve PolygonLayer performance using Canvas.drawVertices Jan 15, 2024
@josxha josxha added this to the v7.0 milestone Jan 16, 2024
@JaffaKetchup JaffaKetchup force-pushed the polygon-draw-vertices branch from 4b78651 to 8766aa1 Compare January 20, 2024 22:08
@mdmm13

This comment was marked as resolved.

@JaffaKetchup

This comment was marked as resolved.

@mdmm13

This comment was marked as resolved.

@JaffaKetchup JaffaKetchup force-pushed the polygon-draw-vertices branch from c27181a to 8766aa1 Compare January 22, 2024 21:35
@JaffaKetchup JaffaKetchup marked this pull request as ready for review January 31, 2024 12:53
Modified types and meanings of `performantRendering` flags
Improved documentation on `performantRendering` flags
@JaffaKetchup
Copy link
Copy Markdown
Member Author

I believe this is now in a reviewable and (hopefully) usuable state!

As well as the normal code reviews, I'd appricate any feedback from anyone else (ping @mdmm13)! See https://docs.fleaflet.dev/v/v7-beta/getting-started/installation#from-github.com for installation instructions from GitHub, and docs at https://docs.fleaflet.dev/v/v7-beta/layers/polygon-layer#performant-rendering-drawvertices for more info.

Updated example app dependencies
@ignatz
Copy link
Copy Markdown
Contributor

ignatz commented Feb 2, 2024

Let's move vector tile related performance discussions to greensopinion/flutter-vector-map-tiles#120.

Just quickly responding to your points...

@greensopinion - you wrote a while ago that aside from greensopinion/flutter-vector-map-tiles#93 (comment), that raster would be the main bottleneck and that greensopinion/flutter-vector-map-tiles#120 (comment) is the way to go. Is that still accurate based on your experiments with the latter?

I know you didn't ask me but I just looked into it. Raster performance is certainly the bottleneck. Though there's quite a bit of optimization opportunities. Just with draw batching I more than halfed raster times while playing around with it in the morning (see the other thread). drawVertices, Impeller, and zoom-level based geometry simplifications would all help to bring them down further.

EDIT: I just implemented drawVertices drawing. It does help but most of the raster time is spent on lines. So it's not as pronounced as for the polygon layer. I'll update above thread in case you wanna see a screencast.

@JaffaKetchup, @ignatz, @josxha from your experiments with drawVertices, can you tell/guess whether this could be enough to get vector performance up drastically?

I'm pretty sure that with some investment the vector performance could be stellar. I don't see why it couldn't. Web clearly demonstrates that vector renders are viable.

Alternatives like flutter_gpu (saw some great news a few weeks back!) and Impeller may be quite some time into the future ... which may also be the answer. Just trying to figure out if drawVertices might solve it in the meantime.

I generally like the flutter GPU layering proposal, though it will be years before this will be somewhat available and portable. When working with the flutter folks, I was promised Impeller in 2019 and it launched in 2023 for iOS only. Besides if you just wanna draw into a texture using OpenGL there's also https://pub.dev/packages/three_dart (looks a bit abandoned)

@JaffaKetchup
Copy link
Copy Markdown
Member Author

See flutter/flutter#131345 (comment) for some performance comparisons.

@josxha
Copy link
Copy Markdown
Contributor

josxha commented Feb 4, 2024

@JaffaKetchup I pushed my attempt with drawVertices here: https://github.com/josxha/flutter_map/tree/draw-vertices

Seeing the current discussions in flutter/flutter#131345 (comment) I'd be interessted to see some benchmarks here (don't have a device that supports impeller myself 😅).

As said I think it's really not compatible with the current PolygonLayer because mine is a completely bare bone implementation. It has basically no of the features the current PolygonLayer has. The idea was to see how much peformance is possible
by Skia and without other polygon optimizations like simplification or even the earcut algorithm (althrough the basic method I use to create vertices is probably cheaper).
It is focussed on these principles:

  • use as few calls on the cancas as possible to avoid an expensive back and forth with Skia
  • use as far and as efficient as possible typed data to avoid the creation of ephemeral objects
  • avoid records because of their performance penalty
  • break down the build logic to O(n)
  • use simple caching

I hope this helps. (:

@JaffaKetchup
Copy link
Copy Markdown
Member Author

JaffaKetchup commented Feb 5, 2024

I've tested out your method @josxha. Whilst the triangulation algorithm doesn't really work quite right (orange is yours, dark is real), it is a whole lot faster (tested with Skia on desktop).

image

I think it shows what the Flutter engineer in the other thread was saying: the majority of the time comes from drawing the outlines. At the same time, as my testing showed, drawVertices does appear to be slower in Impeller (at least with Vulkan) than Skia.

I think this PR will not be the last one, but I'm not sure we should let these experiments block this - we can always come back/add more improvements (and I/we will quite soon, I'm sure :D).

@JaffaKetchup
Copy link
Copy Markdown
Member Author

I've just updated the example to allow for the thickness of the border line to be more carefully fine-tuned (None, 1px, 4px, 9px), to better demonstrate the performance falloff.

@JaffaKetchup
Copy link
Copy Markdown
Member Author

I just found quite a major bug in the renderHashCode that I introduced. I was attempting to use the holePointsList in it, which of course (a) isn't important, and (b) will never result in the same hash. This meant every polygon and border was being drawn individually, and batching was essentially broken. I've resolved the issue, and there's been a massive performance improvement.

@JaffaKetchup JaffaKetchup changed the title perf: improve PolygonLayer performance using Canvas.drawVertices perf: improve PolygonLayer performance using Canvas.drawVertices & fix bundled drawing Feb 6, 2024
@JaffaKetchup JaffaKetchup changed the title perf: improve PolygonLayer performance using Canvas.drawVertices & fix bundled drawing perf: add Canvas.drawVertices render pathway for PolygonLayer & fix bundled drawing Feb 6, 2024
Copy link
Copy Markdown
Contributor

@josxha josxha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added my thoughts as comments, let me know what you think.
Other than that I think it looks good to me.

Comment thread example/lib/pages/polygon_perf_stress.dart
Comment thread example/lib/pages/polygon_perf_stress.dart Outdated
Comment thread example/lib/pages/polygon_perf_stress.dart
Comment thread example/lib/pages/polygon_perf_stress.dart
Comment thread example/lib/pages/polygon_perf_stress.dart Outdated
Comment thread lib/src/layer/polygon_layer/painter.dart
Comment thread lib/src/layer/polygon_layer/polygon.dart Outdated
Comment thread lib/src/layer/polygon_layer/polygon_layer.dart
Comment thread lib/src/layer/polygon_layer/polygon_layer.dart Outdated
Comment thread lib/src/layer/polyline_layer/painter.dart
Removed feature level `Polygon.performantRendering`
Minor improvements to example app
Improved documentation
Made review required changes
@JaffaKetchup
Copy link
Copy Markdown
Member Author

I've also changed the name from performantRendering to useAltRendering, and updated the documentation, to remove the quick assumption that it always results in better performance.

@JaffaKetchup JaffaKetchup requested a review from josxha February 12, 2024 23:40
@mziadd
Copy link
Copy Markdown

mziadd commented Feb 13, 2024

Using

filledPath.reset();
borderPath.reset();

on : image

is better than creating new Path each time, please see this : flutter/flutter#83872

Copy link
Copy Markdown
Contributor

@josxha josxha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one expensive check, other than that we should be good to go.

Comment thread lib/src/layer/polygon_layer/projected_polygon.dart
@JaffaKetchup JaffaKetchup merged commit f9d37df into master Feb 13, 2024
@JaffaKetchup JaffaKetchup deleted the polygon-draw-vertices branch February 13, 2024 11:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants