Symbol SDF Performance Optimization: Render Halo and Glyph in a Single Pass (-40% Time Reduction)#7436
Conversation
…lsl [FIX] expected images in halo test-render
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7436 +/- ##
=======================================
Coverage 92.77% 92.77%
=======================================
Files 289 289
Lines 24017 24023 +6
Branches 5100 5103 +3
=======================================
+ Hits 22282 22288 +6
Misses 1735 1735 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Now it renders the halo in 2 passes only if there is no overlap between glyph halos (it computes the overlap using text-letter-spacing and halo width). |
Hello,
Thank you for considering my PR.
Issue
Text is rendered as SDF symbols, with each glyph represented as a separate symbol. To enhance contrast, a white halo is often added around the text. When a halo is present, rendering occurs in two passes: the first pass draws the halo, and the second pass renders the glyphs themselves. Both passes use the same shader,
symbol_SDF.glsl, with a uniform variable indicating whether the current pass is for the halo or the glyph.This means the fragment shader runs for all pixels within the glyph, including those that are fully transparent. The vertex shader is also executed for each glyph (4 times if it is represented by a quad).
Proposed solution
Both the glyph and halo values are computed within the fragment shader, and the final composited result of the text and halo is rendered in a single pass. This approach reduces the number of shader executions by half.
Here is a screenshot portion of this example: http://localhost:9966/test/examples/filter-symbols-by-text-input.html

Now we enable the overdraw inspector by running

map.showOverdrawInspector=truein the JS console. This animated GIF shows with and without the optimization. There is less overdraw for glyphs with a halo:Benchmarks
There is no benchmark for rendering SDF symbols with a halo (
LayerSymbolbenchmark renders characters without a halo).This PR introduces a new benchmark for that,
LayerSymbolWithHalo. Here are the results:Before:
Google Chrome, Macbook Pro M4 Max:
4.47msGoogle Chrome, Macbook Pro M4 Max with swiftshaders (hardware acceleration disabled):
335msAfter:
Google Chrome, Macbook Pro M4 Max:
3.13ms(30% time reduction)Google Chrome, Macbook Pro M4 Max with swiftshaders (hardware acceleration disabled):
186ms(44% time reduction - it shoud theoretically tend to 50% with even crappier GPU)Tests
npm run test-renderruns exactly as before. I just had to update the expected images for the halo tests.Before, the expected images only had the halo rendered.
With this change, it is not possible to render only the halo. We need to render the glyph + the halo.
Misc
No related issues.
This PR does not include any visual changes and does not require additional tests.
Launch Checklist
CHANGELOG.mdunder the## mainsection.