Mapbox-gl-native: Tiles not rendered correctly

Created on 17 Jul 2017  Â·  9Comments  Â·  Source: mapbox/mapbox-gl-native

Platform: Android
Mapbox SDK version: 5.1.0

screen shot 2017-07-17 at 11 11 11 am

screen shot 2017-07-17 at 11 10 29 am

  • Reproducible in Pixel XL running Android O

It seems to be due to the tilt maxed out at 60 degrees.

cc/ @cammace

Android Core

Most helpful comment

This issue is the same as #962 and #4442: We're exhausting the 8 bit stencil buffer when assigning clipping IDs. We don't normally run into this issue, but using the navigation SDK exacerbates this bug in the following way:

  • We use a high pitch, which leads to more tiles being loaded, thus requiring more bits.
  • We are typically showing the map at a high zoom level > 16. Given that our vector tile sources are maxing out at z16, we continue to render z16 tiles, except we're overzooming them.
  • When selecting a destination, we mark it with an annotation. This uses the Annotations API, which is a separate source + layer. The annotation tile source is not restricted to z16, so when looking at the map at z17, we show the regular z16 vector tiles, and the z17 annotation tiles. This juxtaposition of different tiles means that we can't reuse the same clip IDs for the annotation tiles and have to generate new ones, which leads to the overflow.

When following the strategies outlined above, it's possible to reproduce this bug on desktop as well:

screen shot 2017-10-13 at 15 34 26

There are a few mitigation strategies that we could use:

  • [x] Currently, our annotation tile source doesn't have any zoom level restriction: https://github.com/mapbox/mapbox-gl-native/blob/2166b8577b4bd2812d504ceb31b6c2af243de8f5/src/mbgl/annotation/render_annotation_source.cpp#L41
    We could change this so that we only generate annotation tiles from z0–16. Using z16 is sufficient precision for annotations. However, there's no guarantee that the other tile layers are also going to z16. With a tile source that only goes to z15 for example, we'd still see the same effect. This means limiting the annotation tile source to z16 is only a temporary workaround. Ticketed in https://github.com/mapbox/mapbox-gl-native/issues/10197.
  • [ ] We should reduce the number of tiles we're rendering when the map is tilted. In particular tiles in the upper half of the screen have too much precision anyway. This is ticketed in https://github.com/mapbox/mapbox-gl-native/issues/9037.
  • [x] In this particular case, we're using symbol layers only, and those layers don't require clipping IDs to be generated to begin with. We could either split up the Annotation tile source into a symbol and a non-symbol source, so that merely using symbol layers won't generate clipping IDs. A more robust and generic approach would be to collect the actual tile IDs from the various layers that need clipping instead of collecting all tiles that a source has loaded. This approach would also avoid generating clipping IDs for other tile sources that are only used for symbol/non-clipped layers. Ticketed in https://github.com/mapbox/mapbox-gl-native/issues/10198.
  • [ ] Instead of rendering all clipping masks before starting to render layers, we could switch to a dynamic approach that renders clipping masks to the stencil buffer just in time, and can also reset the stencil buffer when we are overflowing. A simpler, hard-coded fix could be to create an entirely separate stencil buffer for annotation layers. Annotation layers are typically last.
  • [ ] Optimize clipping ID generation: tiles with different zoom levels at the viewport boundary can typically share the same clipping ID since the part that wouldn't be shared is outside of the viewport
  • [ ] [Remove stencil-buffer based clipping altogether.](https://github.com/mapbox/mapbox-gl-native/issues/229) This is a long term project and involves:

    • Clipping geometry to tile boundaries before adding it to the OpenGL buffers

    • For lines, don't render caps on a clipped end

    • For polygons, don't render the antialiasing outline for clipped edges

    • Ensure that rendering parent tiles over child tiles never happens (i.e. render 4 child tiles or 1 parent tile), or that the parent tile geometry is properly clipped to just the part that isn't covered by children

All 9 comments

For reference, this is wider spread than just a Pixel XL. I see this every day on my Nexus 5x running Android 7.

cc @kkaefer

Can reproduce on my OnePlus 3T, Android 7.1.1

screenshot_20170828-115720
screenshot_20170828-131220
screenshot_20170828-132353

@ericrwolfe, @daniel-j-h Can you please report the exact device models? You can find it by going to Settings app, "About phone" (or similar), typically at the bottom. Look for something like "Model number". Sometimes it's also hidden in submenus like "Regulatory information".

Knowing the exact model (not serial) is important because some phones that are marketed under the same name use different chips internally, e.g. there are ~10 different versions of the Samsung Galaxy S3 that use vastly different chips by different manufacturers.

Model Number

ONEPLUS A3003

There's no model number in the regular settings for the Nexus 5X, it just says:

Model: Nexus 5x
Android version: 7.1.2

However, tapping on regulatory labels it lists:

Model: LG-H790

Seeing this on @danesfeder's Nexus 6P (Android O).

@cammace and @danesfeder say that this is a problem on every Android device they've used so far.

As a workaround in the drop-in navigation SDK UI, we've tried reducing the pitch to 50° and 45°, and while the issue becomes less frequent at a lower pitch, it still occurs in regular driving.

I've added a new branch https://github.com/mapbox/mapbox-gl-native/tree/android-v5.1.0-route-demo which consist of android-v5.1.0 tag + my cherry-picked commit ce8d4651fd0243486f886123b32a1fb91abc025f which adds a simple demo route to the GLFW app. It turns out that the demo route (with tilt set to 60 degrees) doesn't show the rendering artifacts seen above.

This leads me to believe it is either an issue on the Android-to-GL-Native code or a device-specific issue.

This issue is the same as #962 and #4442: We're exhausting the 8 bit stencil buffer when assigning clipping IDs. We don't normally run into this issue, but using the navigation SDK exacerbates this bug in the following way:

  • We use a high pitch, which leads to more tiles being loaded, thus requiring more bits.
  • We are typically showing the map at a high zoom level > 16. Given that our vector tile sources are maxing out at z16, we continue to render z16 tiles, except we're overzooming them.
  • When selecting a destination, we mark it with an annotation. This uses the Annotations API, which is a separate source + layer. The annotation tile source is not restricted to z16, so when looking at the map at z17, we show the regular z16 vector tiles, and the z17 annotation tiles. This juxtaposition of different tiles means that we can't reuse the same clip IDs for the annotation tiles and have to generate new ones, which leads to the overflow.

When following the strategies outlined above, it's possible to reproduce this bug on desktop as well:

screen shot 2017-10-13 at 15 34 26

There are a few mitigation strategies that we could use:

  • [x] Currently, our annotation tile source doesn't have any zoom level restriction: https://github.com/mapbox/mapbox-gl-native/blob/2166b8577b4bd2812d504ceb31b6c2af243de8f5/src/mbgl/annotation/render_annotation_source.cpp#L41
    We could change this so that we only generate annotation tiles from z0–16. Using z16 is sufficient precision for annotations. However, there's no guarantee that the other tile layers are also going to z16. With a tile source that only goes to z15 for example, we'd still see the same effect. This means limiting the annotation tile source to z16 is only a temporary workaround. Ticketed in https://github.com/mapbox/mapbox-gl-native/issues/10197.
  • [ ] We should reduce the number of tiles we're rendering when the map is tilted. In particular tiles in the upper half of the screen have too much precision anyway. This is ticketed in https://github.com/mapbox/mapbox-gl-native/issues/9037.
  • [x] In this particular case, we're using symbol layers only, and those layers don't require clipping IDs to be generated to begin with. We could either split up the Annotation tile source into a symbol and a non-symbol source, so that merely using symbol layers won't generate clipping IDs. A more robust and generic approach would be to collect the actual tile IDs from the various layers that need clipping instead of collecting all tiles that a source has loaded. This approach would also avoid generating clipping IDs for other tile sources that are only used for symbol/non-clipped layers. Ticketed in https://github.com/mapbox/mapbox-gl-native/issues/10198.
  • [ ] Instead of rendering all clipping masks before starting to render layers, we could switch to a dynamic approach that renders clipping masks to the stencil buffer just in time, and can also reset the stencil buffer when we are overflowing. A simpler, hard-coded fix could be to create an entirely separate stencil buffer for annotation layers. Annotation layers are typically last.
  • [ ] Optimize clipping ID generation: tiles with different zoom levels at the viewport boundary can typically share the same clipping ID since the part that wouldn't be shared is outside of the viewport
  • [ ] [Remove stencil-buffer based clipping altogether.](https://github.com/mapbox/mapbox-gl-native/issues/229) This is a long term project and involves:

    • Clipping geometry to tile boundaries before adding it to the OpenGL buffers

    • For lines, don't render caps on a clipped end

    • For polygons, don't render the antialiasing outline for clipped edges

    • Ensure that rendering parent tiles over child tiles never happens (i.e. render 4 child tiles or 1 parent tile), or that the parent tile geometry is properly clipped to just the part that isn't covered by children

Was this page helpful?
0 / 5 - 0 ratings