Commit 172fa0e
[MAPS3D-865] Make line-emissive-strength data-driven (#5075)
This PR makes the property `line-emissive-strength` data-driven.
Implemented for both GL JS and Native.
```
<public>
[MAPS3D-865] Make line-emissive-strength data-driven (#5075)
</public>
```
## Background
Making `line-emissive-strength` data-driven should allow merging road
layers in the Standard style as a performance optimization. More details
are in the ticket: https://mapbox.atlassian.net/browse/MAPS3D-865
## Draping support
During draping we must be able to accumulate the per-feature emissive
strength values from each layer, so that they can be used later when the
lighting is applied during the terrain/globe raster pass. For this we
have two approaches: **dual-source blending** and **MRT fallback**.
### Dual-source blending
Dual-source blending is fully compatible with our previous emissive
strength support where the emissive values are accumulated in the alpha
channel of the main color texture. The old approach applies emissive
strength as a constant alpha value for the blend mode, which means no
per-feature emissive strength is possible for draping. With dual-source
blending, we output the emissive strength value from the fragment shader
along with the color value, which are then blended together with
`Src1Alpha` blend factor.
Using dual-source blending is the optimal approach, since it doesn't
increase memory usage and has no performance penalty compared to our
previous approach. Unfortunately it's not available on every device, so
before we use it we must check that it's supported. This is done in
different ways depending on the platform.
**GL-JS:**
- Support for dual-source blending is checked using the WebGL extension
`WEBGL_blend_func_extended`
- Latest versions of Chrome and Safari support dual-source blending.
Firefox doesn't have support for it yet
**GL-Native:**
- OpenGL: Support for dual-source blending is checked using `glad` with
the extensions `GLAD_GL_ARB_blend_func_extended` and
`GLAD_GL_EXT_blend_func_extended`
- Metal: Support is checked by using GPU family information queried at
runtime similar to how it's done for occlusion queries
- Vulkan: Support is checked using physical device feature
`dualSrcBlend` queried at runtime
### MRT (multiple render targets) fallback
All of the platforms and devices that we support should support a
minimum of 4 color attachments for FBOs and we only need 2 for the MRT
fallback approach for data-driven emissive strength. The fallback mode
is only activated when dual-source blending is not available and when
the style has a layer with a data-driven `line-emissive-strength`
property. This is when a secondary color attachment is added to
offscreen textures that are used for draping using the format
`gfx::PixelFormat::R8`. In this mode, all of the layers that use
emissive strength accumulate it into the secondary color texture instead
of the alpha channel of the main color texture. These secondary color
textures are expected to increase memory usage of the draping pool by
25%.
### MRT support for Vulkan
I didn't want to make this PR any bigger than it already is, so it only
includes support for dual-source blending for Vulkan. MRT support for
Vulkan can be implemented as a follow-up PR.
### Render tests
To ensure that support for MRT attachments remains fully functional even
as more platforms start supporting dual-source blending, I added a new
render test flag `forceEmissiveFallback` to force render tests to use
the MRT fallback render path. In this way all platforms will run tests
for the MRT fallback approach even when dual-source blending is
available.
### Shell example
I added a Shell example for data-driven `line-emissive-strength`. By
using the example it is possible to use both dual-source blending (when
available) and MRT fallback. When the example is active it also shows
which mode is currently being used, so it is possible to check if a
particular device supports dual-source blending by running the Shell app
on it and enabling the example. The code for the Shell example is mostly
AI generated.
<img width="1358" height="960" alt="image"
src="https://github.com/user-attachments/assets/806de749-60cd-401b-b7b5-92c5b827c73f"
/>
## Performance considerations
The changes in this PR should not affect the performance of styles that
don't contain any layers with data-driven `line-emissive-strength`
property.
When a style does contain a layer with a data-driven
`line-emissive-strength` property:
**Without draping:**
- No issues here since the emissive strength is applied normally in the
fragment shader during immediate rendering
**With draping:**
- Dual-source blending:
- No extra memory used
- No expected performance decrease (benchmarks still needed)
- MRT fallback:
- Extra memory for draping pool (25% increase)
- Extra memory bandwidth needed for writing to multiple render targets.
For this render path we must write emissive values from **all layers**
to the secondary emissive attachment.
I tested loading and rendering performance using a style with reduced
number of road layers which is available here
https://mapbox.atlassian.net/browse/MAPS3D-865?focusedCommentId=534175
**Loading performance:**
Profiled using Xcode with an iPhone 15. I didn't see any clear
performance difference in my tests.
**Rendering performance:**
Tested with S22 Ultra, zoom 12, pitch 60 near Munich. 113 FPS with the
original style vs 117 FPS with the updated style using data-driven
`line-emissive-strength`.
cc @mapbox/gl-js
cc @mapbox/gl-native
[MAPS3D-865]:
https://mapbox.atlassian.net/browse/MAPS3D-865?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
cc @mapbox/maps-android
cc @mapbox/maps-ios
cc @mapbox/sdk-ci
---------
Co-authored-by: Changelog autocreator bot <[email protected]>
Co-authored-by: Kirill Kediarov <[email protected]>
GitOrigin-RevId: aac743c91adfe15e67295e27cc9ff4702d328d421 parent eea710c commit 172fa0e
File tree
5 files changed
+91
-27
lines changed- Sources/MapboxMaps/Annotations/Generated
- Tests/MapboxMapsTests
- Annotations/Generated
- Style/Generated/IntegrationTests
5 files changed
+91
-27
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 34 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments