Fix depth/stencil state for is3D drawables in layer groups without stencil tiles#4378
Open
Kotelberg wants to merge 4 commits into
Open
Fix depth/stencil state for is3D drawables in layer groups without stencil tiles#4378Kotelberg wants to merge 4 commits into
Kotelberg wants to merge 4 commits into
Conversation
Drawable::draw skips depth-stencil setup for is3D drawables, expecting the layer group to bind the 3D depth state. TileLayerGroup only detected 3D features when stencil tiles were present, so is3D custom-drawable geometry rendered with no depth test at all.
Same gap as the Metal fix: DrawableGL::draw skips stencil setup for is3D drawables, expecting the layer group to handle it, but TileLayerGroupGL only detected 3D features when stencil tiles were present. is3D custom-drawable geometry therefore inherited the previous layer's tile-clip stencil state and all its fragments were discarded (cube invisible on Android GL).
Contributor
Bloaty Results 🐋Compared to main Full report: https://maplibre-native.s3.eu-central-1.amazonaws.com/bloaty-results/pr-4378-compared-to-main.txtCompared to d387090 (legacy) Full report: https://maplibre-native.s3.eu-central-1.amazonaws.com/bloaty-results/pr-4378-compared-to-legacy.txt |
Contributor
|
Benchmark Results ⚡ Full report: https://maplibre-native.s3.eu-central-1.amazonaws.com/benchmark-results/pr-4378-compared-to-main.txt |
Contributor
Bloaty Results (iOS) 🐋Compared to main Full report: https://maplibre-native.s3.eu-central-1.amazonaws.com/bloaty-results-ios/pr-4378-compared-to-main.txt |
louwers
reviewed
Jul 7, 2026
|
|
||
| ### 🐞 Bug fixes | ||
|
|
||
| - Fix missing depth/stencil render-group state for 3D drawables in layer groups without stencil tiles (previously: Metal rendered without depth, OpenGL discarded all fragments). |
Member
There was a problem hiding this comment.
Please add it under a new ## main heading and link the PR.
louwers
reviewed
Jul 7, 2026
| ## 6.27.0 | ||
|
|
||
| - Implement ambient cache for PMTiles sources ([#4290](https://github.com/maplibre/maplibre-native/pull/4290)). | ||
| - Fix missing depth/stencil render-group state for 3D drawables in layer groups without stencil tiles (previously: Metal rendered without depth, OpenGL discarded all fragments). |
Member
There was a problem hiding this comment.
Please add it under a new ## main heading and link the PR.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Layer groups that contain
is3Ddrawables normally derive their depth (Metal) and stencil (GL) render state from the group's stencil tiles. That derivation was gated behind a check for non-empty stencil tiles, so when a group hadis3Ddrawables but no stencil tiles at all - for example, afill-extrusiongroup whose visible tiles happen to produce no stencil clipping work - the group state was never computed, and the per-drawable depth/stencil state that depends on it was never applied.The failure mode differs by backend:
Both are silent failures - no errors or warnings, the layer just renders incorrectly or not at all, and only when this specific combination (is3D drawables, empty stencil tiles) occurs.
Repro
Any style with a
fill-extrusionlayer whose tiles produce no stencil work in the same layer group reproduces this. It's easiest to hit with a 3D buildings layer on the Drawable renderer: as soon as the visible tile set for that group contains no tiles needing stencil clipping, the group's depth/stencil state is skipped and the symptoms above appear (no depth test on Metal, fully discarded fragments on GL).There is no existing automated test harness that exercises this specific layer-group/tile combination (a layer group with
is3Ddrawables and zero stencil tiles), so this PR does not add a new automated test for it. I'd welcome guidance from reviewers on where such a test would best fit - it likely needs a render/gfx test that can construct a layer group withis3Ddrawables and an empty stencil-tile set for the target renderer.Fix
The root cause was that group-level depth/stencil state was computed inside the same conditional branch as the stencil-tiles-non-empty check, so the two were coupled when they shouldn't be:
is3D-derived state should always be computed for a group that hasis3Ddrawables, while the stencil-tile-derived (stencil3d) state should stay gatedon stencil tiles actually being present.
This is split into two commits, one per backend, since each backend's state-tracking code is independent:
src/mbgl/mtl/tile_layer_group.cpp): move theis3D/depth-state detection out of the stencil-tiles-non-empty gate so the group's depth state is computed whenever the group hasis3Ddrawables, independent of whether it has stencil tiles. Thestencil3dcomputation remains gated on stencil tiles being present, since that state genuinely only applies when there's stencil work to do.src/mbgl/gl/layer_group_gl.cpp): the same restructuring for the GL backend -is3Ddetection moves outside the stencil-tiles gate so the group's stencil state gets explicitly (re-)applied foris3Ddrawables even when there are no stencil tiles, instead of leaving a stale stencil configuration in place.A third commit adds changelog entries for both platforms (
platform/ios/CHANGELOG.md,platform/android/CHANGELOG.md) describing the fix.Testing
mbgl-test-runnersuite: 976 of 988 tests executed (12 filtered, 4 disabled), 974 passed. The only 2 failures (MapSnapshotter.setStyleURL,MapSnapshotter.annotation) are pre-existing and reproduce identically on a cleanupstream/maincheckout with no changes applied — this PR introduces no new failures and no regressions.