Compare commits

...

89 Commits

Author SHA1 Message Date
tei
bf7f6193e0 release: finalize unified particle.22
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 16:17:29 +09:00
tei
7cfad1c72f build(release): pin built source and correct SwiftPM RN dependency note
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 16:13:30 +09:00
tei
ea5bd393c6 release: prepare unified particle.22
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 14:08:10 +09:00
tei
40b79764ae build(release): support 13.6.1 v22 and RN 11.5.0 version lock 2026-10-09 14:07:18 +09:00
tei
69922b795a docs(android): close STEP-106 FZG T2 regression PASS
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 13:17:29 +09:00
tei
23f7b8a4d7 docs(android): record T2 old-version reproduction and pending rebuild gate
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 13:03:02 +09:00
tei
86906c8a6a test(android): isolate internal annotation symbol from STEP-102 retained ranges 2026-10-09 13:01:43 +09:00
tei
a49dd936c4 docs(android): close FZG native runtime audit with placement finding
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 12:35:40 +09:00
tei
2c6f673e54 docs(android): record FZG 13.6.1 ADB runtime matrix and T2 blocker 2026-10-09 12:35:24 +09:00
tei
c30add4d33 docs(android): record FZG MapLibre 13.6.1 APK installation verification
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 12:05:55 +09:00
tei
73db0356ac build(android): permit signed Sentry auxiliary ABIs in FZG validation APK 2026-10-09 12:04:38 +09:00
tei
30d0e6665e docs(upgrade): record android 13.6.1 native OpenGL compile PASS
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 10:31:21 +09:00
tei
a4b5f4eaa0 docs(upgrade): record official native 13.6.1 merge checkpoint 2026-10-09 09:37:47 +09:00
tei
f8378fd711 merge(upgrade): port particle extensions onto official native 13.6.1 (unverified) 2026-10-09 09:37:07 +09:00
tei
e4c7af7c40 docs(upgrade): establish native 13.6.1 migration gate and recorder 2026-10-09 09:23:25 +09:00
tei
b433775348 docs: record upstream audit git closure
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 09:06:09 +09:00
tei
2b4075b60b docs: audit upstream MapLibre Native upgrade compatibility
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-09 09:05:22 +09:00
tei
630ec65768 release: finalize unified particle.21
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-08 13:33:00 +09:00
tei
16a5d15f16 release: prepare unified particle.21 2026-10-08 12:03:17 +09:00
tei
d3bf98bc55 docs: record STEP-102 V21 validation waiver 2026-10-08 12:03:03 +09:00
tei
0ce551ad37 feat(step102): isolate placement-free retained segments 2026-10-08 09:59:58 +09:00
tei
6df21dac38 docs: 记录 RenderSegment 多 Retained Placement 审查说明
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-07 23:06:51 +09:00
tei
53a844e818 release: finalize unified particle.20
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-07 21:35:44 +09:00
tei
a4c6047d70 release: prepare unified particle.20 2026-10-07 18:06:02 +09:00
tei
078ba40b76 release: build iOS distribution with bazel opt 2026-10-07 18:05:30 +09:00
tei
6b48f905d2 release: finalize unified particle.19
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-07 16:31:36 +09:00
tei
7c5ed27b0b release: prepare unified particle.19 2026-10-07 08:42:32 +09:00
tei
01863569fb docs: close STEP-101 teardown validation
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-07 08:42:09 +09:00
tei
64cf8f4435 fix: make render orchestrator teardown safe
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-07 08:41:08 +09:00
tei
d29e84c1a9 release: finalize unified particle.18
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-06 20:52:00 +09:00
tei
2780550b62 release: prepare unified particle.18 2026-10-06 17:20:34 +09:00
tei
524aaf4af5 fix: localize retained segment source invalidation
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-06 17:18:09 +09:00
tei
c4b481fd2c docs: close STEP-099 render source diagnostics
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
2026-10-06 15:33:12 +09:00
tei
8a5214d92d diagnostics: add STEP-099 render source readiness audit 2026-10-06 15:15:12 +09:00
Adrian Cojocaru
c7506d6aff Release MapLibre Android 13.6.1 (#4601) 2026-09-08 18:56:06 +00:00
Taiyu Yoshizawa
57d1981497 keep digits and short codes upright in CJK line labels (#4566) 2026-09-07 23:17:43 +02:00
Akash Mohan Chaudhary
042f21da5c Rename OpenGL event to GraphicsBackend (#4515) 2026-09-06 21:02:21 +00:00
VandenOstende
a33d3f00fb fix(ios): use window scene interface orientation for heading compensation (#4548) 2026-09-06 01:04:02 +00:00
Tore Halset
eca9e1db33 mbgl-render add support for style from stdin and png to stdout (#4561) 2026-09-05 23:05:39 +00:00
Taku Fukada
843cdec996 fix(core): bundle fastpfor-lib into the Linux/macOS amalgams (#4538) 2026-09-06 00:06:43 +02:00
John Carmack
474d127bfb fix(core): break a label before a left parenthesis, not after it (#4553) 2026-09-06 00:03:38 +02:00
John Carmack
fed6dc019b ci: cancel superseded rust-ci runs on pull requests (#4555) 2026-09-06 00:02:17 +02:00
Adrian Cojocaru
0b342a1209 fix(core): Fix missing symbols/glyphs (#4554) 2026-09-04 21:42:09 +02:00
Adrian Cojocaru
96e806931d fix(core): Sync image transition based on layout (#4540) 2026-09-02 14:29:54 +03:00
Bart Louwers
e5d0fce32a core: refactor renderable size ownership (#4512) 2026-09-01 18:35:29 +03:00
Taku Fukada
be3f03b86e fix(macos): preserve exception RTTI in amalgam archive (#4350)
Co-authored-by: Bart Louwers <bart@emeel.net>
2026-08-30 10:28:43 +02:00
Bart Louwers
2919f71e39 Release MapLibre Android 13.6.0 (#4529) 2026-08-28 11:38:05 +02:00
Taku Fukada
6010a2e687 fix(core): update amalgam symbol filters for mln namespace rename (#4531) 2026-08-28 11:37:51 +02:00
Taku Fukada
c3b588321b Fix ImageSource not rendering across world copies (#4508) 2026-08-28 02:48:01 +00:00
Alex Cristici
cbe4681ef1 Reduce symbol buffers memory by using instancing (Core optimization) (#4383)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-08-27 00:12:07 +03:00
Haruto Sasaki
1d0908bdaa test: restore heatmap render tests disabled during renderer migration (#4466) 2026-08-25 07:15:18 +00:00
Yul Kang
96afb98b7f core: remove unused Metal RendererBackend state-cache methods (#4519) 2026-08-25 09:10:14 +02:00
Copilot
ef5ff9ac01 Update expected-lite to restore C++23 consumer compatibility for database_file_source.hpp (#4474)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: louwers <649392+louwers@users.noreply.github.com>
Co-authored-by: Bart Louwers <bart@emeel.net>
2026-08-25 04:49:07 +00:00
dependabot[bot]
08f775e2ed build(deps): bump the github-actions group across 1 directory with 13 updates (#4493)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-25 00:21:54 +02:00
Bart Louwers
a4670161a0 Fix iOS Swift package release ordering (#4520) 2026-08-24 23:47:43 +02:00
Bart Louwers
0c7fbe2b29 Release MapLibre iOS 6.29.0 (#4509) 2026-08-23 11:00:37 +00:00
Bart Louwers
2a8ebc4906 core: rename mbgl directories to mln (#4511)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-08-22 20:50:14 +02:00
Bart Louwers
06fcf13d42 fix(glfw): synchronize Metal renderable size (#4510) 2026-08-21 16:32:44 +02:00
Adrian Cojocaru
f0bd259b53 Release MapLibre Android 13.5.1 (#4507) 2026-08-21 14:29:21 +03:00
Trietes
2e13de25f4 Fix surface transform (#4495) 2026-08-18 16:22:23 +03:00
Adrian Cojocaru
65a3405370 fix(core): Fix nullptr access during custom layer pre-render (#4496) 2026-08-18 13:16:09 +02:00
Bart Louwers
550f64be22 core: rename mbgl namespace to mln (#4487)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-08-14 23:25:20 +02:00
Bart Louwers
836b862984 android: allow configurable Maven publication repository (#4485) 2026-08-14 17:52:50 +02:00
Bart Louwers
95a977e12e Reduce Android AAR size with header-only Prefab (#4483) 2026-08-14 14:37:28 +00:00
Bouke van der Bijl
6485d28b3e macOS: report the drawable size to the renderer (#4479) 2026-08-14 13:31:09 +00:00
Bouke van der Bijl
d508e65692 macOS: render the Metal map on demand (#4480) 2026-08-14 15:24:14 +02:00
Adrian Cojocaru
743ed53794 fix (glfw): Remove duplicate glfwSwapInterval (#4484) 2026-08-14 11:57:36 +00:00
Bart Louwers
a666f02633 Release MapLibre Android 13.5.0 (#4477) 2026-08-13 00:37:23 +02:00
munawiki
9a9f831782 feat: implement split and join expressions (#4463)
Co-authored-by: Bart Louwers <bart@emeel.net>
2026-08-12 18:25:47 +02:00
Adrian Cojocaru
bd92c87d39 fix(android): Workaround for Adreno VK_ERROR_DEVICE_LOST (#4442) 2026-08-12 09:21:24 +00:00
Nathan Gass
8be081ae83 accept libpng with different release/patch number (#4467) 2026-08-11 23:37:00 +00:00
Steve Gifford
49f80e95f3 Changes to the custom Metal layer to allow more flexible rendering (#4446)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: louwers <649392+louwers@users.noreply.github.com>
Co-authored-by: Bart Louwers <bart@emeel.net>
2026-08-12 00:23:35 +02:00
Adrian Cojocaru
d9664ee187 core: Add error reporting for corrupted symbols (#4458) 2026-08-11 18:20:59 +02:00
Adrian Cojocaru
7f430aa624 core: Use compatible descriptor set layout for tile clipping (#4470) 2026-08-11 17:18:44 +02:00
Veniamin Vynohradov
b0388d186d Add multiBackend Android flavor for runtime OpenGL/Vulkan switching (#4288) 2026-08-06 15:54:58 +02:00
David Wheatley
ccb9af119e feat: specify layer/property that has a parse error when logging (#4292) 2026-08-05 08:14:36 -07:00
Sargun Vohra
e2b01754b6 build: Make the emdawnwebgpu suspension mode configurable (#4451) 2026-08-05 08:50:19 +02:00
Richard Fairhurst
40be634126 Android: setOverrideSynchronousUpdate for existing sources (#4366)
Co-authored-by: Bart Louwers <bart@emeel.net>
2026-08-04 20:00:50 +00:00
Adrian Cojocaru
f1905c5215 fix(core): Add action journal exception handling (#4438) 2026-08-04 19:34:45 +03:00
Stephan Schmid (MBAG)
e626fc0fbd Make string expressions operate on unicode (#4344) 2026-08-04 18:26:26 +02:00
Vladyslav Odobesku
9ef0f1c790 core: add CustomVectorSource for binary tile data delivery (#4377)
Co-authored-by: Vladyslav Odobesku <VladyslavOdobesku@intellias.com>
Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-08-04 18:23:41 +02:00
Adrian Cojocaru
25e4f6acbf fix(android): Add option to move symbol location indicator bearing down the image stack (#4408) 2026-08-04 18:21:25 +02:00
Brandon Roeder
a34723ff4a fix(core): repaint feature-state-driven symbol paint properties (#4445) 2026-08-04 18:17:53 +02:00
Bart Louwers
5e6fd6bb78 do a recursive checkout in gh-pages-docc.yml workflow (#4450) 2026-08-03 08:59:17 +00:00
Adrian Cojocaru
c8dad00be5 fix(android): Fix surface changed ANR (#4439) 2026-07-29 19:23:35 +02:00
Yul Kang
a6189feecb docs: remove duplicate packages from macOS Homebrew
install command (#4441)
2026-07-29 15:12:01 +00:00
Chris Gervang
83ce54ed3e fix(core): accept alpha in hsl colors (#4435) 2026-07-28 17:29:01 +02:00
Sargun Vohra
5bcdc704b8 core: Drain WebGPU render-thread cleanup jobs (#4367) 2026-07-24 08:11:26 +00:00
Sargun Vohra
15fcee54dc core: emdawnwebgpu build support (#4370) 2026-07-24 07:57:28 +00:00
2334 changed files with 35781 additions and 22410 deletions

View File

@@ -26,7 +26,7 @@ jobs:
outputs:
should_skip: ${{ github.event_name != 'workflow_dispatch' && steps.changed-files.outputs.android_any_modified != 'true' }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -46,7 +46,7 @@ jobs:
strategy:
fail-fast: false
matrix:
renderer: [opengl, vulkan]
renderer: [opengl, vulkan, multiBackend]
defaults:
run:
working-directory: platform/android
@@ -57,14 +57,14 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN_ANDROID }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
- uses: ./.github/actions/setup-android-ci
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: ".nvmrc"
@@ -169,6 +169,7 @@ jobs:
case "${{ matrix.renderer }}" in
opengl) echo "renderer=OpenGL" >> "$GITHUB_ENV" ;;
vulkan) echo "renderer=Vulkan" >> "$GITHUB_ENV" ;;
multiBackend) echo "renderer=MultiBackend" >> "$GITHUB_ENV" ;;
*) echo "::error ::Unknown renderer '${{ matrix.renderer }}'"; exit 1 ;;
esac
@@ -210,7 +211,7 @@ jobs:
working-directory: test/android
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -255,7 +256,7 @@ jobs:
if: needs.pre_job.outputs.should_skip != 'true'
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -283,7 +284,7 @@ jobs:
env:
IS_LOCAL_DEVELOPMENT: false
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -316,7 +317,7 @@ jobs:
C_COMPILER: aarch64-linux-android26-clang
BINDGEN_TARGET: aarch64-linux-android26
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -390,7 +391,7 @@ jobs:
# automatically trigger android-release when code is pushed to main
# and the platform/android/VERSION file has changed
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
- name: VERSION file changed

View File

@@ -78,11 +78,11 @@ jobs:
runs-on: ubuntu-latest
if: github.repository_owner == 'maplibre' && github.event.workflow_run.conclusion == 'success'
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
@@ -145,7 +145,7 @@ jobs:
- name: Configure AWS Credentials
if: env.run_device_test == 'true'
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3
with:
aws-region: us-west-2
role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}

View File

@@ -15,7 +15,7 @@ jobs:
run:
working-directory: platform/android
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Validate and set version
working-directory: .
@@ -52,7 +52,7 @@ jobs:
- name: Create release (draft)
id: create_release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: ${{ steps.prepare_release.outputs.version_tag }}
name: ${{ steps.prepare_release.outputs.version_tag }}
@@ -74,19 +74,20 @@ jobs:
RENDERER:
- vulkan
- opengl
- multiBackend
BUILDTYPE:
- Release
- Debug
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: ".nvmrc"
- uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
- uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: "temurin"
java-version: "17"
@@ -118,7 +119,7 @@ jobs:
"build/debug-symbols-maplibre-android-${{ matrix.RENDERER }}-${{ env.buildtype }}-$version_tag.tar.gz"
- name: Upload release assets (${{ matrix.RENDERER }}, ${{ matrix.BUILDTYPE }})
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: ${{ needs.android-create-release.outputs.version_tag }}
fail_on_unmatched_files: true
@@ -133,8 +134,12 @@ jobs:
if [ "$renderer" = "opengl" ]; then
./gradlew :MapLibreAndroid:publishOpengl${{ env.buildtype }}PublicationToMavenCentralRepository
./gradlew :MapLibreAndroid:publishDefault${{ env.buildtype }}PublicationToMavenCentralRepository
else
elif [ "$renderer" = "vulkan" ]; then
./gradlew :MapLibreAndroid:publishVulkan${{ env.buildtype }}PublicationToMavenCentralRepository
elif [ "$renderer" = "multiBackend" ]; then
./gradlew :MapLibreAndroid:publishMultibackend${{ env.buildtype }}PublicationToMavenCentralRepository
else
echo "::error ::Unknown renderer '$renderer'"; exit 1
fi
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
@@ -149,20 +154,20 @@ jobs:
- android-build-and-upload-release
steps:
- name: Publish release (remove draft)
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: ${{ needs.android-create-release.outputs.version_tag }}
name: ${{ needs.android-create-release.outputs.version_tag }}
draft: false
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
- uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: "temurin"
java-version: "17"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: ".nvmrc"

View File

@@ -10,7 +10,7 @@ jobs:
create-android-testapp-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -30,7 +30,7 @@ jobs:
strategy:
fail-fast: false
matrix:
renderer: [opengl, vulkan]
renderer: [opengl, vulkan, multibackend]
defaults:
run:
working-directory: platform/android
@@ -43,7 +43,7 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN_ANDROID }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -68,11 +68,11 @@ jobs:
needs: [android-build-testapp]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Finalize release (set draft=false)
run: |

View File

@@ -15,7 +15,7 @@ jobs:
contents: read
steps:
- name: Check out code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

View File

@@ -14,7 +14,7 @@ jobs:
create-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
@@ -46,13 +46,13 @@ jobs:
needs: [create-release]
runs-on: macos-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
- run: brew install webp libuv
- run: brew install webp libuv llvm
- uses: taiki-e/install-action@2ca9b94c269419b7b0c711c09d0b21c4e1d51145 # v2.83.1
- uses: taiki-e/install-action@ba47c86ac325773530516bb756137ac718732518 # v2.86.5
with:
tool: armerge@2
@@ -103,14 +103,14 @@ jobs:
- renderer: vulkan
runner: { os: ubuntu-24.04-arm, arch: arm64 }
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
- name: Install dependencies
run: .github/scripts/install-linux-deps
- uses: taiki-e/install-action@2ca9b94c269419b7b0c711c09d0b21c4e1d51145 # v2.83.1
- uses: taiki-e/install-action@ba47c86ac325773530516bb756137ac718732518 # v2.86.5
with:
tool: armerge@2
@@ -156,7 +156,7 @@ jobs:
- run: |
git config --system core.longpaths true
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive

View File

@@ -15,11 +15,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
- uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: "temurin"
java-version: "17"
@@ -28,7 +28,7 @@ jobs:
run: ./gradlew dokkaGenerate
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@d92aa235d04922e8f08b40ce78cc5442fcfbfa2f # v4.8.0
uses: JamesIves/github-pages-deploy-action@fa24774553152dd7873cd16ebd8d959b010c5445 # v4.9.0
with:
branch: gh-pages
folder: platform/android/MapLibreAndroid/build/dokka/html

View File

@@ -17,13 +17,13 @@ jobs:
shell: bash
steps:
- name: Checkout 🛎️
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Generate documentation
run: make mkdocs-build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@d92aa235d04922e8f08b40ce78cc5442fcfbfa2f # v4.8.0
uses: JamesIves/github-pages-deploy-action@fa24774553152dd7873cd16ebd8d959b010c5445 # v4.9.0
with:
branch: gh-pages
folder: platform/android/site

View File

@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: true
@@ -20,7 +20,7 @@ jobs:
run: doxygen
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@d92aa235d04922e8f08b40ce78cc5442fcfbfa2f # v4.8.0
uses: JamesIves/github-pages-deploy-action@fa24774553152dd7873cd16ebd8d959b010c5445 # v4.9.0
with:
branch: gh-pages
folder: docs/doxygen/html

View File

@@ -15,15 +15,17 @@ on:
jobs:
gh-pages-docc-build:
if: ${{ github.ref_name == 'main' }}
name: Build DocC Docs
runs-on: macos-latest
if: ${{ github.ref_name == 'main' }}
steps:
- name: Checkout 🛎️
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3
with:
aws-region: us-west-2
role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}
@@ -52,7 +54,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Download DocC docs artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
@@ -67,7 +69,7 @@ jobs:
rm docs.zip
- name: Deploy DocC documentation (main) 🚀
uses: JamesIves/github-pages-deploy-action@d92aa235d04922e8f08b40ce78cc5442fcfbfa2f # v4.8.0
uses: JamesIves/github-pages-deploy-action@fa24774553152dd7873cd16ebd8d959b010c5445 # v4.9.0
with:
branch: gh-pages
folder: build/docs

View File

@@ -16,7 +16,7 @@ jobs:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
- name: Setup mdBook
uses: peaceiris/actions-mdbook@ee69d230fe19748b7abf22df32acaa93833fad08 # v2.0.0
@@ -40,7 +40,7 @@ jobs:
name: Deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Download book
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
@@ -48,7 +48,7 @@ jobs:
path: artifacts/book
- name: Deploy
uses: JamesIves/github-pages-deploy-action@d92aa235d04922e8f08b40ce78cc5442fcfbfa2f # v4.8.0
uses: JamesIves/github-pages-deploy-action@fa24774553152dd7873cd16ebd8d959b010c5445 # v4.9.0
with:
branch: gh-pages
folder: artifacts/book

View File

@@ -22,7 +22,7 @@ jobs:
outputs:
should_skip: ${{ github.event_name != 'workflow_dispatch' && steps.changed-files-yaml.outputs.ios_any_modified != 'true' }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -58,7 +58,7 @@ jobs:
working-directory: platform/ios
shell: bash
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: false
persist-credentials: false
@@ -211,7 +211,7 @@ jobs:
- name: Configure AWS Credentials
if: github.ref == 'refs/heads/main' && vars.OIDC_AWS_ROLE_TO_ASSUME
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3
with:
aws-region: us-west-2
role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}
@@ -236,7 +236,7 @@ jobs:
runs-on: macos-14
if: needs.pre_job.outputs.should_skip != 'true'
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
@@ -269,7 +269,7 @@ jobs:
if: needs.pre_job.outputs.should_skip != 'true'
runs-on: macos-26
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -304,7 +304,7 @@ jobs:
if: needs.pre_job.outputs.should_skip != 'true'
runs-on: macos-26
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -366,7 +366,7 @@ jobs:
# Trigger release on main if VERSION file changed
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
if: github.ref == 'refs/heads/main'
with:
persist-credentials: false

View File

@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-24.04
if: github.repository_owner == 'maplibre' && github.event.workflow_run.conclusion == 'success'
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -52,7 +52,7 @@ jobs:
files: "${{ matrix.test.xcTestFile }}, ${{ matrix.test.ipaFile }}"
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3
with:
aws-region: us-west-2
role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}

View File

@@ -14,7 +14,7 @@ jobs:
working-directory: platform/ios
runs-on: macos-14
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

View File

@@ -23,7 +23,7 @@ jobs:
working-directory: platform/ios
shell: bash
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
@@ -65,7 +65,7 @@ jobs:
working-directory: platform/ios
shell: bash
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
@@ -104,13 +104,13 @@ jobs:
working-directory: platform/ios
shell: bash
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: ".nvmrc"
@@ -144,7 +144,7 @@ jobs:
cat changelog_for_version.md
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3
with:
aws-region: us-west-2
role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}
@@ -155,7 +155,7 @@ jobs:
- name: Release (GitHub) - Create Draft
id: github_release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
name: ios-v${{ env.version }}
files: |
@@ -177,6 +177,22 @@ jobs:
private-key: ${{ secrets.MAPLIBRE_NATIVE_BOT_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- run: npm install
working-directory: .
- name: Release (CocoaPods)
shell: bash -leo pipefail {0} # so pod is found
run: gh workflow run ios-release-cocoapods.yml --field version=${{ env.version }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish release (remove draft)
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: ios-v${{ env.version }}
name: ios-v${{ env.version }}
draft: false
- name: Release (Swift Package Index)
run: |
echo "::add-mask::${{ steps.generate_token.outputs.token }}"
@@ -192,22 +208,6 @@ jobs:
"version":"${{ env.version }}",
"download_url": "https://github.com/maplibre/maplibre-native/releases/download/ios-v${{ env.version }}/MapLibre.dynamic.xcframework.zip"}}'
- run: npm install
working-directory: .
- name: Release (CocoaPods)
shell: bash -leo pipefail {0} # so pod is found
run: gh workflow run ios-release-cocoapods.yml --field version=${{ env.version }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish release (remove draft)
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
with:
tag_name: ios-v${{ env.version }}
name: ios-v${{ env.version }}
draft: false
- name: Write release notifications
if: github.repository_owner == 'maplibre'
env:

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: macos-26
timeout-minutes: 90
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -49,7 +49,7 @@ jobs:
test -f bazel-bin/platform/ios/app-swift/MapLibreApp.ipa
- name: Upload app to TestFlight
uses: apple-actions/upload-testflight-build@1ad58030672057aa084b4e96beb6f7a8c627f9e6 # v5.2.1
uses: apple-actions/upload-testflight-build@5e75ff58276689011512ba87a381d93dc67dbcf8 # v5.3.0
with:
app-path: bazel-bin/platform/ios/app-swift/MapLibreApp.ipa
issuer-id: ${{ vars.APPSTORE_ISSUER_ID }}

View File

@@ -9,4 +9,4 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0
- uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0

View File

@@ -33,7 +33,7 @@ jobs:
outputs:
should_skip: ${{ github.event_name != 'workflow_dispatch' && steps.changed-files.outputs.linux_any_modified != 'true' }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -66,20 +66,20 @@ jobs:
rust: true
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
with:
languages: cpp
- name: Install dependencies
run: .github/scripts/install-linux-deps
- uses: taiki-e/install-action@2ca9b94c269419b7b0c711c09d0b21c4e1d51145 # v2.83.1
- uses: taiki-e/install-action@ba47c86ac325773530516bb756137ac718732518 # v2.86.5
with:
tool: armerge@2
@@ -156,7 +156,7 @@ jobs:
# CodeQL
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
with:
category: "/language:cpp"
@@ -199,7 +199,7 @@ jobs:
linux-coverage:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -215,7 +215,7 @@ jobs:
${{ runner.os }}-bazel-
path: ~/.cache/bazel
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
@@ -249,7 +249,7 @@ jobs:
- linux-build-and-test
- linux-coverage
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- if: github.event_name == 'pull_request'
uses: ./.github/actions/save-pr-number

View File

@@ -69,7 +69,7 @@ jobs:
shell: bash
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
fetch-depth: 0
@@ -106,7 +106,7 @@ jobs:
name: wgpu
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false

View File

@@ -23,7 +23,7 @@ jobs:
working-directory: platform/macos
shell: bash
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
submodules: recursive
@@ -56,7 +56,7 @@ jobs:
working-directory: .
- name: Upload artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: xcframework
path: |
@@ -70,7 +70,7 @@ jobs:
working-directory: platform/macos
shell: bash
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
submodules: recursive
@@ -92,7 +92,7 @@ jobs:
working-directory: .
- name: Upload artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: xcframework-static
path: |
@@ -111,13 +111,13 @@ jobs:
working-directory: platform/macos
shell: bash
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
submodules: recursive
- uses: actions/download-artifact@v8
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v4
with:
node-version-file: ".nvmrc"
@@ -153,7 +153,7 @@ jobs:
cat changelog_for_version.md
- name: Release (GitHub) - Create Draft
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
name: macos-v${{ env.version }}
files: |
@@ -167,7 +167,7 @@ jobs:
draft: true
- name: Publish release (remove draft)
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: macos-v${{ env.version }}
name: macos-v${{ env.version }}

View File

@@ -100,7 +100,7 @@ jobs:
run: git config --global core.longpaths true
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -141,7 +141,7 @@ jobs:
/usr/sbin/update-ccache-symlinks
- name: Use Node.js from nvmrc
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: 'platform/node/.nvmrc'

View File

@@ -17,12 +17,12 @@ jobs:
run:
shell: bash
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Use Node.js from nvmrc
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: 'platform/node/.nvmrc'
@@ -50,7 +50,7 @@ jobs:
run:
shell: bash
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -118,7 +118,7 @@ jobs:
run: git config --global core.longpaths true
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -159,7 +159,7 @@ jobs:
/usr/sbin/update-ccache-symlinks
- name: Use Node.js from nvmrc
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: 'platform/node/.nvmrc'
@@ -297,12 +297,12 @@ jobs:
shell: bash
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Use Node.js from nvmrc
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: 'platform/node/.nvmrc'
registry-url: 'https://registry.npmjs.org'

View File

@@ -19,14 +19,14 @@ jobs:
outputs:
should_skip: ${{ steps.parent_workflow.outputs.was_skipped_or_cancelled }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
sparse-checkout: |
.github
.nvmrc
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
@@ -45,7 +45,7 @@ jobs:
if: needs.pre_job.outputs.should_skip == 'false'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -85,7 +85,7 @@ jobs:
- name: Configure AWS Credentials
if: vars.OIDC_AWS_ROLE_TO_ASSUME
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3
with:
aws-region: us-west-2
role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}

View File

@@ -22,14 +22,14 @@ jobs:
outputs:
should_skip: ${{ steps.parent_workflow.outputs.was_skipped_or_cancelled }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
sparse-checkout: |
.github
.nvmrc
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
@@ -48,7 +48,7 @@ jobs:
if: needs.pre_job.outputs.should_skip == 'false'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -95,7 +95,7 @@ jobs:
- name: Configure AWS Credentials
if: github.ref == 'refs/heads/main' && vars.OIDC_AWS_ROLE_TO_ASSUME
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3
with:
aws-region: us-west-2
role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}
@@ -139,7 +139,7 @@ jobs:
if: needs.pre_job.outputs.should_skip == 'false'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: true
persist-credentials: false
@@ -170,7 +170,7 @@ jobs:
- name: Configure AWS Credentials
if: github.ref == 'refs/heads/main' && vars.OIDC_AWS_ROLE_TO_ASSUME
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6.2.3
with:
aws-region: us-west-2
role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}

View File

@@ -104,7 +104,7 @@ jobs:
run: git config --global core.longpaths true
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: source
submodules: recursive

View File

@@ -7,6 +7,10 @@ on:
branches: [ main ]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
defaults:
run:
working-directory: rustutils/
@@ -23,9 +27,9 @@ jobs:
- os: windows-latest
- os: ubuntu-latest
steps:
- uses: taiki-e/install-action@2ca9b94c269419b7b0c711c09d0b21c4e1d51145 # v2.83.1
- uses: taiki-e/install-action@ba47c86ac325773530516bb756137ac718732518 # v2.86.5
with: { tool: just }
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- run: just -v ci-test
@@ -34,9 +38,9 @@ jobs:
name: Rust tests MSRV (Minimal Supported Rust Version)
runs-on: ubuntu-latest
steps:
- uses: taiki-e/install-action@2ca9b94c269419b7b0c711c09d0b21c4e1d51145 # v2.83.1
- uses: taiki-e/install-action@ba47c86ac325773530516bb756137ac718732518 # v2.86.5
with: { tool: just }
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Read crate metadata

View File

@@ -12,14 +12,14 @@ jobs:
outputs:
should_run: ${{ !steps.parent_workflow.outputs.was_skipped_or_cancelled }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
sparse-checkout: |
.github
.nvmrc
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
@@ -38,7 +38,7 @@ jobs:
if: needs.pre_job.outputs.should_run == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

View File

@@ -9,9 +9,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: ".nvmrc"

View File

@@ -9,11 +9,11 @@ jobs:
validate-scripts:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: ".nvmrc"

View File

@@ -37,7 +37,7 @@ jobs:
- run: |
git config --system core.longpaths true
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -62,7 +62,7 @@ jobs:
- run: |
git config --system core.longpaths true
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
sparse-checkout: |
platform/windows/vendor
@@ -118,19 +118,19 @@ jobs:
- run: |
git config --system core.longpaths true
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
with:
languages: cpp
- uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
- uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
- uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11
- name: Initialize sccache
run: |
@@ -167,7 +167,7 @@ jobs:
# CodeQL
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
with:
category: "/language:cpp"
@@ -255,7 +255,7 @@ jobs:
git config --system core.longpaths true
git config --system core.autocrlf input
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
persist-credentials: false
@@ -279,11 +279,11 @@ jobs:
libuv:p
- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
with:
languages: cpp
- uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
- uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11
- name: Initialize sccache
run: |
@@ -308,7 +308,7 @@ jobs:
# CodeQL
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
with:
category: "/language:cpp"

View File

@@ -10,7 +10,7 @@ MapLibre Native uses a monolithic repository that houses both core C++ code and
## Core cross-platform C++ code
In the repository, core C++ code is contained in the `include` and `src` directories. The former includes headers that are considered to make up the "public" core C++ API, while the latter includes `.cpp` implementation files and headers that are private to the implementation. Within both directories, files are nested under an `mbgl` directory, which has various subdirectories based on areas of functionality. Both public and private headers therefore can (and should) always be included with the form `#include <mbgl/___/___.hpp>`.
In the repository, core C++ code is contained in the `include` and `src` directories. The former includes headers that are considered to make up the "public" core C++ API, while the latter includes `.cpp` implementation files and headers that are private to the implementation. Within both directories, files are nested under an `mbgl` directory, which has various subdirectories based on areas of functionality. Both public and private headers therefore can (and should) always be included with the form `#include <mln/___/___.hpp>`.
## Platform specific code
@@ -24,7 +24,7 @@ Code and build scripts belonging to platform SDKs are contained in the `platform
## Other directories
- `benchmark` contains the performance tests built using https://github.com/google/benchmark/. The code under this directory builds the `mbgl-benchmark-test` executable to execute the benchmark tests.
- The entry point of this executable is `platform/default/src/mbgl/benchmark/main.cpp -> benchmark/src/mbgl/benchmark/benchmark.cpp`.
- The entry point of this executable is `platform/default/src/mln/benchmark/main.cpp -> benchmark/src/mln/benchmark/benchmark.cpp`.
- iOS SDK runs benchmark test through a separate app named `BenchmarkApp`.
- Android SDK does not have benchmark test.
- `bin` contains the code for tools like `mbgl-cache`, `mbgl-offline`, and `mbgl-render`.
@@ -142,4 +142,4 @@ To minimize data races and invalid memory access, we aim for zero shared memory
Invoking a task on another thread itself creates an ownership obligation: the responsibility for the work happening on the other thread. This ownership is represented by the invocation method returning `std::unique_ptr<AsyncTask>`. Destroying this object indicates that the result of the task is no longer required: the callback is guaranteed not to be called, and the work on the other thread may be aborted (if doing so is convenient).
All this is implemented by [Thread](https://github.com/mapbox/mapbox-gl-native/blob/master/src/mbgl/util/thread.hpp) and [RunLoop](https://github.com/mapbox/mapbox-gl-native/blob/master/include/mbgl/util/run_loop.hpp).
All this is implemented by [Thread](https://github.com/mapbox/mapbox-gl-native/blob/master/src/mln/util/thread.hpp) and [RunLoop](https://github.com/mapbox/mapbox-gl-native/blob/master/include/mln/util/run_loop.hpp).

View File

@@ -29,6 +29,10 @@
### 🐞 Bug fixes
- *...Add new stuff here...*
- [core] Draw numbers and short uppercase codes upright in vertical CJK line labels ([#4565](https://github.com/maplibre/maplibre-native/issues/4565)), compat to [maplibre-gl-js#8205](https://github.com/maplibre/maplibre-gl-js/pull/8205).
- [core] Fix `ImageSource` not rendering across world copies ([#4508](https://github.com/maplibre/maplibre-native/issues/4508)).
- [core] Repaint data-driven symbol paint properties after feature-state updates.
- [core] Accept alpha values in legacy comma-separated `hsl()` colors ([#4434](https://github.com/maplibre/maplibre-native/issues/4434)).
- [core] Fix thread-unsafe headless OpenGL display singleton initialization [#4332](https://github.com/maplibre/maplibre-native/pull/4332)
- [macos] Fix `mlt-cpp` and `mbgl-vendor-icu` not being included in the amalgamation
- [core] Fix memory access violation exception in vector_tile_data.cpp [#632](https://github.com/maplibre/maplibre-native/pull/632)
@@ -85,7 +89,7 @@
- [ios, macos] Allow specifying multiple fonts or font families for local font rendering ([#16253](https://github.com/mapbox/mapbox-gl-native/pull/16253))
By default, CJK characters are now set in the font specified by the `text-font` layout property. If the named font is not installed on the device or bundled with the application, the characters are set in one of the fallback fonts passed into the `localFontFamily` parameter of `mbgl::Renderer::Renderer()` and `mbgl::MapSnapshotter::MapSnapshotter()`. This parameter can now contain a list of font family names, font display names, and font PostScript names, each name separated by a newline.
By default, CJK characters are now set in the font specified by the `text-font` layout property. If the named font is not installed on the device or bundled with the application, the characters are set in one of the fallback fonts passed into the `localFontFamily` parameter of `mln::Renderer::Renderer()` and `mln::MapSnapshotter::MapSnapshotter()`. This parameter can now contain a list of font family names, font display names, and font PostScript names, each name separated by a newline.
### 🐞 Bug fixes
@@ -139,7 +143,7 @@
- [core][tile mode] Fix variable placement for labels with the `icon-text-fit` property set ([#16382](https://github.com/mapbox/mapbox-gl-native/pull/16382))
The `symbolIntersectsTileEdges()` util in `mbgl::TilePlacement` now considers icon shift for the variable symbols with enabled icon-text-fit setting, thus providing more accurate results.
The `symbolIntersectsTileEdges()` util in `mln::TilePlacement` now considers icon shift for the variable symbols with enabled icon-text-fit setting, thus providing more accurate results.
- [core] Correctly log a warning instead of crashing when a non-existent image is attempted to be removed. ([#16391](https://github.com/mapbox/mapbox-gl-native/pull/16391))
@@ -170,7 +174,7 @@
- [android] Add jni binding for styleable snapshotter ([#16286](https://github.com/mapbox/mapbox-gl-native/pull/16286))
- [core] Ability to set generic layer properties using setProperty method ([#16324](https://github.com/mapbox/mapbox-gl-native/pull/16324))
This change enables the following new keys for the `mbgl::Layer::setProperty()` API:
This change enables the following new keys for the `mln::Layer::setProperty()` API:
- "filter" invokes `setFilter()`
- "minzoom" invokes `setMinZoom()`
- "maxzoom" invokes `setMaxZoom()`
@@ -252,7 +256,7 @@
- Fixed using of the `in` expression as a layer filter ([#16272](https://github.com/mapbox/mapbox-gl-native/pull/16272))
The bug was caused by `mbgl::style::conversion::isExpression()` always returning `false` for the `in` expression.
The bug was caused by `mln::style::conversion::isExpression()` always returning `false` for the `in` expression.
### 🧩 Architectural changes
@@ -296,9 +300,9 @@
##### ⚠️ Breaking changes
- Changes to `mbgl::FileSourceManager::getFileSource()` ([#16238](https://github.com/mapbox/mapbox-gl-native/pull/16238))
- Changes to `mln::FileSourceManager::getFileSource()` ([#16238](https://github.com/mapbox/mapbox-gl-native/pull/16238))
It returns now `mbgl::PassRefPtr<FileSource>` (previously was `std::shared_ptr<FileSource>`) in order to enforce keeping the strong reference to the returned object.
It returns now `mln::PassRefPtr<FileSource>` (previously was `std::shared_ptr<FileSource>`) in order to enforce keeping the strong reference to the returned object.
Breaking code example:
`auto fs = FileSourceManager::getFileSource(); fs->..`
@@ -306,9 +310,9 @@
Possible fix:
`std::shared_ptr<FileSource> fs = `;
- The `mbgl::OnlineFileSource` class cannot be used directly ([#16238](https://github.com/mapbox/mapbox-gl-native/pull/16238))
- The `mln::OnlineFileSource` class cannot be used directly ([#16238](https://github.com/mapbox/mapbox-gl-native/pull/16238))
Clients must use the parent `mbgl::FileSource` interface instead.
Clients must use the parent `mln::FileSource` interface instead.
Breaking code example:
`std::shared_ptr<OnlineFileSource> onlineSource = std::static_pointer_cast<OnlineFileSource>(FileSourceManager::get()->getFileSource(..));`

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@ add_library(
${PROJECT_SOURCE_DIR}/benchmark/parse/tile_mask.benchmark.cpp
${PROJECT_SOURCE_DIR}/benchmark/parse/vector_tile.benchmark.cpp
${PROJECT_SOURCE_DIR}/benchmark/renderer/group_layers.benchmark.cpp
${PROJECT_SOURCE_DIR}/benchmark/src/mbgl/benchmark/benchmark.cpp
${PROJECT_SOURCE_DIR}/benchmark/src/mln/benchmark/benchmark.cpp
${PROJECT_SOURCE_DIR}/benchmark/storage/offline_database.benchmark.cpp
${PROJECT_SOURCE_DIR}/benchmark/util/tilecover.benchmark.cpp
${PROJECT_SOURCE_DIR}/benchmark/util/color.benchmark.cpp

View File

@@ -1,17 +1,17 @@
#include <benchmark/benchmark.h>
#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/gfx/headless_frontend.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/image.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mln/map/map.hpp>
#include <mln/map/map_options.hpp>
#include <mln/gfx/headless_frontend.hpp>
#include <mln/renderer/renderer.hpp>
#include <mln/style/style.hpp>
#include <mln/style/image.hpp>
#include <mln/storage/network_status.hpp>
#include <mln/util/image.hpp>
#include <mln/util/io.hpp>
#include <mln/util/run_loop.hpp>
using namespace mbgl;
using namespace mln;
namespace {

View File

@@ -1,24 +1,24 @@
#include <benchmark/benchmark.h>
#include <mbgl/gfx/headless_frontend.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/map/map_observer.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/style/image.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mln/gfx/headless_frontend.hpp>
#include <mln/map/map.hpp>
#include <mln/map/map_observer.hpp>
#include <mln/map/map_options.hpp>
#include <mln/renderer/renderer.hpp>
#include <mln/storage/network_status.hpp>
#include <mln/storage/resource_options.hpp>
#include <mln/style/image.hpp>
#include <mln/style/layers/symbol_layer.hpp>
#include <mln/style/sources/geojson_source.hpp>
#include <mln/style/style.hpp>
#include <mln/util/image.hpp>
#include <mln/util/io.hpp>
#include <mln/util/run_loop.hpp>
#include <sstream>
#include <optional>
using namespace mbgl;
using namespace mln;
namespace {
@@ -124,7 +124,7 @@ static void API_renderStill_recreate_map_2(::benchmark::State& state) {
}
static void API_renderStill_multiple_sources(::benchmark::State& state) {
using namespace mbgl::style;
using namespace mln::style;
RenderBenchmark bench;
HeadlessFrontend frontend{size, pixelRatio};
Map map{frontend,

View File

@@ -1,12 +1,12 @@
#include <benchmark/benchmark.h>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/function.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mln/style/conversion/json.hpp>
#include <mln/style/conversion/function.hpp>
#include <mln/style/conversion/property_value.hpp>
#include <mln/style/conversion_impl.hpp>
using namespace mbgl;
using namespace mbgl::style;
using namespace mln;
using namespace mln::style;
static std::string createFunctionJSON(size_t stopCount) {
std::string stops = "[";

View File

@@ -1,14 +1,14 @@
#include <benchmark/benchmark.h>
#include <mbgl/benchmark/stub_geometry_tile_feature.hpp>
#include <mln/benchmark/stub_geometry_tile_feature.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/function.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mln/style/conversion/json.hpp>
#include <mln/style/conversion/function.hpp>
#include <mln/style/conversion/property_value.hpp>
#include <mln/style/conversion_impl.hpp>
using namespace mbgl;
using namespace mbgl::style;
using namespace mln;
using namespace mln::style;
static std::string createFunctionJSON(size_t stopCount) {
std::string stops = "[";

View File

@@ -1,13 +1,13 @@
#include <benchmark/benchmark.h>
#include <mbgl/benchmark/stub_geometry_tile_feature.hpp>
#include <mln/benchmark/stub_geometry_tile_feature.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mln/style/conversion/json.hpp>
#include <mln/style/conversion/property_value.hpp>
#include <mln/style/conversion_impl.hpp>
using namespace mbgl;
using namespace mbgl::style;
using namespace mln;
using namespace mln::style;
static std::string createFunctionJSON(size_t stopCount) {
std::string stops = "[";

View File

@@ -1,7 +1,7 @@
#pragma once
namespace mbgl {
namespace mln {
int runBenchmark(int argc, char* argv[]);
} // namespace mbgl
} // namespace mln

View File

@@ -1,8 +1,8 @@
#include <ios_test_runner.hpp>
#include <mbgl/benchmark.hpp>
#include <mln/benchmark.hpp>
#include <mbgl/util/logging.hpp>
#include <mln/util/logging.hpp>
#include <unistd.h>
#include <vector>
@@ -22,13 +22,13 @@ bool TestRunner::startTest(const std::string& basePath) {
argv.push_back(nullptr);
if (chdir(basePath.c_str())) {
mbgl::Log::Error(mbgl::Event::General, "Failed to change the directory to " + basePath);
mln::Log::Error(mln::Event::General, "Failed to change the directory to " + basePath);
return false;
}
mbgl::Log::Info(mbgl::Event::General, "Start BenchmarkRunner");
int status = mbgl::runBenchmark(static_cast<uint32_t>(argv.size()), argv.data());
mbgl::Log::Info(mbgl::Event::General, "BenchmarkRunner finished with status: '%d'", status);
mln::Log::Info(mln::Event::General, "Start BenchmarkRunner");
int status = mln::runBenchmark(static_cast<uint32_t>(argv.size()), argv.data());
mln::Log::Info(mln::Event::General, "BenchmarkRunner finished with status: '%d'", status);
return status == 0;
}

View File

@@ -1,13 +1,13 @@
#include <benchmark/benchmark.h>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/benchmark/stub_geometry_tile_feature.hpp>
#include <mln/style/filter.hpp>
#include <mln/style/conversion/json.hpp>
#include <mln/style/conversion/filter.hpp>
#include <mln/style/conversion_impl.hpp>
#include <mln/tile/geometry_tile_data.hpp>
#include <mln/benchmark/stub_geometry_tile_feature.hpp>
using namespace mbgl;
using namespace mln;
style::Filter parse(const char* expression) {
style::conversion::Error error;

View File

@@ -1,8 +1,8 @@
#include <benchmark/benchmark.h>
#include <mbgl/algorithm/update_tile_masks.hpp>
#include <mln/algorithm/update_tile_masks.hpp>
using namespace mbgl;
using namespace mln;
class FakeTile {
public:

View File

@@ -1,9 +1,9 @@
#include <benchmark/benchmark.h>
#include <mbgl/tile/vector_mvt_tile_data.hpp>
#include <mbgl/util/io.hpp>
#include <mln/tile/vector_mvt_tile_data.hpp>
#include <mln/util/io.hpp>
using namespace mbgl;
using namespace mln;
static void Parse_VectorTile(benchmark::State& state) {
auto data = std::make_shared<std::string>(

View File

@@ -1,31 +1,31 @@
#include <benchmark/benchmark.h>
// Core function to benchmark
#include <mbgl/renderer/group_by_layout.hpp>
#include <mln/renderer/group_by_layout.hpp>
// For mock layer properties
#include <mbgl/style/layer_properties.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/style/layers/fill_layer_properties.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/style/layers/line_layer_properties.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp>
#include <mbgl/style/layers/circle_layer_properties.hpp>
#include <mbgl/util/immutable.hpp>
#include <mln/style/layer_properties.hpp>
#include <mln/style/layers/fill_layer_impl.hpp>
#include <mln/style/layers/fill_layer_properties.hpp>
#include <mln/style/layers/line_layer_impl.hpp>
#include <mln/style/layers/line_layer_properties.hpp>
#include <mln/style/layers/symbol_layer_impl.hpp>
#include <mln/style/layers/symbol_layer_properties.hpp>
#include <mln/style/layers/circle_layer_impl.hpp>
#include <mln/style/layers/circle_layer_properties.hpp>
#include <mln/util/immutable.hpp>
// For real style loading
#include <mbgl/style/style_impl.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/layermanager/layer_manager.hpp>
#include <mbgl/renderer/render_layer.hpp>
#include <mbgl/util/thread_pool.hpp>
#include <mln/style/style_impl.hpp>
#include <mln/storage/file_source.hpp>
#include <mln/util/io.hpp>
#include <mln/util/run_loop.hpp>
#include <mln/layermanager/layer_manager.hpp>
#include <mln/renderer/render_layer.hpp>
#include <mln/util/thread_pool.hpp>
using namespace mbgl;
using namespace mbgl::style;
using namespace mln;
using namespace mln::style;
// Minimal FileSource stub for benchmark (doesn't actually fetch resources)
class StubFileSource : public FileSource {

View File

@@ -1,8 +1,8 @@
#include <mbgl/benchmark.hpp>
#include <mln/benchmark.hpp>
#include <benchmark/benchmark.h>
namespace mbgl {
namespace mln {
int runBenchmark(int argc, char* argv[]) {
::benchmark::Initialize(&argc, argv);
@@ -10,4 +10,4 @@ int runBenchmark(int argc, char* argv[]) {
return 0;
}
} // namespace mbgl
} // namespace mln

View File

@@ -1,9 +1,9 @@
#pragma once
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/util/feature.hpp>
#include <mln/tile/geometry_tile_data.hpp>
#include <mln/util/feature.hpp>
using namespace mbgl;
using namespace mln;
class StubGeometryTileFeature : public GeometryTileFeature {
public:

View File

@@ -1,11 +1,11 @@
#include <benchmark/benchmark.h>
#include <mbgl/storage/offline_database.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/storage/sqlite3.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/logging.hpp>
#include <mln/storage/offline_database.hpp>
#include <mln/storage/resource.hpp>
#include <mln/storage/response.hpp>
#include <mln/storage/sqlite3.hpp>
#include <mln/util/string.hpp>
#include <mln/util/logging.hpp>
#include <random>
@@ -18,14 +18,14 @@ public:
response.data = std::make_shared<std::string>(50 * 1024, 0);
response.mustRevalidate = false;
response.expires = mbgl::util::now() + 1h;
response.expires = mln::util::now() + 1h;
resetAmbientTiles();
resetRegion();
}
void resetAmbientTiles() {
using namespace mbgl;
using namespace mln;
db.clearAmbientCache();
@@ -37,7 +37,7 @@ public:
}
void resetRegion() {
using namespace mbgl;
using namespace mln;
auto regions = db.listRegions().value();
if (!regions.empty()) {
@@ -58,8 +58,8 @@ public:
}
}
mbgl::Response response;
mbgl::OfflineDatabase db{":memory:", mbgl::TileServerOptions::DefaultConfiguration()};
mln::Response response;
mln::OfflineDatabase db{":memory:", mln::TileServerOptions::DefaultConfiguration()};
const unsigned tileCount = 100;
int64_t regionID = 0;
@@ -78,7 +78,7 @@ BENCHMARK_F(OfflineDatabase, DeleteRegion)(benchmark::State& state) {
}
BENCHMARK_F(OfflineDatabase, InsertTileRegion)(benchmark::State& state) {
using namespace mbgl;
using namespace mln;
while (state.KeepRunning()) {
const Resource offline = Resource::tile(
@@ -99,7 +99,7 @@ BENCHMARK_F(OfflineDatabase, ClearAmbientCache)(benchmark::State& state) {
}
BENCHMARK_F(OfflineDatabase, InsertTileCache)(benchmark::State& state) {
using namespace mbgl;
using namespace mln;
while (state.KeepRunning()) {
const Resource ambient = Resource::tile(
@@ -109,7 +109,7 @@ BENCHMARK_F(OfflineDatabase, InsertTileCache)(benchmark::State& state) {
}
BENCHMARK_F(OfflineDatabase, InsertBigTileCache)(benchmark::State& state) {
using namespace mbgl;
using namespace mln;
Response big;
big.data = std::make_shared<std::string>(util::DEFAULT_MAX_CACHE_SIZE / 100, 0);
@@ -122,7 +122,7 @@ BENCHMARK_F(OfflineDatabase, InsertBigTileCache)(benchmark::State& state) {
}
BENCHMARK_F(OfflineDatabase, GetTile)(benchmark::State& state) {
using namespace mbgl;
using namespace mln;
std::random_device rd;
std::mt19937 gen(rd());
@@ -136,7 +136,7 @@ BENCHMARK_F(OfflineDatabase, GetTile)(benchmark::State& state) {
}
BENCHMARK_F(OfflineDatabase, AddTilesToFullDatabase)(benchmark::State& state) {
using namespace mbgl;
using namespace mln;
Log::setObserver(std::make_unique<Log::NullObserver>());
db.setMaximumAmbientCacheSize(50 * 1024 * 5);
@@ -152,7 +152,7 @@ BENCHMARK_F(OfflineDatabase, AddTilesToFullDatabase)(benchmark::State& state) {
BENCHMARK_F(OfflineDatabase, AddTilesToDisabledDatabase)
(benchmark::State& state) {
using namespace mbgl;
using namespace mln;
auto regions = db.listRegions().value();
if (!regions.empty()) {
@@ -171,7 +171,7 @@ BENCHMARK_F(OfflineDatabase, AddTilesToDisabledDatabase)
BENCHMARK_F(OfflineDatabase, GetTileFromDisabledDatabase)
(benchmark::State& state) {
using namespace mbgl;
using namespace mln;
auto regions = db.listRegions().value();
if (!regions.empty()) {

View File

@@ -2,7 +2,7 @@
#include <string>
#include <vector>
#include <mbgl/util/color.hpp>
#include <mln/util/color.hpp>
static const std::vector<std::string> testStrings = {"#000000",
"#FFFFFF",
@@ -20,7 +20,7 @@ namespace {
void ColorParse(benchmark::State& state) {
for (auto _ : state) {
for (const auto& str : testStrings) {
auto result = mbgl::Color::parse(str);
auto result = mln::Color::parse(str);
benchmark::DoNotOptimize(result);
}
}

View File

@@ -1,11 +1,11 @@
#include <benchmark/benchmark.h>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/tile_coordinate.hpp>
#include <mbgl/util/tile_cover.hpp>
#include <mbgl/map/transform.hpp>
#include <mln/util/geo.hpp>
#include <mln/util/geometry.hpp>
#include <mln/util/tile_coordinate.hpp>
#include <mln/util/tile_cover.hpp>
#include <mln/map/transform.hpp>
using namespace mbgl;
using namespace mln;
static const LatLngBounds sanFrancisco = LatLngBounds::hull({37.6609, -122.5744}, {37.8271, -122.3204});

View File

@@ -1,8 +1,8 @@
#include <mbgl/storage/file_source_manager.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mln/storage/file_source_manager.hpp>
#include <mln/storage/resource.hpp>
#include <mln/storage/resource_options.hpp>
#include <mln/util/chrono.hpp>
#include <mln/util/run_loop.hpp>
#include <args.hxx>
#include <mapbox/io/io.hpp>
@@ -25,20 +25,20 @@ int main(int argc, char* argv[]) {
args::ValueFlag<unsigned long> expiresValue(p, "expires", "Expires date, will use 'now' otherwise", {'e'});
args::ValueFlag<unsigned long> modifiedValue(p, "modified", "Modified date, will use 'now' otherwise", {'m'});
std::unordered_map<std::string, mbgl::Resource::Kind> typeMap{{"glyphs", mbgl::Resource::Glyphs},
{"image", mbgl::Resource::Image},
{"source", mbgl::Resource::Source},
{"sprite-image", mbgl::Resource::SpriteImage},
{"sprite-json", mbgl::Resource::SpriteJSON},
{"style", mbgl::Resource::Style},
{"tile", mbgl::Resource::Tile}};
std::unordered_map<std::string, mln::Resource::Kind> typeMap{{"glyphs", mln::Resource::Glyphs},
{"image", mln::Resource::Image},
{"source", mln::Resource::Source},
{"sprite-image", mln::Resource::SpriteImage},
{"sprite-json", mln::Resource::SpriteJSON},
{"style", mln::Resource::Style},
{"tile", mln::Resource::Tile}};
std::string typeHelp("One of the following (required):");
for (const auto& key : typeMap) {
typeHelp += " " + key.first;
}
args::MapFlag<std::string, mbgl::Resource::Kind> typeFlag(
args::MapFlag<std::string, mln::Resource::Kind> typeFlag(
p, "type", typeHelp, {"type"}, typeMap, args::Options::Required);
args::Group tileIdGroup(p, "Coordinates (required for 'tile')", args::Group::Validators::AllOrNone);
@@ -67,15 +67,15 @@ int main(int argc, char* argv[]) {
exit(3);
}
mbgl::Response response;
mln::Response response;
response.data = std::make_shared<std::string>(*file);
response.etag = etagValue ? args::get(etagValue) : std::string();
response.expires = expiresValue ? mbgl::Timestamp(mbgl::Seconds(args::get(expiresValue))) : mbgl::util::now();
response.modified = modifiedValue ? mbgl::Timestamp(mbgl::Seconds(args::get(modifiedValue))) : mbgl::util::now();
response.expires = expiresValue ? mln::Timestamp(mln::Seconds(args::get(expiresValue))) : mln::util::now();
response.modified = modifiedValue ? mln::Timestamp(mln::Seconds(args::get(modifiedValue))) : mln::util::now();
mbgl::Resource resource(args::get(typeFlag), args::get(urlValue));
mln::Resource resource(args::get(typeFlag), args::get(urlValue));
if (args::get(typeFlag) == mbgl::Resource::Tile) {
if (args::get(typeFlag) == mln::Resource::Tile) {
if (!xValueFlag || !yValueFlag || !zValueFlag) {
std::cerr << "Error: -x, -y and -z must be provided for tiles" << '\n';
exit(1);
@@ -88,9 +88,9 @@ int main(int argc, char* argv[]) {
.z = static_cast<int8_t>(args::get(zValueFlag))}};
}
mbgl::util::RunLoop loop;
std::shared_ptr<mbgl::FileSource> dbfs = mbgl::FileSourceManager::get()->getFileSource(
mbgl::FileSourceType::Database, mbgl::ResourceOptions().withCachePath(args::get(cacheValue)));
mln::util::RunLoop loop;
std::shared_ptr<mln::FileSource> dbfs = mln::FileSourceManager::get()->getFileSource(
mln::FileSourceType::Database, mln::ResourceOptions().withCachePath(args::get(cacheValue)));
dbfs->forward(resource, response, [&loop] { loop.stop(); });
loop.run();
return 0;

View File

@@ -1,12 +1,12 @@
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/geojson.hpp>
#include <mln/util/run_loop.hpp>
#include <mln/util/string.hpp>
#include <mln/util/geojson.hpp>
#include <mbgl/storage/database_file_source.hpp>
#include <mbgl/storage/file_source_manager.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/util/client_options.hpp>
#include <mbgl/util/tile_server_options.hpp>
#include <mln/storage/database_file_source.hpp>
#include <mln/storage/file_source_manager.hpp>
#include <mln/storage/resource_options.hpp>
#include <mln/util/client_options.hpp>
#include <mln/util/tile_server_options.hpp>
#include <args.hxx>
@@ -51,19 +51,19 @@ mapbox::geometry::geometry<double> parseGeometry(const std::string& json) {
});
}
std::ostream& operator<<(std::ostream& os, mbgl::Response::Error::Reason r) {
std::ostream& operator<<(std::ostream& os, mln::Response::Error::Reason r) {
switch (r) {
case mbgl::Response::Error::Reason::Success:
case mln::Response::Error::Reason::Success:
return os << "Response::Error::Reason::Success";
case mbgl::Response::Error::Reason::NotFound:
case mln::Response::Error::Reason::NotFound:
return os << "Response::Error::Reason::NotFound";
case mbgl::Response::Error::Reason::Server:
case mln::Response::Error::Reason::Server:
return os << "Response::Error::Reason::Server";
case mbgl::Response::Error::Reason::Connection:
case mln::Response::Error::Reason::Connection:
return os << "Response::Error::Reason::Connection";
case mbgl::Response::Error::Reason::RateLimit:
case mln::Response::Error::Reason::RateLimit:
return os << "Response::Error::Reason::RateLimit";
case mbgl::Response::Error::Reason::Other:
case mln::Response::Error::Reason::Other:
return os << "Response::Error::Reason::Other";
}
@@ -122,7 +122,7 @@ int main(int argc, char* argv[]) {
exit(2);
}
auto mapTilerConfiguration = mbgl::TileServerOptions::MapTilerConfiguration();
auto mapTilerConfiguration = mln::TileServerOptions::MapTilerConfiguration();
std::string style = styleValue ? args::get(styleValue) : mapTilerConfiguration.defaultStyles().at(0).getUrl();
std::cout << " Style: " << style << std::endl;
@@ -138,7 +138,7 @@ int main(int argc, char* argv[]) {
const bool includeIdeographs = includeIdeographsValue ? args::get(includeIdeographsValue) : false;
const std::string output = outputValue ? args::get(outputValue) : "offline.db";
using namespace mbgl;
using namespace mln;
OfflineRegionDefinition definition = [&]() {
if (geometryValue) {
@@ -185,7 +185,7 @@ int main(int argc, char* argv[]) {
int retCode = 0;
std::cout << "Start Merge" << std::endl;
inputSource.mergeOfflineRegions(
*mergePath, [&](mbgl::expected<std::vector<OfflineRegion>, std::exception_ptr> result) {
*mergePath, [&](mln::expected<std::vector<OfflineRegion>, std::exception_ptr> result) {
if (!result) {
std::cerr << "Error merging database: " << util::toString(result.error()) << std::endl;
retCode = 1;
@@ -264,7 +264,7 @@ int main(int argc, char* argv[]) {
std::signal(SIGINT, [](int) { stop(); });
fileSource->createOfflineRegion(
definition, metadata, [&](mbgl::expected<OfflineRegion, std::exception_ptr> region_) {
definition, metadata, [&](mln::expected<OfflineRegion, std::exception_ptr> region_) {
if (!region_) {
std::cerr << "Error creating region: " << util::toString(region_.error()) << std::endl;
loop.stop();

View File

@@ -1,11 +1,11 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mln/map/map.hpp>
#include <mln/map/map_options.hpp>
#include <mln/util/image.hpp>
#include <mln/util/run_loop.hpp>
#include <mbgl/gfx/backend.hpp>
#include <mbgl/gfx/headless_frontend.hpp>
#include <mbgl/style/style.hpp>
#include <mln/gfx/backend.hpp>
#include <mln/gfx/headless_frontend.hpp>
#include <mln/style/style.hpp>
#include <args.hxx>
@@ -19,8 +19,10 @@ int main(int argc, char* argv[]) {
args::ValueFlag<std::string> backendValue(argumentParser, "Backend", "Rendering backend", {"backend"});
args::ValueFlag<std::string> apikeyValue(argumentParser, "key", "API key", {'t', "apikey"});
args::ValueFlag<std::string> styleValue(argumentParser, "URL", "Map stylesheet", {'s', "style"});
args::ValueFlag<std::string> outputValue(argumentParser, "file", "Output file name", {'o', "output"});
args::ValueFlag<std::string> styleValue(
argumentParser, "URL|file|-", "Map stylesheet (use '-' for stdin)", {'s', "style"});
args::ValueFlag<std::string> outputValue(
argumentParser, "file|-", "Output file name (use '-' for stdout)", {'o', "output"});
args::ValueFlag<std::string> cacheValue(argumentParser, "file", "Cache database file name", {'c', "cache"});
args::ValueFlag<std::string> assetsValue(
argumentParser, "file", "Directory to which asset:// URLs will resolve", {'a', "assets"});
@@ -69,7 +71,7 @@ int main(int argc, char* argv[]) {
const double lon = lonValue ? args::get(lonValue) : 0;
const double alt = altValue ? args::get(altValue) : 0;
const double zoom = zoomValue ? args::get(zoomValue) : 0;
const double fov = fovValue ? args::get(fovValue) : mbgl::util::rad2deg(mbgl::util::DEFAULT_FOV);
const double fov = fovValue ? args::get(fovValue) : mln::util::rad2deg(mln::util::DEFAULT_FOV);
const double bearing = bearingValue ? args::get(bearingValue) : 0;
const double pitch = pitchValue ? args::get(pitchValue) : 0;
const double roll = rollValue ? args::get(rollValue) : 0;
@@ -87,9 +89,11 @@ int main(int argc, char* argv[]) {
const bool debug = debugFlag ? args::get(debugFlag) : false;
using namespace mbgl;
using namespace mln;
auto mapTilerConfiguration = mbgl::TileServerOptions::MapTilerConfiguration();
auto mapTilerConfiguration = mln::TileServerOptions::MapTilerConfiguration();
std::string json;
std::string style = styleValue ? args::get(styleValue) : mapTilerConfiguration.defaultStyles().at(0).getUrl();
util::RunLoop loop;
@@ -115,11 +119,16 @@ int main(int argc, char* argv[]) {
.withApiKey(apikey)
.withTileServerOptions(mapTilerConfiguration));
if (style.find("://") == std::string::npos) {
style = std::string("file://") + style;
}
if (style == "-") {
json = std::string(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>());
map.getStyle().loadJSON(json);
} else {
if (style.find("://") == std::string::npos) {
style = std::string("file://") + style;
}
map.getStyle().loadURL(style);
map.getStyle().loadURL(style);
}
std::vector<double> bounds = args::get(boundsValue);
if (bounds.size() == 4) {
LatLngBounds boundingBox = LatLngBounds::hull(LatLng(bounds[0], bounds[1]), LatLng(bounds[2], bounds[3]));
@@ -136,14 +145,19 @@ int main(int argc, char* argv[]) {
}
if (debug) {
map.setDebug(debug ? mbgl::MapDebugOptions::TileBorders | mbgl::MapDebugOptions::ParseStatus
: mbgl::MapDebugOptions::NoDebug);
map.setDebug(debug ? mln::MapDebugOptions::TileBorders | mln::MapDebugOptions::ParseStatus
: mln::MapDebugOptions::NoDebug);
}
try {
std::ofstream out(output, std::ios::binary);
out << encodePNG(frontend.render(map).image);
out.close();
std::string png = encodePNG(frontend.render(map).image);
if (output == "-") {
std::cout.write(png.data(), png.size());
} else {
std::ofstream out(output, std::ios::binary);
out << png;
out.close();
}
} catch (std::exception& e) {
std::cout << "Error: " << e.what() << std::endl;
exit(1);

View File

@@ -11,96 +11,93 @@ target_compile_definitions(
)
list(APPEND
INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/command_encoder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/context.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/drawable.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/drawable_builder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/dynamic_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/index_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/mtl_fwd.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/offscreen_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/render_pass.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/renderable_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/texture2d.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/tile_layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/uniform_buffer.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/upload_pass.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/vertex_attribute.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/vertex_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/background.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/circle.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/clipping_mask.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/common.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/collision.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/custom_geometry.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/custom_symbol_icon.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/debug.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill_extrusion.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/heatmap.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/heatmap_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/hillshade.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/hillshade_prepare.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/color_relief.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/line.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/location_indicator.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/particle_gpu_validation.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/retained_underlay_composite.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/raster.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_program.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/symbol.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/command_encoder.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/context.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/drawable.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/drawable_builder.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/dynamic_texture.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/index_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/mtl_fwd.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/offscreen_texture.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/render_pass.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/renderable_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/texture2d.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/tile_layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/uniform_buffer.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/upload_pass.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/vertex_attribute.hpp
${PROJECT_SOURCE_DIR}/include/mln/mtl/vertex_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/background.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/circle.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/clipping_mask.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/common.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/collision.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/custom_geometry.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/custom_symbol_icon.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/debug.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/fill.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/fill_extrusion.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/heatmap.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/heatmap_texture.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/hillshade.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/hillshade_prepare.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/color_relief.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/line.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/location_indicator.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/particle_gpu_validation.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/retained_underlay_composite.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/raster.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/shader_group.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/shader_program.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/mtl/symbol.hpp
)
list(APPEND
SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/context.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_builder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/dynamic_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/index_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/mtl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/offscreen_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/render_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/tile_layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/vertex_attribute.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/vertex_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/shader_program.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/background.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/circle.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/collision.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/clipping_mask.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/custom_geometry.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/custom_symbol_icon.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/debug.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/fill.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/fill_extrusion.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/heatmap.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/heatmap_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/hillshade.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/hillshade_prepare.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/color_relief.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/line.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/location_indicator.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/particle_gpu_validation.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/retained_underlay_composite.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/raster.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/symbol.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/widevector.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/mtl/custom_layer_render_parameters.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/context.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/drawable.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/drawable_impl.hpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/drawable_builder.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/dynamic_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/index_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/mtl.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/offscreen_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/render_pass.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/tile_layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/vertex_attribute.cpp
${PROJECT_SOURCE_DIR}/src/mln/mtl/vertex_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/shader_program.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/background.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/circle.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/collision.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/clipping_mask.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/custom_geometry.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/custom_symbol_icon.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/debug.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/fill.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/fill_extrusion.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/heatmap.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/heatmap_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/hillshade.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/hillshade_prepare.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/color_relief.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/line.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/location_indicator.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/particle_gpu_validation.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/retained_underlay_composite.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/raster.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/symbol.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/mtl/widevector.cpp
${PROJECT_SOURCE_DIR}/src/mln/style/layers/mtl/custom_layer_render_parameters.cpp
)
find_library(METAL_FRAMEWORK Metal)
if (METAL_FRAMEWORK)
target_link_libraries(mbgl-core PRIVATE ${METAL_FRAMEWORK})
endif()
target_link_libraries(mbgl-core PRIVATE "-framework Metal")

View File

@@ -11,143 +11,144 @@ target_compile_definitions(
)
list(APPEND
INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/gl/renderable_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/platform/gl_functions.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/shader_manifest.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/shader_group_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/prelude.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/circle.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/clipping_mask.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/collision_box.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/collision_circle.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/custom_geometry.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/custom_symbol_icon.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/debug.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/fill.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/fill_outline.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/fill_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/fill_outline_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/fill_outline_triangulated.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/fill_extrusion.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/fill_extrusion_instanced.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/fill_extrusion_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/fill_extrusion_pattern_instanced.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/heatmap.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/heatmap_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/retained_underlay_composite.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/hillshade_prepare.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/hillshade.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/color_relief.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line_gradient.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line_sdf.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/location_indicator.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/location_indicator_textured.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/raster.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/symbol_icon.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/symbol_sdf.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/symbol_text_and_icon.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/wide_vector.hpp
${PROJECT_SOURCE_DIR}/include/mln/gl/renderable_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/gl/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mln/platform/gl_functions.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/shader_manifest.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/shader_group_gl.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/prelude.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/background.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/background_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/circle.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/clipping_mask.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/collision_box.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/collision_circle.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/custom_geometry.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/custom_symbol_icon.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/debug.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/fill.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/fill_outline.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/fill_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/fill_outline_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/fill_outline_triangulated.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/fill_extrusion.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/fill_extrusion_instanced.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/fill_extrusion_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/fill_extrusion_pattern_instanced.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/heatmap.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/heatmap_texture.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/particle_gpu_validation.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/retained_underlay_composite.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/hillshade_prepare.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/hillshade.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/color_relief.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/line.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/line_gradient.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/line_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/line_sdf.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/location_indicator.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/location_indicator_textured.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/raster.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/symbol_icon.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/symbol_sdf.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/symbol_text_and_icon.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/wide_vector.hpp
)
list(APPEND
SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/gl/attribute.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/attribute.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/command_encoder.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/context.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/context.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/fence.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/fence.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/debugging_extension.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/debugging_extension.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/defines.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/draw_scope_resource.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/enum.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/enum.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/extension.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/framebuffer.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/index_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/index_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/object.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/object.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/offscreen_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/offscreen_texture.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_pass.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/renderbuffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/renderbuffer_resource.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/resource_pool.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/resource_pool.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/state.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/timestamp_query_extension.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/timestamp_query_extension.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/types.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/uniform.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/uniform.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/upload_pass.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/value.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/value.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_array.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_array.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/platform/gl_functions.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/gl/legacy/clipping_mask_program.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/gl/legacy/program_base.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/gl/legacy/program.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/gl/legacy/programs.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/gl/legacy/programs.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/attribute.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/attribute.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/command_encoder.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/context.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/context.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/fence.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/fence.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/debugging_extension.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/debugging_extension.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/defines.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/draw_scope_resource.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/enum.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/enum.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/extension.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/framebuffer.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/index_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/index_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/object.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/object.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/offscreen_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/offscreen_texture.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/render_pass.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/render_pass.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/renderbuffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/renderbuffer_resource.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/resource_pool.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/resource_pool.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/state.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/timestamp_query_extension.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/timestamp_query_extension.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/types.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/uniform.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/uniform.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/upload_pass.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/value.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/value.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/vertex_array.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/vertex_array.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/vertex_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/vertex_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/src/mln/platform/gl_functions.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/gl/legacy/clipping_mask_program.hpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/gl/legacy/program_base.hpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/gl/legacy/program.hpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/gl/legacy/programs.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/gl/legacy/programs.hpp
)
list(APPEND INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/background_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/circle_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/collision_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/custom_drawable_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/debug_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/fill_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/fill_extrusion_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_texture_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/hillshade_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/color_relief_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/line_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/location_indicator_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/raster_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/shader_defines.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/symbol_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/widevector_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/custom_drawable_layer.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/custom_drawable_layer_factory.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/shader_program_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/buffer_allocator.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl_builder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/dynamic_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/layer_group_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/texture2d.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_buffer_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/vertex_attribute_gl.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/background_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/circle_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/collision_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/custom_drawable_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/debug_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/fill_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/fill_extrusion_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/heatmap_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/heatmap_texture_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/hillshade_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/color_relief_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/hillshade_prepare_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/line_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/location_indicator_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/raster_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/shader_defines.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/symbol_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/widevector_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mln/style/layers/custom_drawable_layer.hpp
${PROJECT_SOURCE_DIR}/include/mln/layermanager/custom_drawable_layer_factory.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/gl/shader_program_gl.hpp
${PROJECT_SOURCE_DIR}/include/mln/gl/buffer_allocator.hpp
${PROJECT_SOURCE_DIR}/include/mln/gl/drawable_gl.hpp
${PROJECT_SOURCE_DIR}/include/mln/gl/drawable_gl_builder.hpp
${PROJECT_SOURCE_DIR}/include/mln/gl/dynamic_texture.hpp
${PROJECT_SOURCE_DIR}/include/mln/gl/layer_group_gl.hpp
${PROJECT_SOURCE_DIR}/include/mln/gl/texture2d.hpp
${PROJECT_SOURCE_DIR}/include/mln/gl/uniform_buffer_gl.hpp
${PROJECT_SOURCE_DIR}/include/mln/gl/vertex_attribute_gl.hpp
)
list(APPEND SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/gl/shader_info.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/gl/shader_program_gl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/buffer_allocator.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl_builder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/dynamic_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/layer_group_gl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/uniform_buffer_gl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_attribute_gl.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/gl/shader_info.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/gl/shader_program_gl.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/buffer_allocator.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/drawable_gl.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/drawable_gl_builder.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/drawable_gl_impl.hpp
${PROJECT_SOURCE_DIR}/src/mln/gl/dynamic_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/layer_group_gl.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/uniform_buffer_gl.cpp
${PROJECT_SOURCE_DIR}/src/mln/gl/vertex_attribute_gl.cpp
)

View File

@@ -12,93 +12,93 @@ target_compile_definitions(
list(APPEND
INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/vulkan/custom_layer_init_parameters.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/vulkan/custom_layer_render_parameters.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/command_encoder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/context.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/drawable.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/descriptor_set.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/drawable_builder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/dynamic_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/index_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/offscreen_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/pipeline.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/render_pass.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/renderable_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/texture2d.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/tile_layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/uniform_buffer.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/upload_pass.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/vertex_attribute.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/vertex_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/shader_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/shader_program.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/background.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/circle.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/clipping_mask.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/collision.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/common.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/custom_geometry.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/custom_symbol_icon.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/fill.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/fill_extrusion.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/heatmap.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/heatmap_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/hillshade.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/hillshade_prepare.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/color_relief.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/line.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/location_indicator.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/raster.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/symbol.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/widevector.hpp
${PROJECT_SOURCE_DIR}/include/mln/style/layers/vulkan/custom_layer_init_parameters.hpp
${PROJECT_SOURCE_DIR}/include/mln/style/layers/vulkan/custom_layer_render_parameters.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/command_encoder.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/context.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/drawable.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/descriptor_set.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/drawable_builder.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/dynamic_texture.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/index_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/offscreen_texture.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/pipeline.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/render_pass.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/renderable_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/texture2d.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/tile_layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/uniform_buffer.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/upload_pass.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/vertex_attribute.hpp
${PROJECT_SOURCE_DIR}/include/mln/vulkan/vertex_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/shader_group.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/shader_program.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/background.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/circle.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/clipping_mask.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/collision.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/common.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/custom_geometry.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/custom_symbol_icon.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/fill.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/fill_extrusion.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/heatmap.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/heatmap_texture.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/hillshade.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/hillshade_prepare.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/color_relief.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/line.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/location_indicator.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/raster.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/symbol.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/vulkan/widevector.hpp
)
list(APPEND
SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/vulkan/custom_layer_render_parameters.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/context.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/descriptor_set.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/drawable.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/drawable_builder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/drawable_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/dynamic_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/index_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/offscreen_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/pipeline.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/render_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/renderable_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/tile_layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/vertex_attribute.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/vertex_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/shader_program.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/background.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/circle.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/clipping_mask.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/collision.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/custom_geometry.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/custom_symbol_icon.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/debug.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/fill.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/fill_extrusion.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/heatmap.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/heatmap_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/hillshade.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/hillshade_prepare.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/color_relief.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/line.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/location_indicator.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/raster.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/symbol.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/widevector.cpp
${PROJECT_SOURCE_DIR}/src/mln/style/layers/vulkan/custom_layer_render_parameters.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/context.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/descriptor_set.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/drawable.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/drawable_builder.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/drawable_impl.hpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/dynamic_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/index_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/offscreen_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/pipeline.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/render_pass.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/renderable_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/tile_layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/vertex_attribute.cpp
${PROJECT_SOURCE_DIR}/src/mln/vulkan/vertex_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/shader_program.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/background.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/circle.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/clipping_mask.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/collision.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/custom_geometry.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/custom_symbol_icon.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/debug.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/fill.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/fill_extrusion.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/heatmap.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/heatmap_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/hillshade.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/hillshade_prepare.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/color_relief.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/line.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/location_indicator.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/raster.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/symbol.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/vulkan/widevector.cpp
)

View File

@@ -17,99 +17,98 @@ target_include_directories(
list(APPEND
SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/context.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/headless_backend.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/drawable.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/drawable_builder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/draw_scope_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/dynamic_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/shader_program.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/wgsl_preprocessor.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/background.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/circle.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/clipping_mask.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/collision.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/custom_geometry.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/custom_symbol_icon.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/debug.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/fill.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/fill_extrusion.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/heatmap.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/heatmap_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/hillshade.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/hillshade_prepare.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/color_relief.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/line.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/location_indicator.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/raster.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/symbol.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/widevector.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/vertex_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/vertex_attribute.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/offscreen_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/tile_layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/context.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/drawable.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/drawable_builder.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/draw_scope_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/dynamic_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/shader_program.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/wgsl_preprocessor.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/background.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/circle.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/clipping_mask.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/collision.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/custom_geometry.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/custom_symbol_icon.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/debug.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/fill.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/fill_extrusion.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/heatmap.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/heatmap_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/hillshade.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/hillshade_prepare.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/color_relief.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/line.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/location_indicator.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/raster.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/symbol.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/widevector.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/vertex_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/vertex_attribute.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/offscreen_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/tile_layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/layer_group.cpp
)
list(APPEND
INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/command_encoder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/context.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/drawable.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/drawable_builder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/dynamic_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/index_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/render_pass.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/shader_program.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/background.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/circle.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/clipping_mask.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/collision.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/common.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/custom_geometry.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/custom_symbol_icon.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/debug.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/fill.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/fill_extrusion.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/heatmap.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/heatmap_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/hillshade.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/hillshade_prepare.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/color_relief.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/line.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/location_indicator.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/raster.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/symbol.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/widevector.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/texture2d.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/uniform_buffer.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/upload_pass.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/webgpu/vertex_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/command_encoder.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/context.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/drawable.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/drawable_builder.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/dynamic_texture.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/index_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/render_pass.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/shader_program.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/background.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/circle.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/clipping_mask.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/collision.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/common.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/custom_geometry.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/custom_symbol_icon.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/debug.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/fill.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/fill_extrusion.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/heatmap.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/heatmap_texture.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/hillshade.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/hillshade_prepare.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/color_relief.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/line.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/location_indicator.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/raster.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/symbol.hpp
${PROJECT_SOURCE_DIR}/include/mln/shaders/webgpu/widevector.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/texture2d.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/uniform_buffer.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/upload_pass.hpp
${PROJECT_SOURCE_DIR}/include/mln/webgpu/vertex_buffer_resource.hpp
)
list(APPEND
SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/context.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/drawable.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/drawable_builder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/dynamic_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/index_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/render_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/shader_program.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/vertex_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/context.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/drawable.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/drawable_builder.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/dynamic_texture.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/index_buffer_resource.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/render_pass.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mln/shaders/webgpu/shader_program.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mln/webgpu/vertex_buffer_resource.cpp
)
# Include WebGPU vendor configuration (Dawn or wgpu)
@@ -119,7 +118,13 @@ include(${PROJECT_SOURCE_DIR}/vendor/webgpu.cmake)
if(MLN_WEBGPU_IMPL_DAWN)
include(${PROJECT_SOURCE_DIR}/vendor/dawn.cmake)
if(TARGET mbgl-vendor-dawn)
target_link_libraries(mbgl-core PRIVATE mbgl-vendor-dawn)
if(MLN_WEBGPU_EMDAWN)
# Emdawn is a compiler/linker port rather than a conventional
# library. Consumers must inherit its final-link options.
target_link_libraries(mbgl-core PUBLIC mbgl-vendor-dawn)
else()
target_link_libraries(mbgl-core PRIVATE mbgl-vendor-dawn)
endif()
endif()
elseif(MLN_WEBGPU_IMPL_WGPU OR MLN_WEBGPU_IMPL_FFI)
# Include wgpu-native integration
@@ -127,6 +132,11 @@ elseif(MLN_WEBGPU_IMPL_WGPU OR MLN_WEBGPU_IMPL_FFI)
if(TARGET mbgl-vendor-wgpu)
target_link_libraries(mbgl-core PRIVATE mbgl-vendor-wgpu)
# Add WebGPU-Cpp implementation file (required for wgpu-native backend)
list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/webgpu/webgpu_cpp_impl.cpp)
list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mln/webgpu/webgpu_cpp_impl.cpp)
endif()
endif()
# Headless backend uses Dawn native / wgpu-native bootstrap; skip for emdawnwebgpu.
if(NOT MLN_WEBGPU_EMDAWN)
list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mln/webgpu/headless_backend.cpp)
endif()

View File

@@ -75,7 +75,7 @@ The shaders need a representation visible outside the toolkit and we need to cha
Individual shaders are represented by an object class with massive amounts of template logic and a minimum of in-line comments. They’re opaque from the outside and only controllable through vector tile data and styles.
The [render_raster_layer](https://github.com/maplibre/maplibre-native/blob/main/src/mbgl/renderer/layers/render_raster_layer.cpp), as an example, asks for the instantiation of (eventually) RasterProgram. Rather than having the source for the program, that then pokes into a compressed chunk of memory that contains the source, which is then uncompressed and fed into OpenGL for compilation.
The [render_raster_layer](https://github.com/maplibre/maplibre-native/blob/main/src/mln/renderer/layers/render_raster_layer.cpp), as an example, asks for the instantiation of (eventually) RasterProgram. Rather than having the source for the program, that then pokes into a compressed chunk of memory that contains the source, which is then uncompressed and fed into OpenGL for compilation.
All of this makes sense in context, but is completely inaccessible outside the toolkit and rather incomprehensible when making changes.
@@ -134,9 +134,9 @@ Modern graphics pipelines use more than one pass to create a visual representati
Without getting too deep into specifics, early rendering passes allow the developer to use the power of the rasterizer for their own data. Later rendering passes are typically used to decorate the map with effects.
#### The way it is now:
The [low level rendering logic](https://github.com/maplibre/maplibre-native/blob/main/src/mbgl/renderer/renderer_impl.cpp) in the toolkit seems to only support one explicit rendering pass.
The [low level rendering logic](https://github.com/maplibre/maplibre-native/blob/main/src/mln/renderer/renderer_impl.cpp) in the toolkit seems to only support one explicit rendering pass.
However, there is the [RenderPass](https://github.com/maplibre/maplibre-native/blob/main/src/mbgl/gl/render_pass.hpp) so some notion of this exists in the toolkit, but it's not clear how complete that is. It may depend on ordering to work things out, rather than the explicit command buffer filling and fences we would use in a more modern approach.
However, there is the [RenderPass](https://github.com/maplibre/maplibre-native/blob/main/src/mln/gl/render_pass.hpp) so some notion of this exists in the toolkit, but it's not clear how complete that is. It may depend on ordering to work things out, rather than the explicit command buffer filling and fences we would use in a more modern approach.
In any case, we need this filled out more explicitly for the render targets.
@@ -205,7 +205,7 @@ In WhirlyGlobe we’ve always called out separate objects for drawing certain ki
Which is to say that Drawable is a good concept which can encapsulate a lot of complexity. So much so that it eventually encapsulates ALL the complexity, at least at that level of rendering. It’s a good interface between the things that construct geometry and the things that render geometry.
To keep the Drawable somewhat manageable, we added the concept of a Drawable Builder. This is an object that you throw geometry at in a somewhat disordered way and it emits Drawables when you’re done. MapLibre's [Buckets](https://github.com/maplibre/maplibre-native/blob/main/src/mbgl/renderer/bucket.hpp) are similar, but not quite the same. Perhaps they'll be adaptable. We'll see.
To keep the Drawable somewhat manageable, we added the concept of a Drawable Builder. This is an object that you throw geometry at in a somewhat disordered way and it emits Drawables when you’re done. MapLibre's [Buckets](https://github.com/maplibre/maplibre-native/blob/main/src/mln/renderer/bucket.hpp) are similar, but not quite the same. Perhaps they'll be adaptable. We'll see.
Drawables and Builders have a subclass for each supported rendering SDK. One mistake we won’t bring over is using multiple inheritance for that. You’re welcome.
@@ -221,7 +221,7 @@ Builders will be used primarily by Layers to emit Drawables for rendering.
This is a big topic because it gets to the very heart of the critical changes we want to make to the toolkit. There are a couple of different categories that are revealing and we'll use some examples.
Most commonly there are *render layers*. These are individual classes that know how to render, for instance, the [fill layer](https://github.com/maplibre/maplibre-native/blob/main/src/mbgl/renderer/layers/render_fill_layer.cpp). You'll see a bunch of these that start with "render" and end with "layer".
Most commonly there are *render layers*. These are individual classes that know how to render, for instance, the [fill layer](https://github.com/maplibre/maplibre-native/blob/main/src/mln/renderer/layers/render_fill_layer.cpp). You'll see a bunch of these that start with "render" and end with "layer".
What's going on here is that the toolkit has broken out a bunch of features from a tile, consolidated them together in a Bucket and then handed them off to a Layer to render. Sure enough, if you look in the render_*_layer you can see it doing just that.
@@ -230,7 +230,7 @@ Now it's not redoing the work of consolidation each frame, but it is doing a lot
- This is more specific logic than we'd want to see in a rendering loop. Remember, this runs every frame.
- If your data is not in tile form, it's going to be hard to render.
That last one is really interesting and we can find an example in MapLibre Native itself. Look to the [Render Location Indicator Layer](https://github.com/maplibre/maplibre-native/blob/main/src/mbgl/renderer/layers/render_location_indicator_layer.cpp). Here's where this approach trips up... rolls down the hill... into a pile of broken glass. You can feel the developers' pain in this module.
That last one is really interesting and we can find an example in MapLibre Native itself. Look to the [Render Location Indicator Layer](https://github.com/maplibre/maplibre-native/blob/main/src/mln/renderer/layers/render_location_indicator_layer.cpp). Here's where this approach trips up... rolls down the hill... into a pile of broken glass. You can feel the developers' pain in this module.
If you're not familiar with real time rendering toolkits, I'll put it this way. Managing the logic for a location puck that updates every time the user moves should not involve direct OpenGL calls. It should be abstracted, at least a little.
@@ -319,7 +319,7 @@ Every real time rendering toolkit has a main rendering loop or something like it
On iOS this runs on the main thread and on Android this runs on its own separate thread. You might think the latter is better, but it has its own problems (gesture lag). In any case, MapLibre Native handles both just fine.
The toolkit's main rendering "loop" lives in [renderer_impl](https://github.com/maplibre/maplibre-native/blob/main/src/mbgl/renderer/renderer_impl.cpp) and it's worth a look. It serves as a central point to begin examining the real time rendering.
The toolkit's main rendering "loop" lives in [renderer_impl](https://github.com/maplibre/maplibre-native/blob/main/src/mln/renderer/renderer_impl.cpp) and it's worth a look. It serves as a central point to begin examining the real time rendering.
As you might suspect, the rendering loop logic and implementation are heavily influenced by OpenGL.

View File

@@ -0,0 +1,184 @@
# Custom Vector Source
## Motivation
MapLibre Native currently supports two ways to provide vector tile data:
1. **URL-based sources** (`vector` source type) — tiles are fetched according to the protocol of the URL (`http://`,
`file://`, etc.).
2. **CustomGeometrySource** — accepts GeoJSON features programmatically, but internally re-encodes them into vector
tiles, adding overhead and limiting control over the tile encoding.
This proposal comes from the need for an efficient and kotlin native way to asynchronously connect a tile data source
similar to vector tile.
CustomGeometrySource was considered, but it has some obvious drawbacks:
1. Tile requests are in the format of a bounding box — since it's not a tile X/Y/Z it is pretty unclear what logic it
conforms to.
1. Is it just a tile X/Y/Z but converted to geo bounds?
2. Can it ever request data in a bounding box that is bigger than just one X/Y/Z tile
3. Additional boilerplate of mapping geo bounds into tile X/Y/Z
2. Internally CustomGeometrySource spawns a 4 thread threadpool and runs tasks one by one inside. It's a good old
technique
but Kotlin has things like coroutines which are a more ergonomic way to handle suspendable operations (like network
requests).
3. CustomGeometrySource operates over GeoJSON. So in case of a vector tiles like format it needs to be converted to
GeoJSON and then internally it will be cut down into vector tile format back.
## Proposed Change
Introduce a new source type, `CustomVectorSource`, that lets the application deliver raw binary tile data (starting with
MVT) directly to the rendering pipeline. The source participates in the standard tile loading lifecycle — the core
requests tiles by `CanonicalTileID`, and the application responds asynchronously with encoded data or an error.
### Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ Platform layer (Kotlin) │
│ │
│ CustomVectorTileProvider.fetchTile(z, x, y) → TileData │
│ ↕ (JNI / platform bridge) │
├─────────────────────────────────────────────────────────────┤
│ Core C++ layer │
│ │
│ CustomVectorSource │
│ ├── Options { fetchTileFunction, cancelTileFunction, │
│ │ zoomRange } │
│ ├── setTileData(CanonicalTileID, shared_ptr<string>, │
│ │ TileDataFormat) │
│ ├── setTileError(CanonicalTileID, exception_ptr) │
│ └── invalidateTile(CanonicalTileID) │
│ │
│ CustomVectorTileLoader (Actor on Scheduler::GetBackground) │
│ └── Receives fetch/cancel requests from tiles │
│ │
│ CustomVectorTile (extends Tile) │
│ └── Parses MVT data via VectorTileData, delegates to │
│ standard GeometryTileWorker for symbol/line/fill │
│ layout │
│ │
│ RenderCustomVectorSource (extends RenderTileSetSource) │
│ └── Standard tile pyramid rendering │
├─────────────────────────────────────────────────────────────┤
│ Existing rendering pipeline (unchanged) │
│ GeometryTileWorker → Buckets → Drawables → GPU │
└─────────────────────────────────────────────────────────────┘
```
### Key Design Decisions
1. **Binary data, not GeoJSON.** For the Kotlin layer to send data to C++, it needs to be marshaled into some
data format that can be passed across languages. One could come up with a new binary format, implement an encoder in
Kotlin and a decoder in C++. But it turns out MVT is already such a format — just a binary blob that can be passed
simply as a sized buffer. Existing infrastructure of `MVT` tile data is just reused as is.
2. **Actor-based concurrency.** `CustomVectorTileLoader` runs on a background thread via MapLibre's Actor system. The
platform callback (fetch/cancel) is invoked on this thread; the platform layer is responsible for dispatching to its
own preferred context (e.g., coroutines on Android).
3. **Cooperative cancellation.** When a tile is no longer needed (e.g., user panned away), the core calls
`cancelTileFunction`. The platform layer can abort in-flight work.
4. **Standard tile pipeline reuse.** Once binary data arrives, it goes through the same `VectorTileData` →
`GeometryTileWorker` path as HTTP-fetched vector tiles. No custom rendering code is needed.
5. **Extensible format enum.** `TileDataFormat` is an enum starting with `MVT`. Future formats (e.g., a hypothetical
compact binary format) can be added without API changes. And obvious next candidate is `MLT` format support in
CustomVectorSource.
### Threading Model
```
Main thread: Source::update() → tile needs data
↓
Background Actor: CustomVectorTileLoader::fetchTile()
↓
Platform bridge: fetchTileFunction callback → platform code
↓ (async, any thread)
setTileData() → mailbox → CustomVectorTile::setData()
↓
GeometryTileWorker: parse MVT, create buckets (background pool)
↓
Main thread: Tile ready → render
```
## API Modifications
### Core C++ (public header)
```cpp
namespace mln::style {
enum class TileDataFormat : uint8_t { MVT = 0 };
using TileFunction = std::function<void(const CanonicalTileID&)>;
class CustomVectorSource final : public Source {
public:
struct Options {
TileFunction fetchTileFunction;
TileFunction cancelTileFunction;
Range<uint8_t> zoomRange = {0, 18};
};
CustomVectorSource(std::string id, const Options& options);
void setTileData(const CanonicalTileID&,
const std::shared_ptr<const std::string>& data,
TileDataFormat format = TileDataFormat::MVT);
void setTileError(const CanonicalTileID&, std::exception_ptr error);
void invalidateTile(const CanonicalTileID&);
};
} // namespace mln::style
```
### Android (Kotlin)
```kotlin
interface CustomVectorTileProvider {
suspend fun fetchTile(z: Int, x: Int, y: Int): TileData
}
sealed class TileData {
class Mvt(val data: ByteArray) : TileData()
}
class CustomVectorSource(
id: String,
provider: CustomVectorTileProvider,
scope: CoroutineScope,
minZoom: Int = 0,
maxZoom: Int = 18
) : Source()
```
The Android API uses Kotlin coroutines for async tile fetching. The `CoroutineScope` is caller-provided. Meaning
`CustomVectorSource` can run on a threadpool but not limited to a threadpool. `CoroutineScope` abstracts it away.
### iOS / macOS
Not included in this initial implementation. The core C++ API is platform-agnostic and can be wrapped in Swift/Obj-C
following the same pattern.
## Migration Plan and Compatibility
All changes are **additive**. No existing APIs are modified or removed. The new source type is opt-in — applications
that don't use it are unaffected.
- A new `SourceType::CustomMVTVector` enum value is added to the core.
- Existing `CustomGeometrySource` remains unchanged and is not deprecated.
## Rejected Alternatives
### Extend CustomGeometrySource to accept binary data
`CustomGeometrySource` is designed around GeoJSON features and internally manages geometry encoding. Bolting binary tile
support onto it would conflate two different data models and complicate its already non-trivial implementation.
### Use a local file source with a custom URL scheme
This approach (e.g., `mbtiles://` or `custom://`) requires the application to write tile data to disk or implement a
custom `FileSource`. It adds I/O overhead, doesn't support cooperative cancellation, and is harder to integrate with
structured concurrency frameworks like Kotlin coroutines.

View File

@@ -0,0 +1,436 @@
# RenderSegment 多 Retained 段全局 Placement 门槛——粒子管理员审查说明 v1
日期:2026-10-07
性质:调查结论 / 修改目标 / 管理员审查输入,不是直接实施任务书。
目标读者:Particle Shared Core / Renderer 维护者。
## 1. 本文要解决的问题
NavSea 当前已经能通过公开 `RendererRuntime.setRenderSegmentPlan()` 配置任意连续的 `RETAINED / CONTINUOUS` Segment,且 `.19 / .20` 的 RenderSegment 实现已经具备 source-local revision / readiness / cache diagnostics 等基础。
但 NavSea 真实运行验证发现:当存在多个 Retained Segment 时,一个与某 Retained Segment 无直接关系的全局 placement/fade 状态,仍可能把所有 Retained Segment 同时打回 fallback,导致多 Segment 不能发挥设计目标。
本文希望 Particle 管理员审查并决定:怎样把剩余的 placement/global fallback 门槛收敛到正确粒度,同时保持 fail-closed、Style Z-order、跨平台语义和 C-001 边界不变。
## 2. 正式边界
跨项目 Contract 仍为 `C-001`。
本问题属于 Particle Renderer 内部实现优化,目标上不要求新增 NavSea 私有 Native 通道,也不要求 Particle 理解 AIS、Route、Weather、Alarm 等 NavSea 业务语义。
NavSea 仍只负责:
- 按 Style Z-order 选择 Segment 边界;
- 通过稳定公开 API 提交 RenderSegmentPlan;
- 读取 diagnostics;
- 决定天气等业务能力何时显示。
Particle 仍负责:
- Segment resolve / cache / invalidation / renderer execution;
- placement / transition / fading / source dependency 的正确性;
- GPU resource 和 stale-cache 安全;
- Android / iOS 共用的 Shared Core 语义。
本修改若不改变公共 API、生命周期、错误语义或双方职责,不需要升级 Contract。
## 3. 当前 Mac 基线需要管理员先确认
本次只读检查发现:
- `/Users/tei/dev/MapLibreParticleLab`
- branch: `particle/main`
- HEAD: `750c14f52708d7dc93d8eb6ec2b21112185afd5c`
- `/Users/tei/dev/MapLibreParticleLab-release-v19`
- branch: `release/particle.19`
- HEAD: `6b48f905d2d17a8271b6ff883e682db7bc45dcd3`
- `/Users/tei/dev/MapLibreParticleLab-release-v20`
- branch: `release/particle.20`
- HEAD: `53a844e81849f254ba2d169c2d875dbd862cc7d5`
- `/Users/tei/dev/MapLibreParticleLab-step101`
- branch: `step101-render-orchestrator-teardown`
NavSea 当前实际消费的是 `.19` 行为;本次检查确认 `release/particle.19` 与 `release/particle.20` 在本文相关 placement gate 代码上相同。
注意:当前 `particle/main` 与 `release/particle.19/.20` 的 RenderSegment 执行细节存在差异,因此管理员开始修改前必须先明确正式修复基线,不要把 main 与 release 分支默认视为完全一致。
## 4. NavSea 当前为什么需要多 Segment
NavSea 当前为了避免旧的 retained fallback,采用保守的两段方案:
```text
R0 [0,31) RETAINED
C0 [31,114) CONTINUOUS
```
C0 从 `rn-weather-color` 开始一直覆盖到 Style 尾部。
真实 diagnostics 已确认该 Continuous 尾段包含天气之后的大量运行时对象,包括 AIS / ownship / navigation / alarm 等 source/layer。
这能保护 R0 底图复用,但代价是:天气粒子需要持续 repaint 时,天气以上整个 Style 尾部都留在 Continuous 区域。
RenderSegment 的原始设计目标本来就是允许:
```text
R0 → C0 → R1 → C1 → R2 ...
```
并严格保持 Style Z-order,不把业务语义写进 Renderer。
## 5. NavSea 真实多段实验 A
第一次临时配置:
```text
R0 [0,31)
C0 [31,79)
R1 [79,98)
C1 [98,114)
```
Native 接受该配置:
```text
configured=true
valid=true
segmentCount=4
retainedSegmentCount=2
continuousSegmentCount=2
coverageComplete=true
fallback=false
```
解析结果:
- R0: `background` → `place-labels-land-ja`
- C0: `rn-weather-color` → `ownshipRangeLabelLayer`
- R1: `routeLineActiveShadowLayer` → `planSimBoatLabelLayer`
- C1: `crossCursorGotoLineLayer` → `chartDangerScanCenterLineLayer`
R1 当时依赖:
- `navigationSource`
- `ownshipTrackSource`
- `planSimRouteSource`
结果 R1 为 `source-fading` fallback,`reuse=0`。
这个结果本身还不能证明 placement 问题,因为 R1 确实包含活动 source。
## 6. NavSea 真实多段实验 B:把 R1 收窄到 idle PlanSim
第二次把 R1 收窄为只有 PlanSim Route 的 10 个 layer:
```text
R0 [0,31)
C0 [31,88)
R1 [88,98)
C1 [98,114)
```
R1:
- start: `planSimRouteShadowLayer`
- end: `planSimBoatLabelLayer`
- dependent source: 仅 `planSimRouteSource`
- 当时 PlanSim 为 idle。
5 秒早期诊断仍有 `source-fading`,所以继续等待到约 20 秒稳定态。
20 秒稳定态关键结果:
```text
fadingSourceIds = []
```
R0:
```text
sourceReady=true
sourceStable=true
cacheState=fallback
build=0
reuse=0
invalidation=306
lastInvalidationReason=static-placement
finalDecision=fallback
```
R1:
```text
sourceReady=true
sourceStable=true
cacheState=fallback
build=1
reuse=0
invalidation=306
lastInvalidationReason=static-placement
finalDecision=fallback
```
这说明稳定 source 已经不是阻塞因素;两个 Retained Segment 被同一个 `static-placement` 门槛同步打回 fallback。
## 7. release/particle.19 / .20 当前代码事实
### 7.1 per-segment source locality 已经存在
`.19 / .20` 在 `renderer_impl.cpp` 中会对每个 Retained Segment 单独计算:
- `retainedSegmentSourceState(begin,end)`
- source-local revision
- source `ready / stable`
- `retainedSegmentIsStable(begin,end)`
- `segmentSupportsCache[]`
- 每个 cache 独立 `evaluate()`
- 每段独立 diagnostics / finalDecision
`render_orchestrator.cpp` 中 `retainedSegmentSourceState()` 已通过 RenderSegment dependency 只检查该 Segment 相关 source 的 loaded / fading 状态。
这部分方向是正确的,不应回退到全局 source invalidation。
### 7.2 剩余 placement gate 仍是全局聚合
`.19 / .20` 的 `renderer_impl.cpp` 仍先对全部 Retained Segment 聚合:
```cpp
bool retainedStaticUsesPlacement = false;
...
retainedStaticUsesPlacement =
retainedStaticUsesPlacement ||
orchestrator.retainedRangeUsesPlacement(...);
const bool retainedPlacementStable =
!retainedStaticUsesPlacement ||
(!renderTreeParameters.placementChanged &&
renderTreeParameters.symbolFadeChange == 0.0f);
```
然后每个 Segment 的 `segmentSupported` 又共同依赖同一个 `retainedPlacementStable`。
因此只要任一 Retained Segment 使用 placement,并且当前全局 frame 有 `placementChanged / symbolFadeChange`,所有 Retained Segment 都可能失去 cache eligibility。
### 7.3 full CPU mixed execution 已有基础,但仍有 globalLiveFallback
`.19 / .20` 已有 `visitRenderSegmentExecution(...)`,理论上可以:
```text
R0 reuse
C0 live
R1 fallback/live
C1 live
R2 reuse
```
但是进入该混合执行前仍有:
```cpp
const bool globalLiveFallback =
...
!retainedPlacementStable ||
orchestrator.retainedGlobalLightTransition();
```
`!retainedPlacementStable` 会直接导致:
```text
drawableOpaquePass(0, layerCount)
drawableTranslucentPass(0, layerCount)
```
即整帧退回全 live,绕过 per-segment mixed execution。
这与 NavSea 实验中 R0/R1 同时出现 `static-placement` fallback 的现象一致。
## 8. 希望管理员审查的核心修改目标
目标不是简单“关闭 placement 检查”。
目标是:
> 当 placement / symbol fade 只影响某些 Segment 时,不应让与其无关、且自身内容/依赖/相机均稳定的 Retained Segment 一起失效。
期望行为示例:
```text
R0:不含 placement layer,source stable
C0:Weather continuous
R1:含 placement 或当前 placement unstable
C1:AIS / Alarm continuous
R2:不含 placement layer,source stable
期望:
R0 = reuse
C0 = live
R1 = fallback/live
C1 = live
R2 = reuse
```
而不是:
```text
R1 placement unstable
→ global retainedPlacementStable=false
→ R0/R1/R2 全部失效
→ 整帧 full live
```
## 9. 建议管理员重点评估的实现方向
以下是审查建议,不是强制实现方案。
### 9.1 先把 placement eligibility 变成 per-retained-segment
对于每个 Retained Segment 分别判断:
- 该 Segment 是否实际 `usesPlacement`;
- 该 Segment 的 layer transition / needsRepaint;
- 该 Segment 的 source readiness / fading;
- placement transition 是否确实会改变该 Segment 的最终像素;
- 是否存在必须全局 fail-closed 的 placement 共享状态。
至少对于 **完全不含 placement layer 的 Retained Segment**,应评估是否有理由继续受全局 `placementChanged / symbolFadeChange` 阻塞。
### 9.2 审查 `globalLiveFallback` 中的 `!retainedPlacementStable`
建议确认是否可以:
- 从 globalLiveFallback 移除纯 placement 条件;
- 让 placement 结果进入每段 `segmentSupported / decision`;
- 真正使用现有 `visitRenderSegmentExecution()` 做 mixed retained/live。
真正全局的条件仍可保持全局,例如:
- 3D;
- Debug 模式;
- MapMode 不支持;
- sprite/image/global resource 未就绪;
- global light transition(若确实会改变所有段);
- context/resource 失效;
- 无法证明安全的全局状态。
### 9.3 不要破坏已有 source-local 机制
`.19/.20` 已有 `retainedSegmentSourceState()` 与 dependency-scoped revision/readiness。
目标应是在此基础上继续收窄 placement/global gate,而不是重新把 source/tile mutation 退回“所有 Retained 一起 invalidate”。
### 9.4 placement 本身若无法简单 local 化,应明确分层
管理员需要判断 MapLibre placement 是否存在以下区别:
1. Segment 完全不使用 placement:理论上是否可忽略全局 placementChanged?
2. Segment 使用 symbol placement,但其相关 source/layer 没变化:是否仍必须 invalidate?
3. cross-source collision / shared collision index 是否会让某 Segment 的符号像素受其他 Segment placement 影响?
4. `symbolFadeChange` 是全局时间量还是可以按 dependency/range 推导?
5. 是否需要一个 per-segment placement revision/fingerprint,而不是 bool?
如果 2/3 无法安全局部化,也至少应优先解决第 1 类,让“无 placement Retained Segment”不被无关 placement 拖死。
## 10. 不能牺牲的正确性约束
任何优化都必须保持:
- Style Z-order 是唯一顺序事实;
- Segment 不重新编号 Layer 的全局 ordinal;
- opaque/translucent/depth 语义不变;
- retained cache 不得显示 stale 像素;
- Camera / viewport / pixelRatio 变化仍正确 invalidation;
- Style reload / topology change 正确释放旧 cache;
- Android / iOS 使用同一 Shared Core 语义;
- 不把 AIS / Route / Weather 等业务名称写进 Renderer;
- 不要求 NavSea 手工 invalidate Native cache;
- 不新增“只为 NavSea 绕过 Renderer”的私有 API。
## 11. 建议新增/补强的 Core 测试
至少建议覆盖:
### Case A:无 placement 的 R0 + 有 placement 的 R1
- R0 stable;
- R1 发生 placement transition;
- 期望 R0 继续 reuse;
- R1 单独 fallback/live;
- 最终 Z-order 正确。
### Case B:两个 Retained 都稳定
- R0/R1 均 build 一次;
- 后续 reuse 持续增长;
- Continuous 段持续 live。
### Case C:单一 source fading
- fading source 只属于 R1;
- R1 fallback;
- R0 不 invalidation。
### Case D:Continuous source 高频 mutation
- mutation 只属于 C1;
- R0/R1 retained revision 不变化;
- cache 可继续 reuse。
### Case E:真正全局状态
- global light transition、3D、Debug、context/resource failure 等;
- 继续 fail-closed;
- 不为追求 reuse 放宽安全边界。
### Case F:topology 变化
- R-C-R-C → R-C;
- 旧 retained texture/compositor 正确释放;
- 不 composite stale resource。
## 12. Diagnostics 验收要求
修复后 diagnostics 必须能证明“局部失败不扩散”。
NavSea 重新做 R-C-R-C 真机测试时,至少需要看到类似:
```text
R0:
sourceReady=true
sourceStable=true
cacheState=reuse
reuse 持续增长
R1:
finalDecision=fallback
lastFallbackReason=static-placement
C0/C1:
正常 live
```
关键验收不是 Fast Path hit。
多 Continuous Segment 本来就可以继续走 full CPU mixed renderer;即使 `fastPathHit=0`,只要稳定 Retained 段能够独立 reuse,优化就是有效的。
## 13. 与 NavSea 最新 Trace 的关系
`Trace-20261007T224751.json` 是 UDP + 天气 UI 的 DevTools Trace。
该 Trace 中约 11–13 秒和 21–23 秒出现两组很高的 JS 峰值;调用栈显示峰值主要落在 React root work 与 `WeatherForecastStrip / WeatherTable`,其中 `WeatherTable` 两次重 render 分别约 0.91s / 1.07s,AIS decoder 并不是这两个峰值的主要执行栈。
代码同时显示 `WeatherForecastStrip` 会订阅 `smoothGPS`,并用经纬度 `toFixed(2)` 形成天气采样位置 key;但当前尚未完成对这两次具体 WeatherTable render 触发源的一一证明,因此本文不把“约 10 秒”直接归因于 GPS 跨格或任何单一 NavSea 机制。
这些 JS/UI 峰值属于 NavSea 侧独立调查项,不应作为 Particle RenderSegment 修改的直接证据。
Particle 本次应以 **RenderSegment diagnostics 的 R0/R1 `static-placement` 同步 fallback** 为主要证据。
## 14. 管理员需要给出的结论
请管理员审查后明确回答:
1. `.19/.20` 当前全局 `retainedPlacementStable` 是否确实过度保守?
2. 对“不含 placement layer”的 Retained Segment,是否可以安全解除全局 placementChanged/symbolFadeChange 阻塞?
3. `globalLiveFallback` 是否应去掉 placement 条件,转为 per-segment decision?
4. 若 placement 必须部分全局,最小安全局部化边界是什么?
5. 正式修改应基于 `release/particle.20`、合并回 `particle/main`,还是先在独立工作树完成?
6. 是否需要新 ADR/RFC?初步判断:若公共 API/C-001 语义不变,只是 Renderer 内部优化,可不新增跨项目 Contract;若管理员认为会改变 RenderSegment 公共语义,再交回 Integration 决定。
## 15. 当前 NavSea 状态
NavSea 临时 R-C-R-C 实验已经撤回。
当前恢复为原有保守方案:
```text
R0 [0,31) RETAINED
C0 [31,114) CONTINUOUS
```
因此管理员可以先只做 Native/Core 审查,不需要 NavSea 同步修改。
等 Particle 给出明确方案和可验证版本后,再由 NavSea 重新选择真实 Style 边界并做 R-C-R-C / R-C-R-C-R 真机验证。

View File

@@ -0,0 +1,690 @@
# STEP-100 Source → RenderSegment 局部 Revision / Invalidation / Readiness 与独立 Fallback — Codex 任务 v2
## 0. 任务性质
这是 STEP-099 之后的正式修复任务。
STEP-099 已经完成纯诊断并 CLOSED / PASS,已确认 V17 的核心问题:
1. 动态 GeoJSON Source/Tile mutation 会推进 global retained content revision;
2. 即使 R0 不依赖该 GeoJSON,R0 retained cache 仍跟着 invalid/build;
3. GeoJSON 更新期间约 200 ms 的 transient `isLoaded=false` 会通过 global `RenderOrchestrator::isLoaded()` 把整个 retained path 拉成 `style-not-loaded`;
4. 当前 renderer 还存在 `useRetainedRanges` all-or-none gate:一个 RETAINED Segment fallback 时,会使其他本来可安全 reuse 的 RETAINED Segment 一起退出 retained path;
5. STEP-099 diagnostics 已能正确给 source mutation 计算 `affectedSegmentIndices`,但该依赖关系仍只是诊断,不参与正式 invalidation。
本任务目标是把 **Source/Tile 变化对 RETAINED Segment 的影响正式局部化**。
本任务不是 V18 发布任务。Codex 只负责实现与源码级说明;Android/iOS 构建、APK、ADB、设备测试、最终 Git push、V18 release 由 RDC/ChatGPT 在 Codex 完成后独立执行。
未经用户明确要求,本任务 **不加入、不运行 Jest**。
---
## 1. 冻结基线
工作目录:
`/Users/tei/dev/MapLibreParticleLab-step100`
分支:
`step100-segment-local-source-invalidation`
开始基线必须重新核对,当前预期:
- `origin/particle/main`
- HEAD:`c4b481fd2c5b5da20d31f6ae54011f0552d7dbd0`
- STEP-099 implementation:`8a5214d92dd2f8899db76d2194da42999fa0c87d`
- V17 frozen tag:`maplibre-particle/rn/13.4.1-particle.17`
- V17 frozen commit:`e8b451fe70054107773e82484c80e90df3889147`
禁止修改、移动、覆盖 V17 tag / release worktree。
STEP-100 是 V17 之后的新开发,最终只有 RDC 验收通过后才允许进入 V18 发布。
开始前必须读取:
- 当前仓库实际 HEAD / status / diff;
- 全局 Codex AGENTS;
- `ARCHITECTURE.md`(若存在);
- STEP-092 / 094 / 099 的任务、Step 记录、完成报告;
- 当前:
- `renderer_impl.cpp`
- `render_orchestrator.*`
- `retained_underlay_cache.*`
- `retained_underlay_runtime_state.hpp`
- `render_segment.*`
- STEP-099 diagnostics 与 Android fixture;
- 当前 RenderSegment / retained cache / particle fast path tests。
不得凭历史印象修改。
---
## 2. 最终架构原则
长期 RenderSegment 模型继续保持通用模型:
```text
Style Z-order
↓
R / C / R / C / R / ...
```
其中:
- R = RETAINED
- C = CONTINUOUS
本任务只用 **R-C-R** 做最小验证,不把 R-C-R 固化成最终架构。
必须保持:
1. Style layer 顺序是唯一 Z-order 真相;
2. Renderer 不理解 AIS / Route / Weather / GeoJSON 等业务名;
3. Source → Segment 依赖由当前实际 Style / RenderLayer / Source 关系推导;
4. 一个 Source 可依赖多个 Segment;
5. source-less layer 不制造假 dependency;
6. unknown/global dependency 必须 fail closed;
7. 相邻 Segment、多个 C、多个 R 的通用模型不能被破坏;
8. 本任务不实现 multi-continuous Fast Path。
---
## 3. 本任务必须实现的核心目标
### 3.1 Source/Tile mutation 局部化
假设:
```text
R0 depends [staticSource]
C depends [particleField]
R1 depends [dynamicGeoJson]
```
当:
```text
dynamicGeoJson mutation
```
正式 renderer 必须达到:
```text
R0:
content/revision 不因该 source mutation 改变
cache 不 invalid
cache 不 rebuild
持续 reuse
R1:
revision/invalidation 正常变化
按需要 build/reuse/fallback
C:
正常 continuous render
```
禁止继续出现:
```text
dynamicGeoJson mutation
↓
global revision 变化
↓
R0 + R1 一起 rebuild
```
### 3.2 保留 global revision 兼容信号
STEP-100 不要求删除现有 global `retainedUnderlayContentRevision`。
为了保持:
- diagnostics;
- 现有 fast-path correctness;
- 旧 API / compatibility;
- conservative fallback;
允许并推荐继续维护 global revision。
但 **RETAINED Segment cache 的正式内容 revision / invalidation 不能再只依赖这个 global source/tile revision**。
当前 `retainedUnderlayRevisionTracker` 同时消费 global content revision 与 `renderTreeParameters.loaded`。STEP-100 必须明确拆成两种用途:
```text
global retained revision / tracker
-> compatibility / Fast Path / diagnostics
segment-local retained content state
-> full CPU renderer 的每个 RETAINED Segment Build / Reuse / Fallback
```
**Segment-local cache content state 禁止继续直接消费:**
- global source/tile content revision;
- global `renderTreeParameters.loaded`。
否则即使 source-scoped revision 已实现,R0 仍会被无关 GeoJSON transient unloaded 或 global revision 连带失效。
允许 global revision / global tracker继续按原逻辑变化;禁止为了让测试 PASS 而停止 global revision 增长或放宽 Fast Path。
### 3.3 per-RETAINED-Segment readiness
不得修改任何 Source `isLoaded()` 定义。
不得修改:
```cpp
renderTreeParameters->loaded = updateParameters->styleLoaded && isLoaded();
```
这个 global loaded 仍作为 MapLibre 现有全局兼容事实。
但 retained segment 的 cache Build/Reuse/Fallback 必须有自己的安全 readiness 判断。
最低语义:
- Style 本身未 ready:fail closed;
- image manager / sprite / glyph 等无法安全定位到单 Segment 的全局前置条件未 ready:fail closed;
- Segment 已知依赖的 source 中任一缺失或 `isLoaded()==false`:仅该 Segment fail closed;
- Segment 已知依赖的 source `hasFadingTiles()==true`:仅该 Segment视为 unstable;
- **不被该 Segment 引用的 source unloaded 或 fading,不得让该 Segment cache fallback/rebuild**;
- `retainedRangeIsStable(begin,end)` 的 source fading 检查必须按该 range 的真实 source dependency 缩小,不能继续遍历全部 `renderSources` 作为 full-CPU retained gate;
- Fast Path 原有 global fading gate 保持不变;
- source ID 无法解析、dependency 缺失或真正无法证明安全时 fail closed。
必须区分:
1. **已知 Source dependency**;
2. **symbol/global prerequisite**(glyph/image/placement 等);
3. **真正 unknown dependency**。
STEP-099 的 `unknownDependencies` 目前会把 symbol 相关条件标为 unknown。STEP-100 不得机械地把“存在 symbol”解释成永久 fallback;symbol 所需 glyph/image/placement 应作为明确的 global prerequisite/fail-closed 条件处理。
因此 T3 中一个:
```text
no layer
enabled=false
isLoaded=false
```
的 RasterArray source 可以继续让 global `RenderOrchestrator::isLoaded()==false`,但不得因此让与它无依赖关系的 R0/R1 cache 全部 `style-not-loaded`。
本 Step 的运行态硬验收范围是 **MapMode::Continuous**(粒子正式实时渲染模式)。当前非 Continuous / still 路径如果在 global unloaded 时提前返回,本 Step 不强行改变其兼容语义;完成报告必须明确该适用范围。
### 3.4 RETAINED Segment 独立决策
当前 V17 路径存在类似:
```text
useRetainedRanges = all retained segments supported
```
的 all-or-none 语义。
STEP-100 必须改为每个 RETAINED Segment 独立拥有:
- readiness/support decision;
- Build / Reuse / Fallback;
- content/source revision;
- invalidation reason。
如果:
```text
R0 = Reuse
R1 = Fallback
```
则本帧必须允许:
```text
R0 composite cached texture
C live render
R1 live render fallback
```
而不是退化为“整个 Style 全部 live render”。
如果某 retained cache 自身 build 失败,应优先只 fallback 该 Segment;只有无法证明局部安全的 context/global resource failure 才允许全 retained fail closed。
---
## 4. Source-scoped revision 设计要求
Codex 必须基于当前代码选择最小、稳定设计,并在完成报告说明实际方案。
推荐方向但不强制具体类名:
- 为 Source/Tile mutation 维护 source-scoped monotonic revision;
- keyed by stable sourceId,但必须处理 source 删除后同 ID recreate,不能让新 source 错误继承可复用的旧 cache identity;可用 generation/epoch 或保留单调 tombstone 语义实现;
- source diff、feature-state mutation、tile changed 等所有当前会进入 Source/Tile retained content invalidation 的正式路径都必须覆盖;
- 能定位 sourceId 的 mutation 只推进对应 source revision;无法定位 sourceId 的 mutation继续 global fail closed;
- Segment content revision 由:
- 该 Segment 的 dependent source revisions;
- 当前 Segment layer fingerprint / layer mutation;
- 必须全局影响 retained 的 global revision 类别;
- topology / camera / viewport 等既有安全条件
共同决定。
Source/Tile mutation 不应推进“所有 Segment 都消费的 retained cache revision”。
必须避免:
- 用屏幕位置猜 dependency;
- 在 renderer 中硬编码 source/layer ID;
- 从 STEP-099 diagnostics JSON 反向驱动正式 renderer;
- 建立 diagnostics 与 production 两套互相漂移的 dependency 真相。
如果需要提取 production-grade dependency helper,应让 diagnostics 和正式逻辑共享同一只读推导源。正式 renderer 不得从 diagnostics JSON 或 `RetainedUnderlayRuntimeState` 反向取 dependency。
Source-scoped revision 属正式 correctness state,不得沿用 STEP-099 diagnostics 的“best-effort 记录失败可忽略”语义。正式 revision/dependency state 若无法可靠更新,必须 conservative global invalidation/fail closed。
---
## 5. Global mutation 仍可保守处理
本任务只要求 **Source/Tile mutation** 与明确 Source readiness 局部化。
以下无法安全局部化的事件,本轮允许继续 invalidate/fail closed 全 retained:
- context reset;
- style reload / topology change;
- image mutation;
- glyph mutation;
- sprite/image manager 全局 readiness;
- placement / symbol fade / glyph/image/sprite 全局状态;
- camera / transform / viewport / resize / pixel ratio;
- debug mode;
- 3D / unsupported / legacy ordering;
- 无法定位 dependency 的 mutation;
- 真正 unknown/global dependency。
注意:**Source 自身的 loaded / fading 不属于这里的 global fail-closed 项**;若 source dependency 可定位,必须按 Segment 局部判断。Fast Path 的 global source/fading gate除外,本轮保持原状。
完成报告必须列出:
- 已局部化的 mutation 类型;
- 仍为 global 的 mutation 类型;
- 为什么保守处理。
---
## 6. Fast Path 本轮严格不改
STEP-099 已确认 Fast Path 仍有 global gates:
- global update signature(sources/layers/images 等);
- global content revision;
- global fade;
- pendingChanges;
- placement/light/non-particle transition/repaint;
- annotation mutation;
- topology/boundary/revision/cache validity;
- `singleContinuousSegment`。
STEP-100 **禁止修改这些 gate 的语义**。
允许:
- Source mutation 后 Fast Path miss;
- transient source readiness 时 Fast Path fail closed;
- full CPU renderer 被调用。
但进入 full CPU renderer 后,必须能做到:
```text
R0 retained cache reuse
R1 rebuild/fallback
```
这正是本任务验收目标。
Multi-continuous Fast Path 明确不在本任务。
---
## 7. Render 顺序与混合 Build/Reuse/Fallback
实现 per-segment mixed decisions 时必须保持原 MapLibre 绘制语义:
- Style Z-order;
- global layerIndex;
- opaque reverse traversal;
- translucent forward traversal;
- currentLayer;
- depthRangeSize;
- legacy item 不双绘;
- debug overlay 不重复;
- retained texture composite 不改变 segment 顺序。
推荐的逻辑行为:
```text
for segment in Style order:
RETAINED + Build:
build cache
composite cache
RETAINED + Reuse:
composite cache
RETAINED + Fallback:
live render only this range
CONTINUOUS:
live render this range
```
实际代码可按现有 RenderPass 安全实现,不要求机械照搬伪代码。
必须特别检查:
- 一个 R fallback 不得导致另一个 R live redraw;
- resource prepare 在 Build 前失败时,必须先把该 Segment 本帧 decision 改为 Fallback,再进入主 buffer 绘制;
- retained build 中途失败时,必须 invalidate/标记该 Segment失败并把该 Segment 本帧 decision 改为 Fallback,禁止 composite 旧纹理;
- 如果失败意味着 context / shared GPU state 已不可信,允许全局 fail closed;
- fallback range 的 legacy items 只绘一次,不得因 per-segment 主循环重复 render;
- debug overlay 全帧只绘一次;
- Segment 间 Opaque/Translucent 语义不得被破坏;
- 相邻 R、多个 C、透明叠加与 legacy scene 不能因 mixed execution 出现漏绘/双绘。
推荐执行顺序:先完成各 Segment resource prepare 与必要离屏 Build;再 clear 主 buffer;最后按 Style Segment 顺序逐段选择 cached composite 或 live range render。
---
## 8. Diagnostics 必须继续可证明局部性
保留 STEP-099 diagnostics,并 additive 增加足够字段,使 RDC 能验证正式行为。
每个 RETAINED Segment 至少应能观察:
- dependentSourceIds;
- segment readiness / support;
- segment-local source/content revision 或等价可证明值;
- Build / Reuse / Fallback 的**最终本帧 execution decision**;
- build/reuse/fallback/invalidation count;
- last invalidation/fallback reason。
Source mutation 继续输出:
- sourceId;
- sequence/reason/action;
- affectedSegmentIndices。
要求:
```text
step099-dynamic mutation
affected=[R1]
R0 revision unchanged
R0 cache reuse++
R0 build unchanged
R0 invalidation unchanged
```
Diagnostics 仍是 pull/event low-frequency,不允许逐帧高频 spam。
---
## 9. Android Test App
复用 STEP-099,不另建独立 App。
至少保留并完善:
### T1 STATIC
验证静态 R-C-R:
- loaded settle;
- R0/R1 build 一次后稳定 reuse;
- 不产生持续 rebuild。
### T2 GEOJSON_1HZ
两个 GeoJSON source 交错,各约 1 Hz。
重点:
- global loaded transient false window 可以继续存在;
- 只引用某 source 的 retained Segment 才允许因该 source mutation 改变;
- 无关 retained Segment build/invalidation 不得跟随增长。
### T3 PERMANENT_UNREADY
保留一个:
- no layer;
- enabled=false;
- isLoaded=false;
- no field submission
的 RasterArray source。
预期:
- global renderOrchestratorLoaded 仍可为 false;
- 但无关 R0/R1 retained cache 不应因它持续 `style-not-loaded` fallback;
- 能安全判断依赖的 retained Segment应继续 build/reuse。
### T4 R-C-R(主验收)
必须保持清晰依赖:
```text
R0 -> dedicated static source only
C -> WeatherColor/Particle field
R1 -> dedicated dynamic GeoJSON source
```
运行动态 GeoJSON 约 1 Hz。
必须调整 fixture,避免 STEP-099 中 R1 再复用 R0 的 static source:
- R0 static source 只出现在 R0;
- R1 dynamic source 只出现在 R1;
- 若 MapLibre 内建 annotation source/layer 自动进入 R1,必须在 diagnostics 中列明,并保证验收窗口内 annotation 不发生 mutation;
- 不允许用业务 ID 特判 renderer。
RDC 验收区间必须支持“settled baseline → 60 s pure dynamic-source mutation window → final”对比。每个 aggregate sample 同时记录 mutation source/sequence、各 Segment local revision、readiness、最终 execution decision 与 cache counters。
---
## 10. STEP-100 硬验收标准
### A. R0 locality
T4 settle 后记录 baseline。
随后至少 60 s dynamic GeoJSON:
- R0 `buildDelta == 0`
- R0 `invalidationDelta == 0`
- R0 `reuseDelta > 0`
- R0 segment-local revision/content state 不因 R1 dynamic source mutation 改变
- 即使某采样点 global `renderOrchestratorLoaded=false`,只要 R0 自身 prerequisites/dependencies ready,R0 final decision 仍可为 Reuse
如果为了安全出现明确 global event,应在日志中可解释并重新选择纯动态 mutation 区间;不能把 global event 混入后声称 PASS。
### B. R1 reacts
同一时间窗:
- R1 必须能观察到 source mutation;
- R1 revision / build / invalidation / fallback 中至少有与动态 source 对应的实际变化;
- `affectedSegmentIndices` 必须只包含真实依赖 Segment。
### C. global revision compatibility
- global `retainedUnderlayContentRevision` 允许并预期继续增长;
- 不能通过停止 global revision 增长来制造 R0 PASS。
### D. readiness locality
T2 transient unloaded 或 T3 permanent unrelated unloaded 时:
- global loaded 可 false;
- R0 不得仅因无关 source 的 unloaded 而 invalid/rebuild/fallback;
- R0 cache 必须继续可复用。
### E. correctness
- 无 crash / ANR;
- 无 stale cache composite;
- 无 Segment Z-order 错乱;
- 无 fallback range 双绘;
- Cache OFF 仍安全走 live renderer;
- plan invalid 仍 fail closed。
任一硬门槛失败,STEP-100 不得宣布 PASS,不得进入 V18。
---
## 11. Native 非 Jest 测试要求
Codex 必须新增或扩展现有 C++ 测试源码,至少覆盖:
1. source A mutation 只改变依赖 A 的 Segment revision;
2. source A 被多个 Segment 共享时,对应多个 Segment 都变化;
3. unrelated Segment revision 不变;
4. source-less Segment 不制造 dependency;
5. unknown/global dependency fail closed;
6. unrelated source unloaded 不使安全 Segment readiness false;
7. dependent source unloaded 使对应 Segment readiness false;
8. R0 Reuse + R1 Fallback 的 mixed decision;
9. 单 Segment build failure 不 composite stale cache;
10. query diagnostics 不改变 revision/cache state;
11. global non-source invalidation 仍影响所有 retained;
12. source 删除后同 ID recreate 不误复用旧 Segment cache identity;
13. dependent source fading 只影响对应 Segment;unrelated source fading 不影响安全 Segment;
14. Cache OFF / invalid plan 行为不回归;
15. 至少有一组能证明实际 mixed render 没有漏绘/双绘的 renderer-level draw-count、pixel 或现有等价测试入口;不能只用 decision unit test 代替。
不得修改测试断言去适应错误实现。
---
## 12. 允许修改范围
允许:
- RenderOrchestrator source mutation/readiness bookkeeping;
- RenderSegment dependency production helper;
- Renderer retained per-segment revision/readiness/decision;
- RetainedUnderlayCache/RuntimeState 为局部状态增加必要字段;
- additive diagnostics JSON/TS;
- Android Validation Test App STEP-099 fixture/log;
- 相关 Native C++ tests;
- STEP-100 Step 记录/完成报告/开发记录。
禁止:
- NavSea;
- Integration;
- V17 tag/release worktree;
- Source `isLoaded()` 定义;
- Particle field/provider/network;
- Fast Path gate semantic;
- `singleContinuousSegment`;
- multi-continuous Fast Path;
- 自动改变 Style Z-order;
- provider/business-specific source/layer ID;
- unrelated cleanup/refactor;
- Jest。
---
## 13. Codex 执行边界
Codex 本轮负责:
1. 读取实际源码和任务书;
2. 实现代码;
3. 编写 Native 非 Jest 测试源码;
4. 更新 Android Test App 验证入口;
5. 执行轻量静态检查,如 `git diff --check`;
6. 生成中文完成报告。
Codex **不得执行**:
- Android Gradle / APK;
- ADB / 安装 / 实机;
- Xcode / iOS device;
- V18 release;
- tag;
- push;
- Jest。
本轮 Codex 完成报告固定:
`docs/报告/STEP-100_SourceScoped_RenderSegment局部失效_Codex完成报告_v1.md`
Step 记录固定:
`docs/50_Step记录/STEP-100_SourceScoped_RenderSegment局部失效_v1.md`
完成报告必须写清:
- 实际 Codex model / reasoning effort;
- start HEAD;
- 修改文件;
- 生产设计;
- source revision/readiness 规则;
- mixed retained decision 规则;
- Fast Path 明确未改;
- 测试源码新增情况;
- 实际执行 / NOT RUN;
- 风险与 RDC 验收点;
- 未 commit / 未 push(如果确实如此)。
Codex 不 commit、不 push。由 RDC 验证通过后统一 Git 收尾。
---
## 14. RDC / ChatGPT 后续独立验收
Codex 返回后由 RDC 负责:
1. source/diff 审计;
2. Native Mac 编译;
3. Native focused + broad related C++ tests;
4. Android x86_64 OpenGL validation APK 单次构建;
5. Mac ADB 直连 FZG1-2;
6. 自动跑 T1/T2/T3/T4;
7. 解析 R0/R1 build/reuse/invalidation/revision/readiness;
8. 确认硬验收标准 A~E;
9. 若失败,回到 STEP-100 修复,不发布;
10. 若全部 PASS,完成 STEP-100 Git push;
11. 再按现有统一发行流程升级到:
`maplibre-particle/rn/13.4.1-particle.18`
12. V18 build/release/public artifact 验证通过后才宣布 V18 发布完成。
---
## 15. 停止条件
Codex 遇到以下任一情况必须停止并报告,不得扩大范围:
- 要修改 Source `isLoaded()` 才能继续;
- 需要放宽 Fast Path gate;
- 必须改变 singleContinuous / multi-continuous;
- production dependency 无法可靠从现有 Style/RenderLayer/Source 推导;
- per-segment fallback 会破坏 RenderPass/Z-order 且无法在当前范围安全解决;
- 发现需要 NavSea/Integration 配合;
- 需要业务 layer/source ID;
- 需要改变 V17 release。
---
## 16. 本任务最终原则
STEP-100 的目标不是让“全局世界看起来 loaded”。
目标是:
> **即使某个 GeoJSON Source 正在变化或短暂 unready,只要 R0 与它没有依赖关系,R0 retained cache 就必须继续安全 reuse,不能被迫一起刷新。**
Fast Path 是否还能 miss,是后续独立问题。
只有这一点经过 Native + Android R-C-R 实测成立,才允许进入 V18 发布。

View File

@@ -0,0 +1,405 @@
# STEP-101 RenderOrchestrator teardown 生命周期修复 — Codex 任务 v1
## 0. 任务目的
修复 Particle V18 Android 在正常 Renderer teardown / MapView reset 时发生的 Native SIGABRT。
现场已在 NavSea Android x86_64 设备稳定复现:
```text
Fatal signal 6 (SIGABRT)
thread: RenderThread 11
FORTIFY:
pthread_mutex_lock called on a destroyed mutex
libmaplibre.so
std::__ndk1::mutex::lock()
...
mbgl::android::MapRenderer::resetRenderer()
```
V17 正常,V18 接入后稳定在启动约 9~11 秒触发。
本任务只修 Particle Native 生命周期;禁止在 NavSea 增加绕路、private wrapper、禁止阻止正常 MapView reset。
未经用户明确要求:不加入、不执行 Jest。
---
## 1. 冻结基线
工作树:
`/Users/tei/dev/MapLibreParticleLab-step101`
分支:
`step101-render-orchestrator-teardown`
起点必须是:
`origin/particle/main = d29e84c1a90daeea104b389d28b000c4f017d08d`
即正式 V18 Final HEAD。
V18 已发布,不得覆盖、重发或移动:
- `maplibre-particle/rn/13.4.1-particle.18`
- Android `13.4.1-particle.18`
- iOS `6.28.0-particle.18`
修复通过后由 RDC/ChatGPT 发布新不可变版本 V19。
---
## 2. 已知根因证据
V18 STEP-100 新增:
```cpp
RenderSegmentRevisionBook retainedSegmentRevisions;
mutable std::mutex readinessDiagnosticsMutex;
uint64_t readinessEventSequence;
std::unordered_map<std::string, SourceReadinessEventState> sourceReadinessEvents;
RenderMutationDiagnostics lastReadinessMutation;
```
多个 RenderSource / Tile observer callback 会进入:
```cpp
advanceRetainedSourceRevision(...)
recordReadinessMutation(...)
onTileChanged(...)
onTileAction(...)
buildReadinessDiagnostics(...)
retainedSegmentSourceState(...)
```
并 lock:
```cpp
readinessDiagnosticsMutex
```
V18 当前成员声明中:
```text
renderSources
renderLayers
...
retainedSegmentRevisions
...
readinessDiagnosticsMutex
sourceReadinessEvents
...
threadPool
```
C++ 成员按声明反序析构,因此 readiness state / mutex 会早于 renderSources 销毁。
而 RenderSource 在创建时:
```cpp
renderSource->setObserver(this);
```
observer 指向 RenderOrchestrator。
当前 `RenderOrchestrator::~RenderOrchestrator()` 只:
1. contextLost 时标记 layer;
2. `threadPool.waitForEmpty()`;
没有在 readiness state 仍有效时显式 detach RenderSource observer / 清理 renderSources。
因此 V18 存在明确生命周期危险:
```text
readinessDiagnosticsMutex destroyed
↓
renderSources still destroying/alive
↓
late tile/source callback
↓
RenderOrchestrator::onTile*
↓
lock destroyed mutex
↓
FORTIFY SIGABRT
```
---
## 3. 修复原则
不要只依赖调整成员声明顺序。
本任务应建立显式 teardown contract:
```text
RenderOrchestrator destructor begins
↓
stop / drain deferred scheduler work
↓
detach observer from every RenderSource
↓
destroy/clear renderSources while all orchestrator state is still alive
↓
only then continue member teardown
```
同时 `RenderSource::setObserver(nullptr)` 必须安全恢复到 NullObserver。
目标是即使未来成员声明顺序变化,Source callback 也不能在 owner teardown 后访问 RenderOrchestrator。
---
## 4. 必做实现
### 4.1 RenderSource nullptr observer 语义
当前:
```cpp
void RenderSource::setObserver(RenderSourceObserver* observer_) {
observer = observer_;
}
```
改成与 Style Source / Layer 一致的安全语义:
```cpp
observer = observer_ ? observer_ : &nullObserver;
```
要求:
- constructor 仍默认 NullObserver;
- `setObserver(nullptr)` 是合法 detach;
- onTileChanged / onTileError / onTileAction 不需要加 null 分支;
- 不吞掉正常有 observer 时的回调。
必须加非 Jest C++ 回归测试验证 nullptr detach 后 callback 不 crash、不调用旧 observer。
### 4.2 RenderOrchestrator 显式 teardown
在 `RenderOrchestrator::~RenderOrchestrator()` 中,在 readiness mutex/state 仍确定存活时:
1. 保留现有 contextLost layer handling;
2. 等待已有 deferred work 完成;
3. 对所有 `renderSources` 执行 observer detach;
4. 显式 `renderSources.clear()`;
5. 必要时对 glyph/image observer 也做已有 API 支持的 detach,但不要扩大范围;
6. 不允许 teardown callback 再进入 RenderOrchestrator source callback。
顺序必须结合当前 TaggedScheduler / RenderSource / TilePyramid 的真实生命周期检查,而不是机械照抄上述编号。
如果存在“clear renderSources 本身可能产生新的 scheduler work”,需要设计第二次 drain 或更安全顺序,并在报告解释。
### 4.3 生命周期状态可选保护
如果仅 detach + explicit clear 仍无法证明并发安全,允许增加最小 teardown flag,例如 atomic bool,但只作为二次防线。
禁止用 flag 代替 observer detach。
禁止 catch FORTIFY;destroyed mutex abort 不是 C++ exception。
---
## 5. 不得修改
- STEP-100 Source→Segment locality 语义;
- per-segment revision;
- per-segment readiness;
- mixed Build/Reuse/Fallback;
- Fast Path gate;
- singleContinuousSegment;
- Source::isLoaded;
- Style Z-order;
- provider/network;
- NavSea;
- MapRenderer::resetRenderer 正常生命周期;
- Android Activity 为避免 reset 而加 workaround。
---
## 6. 必做测试
### 6.1 Native 非 Jest
至少覆盖:
1. RenderSource 默认 NullObserver 可安全接 callback;
2. setObserver(real) 正常转发;
3. setObserver(nullptr) 后不再调用旧 observer;
4. detach 后 onTileChanged / onTileError / onTileAction 安全;
5. RenderOrchestrator teardown 有至少一个含 RenderSource 的场景;
6. source callback 与 teardown 边界不访问已销毁 readiness state;
7. STEP-100 locality 相关 focused tests 不回归。
如果现有测试设施不方便直接构造完整 RenderOrchestrator teardown,允许提取最小可测试 teardown helper,但禁止为了测试重构大范围生产结构。
### 6.2 Android Test App
在现有 ParticleCoreLayerValidationActivity / Validation App 增加专门 STEP-101 teardown 场景。
场景必须真实触发 Native Renderer teardown,而不是只 clear field。
至少提供:
```text
T1 RESET_ONCE
T2 RESET_LOOP_20
T3 RESET_WITH_DYNAMIC_GEOJSON
T4 RESET_WITH_DIAGNOSTICS
```
目标:
- recreate/destroy MapView 或等价真实 renderer.reset;
- 每轮等待足够让 source/tile work 进入正常运行;
- T3 同时保持动态 GeoJSON/source mutation;
- T4 在 reset 前调用一次 RendererRuntime diagnostics,模拟 NavSea probe 时序;
- 20 次循环无 SIGABRT / crash / ANR;
- reset 后新 renderer 能继续正常显示 / 获取 diagnostics。
不得通过延迟 reset、禁用 observer、关闭 GeoJSON 来逃避问题。
---
## 7. NavSea 现场等价验收
RDC 在 Codex 完成后独立执行。
Android 设备:
`192.168.200.139:5555`
必须显式 `adb -s`。
最终至少执行:
1. Validation App STEP-101 T1~T4;
2. crash buffer 检查;
3. 20 次 reset/recreate;
4. 安装 V19 进 NavSea 后做真实启动;
5. 保留 NavSea 当前 `key={map-style-generation-...}` 正常 reset 触发条件;
6. 保留/启用一次 RenderSegment diagnostics probe A/B;
7. 连续至少 5 次冷启动,每次观察 >30 秒;
8. 不允许出现:
- `pthread_mutex_lock called on a destroyed mutex`
- SIGABRT RenderThread
- `MapRenderer::resetRenderer` teardown crash。
---
## 8. STEP-100 回归验收
修复 teardown 后必须确认 V18 的核心 locality 没被破坏。
至少复测 T4 R-C-R:
无关 R0:
```text
buildDelta = 0
invalidationDelta = 0
reuseDelta > 0
```
动态 R1 正常 build/invalidation。
禁止通过删除 mutex/readiness/revision 功能来修 crash。
---
## 9. Codex 执行边界
Codex负责:
- 只读检查真实 V18 代码;
- 实现最小 Native 修复;
- 编写/更新非 Jest C++ tests;
- 更新 Android Validation STEP-101 场景;
- 静态检查;
- 生成报告。
Codex不负责:
- NavSea 修改;
- V19 release;
- tag;
- publish;
- 覆盖 V18;
- Jest。
Mac Native 开发/编译原则保持;不要使用 Linux Native 环境。
---
## 10. 完成报告
生成:
`docs/报告/STEP-101_RenderOrchestrator销毁生命周期修复_Codex完成报告_v1.md`
Step 记录:
`docs/50_Step记录/STEP-101_RenderOrchestrator销毁生命周期修复_v1.md`
报告必须写:
- root cause;
- start HEAD;
- 修改文件;
- destructor teardown 顺序;
- observer detach 语义;
- 为什么不依赖成员声明顺序;
- tests added;
- 实际运行 / NOT RUN;
- STEP-100 locality 是否保持;
- 风险;
- 未发布 V19(Codex 阶段)。
Codex阶段不 push,由 RDC 验收后统一 commit/push。
---
## 11. V19 发布门槛
仅当:
- Native compile PASS;
- focused C++ tests PASS;
- Android Validation teardown loop PASS;
- STEP-100 locality regression PASS;
- NavSea V19 真实 5 次冷启动 >30s PASS;
- crash buffer 无 destroyed mutex;
才允许发布:
- RN / Android:`13.4.1-particle.19`
- iOS:`6.28.0-particle.19`
- tag:`maplibre-particle/rn/13.4.1-particle.19`
V18 保持不可变,不覆盖、不删除。
---
## 12. 最终原则
正常:
```text
MapView unmount
Style generation replacement
renderer.reset()
Activity recreate
```
都是合法生命周期。
Particle Native 必须做到:
> Renderer teardown 永远不能因为 observer late callback 访问已销毁 mutex/state 而杀掉宿主 App。

View File

@@ -0,0 +1,510 @@
# STEP-101 RenderOrchestrator teardown 生命周期修复 — Codex 任务 v1
## 0. 任务目的
修复 Particle V18 Android 在正常 Renderer teardown / MapView reset 时发生的 Native SIGABRT。
现场已在 NavSea Android x86_64 设备稳定复现:
```text
Fatal signal 6 (SIGABRT)
thread: RenderThread 11
FORTIFY:
pthread_mutex_lock called on a destroyed mutex
libmaplibre.so
std::__ndk1::mutex::lock()
...
mbgl::android::MapRenderer::resetRenderer()
```
V17 正常,V18 接入后稳定在启动约 9~11 秒触发。
本任务只修 Particle Native 生命周期;禁止在 NavSea 增加绕路、private wrapper、禁止阻止正常 MapView reset。
未经用户明确要求:不加入、不执行 Jest。
---
## 1. 冻结基线
工作树:
`/Users/tei/dev/MapLibreParticleLab-step101`
分支:
`step101-render-orchestrator-teardown`
起点必须是:
`origin/particle/main = d29e84c1a90daeea104b389d28b000c4f017d08d`
即正式 V18 Final HEAD。
V18 已发布,不得覆盖、重发或移动:
- `maplibre-particle/rn/13.4.1-particle.18`
- Android `13.4.1-particle.18`
- iOS `6.28.0-particle.18`
修复通过后由 RDC/ChatGPT 发布新不可变版本 V19。
---
## 2. 已知根因证据
V18 STEP-100 新增:
```cpp
RenderSegmentRevisionBook retainedSegmentRevisions;
mutable std::mutex readinessDiagnosticsMutex;
uint64_t readinessEventSequence;
std::unordered_map<std::string, SourceReadinessEventState> sourceReadinessEvents;
RenderMutationDiagnostics lastReadinessMutation;
```
多个 RenderSource / Tile observer callback 会进入:
```cpp
advanceRetainedSourceRevision(...)
recordReadinessMutation(...)
onTileChanged(...)
onTileAction(...)
buildReadinessDiagnostics(...)
retainedSegmentSourceState(...)
```
并 lock:
```cpp
readinessDiagnosticsMutex
```
V18 当前成员声明中:
```text
renderSources
renderLayers
...
retainedSegmentRevisions
...
readinessDiagnosticsMutex
sourceReadinessEvents
...
threadPool
```
C++ 成员按声明反序析构,因此 readiness state / mutex 会早于 renderSources 销毁。
而 RenderSource 在创建时:
```cpp
renderSource->setObserver(this);
```
observer 指向 RenderOrchestrator。
当前 `RenderOrchestrator::~RenderOrchestrator()` 只:
1. contextLost 时标记 layer;
2. `threadPool.waitForEmpty()`;
没有在 readiness state 仍有效时显式 detach RenderSource observer / 清理 renderSources。
因此 V18 存在明确生命周期危险:
```text
readinessDiagnosticsMutex destroyed
↓
renderSources still destroying/alive
↓
late tile/source callback
↓
RenderOrchestrator::onTile*
↓
lock destroyed mutex
↓
FORTIFY SIGABRT
```
---
## 3. 修复原则
不要只依赖调整成员声明顺序。
本任务应建立显式 teardown contract:
```text
RenderOrchestrator destructor begins
↓
stop / drain deferred scheduler work
↓
detach observer from every RenderSource
↓
destroy/clear renderSources while all orchestrator state is still alive
↓
only then continue member teardown
```
同时 `RenderSource::setObserver(nullptr)` 必须安全恢复到 NullObserver。
目标是即使未来成员声明顺序变化,Source callback 也不能在 owner teardown 后访问 RenderOrchestrator。
---
## 4. 必做实现
### 4.1 RenderSource nullptr observer 语义
当前:
```cpp
void RenderSource::setObserver(RenderSourceObserver* observer_) {
observer = observer_;
}
```
改成与 Style Source / Layer 一致的安全语义:
```cpp
observer = observer_ ? observer_ : &nullObserver;
```
要求:
- constructor 仍默认 NullObserver;
- `setObserver(nullptr)` 是合法 detach;
- onTileChanged / onTileError / onTileAction 不需要加 null 分支;
- 不吞掉正常有 observer 时的回调。
必须加非 Jest C++ 回归测试验证 nullptr detach 后 callback 不 crash、不调用旧 observer。
### 4.2 RenderOrchestrator 显式 teardown
在 `RenderOrchestrator::~RenderOrchestrator()` 中,在 readiness mutex/state 仍确定存活时:
1. 保留现有 contextLost layer handling;
2. 等待已有 deferred work 完成;
3. 对所有 `renderSources` 执行 observer detach;
4. 显式 `renderSources.clear()`;
5. 必要时对 glyph/image observer 也做已有 API 支持的 detach,但不要扩大范围;
6. 不允许 teardown callback 再进入 RenderOrchestrator source callback。
顺序必须结合当前 TaggedScheduler / RenderSource / TilePyramid 的真实生命周期检查,而不是机械照抄上述编号。
如果存在“clear renderSources 本身可能产生新的 scheduler work”,需要设计第二次 drain 或更安全顺序,并在报告解释。
### 4.3 生命周期状态可选保护
如果仅 detach + explicit clear 仍无法证明并发安全,允许增加最小 teardown flag,例如 atomic bool,但只作为二次防线。
禁止用 flag 代替 observer detach。
禁止 catch FORTIFY;destroyed mutex abort 不是 C++ exception。
---
## 5. 不得修改
- STEP-100 Source→Segment locality 语义;
- per-segment revision;
- per-segment readiness;
- mixed Build/Reuse/Fallback;
- Fast Path gate;
- singleContinuousSegment;
- Source::isLoaded;
- Style Z-order;
- provider/network;
- NavSea;
- MapRenderer::resetRenderer 正常生命周期;
- Android Activity 为避免 reset 而加 workaround。
---
## 6. 必做测试
### 6.1 Native 非 Jest
至少覆盖:
1. RenderSource 默认 NullObserver 可安全接 callback;
2. setObserver(real) 正常转发;
3. setObserver(nullptr) 后不再调用旧 observer;
4. detach 后 onTileChanged / onTileError / onTileAction 安全;
5. RenderOrchestrator teardown 有至少一个含 RenderSource 的场景;
6. source callback 与 teardown 边界不访问已销毁 readiness state;
7. STEP-100 locality 相关 focused tests 不回归。
如果现有测试设施不方便直接构造完整 RenderOrchestrator teardown,允许提取最小可测试 teardown helper,但禁止为了测试重构大范围生产结构。
### 6.2 Android Test App
在现有 ParticleCoreLayerValidationActivity / Validation App 增加专门 STEP-101 teardown 场景。
场景必须真实触发 Native Renderer teardown,而不是只 clear field。
至少提供:
```text
T1 RESET_ONCE
T2 RESET_LOOP_20
T3 RESET_WITH_DYNAMIC_GEOJSON
T4 RESET_WITH_DIAGNOSTICS
```
目标:
- recreate/destroy MapView 或等价真实 renderer.reset;
- 每轮等待足够让 source/tile work 进入正常运行;
- T3 同时保持动态 GeoJSON/source mutation;
- T4 在 reset 前调用一次 RendererRuntime diagnostics,模拟 NavSea probe 时序;
- 20 次循环无 SIGABRT / crash / ANR;
- reset 后新 renderer 能继续正常显示 / 获取 diagnostics。
不得通过延迟 reset、禁用 observer、关闭 GeoJSON 来逃避问题。
---
## 7. NavSea 现场等价验收
RDC 在 Codex 完成后独立执行。
Android 设备:
`192.168.200.139:5555`
必须显式 `adb -s`。
最终至少执行:
1. Validation App STEP-101 T1~T4;
2. crash buffer 检查;
3. 20 次 reset/recreate;
4. 安装 V19 进 NavSea 后做真实启动;
5. 保留 NavSea 当前 `key={map-style-generation-...}` 正常 reset 触发条件;
6. 保留/启用一次 RenderSegment diagnostics probe A/B;
7. 连续至少 5 次冷启动,每次观察 >30 秒;
8. 不允许出现:
- `pthread_mutex_lock called on a destroyed mutex`
- SIGABRT RenderThread
- `MapRenderer::resetRenderer` teardown crash。
---
## 8. STEP-100 回归验收
修复 teardown 后必须确认 V18 的核心 locality 没被破坏。
至少复测 T4 R-C-R:
无关 R0:
```text
buildDelta = 0
invalidationDelta = 0
reuseDelta > 0
```
动态 R1 正常 build/invalidation。
禁止通过删除 mutex/readiness/revision 功能来修 crash。
---
## 9. Codex 执行边界
Codex负责:
- 只读检查真实 V18 代码;
- 实现最小 Native 修复;
- 编写/更新非 Jest C++ tests;
- 更新 Android Validation STEP-101 场景;
- 静态检查;
- 生成报告。
Codex不负责:
- NavSea 修改;
- V19 release;
- tag;
- publish;
- 覆盖 V18;
- Jest。
Mac Native 开发/编译原则保持;不要使用 Linux Native 环境。
---
## 10. 完成报告
生成:
`docs/报告/STEP-101_RenderOrchestrator销毁生命周期修复_Codex完成报告_v1.md`
Step 记录:
`docs/50_Step记录/STEP-101_RenderOrchestrator销毁生命周期修复_v1.md`
报告必须写:
- root cause;
- start HEAD;
- 修改文件;
- destructor teardown 顺序;
- observer detach 语义;
- 为什么不依赖成员声明顺序;
- tests added;
- 实际运行 / NOT RUN;
- STEP-100 locality 是否保持;
- 风险;
- 未发布 V19(Codex 阶段)。
Codex阶段不 push,由 RDC 验收后统一 commit/push。
---
## 11. V19 发布门槛
仅当:
- Native compile PASS;
- focused C++ tests PASS;
- Android Validation teardown loop PASS;
- STEP-100 locality regression PASS;
- NavSea V19 真实 5 次冷启动 >30s PASS;
- crash buffer 无 destroyed mutex;
才允许发布:
- RN / Android:`13.4.1-particle.19`
- iOS:`6.28.0-particle.19`
- tag:`maplibre-particle/rn/13.4.1-particle.19`
V18 保持不可变,不覆盖、不删除。
---
## 12. 最终原则
正常:
```text
MapView unmount
Style generation replacement
renderer.reset()
Activity recreate
```
都是合法生命周期。
Particle Native 必须做到:
> Renderer teardown 永远不能因为 observer late callback 访问已销毁 mutex/state 而杀掉宿主 App。
---
# 13. Codex 6-Sol High 架构评审修订(v2,优先级高于前文冲突表述)
只读评审结论:`APPROVE_WITH_CHANGES`。
## 13.1 根因表述修正
当前已经**代码层证实**存在生命周期漏洞:`readinessDiagnosticsMutex` / readiness state 的析构顺序早于 `renderSources`,而 `RenderSource` observer 仍指向 `RenderOrchestrator`;source/tile teardown 可同步或延迟回调进入 `onTileAction/onTileChanged` 并访问 mutex。
该漏洞与现场 `pthread_mutex_lock called on a destroyed mutex` 高度吻合;在没有完整符号化 crash stack 精确到具体 callback 前,不把“唯一现场根因”写成数学意义上的唯一证明。
## 13.2 teardown 必须双 drain
最低安全顺序调整为:
```text
contextLost layer handling
↓
第一次 threadPool.waitForEmpty()
↓
detach RenderSource observers
↓
detach GlyphManager / ImageManager observers
↓
renderSources.clear() // readiness mutex/state 此时仍存活
↓
第二次 threadPool.waitForEmpty()
↓
继续既有 backend/context render-job teardown
↓
成员析构
```
原因:source/tile destruction 本身可能投递新的 tagged cleanup/deferred work,第一次 drain 不能覆盖 clear 过程中产生的新任务。
同时必须审计并在报告说明:`TaggedScheduler::waitForEmpty()` 不等于清空 `runOnRenderThread` 队列;后者依赖现有 backend/context render-job 生命周期。不得声称双 drain 自动证明所有 render-thread job 已清空。
## 13.3 Observer detach 范围
除了所有 `RenderSource`:
- `glyphManager->setObserver(nullptr)`;
- `imageManager->setObserver(nullptr)`;
也应在 owner teardown 时显式 detach(前提是现有 API 的 nullptr 已安全回 NullObserver)。
`RenderSource::setObserver(nullptr)` 必须改为 NullObserver fallback。
不得直接给 `TilePyramid` / `Tile` observer 写 nullptr,除非其 API 本身有同等安全语义;本任务不扩展到这一步。
## 13.4 teardown flag
默认不增加 teardown atomic flag。
若实现审计发现真实并发 callback 不受 renderer thread / tagged scheduler 串行保证约束,必须先报告;atomic flag 只能二次防护,不能替代 observer detach、drain 和可等待取消。
## 13.5 Android Validation 证据升级
T1~T4 每一轮必须能证明发生了**真实 Native renderer reset**:
- 旧 MapView detach / SurfaceView detach;
- `nativeReset()`;
- `MapRenderer::resetRenderer()` 进入/完成;
- 新 renderer style ready;
- 新 renderer diagnostics 可用。
不能把 `setStyle()`、clear field、只读 diagnostics 当成 teardown 测试。
推荐按代次销毁并重建 MapView,或 Activity recreate;T2 至少 20 次已确认 reset。
T3:每轮 reset 前保持动态 GeoJSON/source mutation。
T4:每轮 reset 前调用一次 Native diagnostics,模拟 NavSea 8 秒 probe 的等价条件。
每轮应等待 source/tile 确实进入运行态,而不是只按固定 sleep 机械计数。
## 13.6 测试必须覆盖真实 source teardown
空 `RenderOrchestrator` 析构测试不够。
非 Jest C++ 测试至少需要一个含 RenderSource / tile callback 的 teardown 场景,使 source cancellation / callback 能在销毁边界发生,并验证旧 observer 不再收到回调。
## 13.7 正常 source erase / clearData 审计
必须只读检查 `clearData()` 和正常 source erase/replacement 路径,因为它们也会销毁 RenderSource。
本任务主要修 owner teardown;不得未经证明把 destructor 修复泛化为“所有 source replacement 异步问题均已解决”。若发现相同 observer 生命周期漏洞在正常 erase 路径存在,应做最小同源修复或明确 BLOCK,不得隐藏。
## 13.8 V19 候选验收顺序
V19 发布门槛修正为:
```text
STEP-101 source code PASS
→ 构建未公开的 V19 candidate artifacts
→ Validation App 实机 PASS
→ NavSea 使用 candidate 做 5 次冷启动/teardown 验收
→ 公开发布不可变 V19
→ public readback
→ finalize/tag
```
不得先公开 V19 再做 NavSea 验收。

View File

@@ -0,0 +1,262 @@
# STEP-102 RenderSegment 无 Placement 段局部复用 Codex 任务 v1
## 1. Step 编号和目的
STEP-102:修复 full CPU 多 Retained Segment 下 placement aggregate gate 的不必要扩散,使**结构上不具备 placement 能力**的 Retained Segment 能在其他 placement-bearing Segment fallback/live 时继续独立 composite/reuse。
本 Step 的设计依据:
`docs/20_调查/RenderSegment多Retained段全局Placement门槛_粒子管理员审查说明_v3.md`。
## 2. 当前已冻结基线
- 仓库:`/Users/tei/dev/MapLibreParticleLab-step102`
- branch:`step102-placement-free-retained-locality`
- start HEAD:`6df21dac38f072c5ad35b8dfc7ec5217509602bc`
- upstream base:MapLibre Native core 既有冻结基线,不升级
- V19/V20 release worktree:冻结,只读,不修改
- STEP-100 source-scoped locality:必须保持
- STEP-101 teardown 修复:必须保持
- Fast Path:本 Step 不修改
- C-001:不升级
## 3. 本 Step 目标
必须实现:
1. 增加结构性 placement-capable range 查询;
2. full CPU 每个 Retained Segment 独立计算 placement gate;
3. placement-free Retained 不再被其他 Segment 的 placementChanged/symbolFadeChange 纯 aggregate gate 拖入 fallback;
4. placement-bearing Retained 继续使用现有保守 placement gate;
5. 从 full CPU `globalLiveFallback` 移除纯 aggregate placement 条件;
6. 保持真正全局 fail-closed 条件;
7. diagnostics 增加结构 placement、per-segment gate、实际 composite/live 与全局 main-buffer execution 信息;
8. RN diagnostics TS 类型做 additive 扩展;
9. 增加对应 C++ 测试源码与 Android Validation 场景源码;
10. 不改变 Style Z-order、mixed executor、C-001 和 RN method surface。
## 4. 非目标 / 禁止事项
禁止:
- placement-bearing Segment 之间的局部碰撞缓存;
- per-segment collision graph / symbol fade / placement fingerprint;
- Fast Path 改造;
- multi-continuous Fast Path;
- 重写 `visitRenderSegmentExecution()`;
- 修改 NavSea;
- 新增 NavSea 私有 Native API;
- 修改 C-001;
- 修改 V19/V20 release worktree/tag;
- 升级 MapLibre、NDK、Gradle、AGP、Java、Node 或其他工具链;
- 为通过测试降低 fail-closed 门槛;
- Android Gradle/build、APK/AAR build、ADB、设备操作;
- Jest。用户未要求 Jest,本任务不得新增或执行 Jest。
## 5. 允许修改范围
生产代码优先限制在:
- `src/mbgl/renderer/render_orchestrator.hpp`
- `src/mbgl/renderer/render_orchestrator.cpp`
- `src/mbgl/renderer/renderer_impl.cpp`
- `include/mbgl/renderer/render_segment.hpp`
- `src/mbgl/renderer/retained_underlay_runtime_state.hpp`
- `src/mbgl/renderer/render_segment_json.hpp`
- `packages/maplibre-particle-rn/src/types.ts`
测试/Validation 允许:
- `test/renderer/retained_underlay_cache.test.cpp`
- 与现有 Particle Validation 场景直接相关的最小 Android Test App 文件
文档允许:
- 本任务书
- `docs/50_Step记录/STEP-102_RenderSegment无Placement段局部复用_v1.md`
- `docs/报告/STEP-102_RenderSegment无Placement段局部复用_Codex完成报告_v1.md`
- `粒子开发记录.md`
- v3 审查说明只读,除非发现明确事实错误;若需改,停止并先报告
如果实现必须扩大生产代码范围,先停止并报告原因,不得自行扩张架构。
## 6. 禁止修改范围
- NavSea 仓库
- `navsea-particle-integration` contract/RFC/ADR
- Fast Path 逻辑、`tryRenderParticleFastFrame()`、`singleContinuousSegment()` 语义
- `retainedRangeUsesPlacement()` 现有动态语义
- mixed executor 算法
- Source `isLoaded()` 定义
- STEP-100 source revision/locality 语义
- STEP-101 teardown 生命周期语义
- renderer/backend 架构
- release/version/tag/publish 坐标
## 7. 实施要求
### 7.1 结构性 placement-capable 查询
新增 full CPU retained 专用查询,必须基于 layer 结构,而不是当前帧 placementData。
最小保守语义:
- range 中存在 `symbol` layer → placement-capable
- 无 `symbol` layer → placement-free
- custom/custom-drawable 继续由 unsupported gate 处理
不得用 `needsPlacement()==false` 证明 placement-free。
### 7.2 per-segment placement gate
每个 Retained Segment 至少形成两个明确事实:
- structural placement capability
- current full-CPU placement gate result
placement-free Segment 不受纯 global placement gate 阻塞。
placement-bearing Segment 本 Step 继续沿用旧保守 gate,不承诺稳定后 reuse。
变量/字段命名不得把 `symbolFadeChange==0` 错称为严格 placement stable。
### 7.3 full CPU mixed execution
`segmentSupported` 改为使用对应 Segment placement gate。
`globalLiveFallback` 仅移除纯 aggregate placement 条件,其他真正 global 条件继续保留。
不得重写 `visitRenderSegmentExecution()`。
### 7.4 fallback reason
`static-placement` 必须按 Segment 自身 placement capability/gate 判定,不能从 aggregate reason 无差别传播。
### 7.5 diagnostics
每个 Segment 最少新增等价语义:
- `placementCapable`
- `placementGatePassed`
- `actualExecution = composite | live`
全局最少新增等价语义:
- `placementChanged`
- `symbolFadeChange`
- `placementTransitionActive`
- `crossSourceCollisions`
- `mainBufferExecutionMode = mixed | global-live`
- `globalLiveFallbackReason`
`actualExecution` 必须反映本帧 main-buffer 最终实际执行,不能根据 cache finalDecision 推导。
Diagnostics 查询必须无副作用、不得推进 revision。
### 7.6 RN 类型
只扩展现有 diagnostics 返回类型,不新增 method,不改变 `setRenderSegmentPlan()` 输入 contract。
Android/iOS Shared Core JSON 语义保持一致。
## 8. 构建要求
Codex 本阶段**不得执行任何 Android 编译/Gradle/APK/AAR build**,也不得启动长时间 CMake/Ninja/Bazel 构建。
Codex 完成代码后只需提供精确验证命令,由后续 RDC/用户按规则执行。其中 Android 编译由用户手工执行。
Codex 可执行的机械静态检查仅限:
- `git diff --check`
- 只读 grep/rg/git diff/status
- 不产生构建产物的格式/静态检查(若仓库已有且无需安装依赖)
不得安装或升级系统依赖来制造测试 PASS。
## 9. 测试要求
Codex 必须新增/补强测试源码,但本阶段不执行大型测试。
至少覆盖:
1. placement-free R0 + placement-bearing R1:R0 可 composite,R1 live;
2. 含 symbol 但当前 placementData 为空:仍判定 placementCapable=true;
3. 两个 placement-free Retained:持续 reuse/composite;
4. source-local fading/mutation 回归不误伤 R0;
5. placement-bearing 在 transition disabled / `symbolFadeChange=1` 等状态仍不被本 Step 放宽;
6. 真正 global gate 继续 global-live/fail-closed;
7. topology 变化释放旧 resource;
8. cache decision=reuse 但 global-live 时,diagnostics 的 actualExecution 必须为 live;
9. diagnostics JSON/TS 字段语义一致且查询无副作用。
Android Validation 场景应能在后续手工构建后明确输出 STEP-102 验收所需字段,不依赖 NavSea。
## 10. 验收标准
代码审计门槛:
- [ ] 新增结构性 placement-capable 查询
- [ ] 未改变 `retainedRangeUsesPlacement()` 旧语义
- [ ] full CPU per-segment placement gate 生效
- [ ] placement-bearing 继续保守
- [ ] `globalLiveFallback` 只移除纯 aggregate placement 条件
- [ ] 真正 global gate 保留
- [ ] mixed executor 未重写
- [ ] Fast Path 无语义修改
- [ ] per-segment fallback reason 正确
- [ ] diagnostics 有 actualExecution 与 main-buffer mode/fallback reason
- [ ] RN method surface 不变
- [ ] C-001 不变
- [ ] 测试源码覆盖设计矩阵
- [ ] `git diff --check` PASS
运行态 PASS 不在 Codex 阶段宣称。Android 手工编译与真机验证未完成前,STEP-102 状态只能写“代码完成 / 等待验证”或同等非 PASS 状态。
## 11. Git 要求
- 工作分支:`step102-placement-free-retained-locality`
- 禁止修改 particle/main 工作区
- 禁止 `git add -A`、`git add .`、`git reset --hard`、`git clean`
- 只 scoped staging 本任务文件
- 不提交无关 dirty/untracked 文件
- Codex 可在实现完成、静态检查通过后创建 scoped implementation commit,但**不得 merge 到 particle/main、不得 push release 分支/tag、不得发布制品**
- 是否 push/merge 由后续独立验收决定
## 12. 必做输出
Codex 完成后必须交付:
1. 生产代码修改;
2. C++ 测试源码;
3. Android Validation STEP-102 场景源码/日志字段;
4. `docs/50_Step记录/STEP-102_RenderSegment无Placement段局部复用_v1.md`;
5. `docs/报告/STEP-102_RenderSegment无Placement段局部复用_Codex完成报告_v1.md`;
6. 追加 `粒子开发记录.md`;
7. 精确列出后续验证命令;
8. 明确列出所有 NOT RUN / BLOCKED 项;
9. Git diff/status/commit(若创建)事实。
## 13. 执行报告完整文件名
固定:
`docs/报告/STEP-102_RenderSegment无Placement段局部复用_Codex完成报告_v1.md`
同主题后续报告只递增 `_v2/_v3`,不得另造近义文件名。
## 14. 执行报告固定内容
至少包含:
1. 执行结论:只能按实际写代码完成/等待验证、PARTIAL、BLOCKED 或 FAIL;未运行 Android 不得写运行态 PASS
2. Git 基线:branch/start HEAD/end HEAD/status
3. 实际修改文件
4. 新增文件
5. 实现内容逐条对照任务书
6. 与 v3 设计差异
7. Fast Path / mixed executor / C-001 未修改审计
8. diagnostics 新字段与语义
9. 测试源码覆盖矩阵
10. 实际执行的静态检查
11. 未执行的 build/test/Android/设备项目
12. 用户手工 Android 构建命令
13. 后续 RDC/真机验收命令与硬门槛
14. 已知风险与未完成事项
15. Git commit 信息(若有)
## 15. 阻塞与停止条件
遇到以下任一情况必须停止扩大修改并报告:
- 结构性 placement capability 不能仅靠既有 layer type 安全判定,需要新增更大公共抽象;
- 必须修改 Fast Path 才能完成本任务;
- 必须重写 mixed executor;
- 必须改变 collision/Placement 核心算法;
- 必须修改 C-001 / RN method surface;
- 必须修改 NavSea;
- 必须扩大到 renderer/backend 架构重构;
- 发现 global revision 仍有未预期的 placement 推进,需要新设计;
- 需要升级工具链/依赖;
- 需要删除或弱化既有测试/安全门槛。
若实现范围保持在 v3 冻结边界内,可直接完成代码并停在“等待手工构建/运行验证”。

View File

@@ -0,0 +1,43 @@
# STEP-104 官方 MapLibre Native Android 13.6.1 迁移:第一阶段 Codex 任务 v1
## 1. 基线与职责
- 用户授权 **GPT-6.1 Sol / High** 实施官方跟进,使用 Mac 固定 GNU Screen 会话 `20825.7445.codex`,不要自行切换模型和推理档位。
- 项目独立 worktree:`/Users/tei/dev/MapLibreParticleLab-upgrade-android-1361`,分支 `upgrade/android-native-13.6.1-20261009`。
- 当前第一父基线:**官方 Android Native 13.6.1** peeled commit `c7506d6aff3800e946f89e1a51432fc22d1a6534`;原有自研稳定版本(.21)HEAD `630ec657687bad4200c059bbccbb950d9c6f7ce9`,审计与报告闭环 HEAD `b433775348373b10fba02dc0e1f728bacd72f9e7`。
- Integrated repo Linux 远端 `main` 已同步至 `80667d6c343411d03a760425438e3d292f452118`;当前遵守 C-001/C-002、RFC-004、ADR-001,不得擅自改公开 API 或将 Android 新行为写进跨平台 contract。
- 先读原工作树 `/Users/tei/dev/MapLibreParticleLab/AGENTS.md`、`PARTICLE_BASELINE.md`、`docs/00_项目规范/`、`docs/00_项目总则/README.md` 与四份有效总则,再读现有审计报告 `/Users/tei/dev/MapLibreParticleLab-upstream-audit-20261009/docs/报告/UPSTREAM-001_MapLibre官方升级兼容性架构审计_Codex完成报告_v1.md`、近期 STEP-100/101/102 记录以及本任务。
- 另一个 Mac `particle/main` 工作树有用户未跟踪文件且落后远端,禁止修改;历史 release/STEP-103 工作树均不可改。
## 2. 本轮的工程目标和停点
目标是形成一个**可测试的 Android Native 13.6.1 官方底座候选**,继续保留自研 Field/QBIN/Particle/WeatherColor/RenderSegment/Retained 功能,不重写、不扩大功能。当前不是新版发行。
- A:在本分支以官方 13.6.1 为第一父,安全合入 `b433775348...` 自研历史的有效差异。优先使用 `git merge --no-commit --no-ff b433775348...`;解决全部 rename/content/modify-delete 冲突,不允许选择整文件 `ours/theirs` 丢失官方修复或自己的功能。核实 `git diff --check`、冲突标记和完整树,再创建明确 merge commit。可启用 rerere。
- B:适配官方 `mbgl→mln` 命名空间、include、Layer/Source/Shader factory、`RenderLayer::update(PaintParameters)`、`RenderStaticData::backendSize` 移除、Renderer lifecycle、RenderSegment 和 GL 粒子后端。只修改当前升级必要的官方接入点,保留现有 fail-closed、source/placement/revision/fast-path gate、map Style 顺序、stencil/target 安全。
- C:源码修改完成后,列出**精确可执行**的 Android Native C++/OpenGL 编译与定向测试命令,让 RDC 在 Mac 或 Linux 执行;Codex 自身不得进行耗时 build、link、codegen、打包或 Jest。可以执行 `git diff --check`、少量静态检查。
- D:若完整迁移无法在本轮完成,优先形成单独的、可复现且可回退的 Git checkpoint、明确残留冲突/失败清单;未清除 Git 冲突不得提交伪造的成功 merge。发生公共 API/Contract 变化或 iOS 专属需求立即停下来报告,不自行扩大跨团队范围。
## 3. 必须保留的现有行为
- C-002 QBIN V4 单帧 exact match、双帧合法插值、每 fieldKey 八帧和原子拒绝语义不变;不同 reference/dataset/profile 不混用;RN Host 负责加载、requestedForecastTime,Native submit 不调整时间。
- WeatherColorLayer 与 RasterParticleLayer 独立;粒子 GPU ping-pong、trail 和 RenderSegment 局部缓存存在;不允许用 CPU 动画替代、不允许关闭关键保护逻辑使其编译通过。
- Retained 保留 Z-order、opaque/translucent 绘制语义与 segment 索引;Source/layer/style/context/placement 变更失效安全、销毁不泄漏或使用陈旧 texture。
- 官方新版 Feature State 接口不得被自研逻辑覆盖或静默禁用;只记录 Native 后续 RN 11.5 测试 Gate,不升级 RN 包本轮版本锁。
## 4. 范围
- 允许:升级分支中的官方 Native Core/Shader/CMake、必要的 Android Native/JNI 接入、粒子模块源码、测试代码的机械迁移与必要接口适配,以及必要记录。
- 禁止:修改 `particle/main`、`release/particle.21`、STEP-103 工作树、NavSea、Integration 合同、iOS 专属 Metal/Bridge 功能实现、官方仓库、Node/Gradle/NDK 工具链;禁止发布 AAR/npm、build APK、改 public API/ABI 语义。
- 旧 .21 所有发布坐标保持冻结。iOS 旧实现应尽可能保留源码,但本轮只允许写 **NOT VERIFIED**,不允许声称 Metal/Swift/XCFramework PASS。
## 5. 记录和 Git:强制多次小提交
- 在仓库**根目录的 `recoder_step.md`** 追加每项实质进展,简明中文且 append-only,记录日期、基线、当前变化、已完成、剩余问题、下一步、关联 commit。还需追加 `粒子开发记录.md`(合入后存在),同步更新 `docs/50_Step记录/STEP-104_官方Native13.6.1升级阶段A_v1.md`。
- 本任务已有独立启动 checkpoint 提交。后续**至少尝试**按合并/结构迁移/接口修复/文档三个功能批次提交。每次提交限定本主题的文件并有清晰中英 commit message。不允许为了凑提交提交空文件或破坏历史;若阻塞,就如实说明只完成哪些。
- **仅 push 本次升级分支**到 `origin/upgrade/android-native-13.6.1-20261009`;切勿 push `particle/main`、force push、合并回主线、push upstream。需等 RDC 独立编译验收后再由 RDC 最终执行 push;Codex 此轮只 commit,不负责最终远端验收。
- 用户正式要求阶段记录必须叫 `recoder_step.md`,**不可擅自纠正拼写或用其它文件代替**。
- 工作期间若发现现存不相关改动,不能纳入任何提交。
## 6. 完成报告与检查
- 完成报告固定 `docs/报告/STEP-104_官方Native13.6.1升级阶段A_Codex完成报告_v1.md`,必须记录:实际模型与推理档位、原始 SHA 和候选 SHA、每个 commit 与变更范围、merge 冲突解决的准确状态、迁移清单、具体核心 API/行为检查、无 build 时 NOT RUN、给 RDC 的精确构建命令、剩余问题、Android/iOS/RN 明确边界、下一 Gate。
- 命名绝对不能自称正式 SDK PASS;如只完成局部迁移标 PARTIAL / BLOCKED。Codex 结束前检查 `git status --short`、`git diff --check`、阶段日志存在,任务范围与 commit 对得上。
- 对用户的最终下一停点是 Android 官方 13.6.1 候选的 Core/Android OpenGL 精确编译 Gate;RN 11.5/iOS/发布留后续。
- 若需要新增跨平台语义/接口必须暂停并记录 Integration 协调所需证据,而不是自行做新合同。
## 7. 本阶段特殊实施规则
按现有项目 `AGENTS.md`:**Codex 写代码,RDC 负责独立编译和验收**。仅在完成局部代码和提交后提供精确编译命令,等待 RDC 结果,如失败再进入下一轮修复。不要自行执行长时间构建。

View File

@@ -0,0 +1,39 @@
# UPSTREAM-001 MapLibre 官方升级兼容性架构审计(只读代码,2026-10-09)
## 授权与模式
- 用户明确授权 Mac 使用 **GPT-6 Astra High** 做以未来跟随官方升级为目的的架构审计。
- Codex 执行器须显式指定 `gpt-6-astra`、`model_reasoning_effort=high`,实际配置从 Codex JSONL 开始事件核实;如不一致,报告 BLOCKED,不能伪称。
- 只读源代码。仅允许生成/修改本任务书和 `docs/报告/UPSTREAM-001_MapLibre官方升级兼容性架构审计_Codex完成报告_v1.md`;禁止改 C++、RN、Java、ObjC、构建脚本和依赖。
- 仓库为独立干净审计 worktree,基于正式远端 `origin/particle/main` 的 `.21`,不可操作其他已有脏工作树。无需构建 APK、AAR、Xcode,无需 Jest。不能伪造运行验收。
- 不修改 Integration COORD/RFC/ADR/Contract;如建议跨平台契约变化仅列出待协调项。
## 权威输入
- `/root/sourceserver/navsea-particle-integration` 为 Linux Integration;已由 RDC 同步到 `80667d6c343411d03a760425438e3d292f452118`。Mac 上可读取到的合同以已存在文件为准,不要猜测。
- 阅读本仓库 `AGENTS.md`、`PARTICLE_BASELINE.md`、`docs/10_架构/20_粒子系统总体架构设计_v1.md`、`docs/00_项目总则/粒子系统项目规则与设计决策_v1.md`、`docs/30_设计/STEP-094_通用RenderSegment模型与Style分类Diagnostics设计_v1.md` 和相关 STEP-098/099/100/101/102/103 实现记录。
- 自定义现行发布:`630ec657687bad4200c059bbccbb950d9c6f7ce9` (`13.4.1-particle.21`)。
- 初始 upstream Core:`18545ca10d296704b2cba675b182ff2c8da24588` (见 `PARTICLE_BASELINE.md`);验证实际 merge-base。
- 官方 MapLibre Native Android `android-v13.6.1` peeled commit `c7506d6aff3800e946f89e1a51432fc22d1a6534`。
- 官方 MapLibre Native iOS `ios-v6.31.0` peeled commit `01791ad02c1bfe3b22c42a97619b972aba962f82`。
- 官方 MapLibre React Native `v11.5.0`;现有 Particle RN `11.3.6` peer/dev 锁及 Android AAR replacement、iOS SPM/Podspec 需独立审计。不能混淆 RN 11.5.0 与 Native 13.6.1。
## 必查问题
1. 原始目标“官方可持续升级、自研粒子和 RenderSegment 可重复移植”离目前真实代码有多远?用逐文件证据分类:**纯新增扩展**、**不可避免的官方接入 hook**、**可外提的官方修改**、**深耦合必须重构**,另列构建/平台桥接。不要用“62 个修改文件 = 62 个冲突”。
2. 在 `git diff` 与 `git merge-tree` dry-run 基础上,对 Android 13.6.1 和 iOS 6.31.0 分别量化冲突文件与交叉文件、可自动合并与疑似行为冲突。绝不可真实 merge/rebase 任何生产分支。优先核对 `renderer_impl.cpp`、`render_orchestrator.cpp`、`render_target.cpp`、`render_layer.hpp`、`render_source.cpp`、`paint_parameters.cpp`、RenderSegment/Retained cache、GPU backend、Style/Layer factory、JNI/Android/iOS 对接代码。
3. 以源代码里的函数/类名证明现有 Particle Core/Field/WeatherColorLayer/GPU 模块是否独立;列出真正只需 hook 的文件和未来易碎调用。用修复方案区分 thin hook、抽象接口、适配器、source-to-segment dependency、offscreen target/placement 等,不得建议一刀切“重写”。
4. RenderSegment 与 Particle Fast Path 的数据依赖、分层失效、Style 顺序、Opaque/Translucent、Placement、Context loss、资源所有权、Top/Bottom Retained、multi-segment 未来兼容约束。区分已实现功能和目前 fail-closed 限制。
5. 核查 `packages/maplibre-particle-rn` 的 `package.json`、`app.plugin.js`、`MapLibreParticleRN.podspec`、Native API 等;给出 RN 11.5.0 受官方 Android 13.6.1/iOS 6.31.0 依赖推动的单 SDK 依赖收敛风险、代码适配点、功能验证清单。
6. 准备升级顺序和可回滚 Gate:什么必须先重构、什么可以直接合并、哪些要不同平台分别验证,什么情况下必须停止并回 Integration 新 RFC/Contract。建议未来 upstream 版本跟踪工作流和“patch footprint budget”;明确对长期维护代价影响。
7. 逐项目给出 P0/P1/P2 表,包含路径、当前耦合证据、方案、风险、工作量相对估计、验收标准、Android/iOS影响;结论为 GO / CONDITIONAL GO / BLOCKED,不得把未编译当 PASS。
## 调查方法与客观限制
- 最少执行 `git merge-base`、`git diff --name-status`、`git merge-tree --write-tree --messages` 对两个官方 Native 目标作三方模拟;记录命令、exit code、冲突路径。merge-tree 会在 Git object db 创建对象但不改源码或分支,允许。
- 深入看源码定义和调用,不只扫描关键词;尽量提供可读且可复核的 `path:line` 和 commit hash。
- 官方 tag 比较若产生无共同祖先、shallow、无法下载等障碍,如实记录并提出可复现替代方案。
- 不强行运行常规编译、Android 实机、iOS 设备或 Jest。
- 对官方 RN 版本差异使用 release changelog、已有源码;未下载的 RN 文件不得假称已审查。
- 审计报告必须中文,章节包含:结论摘要、核对的版本与 SHA、方法和数据可信度、两条 Native 升级线冲突统计与具体文件、Particle 耦合清单、RenderSegment 耦合清单、RN 11.5.0 适配风险、改造优先级矩阵、阶段性迁移与验收、阻塞和未知、实际模型和文件修改清单。
## 必做输出和 Git 收尾
- 写入 `docs/报告/UPSTREAM-001_MapLibre官方升级兼容性架构审计_Codex完成报告_v1.md`;如不存在 `docs/报告/` 则创建。
- 工作树中仅允许审计任务 MD 和审计报告两份新增文档;完成 `git diff --check`、路径与报告完整性检查。
- **不要自行 commit 或 push**;执行器将先独立核对报告,再将仅这两份文档以隔离分支提交、确认快进后 push 到 `origin/particle/main`,最终回填 Git 状态。若未收到执行器的最终 Git 回执,报告必须写 `Git 收尾待 RDC 验收`,不能自称已推送。

View File

@@ -0,0 +1,175 @@
# STEP-099 RenderSource 就绪与 RenderSegment 失效诊断
状态:**CLOSED / PASS**
日期:2026-10-06(JST)
## 基线
- 仓库:`/Users/tei/dev/MapLibreParticleLab-step099`
- 分支:`step099-render-source-diagnostics`
- frozen release:`maplibre-particle/rn/13.4.1-particle.17`
- frozen release commit:`e8b451fe70054107773e82484c80e90df3889147`
- implementation commit:`8a5214d92dd2f8899db76d2194da42999fa0c87d`
- Integration/NavSea:未修改。
## 本 Step 完成内容
- Renderer readiness snapshot additive 暴露 style/image manager/render orchestrator/sprite readiness、fading、global content revision、per-source 状态和最近 mutation。
- per-source diagnostics 暴露 sourceId/type/enabled/isLoaded;tile-backed source 提供 tileCount/incomplete/loaded/fading。
- RenderSegment diagnostics 只读推导 `dependentSourceIds` / `unknownDependencies`;source-less layer 不制造 source dependency,共享 source 可出现在多个 segment。
- mutation sequence/source/tile action/reason 只消费既有 renderer 事件;正式 revision 增长逻辑不变。
- 正式 loaded 判定保持:
`renderTreeParameters->loaded = updateParameters->styleLoaded && isLoaded();`
- diagnostics snapshot 不进入正式 loaded/cache/fast path/segment execution。
- RN 仅增加 diagnostics 类型字段;没有 NavSea 私有 API,没有改变业务 API。
- Android Test App 提供 T1 STATIC、T2 GEOJSON_1HZ、T3 PERMANENT_UNREADY、T4 R-C-R。
## Native 验证
Metal host `RenderSegmentDiagnostics.*`:
- 6/6 PASS;
- 新增 `ReadinessSnapshotMapsSourcesToSegmentsWithoutSideEffects` PASS;
- 覆盖 source readiness、tile stats、source→segment、shared source、source-less 与重复 query 无副作用。
最终源码再次尝试 Metal configure 时当前 Mac 缺 `libuv` pkg-config,因此第二次 host rerun 未进入 build;不虚报 PASS。最终代码已经被 Android 全量 native build 成功编译并由 T1~T4 运行覆盖。
Vulkan:因当前 Mac 缺 `libuv`,NOT RUN tests。
Jest:NOT RUN,用户未要求。
## Android 构建
首轮 Android NDK 暴露:
```text
error: missing field 'tileCount' initializer
[-Werror,-Wmissing-designated-field-initializers]
```
只补全 `RenderSourceReadinessStats` 默认空字段显式初始化。
随后 native build 通过,但 strip 阶段因 Mac 磁盘仅剩约 2 GiB:
```text
No space left on device
```
仅清理可再生 Gradle 9.5.1 cache / 失败中间产物后恢复约 12 GiB,再次增量构建:
- `BUILD SUCCESSFUL in 4m 54s`
- 86 actionable tasks:7 executed / 79 up-to-date
- OpenGL Debug / x86_64
- APK:61,923,024 bytes
- libmaplibre.so:39,602,856 bytes
- SHA-256:
`5de73f0358b835a78d3ae7e2ac22f4efdb2a66775b8c63654a8bb7313957d90a`
设备:
- `192.168.200.139:5555`
- FZG1-2
- Android 13 / API 33 / x86_64
## T1~T4 结果
### T1 STATIC
- 1 个启动 false window;
- avg/max = 204 ms;
- 随后 global loaded 稳定为 true;
- retained cache 可持续 reuse;
- fast path 可进入 active。
### T2 GEOJSON_1HZ
- 两个 GeoJSON source 交错更新,总 update 122 次,约 61 次/源;
- 10 个 loaded=false window;
- avg 203 ms;
- max 205 ms;
- open 0;
- 约 60 s 中 false 总时长约 2.03 s,约 3.4%。
结论:存在 readiness thrash,但不是“几乎永远 false”。
### T3 PERMANENT_UNREADY
`step099-unready-raster-array`:
- 无 layer;
- enabled=false;
- isLoaded=false;
- 其他主要 source loaded。
结果:
- global renderOrchestratorLoaded=false 持续;
- 观察结束 open false window = 21,459 ms;
- retained cache 持续 style-not-loaded fallback。
结论:单个与 segment 无关的 permanently unready source 足以拉低 V17 全局 loaded。
### T4 R-C-R
- R0 deps=[step099-static]
- C deps=[particle-fixture]
- R1 deps=[org.maplibre.annotations, step099-dynamic, step099-static]
- dynamic update:61 次
结果:
- loaded false windows:4
- avg 203 ms
- max 207 ms
- contentRevision:1760 → 2540
- diagnostics 对 dynamic source 正确给出 affected=[2]
- R0 不依赖 dynamic source,但:
- build 1 → 121
- invalidation 20 → 200
结论:dependency diagnostics 已能表达 source-local 影响,但 V17 正式 content revision/cache invalidation 仍为 global。
## Q1~Q7
1. Q1:**YES**。permanently unloaded source 会造成全局 style-not-loaded。
2. Q2:**YES**。1 Hz GeoJSON 会产生约 200 ms readiness false window;T2 avg 203 / max 205 ms。
3. Q3:**NO(本次观测)**。双 1 Hz source 并未让 global loaded 几乎始终 false。
4. Q4:**YES**。GeoJSON tile mutation 推进 global content revision,并使 retained cache 重建/失效。
5. Q5:**YES**。不引用动态 GeoJSON 的 R0 仍受 global revision 影响;源码还确认 `retainedRangeIsStable` 全局检查所有 source fading。
6. Q6:fast path 仍有 global update signature(sources/layers/images 等)、global content revision、global fade、pendingChanges、placement/light/non-particle transition/repaint、annotation mutation、retained revision/cache/topology/boundary,以及 singleContinuous gate。
7. Q7 blocker:
- runtime confirmed:`PERMANENT_SOURCE_UNLOADED`、`DYNAMIC_SOURCE_READINESS_THRASH`、`GLOBAL_CONTENT_REVISION`
- source confirmed:`GLOBAL_FADE`、`GLOBAL_UPDATE_SIGNATURE`
- OTHER:pending/placement/light/repaint/annotation/topology/boundary/singleContinuous。
## 证据
忽略目录:
`artifacts/maplibre-particle/android-validation/`
- `build-info.txt`
- `build.log`
- `MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk`
- `step099-logcat.txt`
- `step099-device-info.txt`
- `step099-metal-gtest.log`
STEP-099 log SHA-256:
`0f15d75dde77e7dd2f4d98c46a4c1501a628205e8aae62130b0cb96db6b8482f`
## 边界结论
本 Step 未修改:
- retained cache 算法;
- fast path gate;
- singleContinuous / multi-continuous;
- segment-local invalidation 正式语义;
- RenderSegment execution;
- NavSea;
- Source isLoaded;
- RN 业务 API。
下一阶段应拆分处理 global source readiness、source/segment-local content revision/invalidation,再独立处理 fast-path global gates。

View File

@@ -0,0 +1,132 @@
# STEP-100 SourceScoped RenderSegment 局部失效记录 v1
状态:**CLOSED / PASS(Android runtime)**
日期:2026-10-06
## 基线
- worktree:`/Users/tei/dev/MapLibreParticleLab-step100`
- branch:`step100-segment-local-source-invalidation`
- start HEAD:`c4b481fd2c5b5da20d31f6ae54011f0552d7dbd0`
- V17 tag:`maplibre-particle/rn/13.4.1-particle.17`
- V17 frozen commit:`e8b451fe70054107773e82484c80e90df3889147`
## 实现
- Source/Tile mutation 增加 source-scoped revision;
- global retained content revision 继续保留;
- production renderer 与 diagnostics 共用 source→segment dependency;
- RETAINED Segment 独立 readiness / stability / Build / Reuse / Fallback;
- unrelated source unloaded/fading 不再拖垮该 Segment;
- full CPU mixed execution 支持 R0 Reuse + C Live + R1 Fallback;
- Fast Path gate、singleContinuous、多 Continuous语义未改;
- Source::isLoaded 与 global renderTree loaded 语义未改。
## Android Build
标准 validation pipeline 最终:
```text
RC=0
BUILD SUCCESS
variant=OpenglDebug
abi=x86_64
apk_bytes=61956640
libmaplibre_bytes=39636472
sha256=86e22bf081bf7d3196f0bf0e7c56af51bde01e9f0b01e0bab238cb794273315a
```
RDC 另修复 validation script 的 pipefail/SIGPIPE 141:
`awk ... {print $1; exit}` → 完整消费管道。
## FZG1-2
- Android 13
- API 33
- x86_64
- ADB:`192.168.200.139:5555`
### T1 STATIC
- false window:1
- avg/max:203 ms
- R0/R1 build=1 后持续 reuse
### T4 R-C-R 主验收
窗口:
- baseline:tick 8
- final:tick 130
- 约 61.6 s
global revision:
`128 → 973`
R0:
```text
build 1 → 1
invalidation 20 → 20
reuse 132 → 4042
sourceRevision unchanged
```
R1:
```text
build 5 → 135
invalidation 26 → 211
```
结论:
- R0 buildDelta=0
- R0 invalidationDelta=0
- R0 reuseDelta=+3910
- global revision 仍增长
- dynamic source affected=[2]
**主硬门槛 PASS。**
### T2 GEOJSON 1HZ
- 约 35 s
- falseWindowCount=6
- avg=203 ms
- max=205 ms
- R0 build=1 / invalidation=18 保持稳定,reuse 增长
### T3 PERMANENT UNREADY
global loaded=false 持续约 21.468 s。
unready source:
- no layer
- enabled=false
- isLoaded=false
R0/R1:
- build=1 不变
- invalidation=19 不变
- reuse:11 → 1200
- decision=reuse
说明 global loaded 兼容事实仍为 false,但无关 retained cache 继续安全复用。
## Native Host Test
Codex 已新增 `RenderSegmentLocality.*` 测试源码。
当前 Intel Mac 缺 `libuv`,Metal host configure 被环境阻塞。RDC 曾尝试 Homebrew 安装,但发现会连带升级 CMake/OpenSSL/Python 且 Intel 无 bottle 支持,已主动停止。
因此:
- Native host GTest:ENV BLOCKED / NOT RUN
- Android full native build:PASS
- Android runtime:PASS
Jest:NOT RUN。
## 结论
STEP-100 功能目标成立:
> GeoJSON Source 更新只刷新依赖它的 retained segment;无关 retained segment 不再一起刷新。
允许进入 V18 unified release。

View File

@@ -0,0 +1,54 @@
# STEP-101 RenderOrchestrator 销毁生命周期修复记录 v1
状态:**CLOSED / PASS(Native + Android runtime)**
日期:2026-10-07
## 目标与基线
- 工作区:`/Users/tei/dev/MapLibreParticleLab-step101`
- 分支:`step101-render-orchestrator-teardown`
- start HEAD:`d29e84c1a90daeea104b389d28b000c4f017d08d`
- implementation commit:`64cf8f44350eb8ec4b45360db4d3f9505ac4ac0b`(`fix: make render orchestrator teardown safe`),已 push 到 `origin/particle/main` 并回读一致。
- 工作合同:`docs/40_任务/STEP-101_RenderOrchestrator销毁生命周期修复_Codex任务_v2.md`,第 13 节优先于前文冲突项。
- V18 为不可变已发布版本;本阶段未创建、发布或标记 V19。
- 目标:修复 RenderSource/Tile 销毁时 observer 可能回调已析构的 RenderOrchestrator readiness mutex/state 的生命周期漏洞。
V18 成员声明使 readiness mutex/state 早于 `renderSources` 自动析构。Tile 销毁时同步发出 `Cancelled` 回调的路径可达,且与现场 Android destroyed mutex SIGABRT 高度吻合;没有完整符号化栈与修复后等价实机结果,暂不把它写成唯一确认的现场根因。
## 必做项进度
- [x] `RenderSource::setObserver(nullptr)` 恢复 NullObserver,保留正常 observer 转发。
- [x] Orchestrator 析构:保留 contextLost layer handling;第一次 tagged drain;detach RenderSource、GlyphManager、ImageManager observer;在 readiness state 存活时清理 sources;第二次 tagged drain。
- [x] 静态审计独立 render-job 队列:`waitForEmpty()` 不排空该队列;OpenGL context 析构的 `runRenderJobs(true)` 属于后续 backend 清理,测试中也单独调用 `runRenderJobs()`。不能以双 drain 代替 render-job 验收。
- [x] 新增非 Jest C++ 测试源码:默认/真实/detach observer、三种 tile callback、Cancelled、source 清理后第二次 drain、render-job 单独处理和重复 teardown。helper 像生产代码一样注册 Orchestrator observer,并断言 source 销毁前旧 observer 已被替换。
- [x] Android Validation 增加 T1 RESET_ONCE、T2 RESET_LOOP_20、T3 RESET_WITH_DYNAMIC_GEOJSON、T4 RESET_WITH_DIAGNOSTICS;通过 Activity recreate 触发 MapView 销毁/新建,并输出 SurfaceView detach、nativeReset、resetRenderer、style ready 与 diagnostics 日志供逐次配对。
- [x] 只读审计正常 `renderSources.erase()` / `clearData()`:两者在 Orchestrator 存活期间执行;TileCache 析构等待其延迟释放任务结束。本阶段没有扩大其行为修改,运行态异步边界仍待 RDC 验证。
- [x] 静态核对 STEP-100 locality、Fast Path、`singleContinuousSegment`、`Source::isLoaded()` 等代码未被本次 diff 修改。
- [x] Native:Android full native build PASS;focused Android C++ TestRunner 6/6 PASS。Mac host 因 libuv 环境阻塞,未虚报。
- [x] Android Validation APK build PASS;T1~T4 实机 PASS;T2 完整 20 次真实 reset/recreate,crash buffer 为空。
- [x] STEP-100 T4 R-C-R locality 回归 PASS:R0 buildDelta=0、invalidationDelta=0、reuseDelta=+3878。
- [ ] V19 candidate、NavSea 五次冷启动与正式 V19 发布:属于后续发行 Gate,尚未执行。
## 允许与禁止范围
实际变更限于 Orchestrator/RenderSource 生命周期、对应 C++ 测试、Android Validation 场景及 Java/JNI reset 观测日志。未修改 NavSea、provider/network、STEP-100 locality 实现、发布坐标或 V18 产物。未运行 Jest。
## 检查与当前结果
本次验证仅包含源码 diff 静态审计与 `git diff --check`。构建、链接、GTest、Gradle/APK、ADB、设备、NavSea、发布均 **NOT RUN**;源码交付不能记为运行态 PASS。完成报告:`docs/报告/STEP-101_RenderOrchestrator销毁生命周期修复_Codex完成报告_v1.md`。
## 阻塞与下一步
当前没有已观测编译失败;实际编译与场景行为仍未知。由 RDC 按完成报告的命令独立编译、运行 Native 测试、Android T1~T4、STEP-100 locality,并核对每次 `RESET_REQUEST` 对应 SurfaceView detach、`nativeReset`、`resetRenderer` 和新 renderer ready。随后才进入 V19 candidate 与 NavSea 等价验收;全部门槛满足后才可考虑正式发布。
## RDC 最终证据
- Android Validation APK:61,957,678 bytes;`libmaplibre.so` 39,637,512 bytes;SHA-256 `14cbd35ed0bc1366389ddea69925901013e3b209ed3575462421a7920c73c721`。
- T1~T4 teardown:全部 PASS;T2 20 次 reset;动态 GeoJSON / diagnostics 条件均无 crash。
- STEP-100 locality:global revision 62→894;R0 build 1→1、invalidation 19→19、reuse 12→3890;PASS。
- Android C++ focused TestRunner:4 个 `RenderSegmentLocality` + 2 个 `RenderOrchestratorTeardown` 全部 PASS;status=0。
- Mac host GTest:ENV BLOCKED(本机缺可用 libuv pkg-config),不影响 Android full native/device 闭环结论。
- Jest:NOT RUN。
**STEP-101 CLOSED / PASS。** 下一阶段进入 V19 candidate → NavSea 等价冷启动 Gate → 不可变公开发行。

View File

@@ -0,0 +1,60 @@
# STEP-102 RenderSegment 无 Placement 段局部复用记录 v1
状态:**进行中(代码完成,等待独立构建与运行验证)**
日期:2026-10-08
## 目标与基线
- 工作区:`/Users/tei/dev/MapLibreParticleLab-step102`
- 分支:`step102-placement-free-retained-locality`
- 起点 HEAD:`6df21dac38f072c5ad35b8dfc7ec5217509602bc`
- 工作合同:`docs/40_任务/STEP-102_RenderSegment无Placement段局部复用_Codex任务_v1.md`
- 设计依据:`docs/20_调查/RenderSegment多Retained段全局Placement门槛_粒子管理员审查说明_v3.md`
- 发布坐标:V19/V20 工作区与发行内容冻结;本 Step 不创建版本。
目标是让结构上没有 symbol layer 的 Retained Segment 在其他段 placement 活跃时继续独立缓存并经 main-buffer composite。
## 必做项
- [x] 基于 style layer type 查询结构性 placement capability;不使用当前帧 `needsPlacement()` 证明 placement-free。
- [x] full CPU 每段计算 placement gate;含 symbol 的段仍受 changed、fade 与 transition 保守门槛约束。
- [x] `segmentSupported` 和 fallback reason 按段生成;full CPU global-live 只移除纯 aggregate placement 条件。
- [x] 保留 3D、debug、MapMode、sprite/image、light 等真实全局门槛和既有 revision/key 失效。
- [x] diagnostics 增加结构、逐段 gate、实际 main-buffer 执行及全局 placement/execution 字段;RN TS 只增加诊断字段。
- [x] 新增 C++ 源码测试与 Android STEP-102 Validation fixture/日志场景。
- [x] 静态核对 Fast Path、mixed executor、C-001、RN method surface 未修改。
- [ ] C++ 编译与定向测试、Android 用户手工构建、设备场景、iOS/Metal 验证:尚未执行。
## 允许与禁止范围
代码修改仅在任务书允许的 renderer、RN diagnostics 类型、`retained_underlay_cache.test.cpp` 和 Android Particle Validation 文件。未修改 `visitRenderSegmentExecution()`、`tryRenderParticleFastFrame()`、`retainedRangeUsesPlacement()`、Placement 算法、NavSea、C-001、发布文件或总则。既有未跟踪 v2/v3 审查说明及任务书保持原样。
## 构建、测试与当前结果
只读源码/diff 审计及 `git diff --check` 已执行,后者通过;新增未跟踪文件另用 `git diff --no-index --check` 检查,无空白错误(差异本身使退出码为 1)。CMake/Ninja/Bazel、GTest、Android Gradle、APK/AAR、ADB、设备、Jest、NavSea、发布全部 **NOT RUN**。静态检查不构成运行态 PASS。
## 必做输出
- STEP-102 生产代码、C++ 测试源码、Android Validation 场景源码。
- `docs/报告/STEP-102_RenderSegment无Placement段局部复用_Codex完成报告_v1.md`。
- 本记录与 `粒子开发记录.md` 追加。
- 报告中列出精确后续验证命令、硬门槛、NOT RUN 与剩余风险。
## 阻塞与下一步
目前没有已观察到的编译或运行失败;真正结果仍未知。由 RDC/用户按报告完成 Native focused tests、用户手工 Android APK 构建和 T1/T2 设备场景,核对 R0/R1 的 `placementCapable`、`placementGatePassed`、`actualExecution` 与 build/reuse/invalidation。构建或设备失败时保留首个真实错误与日志,再按任务边界修复;本 Step 未进入后续发行阶段。
## RDC 独立验证补记(2026-10-08)
- 从现有工作树、任务书、v3 审查依据和项目总则恢复审查;原 Codex 阶段的 NOT RUN 记录保留,以下为新增 RDC 事实。
- `git diff --check`:退出码 0,PASS;无关的 `platform/windows/vendor/vcpkg` 子模块状态变化不纳入本任务。
- 以 AppleClang 对 `test/renderer/retained_underlay_cache.test.cpp` 执行 `-std=c++20 -fsyntax-only`:退出码 0,语法检查 PASS;不是 GTest 运行结果。
- 本地临时独立 C++ helper smoke 测试:结构性 symbol 判定、placement gate、全局 live reason 共 10 个断言,10/10 PASS;测试文件位于 `/tmp/step102-placement-smoke.cpp`,不是正式 GTest。
- Mac CMake `cmake --preset macos-metal`:配置退出码 1,阻塞于缺少 `libuv`;未进入 GTest 编译或运行,未安装/升级依赖。日志 `/tmp/step102-cmake-config.log`。
- 额外审查并修复 Android STEP-102 Validation 切换入口:进入该场景时停止 STEP-093 诊断轮询、清除 STEP-093/097 标志,避免旧场景轮询污染 STEP-102 证据。
- Metal Bazel Core 构建 `bazel build -c opt --//:renderer=metal //:mbgl-core` 已完成:退出码 0,642/642 actions,耗时 875.118s,产物 `bazel-bin/libmbgl-core.a`,构建 PASS;日志 `/tmp/step102-bazel-core.log`。该 PASS 仅表示 Native Core 编译,不代表 GTest/Android/运行态 PASS。
- Android Gradle/APK/ADB 与设备验证依任务规则均未执行;STEP-102 继续保持“进行中 / 待 Android 实际验收”,不得标记 CLOSED / PASS。
## V21 发布决策(2026-10-08)
用户明确接受未执行正式 GTest、Android T1/T2、iOS/Metal 运行态验证的风险,要求 STEP-102 经源码审查即纳入 V21 发行。代码审查未发现明确阻断项;先前 Metal Core 642/642 编译通过。本步骤依然不属于运行态验收 PASS。发布须完整执行 `prepare → build → publish → finalize`;发布记录应明确验收豁免。

View File

@@ -0,0 +1,28 @@
# STEP-104 官方 Native 13.6.1 升级阶段 A
- 状态:进行中。
- 当前基线:官方 Android Native `c7506d6aff3800e946f89e1a51432fc22d1a6534`;自研旧版本 .21 `630ec657687bad4200c059bbccbb950d9c6f7ce9`。
- 目标:把现有 Particle、WeatherColor、RasterArray、RenderSegment/Retained 与 Android Native 接口移植到官方 13.6.1,保持原语义;形成能进行精确编译验证的候选代码。
- 必做:合并/冲突、代码边界适配、append-only `recoder_step.md`、多提交、完成报告、RDC 静态及精确编译。
- 允许:本分支 Core/Android Native/构建配置/必要测试/记录。
- 禁止:NavSea、其他 worktree、主线和正式发行、未经协调的公共合同变化。
- 构建与测试:暂未运行;由 RDC 独立执行,不因任务书生成而记 PASS。
- 本轮输出:`docs/40_任务/STEP-104_官方Native13.6.1升级阶段A_Codex任务_v1.md`、`docs/报告/STEP-104_官方Native13.6.1升级阶段A_Codex完成报告_v1.md`、`recoder_step.md`、阶段代码 Git checkpoints。
- 当前结果:Gate 0 官方第一父基线检出;自研合并未开始。
- 阻塞:尚无;旧/新版差异已在 UPSTREAM-001 审计,需逐项移植。
- 下一步:Codex 迁移,RDC 独立编译,失败反馈给 Codex;未获得真实编译/设备结果不得宣称发布成功。
## Gate 1 实际进展(2026-10-09)
- 官方为第一父的 Git merge commit:`f8378fd7113c4d230500f0b82902d2356907f4a9`。
- 76 个冲突路径已处理、没有未合并 index 条目;RDC 已检查 Git history 和 Native 代码空白格式。
- 与旧发布的 Particle/QBIN/RenderSegment 功能是否能够完整编译、正确渲染仍未验证。本任务目标保持进行中;下一 Gate 为 Android Native 精确编译。
- 本检查点只能称为 `SOURCE_MERGED / BUILD_NOT_RUN`,不是 Android/iOS SDK PASS。
## Gate 2 / 2026-10-09 / RDC Native 编译实际结果
- 结果:Android x86_64 OpenGL Native **PASS**(Gradle `BUILD SUCCESSFUL in 22m 24s`;进程退出码 0),编译提交 `a4b5f4eaa0eccb734e00d67adb5e750bba320404`。
- 产物:`MapLibreAndroid/build/intermediates/cmake/openglDebug/obj/x86_64/libmaplibre.so`,`377246848` bytes,SHA-256 `ff5a5eb45f84ff633a87fe385fb04ee39ba63ed3bc486003408e02cea78c8907`。
- 已排除的构建阻塞:新 worktree 的 cheap-ruler-cpp、tile-spec/earcut、supercluster LICENSE 依赖检出缺失;按 Git 固定提交恢复,无需修改产品源码。
- 未完成项:其余 ABI、Android 安装/真机 GPU、Vulkan、RN 11.5.0、iOS Metal、发布均 NOT RUN;STEP-104 为 **PARTIAL**(阶段 A Native 编译 Gate 通过,产品发行 Gate 未开始)。
- 下一步:Android 多 ABI + 真实 GPU/Style/RenderSegment 功能验收,再进入 RN 11.5.0 公共桥接联调。

View File

@@ -0,0 +1,11 @@
# STEP-105 FZG1-2 MapLibre Native 13.6.1 Validation APK 安装记录
- 日期:2026-10-09(JST)
- 代码来源:官方 Native Android 13.6.1 + Particle .21 迁移候选,分支 `upgrade/android-native-13.6.1-20261009`,构建源提交 `30d0e6665e`。
- 构建与目标:Mac,`MapLibreAndroidTestApp`、OpenGL Debug、Native x86_64,Gradle 6m48s 初次完成;因 Sentry 辅助库多 ABI 被旧检查规则拒绝;修订验证规则后增量 Gradle 10s,ZIP/ABI/体积检查 PASS。
- 脚本修改:`tools/particle_android_validation/build_validation_apk.sh` 仅允许非目标 ABI 中已确认的 Sentry 库;`libmaplibre.so` 与 Custom Layer 必须仍为 x86_64;独立提交 `73db0356ac5860366f314ddba23b716220e7c16a`。
- APK:`artifacts/maplibre-particle/step105-native1361-fzg/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk`,66,505,502 字节,SHA-256 `77bc0b238fb476494410a603443030b104d78f97a737307be52460bf5a68f5aa`。
- 设备:FZG1-2 / Android 13 / ADB `192.168.200.139:5555`。覆盖安装 `adb install -r` **Success**;设备实际版本 `13.6.1`,签名一致、首次安装日期不变,设备文件 SHA 与 Mac 完全一致。
- NavSea 仍为前台 App,未主动启动测试 App;运行、GPU 绘制、RenderSegment 等仍 **NOT RUN**,不可写成已通过。
- 回退:旧版 13.4.1-particle.21 APK 已独立保存于忽略目录 `artifacts/.../rollback/`,未纳入 Git。
- Gate:本阶段 **APK_BUILD_AND_INSTALL_PASS**;下一阶段是 FZG 可视运行及完整功能回归。

View File

@@ -0,0 +1,13 @@
# STEP-105 / FZG1-2 MapLibre Native 13.6.1 实机运行记录 v1
- 日期:2026-10-09 JST。
- 设备:FZG1-2 Android 13 x86_64,ADB 192.168.200.139:5555。源码:upgrade/android-native-13.6.1-20261009 / c30add4d335c5c02aadac5756c1606b5bc497269。
- PASS:粒子页面启动和用户观察、Cache 开关、Pan/双击 Zoom 后存活与缓存边界失效、STEP-101 单次重建、STEP-101 流式 Logcat 20 次 Native reset 完整配对、STEP-099 R-C-R 底层复用、QBIN V4 Golden 时间控制六项、STEP-102 T1 Symbol 安全回退、默认界面恢复。
- STEP-101 T2 证据:20 请求、20 Native reset enter/complete、40 Renderer reset enter/complete、21 ready、crash buffer 0;最初的环形缓冲被覆盖测试不计正式 PASS。
- STEP-099 T4:动态 GeoJSON 71 次更新,R0 buildDelta=0、reuseDelta=3677、invalidationDelta=0。
- STEP-102 T1:R0 buildDelta=0、reuseDelta=3683、invalidationDelta=0;R1 包含 Symbol,gate=false、Live/Fallback,符合预期。
- FAIL:STEP-102 T2_TWO_FREE 的 R1 持续 placementCapable=true、gate=false、Live/Fallback,reuse=0、invalidation 增加 3682;按 fixture R1 为 Fill,理应支持 retained;R0 reuseDelta=3682、buildDelta=0、invalidationDelta=0。无 crash,不证明错绘或确定回归起点。
- 疑点:运行时注入的 Annotation Symbol、真实 Style Layer Index 或 Segment 范围;应先提取完整诊断和旧 .21 对照,保留 fail-closed,不直接改 Core 公共语义。
- 证据目录(不提交 Git):artifacts/maplibre-particle/step105-fzg-runtime-20261009/。截图、UI XML、Logcat、crash buffer 齐备。
- 恢复:ADB 冷启动默认粒子页 GLOBAL/ACTIVE/EAST/MIX0%/256,当前 FZG 前台 Test App 13.6.1,Crash Buffer 0。
- 状态:PARTIAL / T2 EXPECTATION FAIL。未编译、未执行 Jest、未更改源码或 NavSea,下一 Gate 是 T2 定向调查修正后回归。

View File

@@ -0,0 +1,48 @@
# STEP-106 STEP-102 T2 自动 Annotation 层边界修正记录 v1
日期:2026-10-09(JST)
**状态:SOURCE_FIXED / STATIC_PASS / ANDROID_BUILD_NOT_RUN / DEVICE_RETEST_NOT_RUN**
## 事实
- 旧版 13.4.1-particle.21 在 FZG 同样复现 T2 R1 placementCapable=true/gate=false/live/static-placement/reuse0,已保存同场景旧版日志。新版 13.6.1 在比较结束后成功恢复,设备 APK SHA 正确。
- 两版 AnnotationManager 会自动在 Style 末尾插入 Symbol Layer org.maplibre.annotations.points。T2 测试 Fixture 的上层自身为 Fill,但原 R-C-R Plan 的 R1 从 step102-upper 延续至最后一层,把该内部 Symbol 也算进去。
- 不允许修改或跳过 Shared Core/Renderer Placement 安全 Gate。此次只改两个 Android Test App Kotlin 文件;新增 C2 live 尾部区段,单独承载 MapLibre Annotation Symbol,从而使 T2 的 R1 仅含 Fill;T1 R1 仍含自身 Symbol。
- 为 tick8 新增 STEP102_STYLE_LAYER_LAYOUT 日志,供下次实际 APK 验证真实 Style Layer 顺序、分段边界。
- 代码 Git 提交:86906c8a6af474a8d064c6f6d7d431e2a7e3efe6;静态检查 PASS,没有执行 Gradle、ADB 修正版验证、Jest。
## 需用户手工编译
在 Mac 终端:
```bash
cd /Users/tei/dev/MapLibreParticleLab-upgrade-android-1361
export JAVA_HOME=/usr/local/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home
export ANDROID_HOME=/Users/tei/Library/Android/sdk
export ANDROID_SDK_ROOT="$ANDROID_HOME"
export PATH="$JAVA_HOME/bin:$ANDROID_HOME/platform-tools:$PATH"
export MAPLIBRE_VALIDATION_OUT_DIR="$PWD/artifacts/maplibre-particle/step106-t2-fix"
./tools/particle_android_validation/build_validation_apk.sh
```
脚本内部使用 Gradle `--console=plain`。请保留 BUILD SUCCESS 和 build-info.txt,APK 生成后再由 RDC 安装到 FZG。不得把目前设备上的 13.6.1 旧 APK 当成包含本修复的版本。
## 复测门槛
- APK 完整性、包名、版本、Native x86_64、哈希校验;签名不符禁止卸载重装。
- 新版 STEP102_STYLE_LAYER_LAYOUT 必须显示自动 Annotation Symbol 在最后的独立 Continuous C2;Plan valid、segments=4。
- T1_FREE_SYMBOL:R0 continued Composite/Reuse、R1 placementCapable=true 且需要时 Live、C2 包含 Annotation;不崩溃。
- T2_TWO_FREE:R0 和 R1 均 placementCapable=false、gate=true、actualExecution=composite;tick8→130 的 buildDelta=0、invalidationDelta=0、reuseDelta>0;C2 Live;不崩溃。
- 复测 STEP-099 T4 R-C-R R0 locality,STEP-101 单次/20次 Native Reset(日志须持续采集),V4 Golden 最小烟测。保留失败路径及原始日志。
- 修正作用域限定 Test App 分段验证,不等同生产快帧性能达标。若仍 fallback,应保留 Placement fail-closed,重新诊断而非强制 PASS。
## 2026-10-09 手工边界获用户明确授权后的 RDC 编译与 FZG 闭环
- 本轮用户明确要求“你编译和验证吧”。在 Mac 执行 Android Test App Gradle,源码 HEAD 23f7b8a4d7、干净;Gradle/Validation PASS。新版 APK SHA256=0ef3b033cd33139db07258745e9cd9d023170ce69767e3f8a5159821776ec9ef,66,505,495 字节,x86_64 MapLibre Native。
- FZG1-2 签名检查一致,adb install -r Success;设备 base.apk SHA 与 Mac 相同、versionName=13.6.1。
- T1_FREE_SYMBOL(两窗口):Style 实际 5 层/4 段;R0 reuseΔ+3682、buildΔ0、invalidΔ0;R1 Symbol 继续保守 live/static-placement,PASS。
- T2_TWO_FREE(两窗口):R0、R1 均 placementCapable=false/gate=true/composite;两段各 reuseΔ+3683、buildΔ0、invalidΔ0;尾部 Annotation Symbol C2 live,PASS,原 T2 阻塞正式解除。
- STEP099 T4:R0 reuseΔ+3675、build/invalidΔ0,PASS。STEP101 T1:1 个 nativeReset 完成,PASS;T2:20 Native reset 完整配对、21 ready、40 Render reset enter/complete,PASS。
- QBIN V4 Golden t0/t1 插入、Runtime V4 READY 最小烟测 PASS。Crash Buffer 均无故障记录。FZG 已恢复默认 GLOBAL/ACTIVE/EAST/MIX0%/256,修正版 APK 哈希再次核对一致。
- 状态更新:**STEP-106 CLOSED/PASS(FZG Android x86_64/OpenGL 定向问题及回归)**。不代表 ARM64、RN、iOS、Vulkan、全链发行通过。原始日志保存在 Git 忽略的 artifacts/maplibre-particle/step106-t2-fix/。

View File

@@ -4,12 +4,15 @@ The rendering backend is selected at build time through Gradle product flavors.
## Available backends
| Flavor | Backend | Status | Notes |
|---|---|---|---|
| `opengl` | OpenGL ES | Stable | Default, widest device compatibility |
| `vulkan` | Vulkan | Stable | Better performance on modern devices |
| `webgpuDawn` | WebGPU (Dawn) | Experimental | Uses Vulkan internally, see [WebGPU](./android-webgpu.md) |
| `webgpuWgpu` | WebGPU (wgpu-native) | Experimental | Uses Vulkan internally, arm64-v8a only, see [WebGPU](./android-webgpu.md) |
| Flavor | Backend | Status | Maven Central artifact | Notes |
|---|---|---|---|---|
| `opengl` | OpenGL ES | Stable | `org.maplibre.gl:android-sdk-opengl` | Default, widest device compatibility |
| `vulkan` | Vulkan | Stable | `org.maplibre.gl:android-sdk-vulkan` | Better performance on modern devices |
| `webgpuDawn` | WebGPU (Dawn) | Experimental | not published | Uses Vulkan internally, see [WebGPU](./android-webgpu.md) |
| `webgpuWgpu` | WebGPU (wgpu-native) | Experimental | not published | Uses Vulkan internally, arm64-v8a only, see [WebGPU](./android-webgpu.md) |
| `multiBackend` | OpenGL ES + Vulkan | Experimental | `org.maplibre.gl:android-sdk-vulkan-opengl` | Both backends in one AAR, chosen at runtime |
`org.maplibre.gl:android-sdk` is also published and currently maps to the `vulkan` flavor's release build. `-debug` suffixed artifact (e.g. `android-sdk-vulkan-debug`) is published for each flavor as well.
## Building with a specific backend
@@ -29,6 +32,9 @@ cd platform/android
# WebGPU (wgpu-native)
./gradlew :MapLibreAndroidTestApp:installWebgpuWgpuDebug
# Both OpenGL ES and Vulkan, backend chosen at runtime
./gradlew :MapLibreAndroidTestApp:installMultiBackendDebug
```
The same pattern applies to the library module (`MapLibreAndroid`):
@@ -49,5 +55,8 @@ Each flavor sets different CMake arguments:
- `vulkan`: `-DMLN_WITH_VULKAN=ON`
- `webgpuDawn`: `-DMLN_WITH_WEBGPU=ON`, `-DMLN_WEBGPU_IMPL_DAWN=ON`
- `webgpuWgpu`: `-DMLN_WITH_WEBGPU=ON`, `-DMLN_WEBGPU_IMPL_WGPU=ON`
- `multiBackend`: `-DMLN_ANDROID_MULTI_BACKEND=ON`
Only one backend is active per build. Renderer-specific Java code lives in `src/opengl/`, `src/vulkan/`, or `src/webgpu/` source sets.
For `opengl`, `vulkan`, and the WebGPU flavors, only one backend is compiled in and it's fixed for the lifetime of the app. `multiBackend` is the exception - it ships both the OpenGL ES and Vulkan native libraries and picks one at runtime.
Renderer-specific Java code is split between flavor-specific source sets (`src/opengl/`, `src/vulkan/`, `src/multiBackend/`) and shared per-backend code in `src/sharedRenderer/opengl/` and `src/sharedRenderer/vulkan/`.

View File

@@ -1,6 +1,6 @@
# WebGPU on Android
Two WebGPU implementations are supported: **Dawn** (Google, C++) and **wgpu-native** (Rust). Both use Vulkan internally on Android. The Gradle product flavors are `webgpuDawn` and `webgpuWgpu`, sharing the `src/webgpu/` Java source set.
Two WebGPU implementations are supported: **Dawn** (Google, C++) and **wgpu-native** (Rust). Both use Vulkan internally on Android. The Gradle product flavors are `webgpuDawn` and `webgpuWgpu`, sharing the `src/vulkan/` and `src/sharedRenderer/vulkan/` Java source sets.
## Building with Dawn

View File

@@ -25,7 +25,7 @@ git clone --recurse-submodules git@github.com:maplibre/maplibre-native.git
Make sure the following Homebrew packages are installed:
```sh
brew install bazelisk webp libuv webp icu4c jpeg-turbo glfw libuv
brew install bazelisk webp libuv icu4c jpeg-turbo glfw
brew link icu4c --force
```

View File

@@ -23,7 +23,7 @@ Tracy computational overhead is very low but by default it keeps all instrumenta
#### Instrumentation in MapLibre
The file `include/mbgl/util/instrumentation.hpp` defines the following instrumentation macros:
The file `include/mln/util/instrumentation.hpp` defines the following instrumentation macros:
##### `MLN_TRACE_ZONE(label)`
The macro records the timestamps at the start and end of the code scope. The parameter label is a user defined name for the zone. Example:

View File

@@ -55,22 +55,22 @@ To create a new module:
1. Add a new source file to `rustutils/src/example.rs`.
2. Implement it, see the [CXX documentation](https://cxx.rs/index.html) or see `rustutils/src/color.rs` for an example.
3. Create a C++ source file that will use the generated C++ header. See `src/mbgl/util/color.rs.cpp` for an example. Import the generated header with
3. Create a C++ source file that will use the generated C++ header. See `src/mln/util/color.rs.cpp` for an example. Import the generated header with
```cpp
#include <rustutils/example.hpp>
```
4. Conditionally include either the `*.rs.cpp` file or the `*.cpp` file it replaces in CMake and Bazel. Here is what it looks like for CMake:
```cmake
${PROJECT_SOURCE_DIR}/src/mbgl/util/color$<IF:$<BOOL:${MLN_USE_RUST}>,.rs.cpp,.cpp>
${PROJECT_SOURCE_DIR}/src/mln/util/color$<IF:$<BOOL:${MLN_USE_RUST}>,.rs.cpp,.cpp>
```
And here for Bazel:
```bazel
select({
"//:rust": [
"src/mbgl/util/color.rs.cpp",
"src/mln/util/color.rs.cpp",
],
"//conditions:default": [
"src/mbgl/util/color.cpp",
"src/mln/util/color.cpp",
],
})
```

View File

@@ -0,0 +1,536 @@
# STEP-099 RenderSource 就绪与 RenderSegment 失效诊断 — Codex 完成报告 v1
## 1. 执行结论
**CLOSED / PASS(诊断阶段完成)**。
STEP-099 按任务书保持“纯诊断、fail-closed、不优化正式语义”的范围完成。Renderer/Source/RenderSegment diagnostics、Android Test App T1~T4 场景、定向 native 测试和 Android 实机运行证据均已取得,Q1~Q7 可以据实回答。
本 Step **没有**修改 retained cache 算法、fast path gate、`singleContinuousSegment`、multi-continuous 行为、segment-local invalidation、RenderSegment 执行语义、NavSea、Source `isLoaded()` 定义或 RN 业务 API 语义。
## 2. 基线与 Git
- 仓库:`/Users/tei/dev/MapLibreParticleLab-step099`
- branch:`step099-render-source-diagnostics`
- frozen release tag:`maplibre-particle/rn/13.4.1-particle.17`
- frozen release commit / start base:`e8b451fe70054107773e82484c80e90df3889147`
- implementation commit:`8a5214d92dd2f8899db76d2194da42999fa0c87d`
- implementation message:`diagnostics: add STEP-099 render source readiness audit`
- Integration/NavSea:未修改。
- 文档 closeout commit、push result、`origin/particle/main` Final HEAD:Git 提交无法在自身内容中自指其最终 SHA,按项目既有规则由最终交付回读记录。
## 3. 实际修改范围
生产源码 / diagnostics:
- `include/mbgl/renderer/render_segment.hpp`
- `src/mbgl/renderer/render_orchestrator.cpp`
- `src/mbgl/renderer/render_orchestrator.hpp`
- `src/mbgl/renderer/render_segment_json.hpp`
- `src/mbgl/renderer/render_source.hpp`
- `src/mbgl/renderer/retained_underlay_runtime_state.hpp`
- `src/mbgl/renderer/sources/render_tile_source.cpp`
- `src/mbgl/renderer/sources/render_tile_source.hpp`
- `packages/maplibre-particle-rn/src/index.ts`
- `packages/maplibre-particle-rn/src/types.ts`
测试 / Test App:
- `test/renderer/retained_underlay_cache.test.cpp`
- `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt`
- `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/Step099ReadinessFixture.kt`
项目记录:
- `docs/50_Step记录/STEP-099_RenderSource就绪与RenderSegment失效诊断_v1.md`
- `docs/报告/STEP-099_RenderSource就绪与RenderSegment失效诊断_Codex完成报告_v1.md`
- `粒子开发记录.md`
## 4. 诊断能力
### 4.1 全局 readiness
新增只读 snapshot:
- `styleLoaded`
- `imageManagerLoaded`
- `renderOrchestratorLoaded`
- `spriteLoaded`
- `hasFadingTiles`
- global retained `contentRevision`
- RenderSegment plan/config/topology 信息
- 最近 mutation sequence / reason / source / affected segment diagnostics
正式 loaded 路径保持原式:
```cpp
renderTreeParameters->loaded = updateParameters->styleLoaded && isLoaded();
```
diagnostics snapshot 在旁路采样,失败被 best-effort 隔离,不决定正式 loaded。
### 4.2 per-source readiness
每个 RenderSource additive 暴露:
- sourceId / sourceType
- enabled / isLoaded
- tileBacked
- tileCount / incompleteTileCount / loadedTileCount
- hasFadingTiles
- last source/tile mutation sequence
- last tile action / reason
默认非 tile source 返回完整显式初始化的空统计,Android NDK `-Werror` 下已验证通过;未改变任何 Source `isLoaded()` 实现。
### 4.3 RenderSegment 只读依赖
每个 segment additive 暴露:
- segmentIndex / strategy / beginIndex / endExclusive
- `dependentSourceIds`
- `unknownDependencies`
规则:
- 从实际 ordered layers 的 sourceId 推导;
- shared source 可出现在多个 segment;
- source-less background 不制造假依赖;
- symbol/custom 等无法仅靠 sourceId 完整表达的依赖标记为 unknown/global;
- 依赖图只用于诊断,不参与 cache/loaded/fast path/execution。
### 4.4 mutation 定位
Source/tile mutation 复用已有回调记录 sequence/source/reason/action。原 `retainedUnderlayContentRevision` 的增长次数与正式调用路径不变;diagnostics 不增加额外 revision。
query 路径不清理或修改 event history,重复 snapshot/JSON 查询保持无副作用。
## 5. Native 定向测试
### 5.1 Metal host 定向 GTest
实际执行:
```bash
cmake --preset macos-metal
cmake --build build-macos-metal --target mbgl-test-runner --parallel 3
build-macos-metal/mbgl-test-runner --gtest_filter='RenderSegmentDiagnostics.*'
```
结果:
- `RenderSegmentDiagnostics.*`:**6/6 PASS**
- 新增 `ReadinessSnapshotMapsSourcesToSegmentsWithoutSideEffects`:PASS
- 覆盖 source loaded/unloaded、tile stats、source→segment、shared source、source-less、重复 query、topology/cache/content revision 无副作用。
证据:
`artifacts/maplibre-particle/android-validation/step099-metal-gtest.log`
SHA-256:
`f0618750ead03eae1b251126dd49488a9269a120373a66e3453fa9aaa1dc0f10`
说明:该 6/6 发生在 Android NDK 首轮暴露“默认 readiness struct designated initializer 未显式列完 optional 字段”之前;随后仅补全默认空字段初始化。最终源码由 Android 全量 native build 成功覆盖。为了在最终源码上重跑 Metal,重新 configure 时当前 Mac 缺 `libuv` pkg-config,configure fail;没有安装系统依赖来制造 PASS。
### 5.2 Vulkan
`macos-vulkan` configure:**BLOCKED / NOT RUN TESTS**。
原因:
```text
The following required packages were not found:
- libuv
```
这是当前 Mac host 环境依赖,不是 STEP-099 源码编译错误。
### 5.3 Jest
**NOT RUN**。用户未要求 Jest,任务未加入 Jest。
## 6. Android 构建与设备
### 6.1 首轮 Android 编译问题
首轮 x86_64 OpenGL build 在 Android NDK `-Werror` 下发现:
```text
render_source.hpp:84:51:
error: missing field 'tileCount' initializer
[-Werror,-Wmissing-designated-field-initializers]
```
修复仅补全 `RenderSourceReadinessStats` 默认空字段初始化,不改变运行语义。
随后 native C++ 已越过原失败点并完整编译。
### 6.2 磁盘阻塞与恢复
第一次完整 native build 后,在:
`MapLibreAndroidTestApp:stripOpenglDebugDebugSymbols`
因 Mac 仅剩约 2 GiB 出现:
```text
No space left on device
```
RDC 只清理可再生 Gradle 9.5.1 cache / 本轮失败中间产物,保留 Android native object;可用空间恢复到约 12 GiB 后增量重跑。
### 6.3 最终 APK
命令:
```bash
./tools/particle_android_validation/build_validation_apk.sh
```
最终结果:
- Gradle:**BUILD SUCCESSFUL in 4m 54s**
- actionable tasks:86(7 executed / 79 up-to-date)
- variant:OpenGL Debug
- ABI:x86_64
- APK:61,923,024 bytes
- `libmaplibre.so`:39,602,856 bytes
- APK SHA-256:
`5de73f0358b835a78d3ae7e2ac22f4efdb2a66775b8c63654a8bb7313957d90a`
构建时 metadata:
- base commit:`e8b451fe70054107773e82484c80e90df3889147`
- `git_dirty=true`
- 构建内容与随后形成的 implementation commit `8a5214d92` 源码一致;当前 source tree 对 implementation commit clean,剩余仅 docs closeout。
### 6.4 Android 设备
Mac ADB 直接连接:
- serial:`192.168.200.139:5555`
- model:`FZG1-2`
- Android:13
- API:33
- ABI:x86_64
APK 覆盖安装成功,`ParticleCoreLayerValidationActivity` 冷启动成功。
运行 log:
`artifacts/maplibre-particle/android-validation/step099-logcat.txt`
log SHA-256:
`0f15d75dde77e7dd2f4d98c46a4c1501a628205e8aae62130b0cb96db6b8482f`
## 7. T1~T4 实测
### T1 STATIC
场景:
- R0:静态 GeoJSON retained
- C:本地静态 RasterArray field 驱动 WeatherColor + Particle
- R1:静态 retained
- camera fixed
结果:
- 启动阶段 1 个 false window:204 ms;
- 随后 `renderOrchestratorLoaded=true` 稳定;
- `particle-fixture` 与 `step099-static` 均 loaded;
- retained cache 建立后持续 reuse;
- fast path 进入 `active=true / eligible=true / reason=none`;
- 没有持续 style-not-loaded。
aggregate:
```text
falseWindowCount=1
falseWindowAvgMs=204
falseWindowMaxMs=204
openFalseWindowMs=0
```
结论:静态基线可稳定进入 loaded/cache reuse/fast path。
### T2 GEOJSON_1HZ
两个 GeoJSON source 每 500 ms 交错更新,因此每个约 1 Hz。
实际:
- 总 source update:122 次,约 61 次/源;
- 60 秒量级观察中,出现 10 个 loaded=false window;
- 平均 203 ms;
- 最大 205 ms;
- 最终 open window = 0;
- 总 false 时间约 2.03 s,约占 60 s 的 3.4%,不是“几乎始终 false”。
aggregate:
```text
falseWindowCount=10
falseWindowAvgMs=203
falseWindowMaxMs=205
openFalseWindowMs=0
```
同时 final sample:
- global contentRevision 已到 1679;
- R0 仅依赖 `step099-static`,但 cache build=241、invalidation=362;
- R1 依赖动态 GeoJSON,也同样 build=241;
- mutation diagnostics 能正确指出动态 source 只 `affected=[2]`,但正式 cache invalidation 仍非局部。
### T3 PERMANENT_UNREADY
额外加入:
`step099-unready-raster-array`
它:
- 没有 layer;
- 因此 `enabled=false`;
- host-submission 无 field;
- `isLoaded=false`。
其他主要 source 均 loaded。
实测:
- `renderOrchestratorLoaded=false` 持续;
- retained segment cache 持续 fallback;
- `lastInvalidationReason=style-not-loaded`;
- 观察结束仍没有恢复。
aggregate:
```text
falseWindowCount=0
openFalseWindowMs=21459
```
结论:即使 source 与当前 layer/segment 无关且 disabled,只要仍在 `renderSources` 且 `isLoaded=false`,V17 全局 `RenderOrchestrator::isLoaded()` 就保持 false。
### T4 R-C-R
结构:
- R0:`deps=[step099-static]`
- C:`deps=[particle-fixture]`,WeatherColor + Particle
- R1:`deps=[org.maplibre.annotations, step099-dynamic, step099-static]`
- `step099-dynamic` 约 1 Hz 更新
实际:
- dynamic update:61 次;
- loaded false window:4;
- 平均 203 ms;
- 最大 207 ms;
- global contentRevision:1760 → 2540;
- mutation diagnostics:`step099-dynamic` 对应 `affected=[2]`;
- R0 并不依赖 `step099-dynamic`,但:
- build:1 → 121
- invalidation:20 → 200
- R1 同步得到相同级别 build/invalidation 增长;
- fast path 在稳定窗口可恢复 active,但 global revision / transient readiness 会反复制造 full CPU work。
aggregate:
```text
falseWindowCount=4
falseWindowAvgMs=203
falseWindowMaxMs=207
openFalseWindowMs=0
```
结论:依赖诊断已经能准确表达“R1 source-local”,但 V17 正式 content revision/cache invalidation 仍是 global。
## 8. Q1~Q7
### Q1:单个 permanently unloaded source 会造成 V17 style-not-loaded 吗?
**YES / CONFIRMED。**
T3 中 `step099-unready-raster-array` 无 layer、`enabled=false`、`isLoaded=false`;其他主要 source loaded,但整体 `renderOrchestratorLoaded=false` 持续 21.459 s 未恢复,retained cache 持续 `style-not-loaded` fallback。
源码事实与运行事实一致:`RenderOrchestrator::isLoaded()` 遍历全部 `renderSources`,不按 enabled/segment dependency 排除 source。
### Q2:1 Hz GeoJSON 会周期性让 isLoaded=false 吗?平均/最大窗口?
**YES / CONFIRMED。**
T2 双 source 交错各约 1 Hz:
- 10 次 false window;
- avg 203 ms;
- max 205 ms。
T4 单动态 source 约 1 Hz:
- 4 次 false window;
- avg 203 ms;
- max 207 ms。
### Q3:错开的多个 1 Hz GeoJSON 会导致 global loaded 几乎无法稳定为 true 吗?
**NO / 本次观测不支持。**
T2 约 60 s 中总 false 时间约 2.03 s,约 3.4%;绝大多数时间 global loaded=true。它确实产生 readiness thrash,但不是“几乎永远 false”。
### Q4:GeoJSON tile mutation 会推进 global retainedUnderlayContentRevision 并影响 retained cache 吗?
**YES / CONFIRMED。**
T4 global contentRevision 1760 → 2540。仅依赖静态 source 的 R0 也从 build 1 → 121、invalidation 20 → 200。
### Q5:不引用 GeoJSON 的 retained segment 仍会受它的 loaded/fading/tile mutation 影响吗?
**YES。**
运行证据:
- T4 diagnostics 正确报告动态 source `affected=[2]`;
- 但 R0 `deps=[step099-static]` 仍随动态 source mutation 重建/失效。
源码证据:
- `retainedRangeIsStable(begin,end)` 虽为 range API,但最后遍历 **全部 `renderSources`**,任一 source `hasFadingTiles()` 都让任意 retained range unstable。
本次 T4 稳态 `fade=false`,因此 R0 的实际反复失效主要直接证明 global content revision/tile mutation;GLOBAL_FADE 属源码确认、未在本轮场景主动触发的全局 gate。
### Q6:`tryRenderParticleFastFrame` 仍有哪些 global gate 会阻挡未来 localized cache CPU fast path?
**确认仍存在:**
1. **GLOBAL_UPDATE_SIGNATURE**
- `particleFastPathNonCameraInputsMatch` 全局比较:
- styleLoaded / spriteLoaded
- light
- images
- **sources**
- **layers**
- fontFaces / fileSource / glyphURL
- transition / placement / tile LOD 等全局输入。
2. **GLOBAL_CONTENT_REVISION**
- `particlePreparedContentRevision == orchestrator.getRetainedUnderlayContentRevision()`。
3. **GLOBAL_FADE**
- `particleFastPathDynamicState` 遍历全部 renderSources 汇总 fading;
- `retainedRangeIsStable` 也遍历全部 renderSources。
4. **GLOBAL_PENDING / TRANSITION / REPAINT**
- pendingChanges
- renderLight transition
- 任意 layer transition
- 任意非粒子 layer repaint
- placement transition。
5. **GLOBAL_ANNOTATION_MUTATION**
- AnnotationManager `hasPendingChanges()`。
6. **RETAINED REVISION / CACHE / TOPOLOGY / BOUNDARY**
- retained cache validity/static revision
- global retained revision tracker
- topology revision
- boundary/config revision。
7. **singleContinuousSegment**
- 仍要求 plan 恰好能由一个 Continuous segment 表达;
- multi-continuous 继续 fail closed,本 Step 未修改。
因此即使未来 cache invalidation 变成 source/segment-local,fast path 仍有多组 global gate 需要后续 Step 单独设计,不能在 STEP-099 顺手放宽。
### Q7:blocker 分类
**运行态 CONFIRMED:**
- `PERMANENT_SOURCE_UNLOADED`
- `DYNAMIC_SOURCE_READINESS_THRASH`
- `GLOBAL_CONTENT_REVISION`
**源码 CONFIRMED,本轮未主动触发独立运行场景:**
- `GLOBAL_FADE`
- `GLOBAL_UPDATE_SIGNATURE`
**OTHER:**
- global pendingChanges
- placement/light/non-particle transition/repaint
- annotation mutation
- topology/boundary/revision/cache validity
- singleContinuous fail-closed
## 9. 任务边界审计
确认未改:
- retained cache 核心算法;
- fast path gate 逻辑;
- `singleContinuousSegment`;
- multi-continuous 策略;
- segment-local invalidation 正式语义;
- RenderSegment execution;
- NavSea;
- private NavSea Native API;
- RN 业务 API;
- Source `isLoaded()` 定义。
新增 dependency / affectedSegmentIndices 只是观察信息;它没有参与正式 invalidation。
## 10. 证据文件
忽略目录:
`artifacts/maplibre-particle/android-validation/`
主要文件:
- `build-info.txt`
- `build.log`
- `MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk`
- `step099-logcat.txt`
- `step099-device-info.txt`
- `step099-metal-gtest.log`
- `step099-cmake-metal.log`
APK SHA-256:
`5de73f0358b835a78d3ae7e2ac22f4efdb2a66775b8c63654a8bb7313957d90a`
STEP-099 log SHA-256:
`0f15d75dde77e7dd2f4d98c46a4c1501a628205e8aae62130b0cb96db6b8482f`
## 11. 下一阶段建议
STEP-099 只负责定位,不在本 Step 修复。
下一阶段应基于本轮证据拆开处理:
1. 先决定 global source readiness 是否要引入“影响当前 style/render segment 的 readiness 范围”,解决 permanently unready / transient unrelated source 对全局 loaded 的影响;
2. 再设计 source/segment-local content revision 与 invalidation,避免 R1 GeoJSON mutation 重建 R0;
3. 最后单独审查 fast-path global signature/fade/pending/placement 等 gate,不能把 cache locality 与 fast-path locality 混成一个修改;
4. 保持 Style Z-order 唯一事实来源和当前通用 Render Segment 模型。
## 12. 最终状态
**STEP-099 CLOSED / PASS。**
Pass 含义仅为:
- diagnostics 能回答任务问题;
- Native 定向测试已有 PASS 证据;
- 最终 Android x86_64 OpenGL APK BUILD SUCCESS;
- FZG1-2 T1~T4 实跑完成;
- Q1~Q7 有源码/运行证据;
- 未改变正式渲染语义。
不代表:
- Vulkan host 已通过;
- iOS runtime 已测试;
- 下一阶段 localized readiness/invalidation 已实现;
- fast path global gates 已优化。

View File

@@ -0,0 +1,454 @@
# STEP-100 SourceScoped RenderSegment 局部失效 — 完成报告 v1
## 1. 最终结论
**CLOSED / PASS(功能与 Android 运行态目标确认)**。
Codex 实现使用:
- model:`gpt-6-sol`
- reasoning effort:`high`
RDC 独立完成:
- 源码 diff 审计;
- Android x86_64 OpenGL 全量 native build;
- Validation APK;
- FZG1-2 自动安装与 T1/T2/T3/T4;
- STEP-100 60 秒 locality window;
- validation build script 小型工程修复;
- Git diff/status 审计。
本 Step 核心目标已确认:
> 动态 GeoJSON Source 更新只影响依赖它的 RETAINED Segment;无关 R0 cache 不再跟着 invalid/rebuild,并且在 global loaded=false 时仍可安全 reuse。
Native host GTest 因当前 Intel Mac 缺 `libuv` 未执行;曾尝试 Homebrew 安装,但 Homebrew 要连带升级 CMake/OpenSSL/Python 且 Intel 已无 bottle 支持,因此 RDC 主动终止,未把环境变化作为任务依赖。Android 最终 C++ native build 与设备运行态用于本轮功能验收。
Jest:**NOT RUN**,用户未要求。
## 2. Git / 基线
- worktree:`/Users/tei/dev/MapLibreParticleLab-step100`
- branch:`step100-segment-local-source-invalidation`
- start HEAD:`c4b481fd2c5b5da20d31f6ae54011f0552d7dbd0`
- start remote:`origin/particle/main = c4b481fd2c5b5da20d31f6ae54011f0552d7dbd0`
- frozen V17 tag:`maplibre-particle/rn/13.4.1-particle.17`
- frozen V17 commit:`e8b451fe70054107773e82484c80e90df3889147`
- V17 tag/release worktree:未修改。
最终 STEP-100 commit / push / remote HEAD 在 Git 收尾后由最终交付回读记录,避免文档自引用。
## 3. 实际修改
生产源码:
- `include/mbgl/renderer/render_segment.hpp`
- `src/mbgl/renderer/render_orchestrator.hpp`
- `src/mbgl/renderer/render_orchestrator.cpp`
- `src/mbgl/renderer/renderer_impl.cpp`
- `src/mbgl/renderer/retained_underlay_cache.cpp`
- `src/mbgl/renderer/retained_underlay_runtime_state.hpp`
- `src/mbgl/renderer/render_segment_json.hpp`
- `packages/maplibre-particle-rn/src/types.ts`
Test App / tests:
- `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/Step099ReadinessFixture.kt`
- `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt`
- `test/renderer/retained_underlay_cache.test.cpp`
工具:
- `tools/particle_android_validation/build_validation_apk.sh`
- RDC 修复 `unzip | awk ... exit` 在 `pipefail` 下偶发 SIGPIPE/141;
- 仅移除 awk 的提前 exit,不改变 APK 验证语义。
文档:
- `docs/40_任务/STEP-100_SourceScoped_RenderSegment局部失效_Codex任务_v2.md`
- `docs/50_Step记录/STEP-100_SourceScoped_RenderSegment局部失效_v1.md`
- 本报告;
- `粒子开发记录.md`
## 4. 生产设计
### 4.1 Source-scoped revision
新增正式 source-scoped revision bookkeeping。
明确的 Source/Tile mutation:
- source diff;
- feature state;
- tile changed;
推进对应 sourceId revision。
现有 global `retainedUnderlayContentRevision` 继续增长,供:
- compatibility;
- diagnostics;
- Fast Path fail-closed。
RETAINED Segment cache 不再直接以 global Source/Tile revision 作为内容 revision。
### 4.2 Segment dependency
正式 renderer 与 diagnostics 共用 source→segment 依赖推导。
规则:
- layer sourceId 决定 source dependency;
- source-less background 不制造假 dependency;
- shared source 可影响多个 segment;
- symbol 的 glyph/image/placement 作为明确 global prerequisite;
- 真正无法证明的 dependency fail closed。
### 4.3 Per-segment readiness
未修改:
- `Source::isLoaded()`;
- `renderTreeParameters->loaded = styleLoaded && isLoaded()`。
full CPU retained path 增加 per-segment source readiness/stability:
- dependent source unloaded → 仅该 Segment fallback;
- dependent source fading → 仅该 Segment unstable;
- unrelated source unloaded/fading → 不影响该 Segment;
- style/image/sprite/glyph/placement/context 等 global prerequisite 仍 fail closed。
### 4.4 Mixed Build / Reuse / Fallback
移除 retained full-CPU path 的 all-or-none `useRetainedRanges` 依赖。
每个 RETAINED Segment独立决定:
- Build
- Reuse
- Fallback
主 buffer 按 Style Segment 顺序执行:
- RETAINED Build/Reuse → composite cache
- RETAINED Fallback → live render only that range
- CONTINUOUS → live render
因此允许:
```text
R0 = Reuse
C = Live
R1 = Fallback
```
不再因为 R1 fallback 把 R0 一起变成 live redraw。
Fast Path gate / `singleContinuousSegment` / multi-continuous Fast Path:**未修改**。
## 5. Android build
首次标准 validation script 的 Gradle 本体实际结果:
```text
BUILD SUCCESSFUL in 12s
86 actionable tasks: 6 executed, 80 up-to-date
```
但脚本在 Gradle 成功后以 141 退出。RDC 用 `bash -x` 精确定位到:
```bash
LIB_BYTES="$(unzip ... | awk '/.../ {print $1; exit}')"
```
在 `set -o pipefail` 下触发 SIGPIPE。
RDC 仅去掉 awk 的 `exit`,重跑标准脚本:
```text
RC=0
[validation-apk] BUILD SUCCESS
```
最终 APK:
- variant:OpenglDebug
- ABI:x86_64
- apk bytes:61,956,640
- libmaplibre.so bytes:39,636,472
- SHA-256:
`86e22bf081bf7d3196f0bf0e7c56af51bde01e9f0b01e0bab238cb794273315a`
证据:
`artifacts/maplibre-particle/android-validation/`
## 6. 设备
- serial:`192.168.200.139:5555`
- model:FZG1-2
- Android:13
- API:33
- ABI:x86_64
APK 覆盖安装成功,`ParticleCoreLayerValidationActivity` 冷启动成功。
STEP-100 log:
`artifacts/maplibre-particle/android-validation/step100-logcat.txt`
log SHA-256:
`e9d18ea987d12cb30e321d0d9c669b2588972aac89e5277920bf1fa9fee8146b`
## 7. T1 STATIC
运行约 20 秒。
aggregate:
```text
falseWindowCount=1
falseWindowAvgMs=203
falseWindowMaxMs=203
openFalseWindowMs=0
```
最终:
- R0 build=1
- R0 reuse=1217
- R0 decision=reuse
- R1 build=1
- R1 reuse=1187
- R1 decision=reuse
静态 R-C-R 正常。
## 8. T4 R-C-R 主验收
结构:
```text
R0 -> step099-static
C -> particle-fixture
R1 -> step099-dynamic (+ framework annotation source if present)
```
window marker:
```text
baseline tick=8 17:05:21.642
final tick=130 17:06:23.240
```
窗口约 61.6 秒。
dynamic update 总计:68 次。
global revision:
```text
128 -> 973
```
说明 global compatibility revision **仍正常增长**,没有通过停掉 global revision“作弊”。
### R0
baseline:
```text
build=1
reuse=132
invalidation=20
srcRev=5127273714767523329
decision=reuse
```
final:
```text
build=1
reuse=4042
invalidation=20
srcRev=5127273714767523329
decision=reuse
```
Delta:
```text
buildDelta = 0
invalidationDelta = 0
reuseDelta = +3910
sourceRevision = unchanged
```
**硬门槛 PASS。**
### R1
baseline:
```text
build=5
invalidation=26
```
final:
```text
build=135
invalidation=211
```
动态 Source mutation 正常驱动 R1。
mutation diagnostics 持续:
```text
sourceId=step099-dynamic
affected=[2]
scope=source-local-diagnostic
```
### loaded false windows
T4:
```text
falseWindowCount=5
falseWindowAvgMs=202
falseWindowMaxMs=203
openFalseWindowMs=0
```
即 transient global loaded=false 仍存在,但不再让 R0 build/invalidation 增长。
## 9. T2 双 GeoJSON readiness 回归
约 35 秒。
aggregate:
```text
falseWindowCount=6
falseWindowAvgMs=203
falseWindowMaxMs=205
openFalseWindowMs=0
```
R0 在动态窗口保持:
- build=1
- invalidation=18
- revision unchanged
- reuse 持续增长。
R1 随两个动态 GeoJSON 持续 build/invalidate。
结论:
**DYNAMIC_SOURCE_READINESS_THRASH 仍是 global loaded 事实,但不再误伤无关 retained cache。**
## 10. T3 permanently unready unrelated source
`step099-unready-raster-array`:
- no layer;
- enabled=false;
- isLoaded=false。
global:
```text
renderOrchestratorLoaded=false
openFalseWindowMs=21468
```
约 21.468 秒持续 false。
与此同时:
R0:
- build=1
- invalidation=19
- reuse:11 → 1200
- decision=reuse
R1:
- build=1
- invalidation=19
- reuse:11 → 1200
- decision=reuse
因此:
> global loaded 仍保持旧兼容语义,但 unrelated permanently-unready source 已不能把无关 RETAINED Segment 拖成 style-not-loaded fallback。
**硬门槛 PASS。**
## 11. Mixed fallback
T4 中 R1 `fallbackCount` 从约 21 增长到 76,而 R0 fallback 计数保持不变,同时 R0 reuse 持续增长。
这证明运行期间真实发生了:
```text
R0 = Reuse
R1 = transient Fallback / rebuild
```
而不是只有“两个段都 ready”的理想场景。
未观察到 crash / ANR。
## 12. Fast Path 边界
RDC diff 审计确认未修改:
- `tryRenderParticleFastFrame`
- `particleFastPathNonCameraInputsMatch`
- `singleContinuousSegment`
- multi-continuous fail-closed
- global Fast Path signature/fade/contentRevision/pending/placement 等 gate。
STEP-100 只修 full CPU retained locality。
## 13. Native host tests
Codex 已新增 `RenderSegmentLocality.*` C++ 测试源码。
RDC 尝试恢复 `macos-metal` test runner,但 host configure 需要 `libuv`,当前未安装。
尝试 `brew install libuv` 时发现 Intel Homebrew 会连带升级:
- CMake
- OpenSSL
- Python
- ca-certificates 等
且当前 Intel macOS 已无官方 bottle 支持。为避免污染开发环境,RDC 主动停止。
因此:
- Native host GTest:**ENV BLOCKED / NOT RUN**
- Android C++ full native build:**PASS**
- Android device runtime:**PASS**
## 14. Jest / iOS
- Jest:NOT RUN。
- iOS runtime:本 Step 未运行。
- V18 unified release:在 STEP-100 Git 收尾后单独执行。
## 15. 最终判定
STEP-100 的核心实现目标全部成立:
1. global revision 继续增长;
2. R1 GeoJSON mutation 不再 invalid/rebuild R0;
3. R0 buildDelta=0;
4. R0 invalidationDelta=0;
5. R0 reuseDelta>0;
6. transient unrelated unloaded 不影响 R0 reuse;
7. permanent unrelated unloaded 不影响 R0 reuse;
8. mixed Reuse/Fallback 实际发生;
9. Fast Path 语义未放宽。
因此本 Step 功能与 Android runtime 验收:
**PASS / CLOSED**。
下一步允许进入 V18 unified release。

View File

@@ -0,0 +1,184 @@
# STEP-101 RenderOrchestrator 销毁生命周期修复 Codex 完成报告 v1
## 1. 执行结论
**PASS(RDC Native / Android runtime):V18 teardown destroyed-mutex 回归已修复并通过设备闭环。** Codex 阶段仅交付源码;随后 RDC 独立完成 Android full Native build、focused C++ TestRunner、STEP-101 T1~T4、20 次真实 renderer reset/recreate、STEP-100 locality 回归与 crash buffer 检查。V19 尚未在本报告阶段公开发布。
## 2. Git 基线
- 工作区:`/Users/tei/dev/MapLibreParticleLab-step101`
- 分支:`step101-render-orchestrator-teardown`
- start HEAD:`d29e84c1a90daeea104b389d28b000c4f017d08d`
- implementation commit:`64cf8f44350eb8ec4b45360db4d3f9505ac4ac0b`
- implementation message:`fix: make render orchestrator teardown safe`
- push result:**PASS**,`origin/particle/main` 独立回读与 implementation commit 一致。
- 文档 closeout commit / 最终远端 HEAD:Git 提交无法在自身内容中自指其最终 SHA,按项目既有规则由最终交付回读记录。
- 子模块:`git submodule status` 列出的子模块均以 `-` 开头,表示当前工作区未初始化;本轮未修改或初始化子模块。
- V18 Android/RN `13.4.1-particle.18`、iOS `6.28.0-particle.18` 保持不变;V19 **未发布**。
## 3. 根因与实现
V18 `readinessDiagnosticsMutex` 等成员声明在 `renderSources` 之后,按 C++ 反序析构会先于 sources 消失。RenderSource/Tile 销毁存在同步 `Cancelled` callback 到 Orchestrator 的可达路径,随后可能锁已销毁 mutex。这是已证实的生命周期漏洞,与 Android FORTIFY 报错高度吻合。虽未取得精确到最终 callback 的完整符号化现场栈,但同一设备上 V18 条件稳定复现,而 STEP-101 修复后 T1~T4、20 次 reset、动态 GeoJSON 与 diagnostics 条件均不再崩溃,因此将其作为本次 Android teardown 回归的已确认工程根因。
当前源码的析构顺序为:处理 contextLost layers → 第一次 `threadPool.waitForEmpty()` → detach 各 RenderSource、GlyphManager、ImageManager observer → readiness state 仍活着时 `renderSources.clear()` → 第二次 `threadPool.waitForEmpty()` → 常规成员析构。`RenderSource::setObserver(nullptr)` 恢复 NullObserver,tile 回调无需新增空指针分支。显式 detach 与清理建立 owner teardown 合同,不依赖今后成员顺序碰巧安全;没有增加 teardown flag。
render-job 队列独立于 tagged scheduler work。静态检查显示 tile/worker 销毁可投递捕获 render data/bucket 的 render jobs;`waitForEmpty()` 不处理它们。OpenGL 同步 Android reset 路径先 `renderer.reset()`、再 `backend.reset()`,其 Context 析构调用 `runRenderJobs(true)`;若启用 async renderer cleanup,backend 的清理时点另由后续生命周期决定。Metal Context 与 Vulkan backend 也有各自的 `runRenderJobs(true)` 清理入口,均未在本轮运行验证。测试显式 `runRenderJobs()`,但没有构建或设备证据证明所有 backend 模式均安全。这是 RDC 必须核对的剩余风险。
正常 source remove 使用 `renderSources.erase()`,`clearData()` 使用 `renderSources.clear()`;两者均在 Orchestrator 实体及 readiness state 存活时执行。`TileCache::~TileCache()` 会清理 pending releases 并等待先前 deferred deletion 结束。这个审计没有证成任意外部并发调用都安全,本轮不修改正常 erase/clearData 行为,也不声称所有 source replacement 异步问题已解决。
## 4. 实际修改与审计结论
源码/测试差异共七个文件:
1. `src/mbgl/renderer/render_orchestrator.cpp`:显式 detach、source clear 与双 drain。
2. `src/mbgl/renderer/render_orchestrator.hpp`:仅为 focused test 开放 friend helper。
3. `src/mbgl/renderer/render_source.cpp`:nullptr observer 回退 NullObserver。
4. `test/renderer/render_orchestrator_error.test.cpp`:新增两个非 Jest teardown tests;helper 注册 Orchestrator observer,测试断言 source 销毁前 observer 已 detach、Cancelled 不再到旧 observer、第二次 drain 和独立 render-job 队列。
5. `platform/android/MapLibreAndroid/src/cpp/map_renderer.cpp`:`nativeReset` 与 `resetRenderer` 入口/完成日志,仅用于配对观测,未改变 reset 调用顺序。
6. `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/renderer/surfaceview/SurfaceViewMapRenderer.java`:SurfaceView detach 与 Java `nativeReset()` 进入/返回日志。
7. `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt`:T1~T4,tile ready/diagnostics、动态 GeoJSON、Activity recreate、重建与完成日志;保存状态里的空场景不会在配置变更后重新从 Intent 启动。
本轮新增/更新文档:本报告、`docs/50_Step记录/STEP-101_RenderOrchestrator销毁生命周期修复_v1.md`、`粒子开发记录.md`。既有未跟踪的 STEP-101 任务书 v1/v2 没有修改。
与 v2 合同静态核对:observer、双 drain、render-job 独立审计、四个 Android 场景均有对应代码;STEP-100 locality/fast path/source loaded 语义无本次差异。T2 代码计的是 reset **请求**,20 次 Native reset 必须由 log 中每轮 Java `nativeReset`、JNI `nativeReset`、`MapRenderer::resetRenderer entered/completed` 和新 renderer ready 独立确认,不能凭 UI DONE 计数认定。T3 使用已有 T4 R-C-R fixture 并持续更新动态 GeoJSON;T4 在 reset 前额外取 diagnostics。现有 C++ test 使用最小 tile-backed Source,并非实际 Android source;设备等价验收仍不可省略。
## 5. 实际检查与未执行项目
- `git diff --check`:**PASS**(已跟踪 diff 的 whitespace/error 静态检查;未跟踪的新文档不在此命令检查范围)。
- 源码 diff/合同静态审计:完成;补了 observer detach 断言、Java/JNI reset 边界日志、T3 mutation 证据及场景恢复边界。
- CMake/Ninja/Native compile、C++ GTest:**NOT RUN**。
- Android Gradle、Validation APK、AAR/RN candidate:**NOT RUN**。
- ADB、T1~T4、crash buffer、STEP-100 locality 运行态、NavSea 冷启动:**NOT RUN**。
- Jest、iOS/Metal build 与设备、publish/tag/commit/push:**NOT RUN**。
- 产物路径、大小、SHA-256、运行日志:本轮没有新产物,均无结果。
## 6. RDC 精确验证命令与验收证据
在本工作区执行 Mac Native 定向验证(若既有 `libuv` 环境问题仍在,保留首个错误并标为环境阻塞):
```bash
cmake --preset macos-metal
cmake --build build-macos-metal --target mbgl-test-runner --parallel 3
build-macos-metal/mbgl-test-runner --gtest_filter='RenderOrchestratorTeardown.*:RenderSegmentLocality.*'
```
Android Validation APK 使用固定入口,不手拼 Gradle:
```bash
./tools/particle_android_validation/build_validation_apk.sh
```
RDC 使用显式设备 serial。每个场景先清日志、停止旧 Activity,再单独启动;`T2` 等待 20 轮结束。安装前核对 APK 文件、SHA-256、ABI 与运行设备:
```bash
adb -s 192.168.200.139:5555 install -r artifacts/maplibre-particle/android-validation/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk
adb -s 192.168.200.139:5555 logcat -c
adb -s 192.168.200.139:5555 shell am force-stop org.maplibre.android.testapp
adb -s 192.168.200.139:5555 shell am start -n org.maplibre.android.testapp/.activity.particle.ParticleCoreLayerValidationActivity --es step101_scenario T2_RESET_LOOP_20
adb -s 192.168.200.139:5555 logcat -v threadtime -d > /tmp/step101-t2-logcat.txt
rg -n 'STEP101_|SurfaceView detached; nativeReset|nativeReset returned|MapRenderer::nativeReset|MapRenderer::resetRenderer|pthread_mutex_lock called on a destroyed mutex|Fatal signal|ANR' /tmp/step101-t2-logcat.txt
```
对 T1/T3/T4 分别重复相同 `logcat -c`、`force-stop`、`am start`、日志保存步骤,将 `step101_scenario` 依次替换为 `T1_RESET_ONCE`、`T3_RESET_WITH_DYNAMIC_GEOJSON`、`T4_RESET_WITH_DIAGNOSTICS`。逐轮配对 `RESET_REQUEST`、`MAPVIEW_DESTROY_ENTER/RETURN`、`SurfaceView detached; nativeReset entered`、JNI `MapRenderer::nativeReset entered/completed`、Native `resetRenderer entered/completed`、新 `STYLE_READY` 与 `NEW_RENDERER_READY`;T2 需至少 20 个完整 reset/recreate 配对,且无 SIGABRT/ANR。T3 核对 `STEP101_DYNAMIC_SOURCE_MUTATION` 在每轮 reset 前持续出现,T4 核对 `PRE_RESET_DIAGNOSTICS` 与 reset 后 diagnostics。STEP-100 T4 R-C-R 另按既有 Validation 菜单复跑,核对无关 R0 `buildDelta=0`、`invalidationDelta=0`、`reuseDelta>0`,动态 R1 正常 build/invalidation。
上述只是交接命令,**本轮均未执行**。V19 candidate 必须先于 NavSea 临时锁包和五次超过 30 秒的冷启动;crash buffer 与 locality 均通过后,才可进入不可变发布。NavSea 外部工作区/候选制品命令由 RDC 按其实际环境另行确定,本轮不伪造路径或结果。
## 7. 已知问题、未完成事项与下一步
静态审计无法证明 Android 每次 Activity recreate 都实际完成 native reset,也无法证明异步 backend 清理和真实 Source 并发场景无 late callback。Native 编译与定向测试、四个 Validation 场景、STEP-100 locality、NavSea 等价五次冷启动、crash buffer 均待 RDC;任何失败均应保留现场并按首个真实错误回传。无理由在本阶段修改 NavSea、发布 V19 或重写 STEP-100 语义。
## 8. RDC 独立验收(2026-10-07)
### 8.1 Android full Native / Validation APK
标准入口:
```text
./tools/particle_android_validation/build_validation_apk.sh
```
结果:**PASS**。
```text
variant=OpenglDebug
abi=x86_64
apk_bytes=61957678
libmaplibre_bytes=39637512
sha256=14cbd35ed0bc1366389ddea69925901013e3b209ed3575462421a7920c73c721
```
该构建实际编译了本 Step 修改后的 C++ Core、`libmaplibre.so`、JNI/Java reset 日志和 Android Validation T1~T4。
### 8.2 STEP-101 Android teardown runtime
设备:FZG1-2 / Android 13 / API 33 / x86_64 / `192.168.200.139:5555`。
- T1 `RESET_ONCE`:真实 `MapRenderer::resetRenderer entered/completed`、`nativeReset entered/completed`、新 renderer `STYLE_READY / NEW_RENDERER_READY`;PASS。
- T2 `RESET_LOOP_20`:完整运行至 iteration 20,最终 `STEP101_SCENARIO_DONE ... resetsRequested=20`;逐轮出现 destroy/reset/new renderer ready;PASS。
- T3 `RESET_WITH_DYNAMIC_GEOJSON`:reset 前动态 GeoJSON mutation 持续产生,reset 完成后新 renderer 继续 ready;PASS。
- T4 `RESET_WITH_DIAGNOSTICS`:reset 前 `getRenderSegmentDiagnostics()` 可读,随后真实 reset 完成并重建;PASS。
- 四组验收 crash buffer 均为空;未出现 `pthread_mutex_lock called on a destroyed mutex`、SIGABRT 或 ANR。
### 8.3 STEP-100 locality 回归
R-C-R T4 重新运行 60+ 秒,稳定窗口:
```text
global revision: 62 -> 894
R0 retained:
build 1 -> 1 delta 0
invalidation 19 -> 19 delta 0
reuse 12 -> 3890 delta +3878
R1 retained:
build / invalidation 持续增长
```
动态 source mutation 仍只影响对应 segment;R0 source revision 保持不变。STEP-101 teardown 修复没有破坏 STEP-100 Source→Segment locality。
### 8.4 Focused Android C++ TestRunner
Mac host `mbgl-test-runner` 仍因本机缺失可用 `libuv` pkg-config 包而 ENV BLOCKED;没有安装或升级系统依赖来掩盖该环境事实。
改用仓库已有 Android Native C++ TestRunner,x86_64 build **PASS**。RDC 为 TestRunner 临时打包真实 `test/fixtures/` 到 `data.zip`,仅满足 Android runner 既有解压契约;该临时 asset 已删除,不进入 Git。
设备过滤执行:
```text
RenderSegmentLocality.SourceRevisionsAreScopedAndRecreationUsesNewIdentity PASS
RenderSegmentLocality.ReadinessAndFadeFollowOnlyDependencies PASS
RenderSegmentLocality.MixedExecutionDrawsEachLiveRangeOnceInStyleOrder PASS
RenderSegmentLocality.FailedBuildCannotReuseOldTexture PASS
RenderOrchestratorTeardown.NullObserverAndDetachCoverEveryTileCallback PASS
RenderOrchestratorTeardown.PendingTileCancellationAndSecondDrainRepeatSafely PASS
TestRunner finished with status: '0'
```
最终 TestRunner APK(含临时 fixtures,仅作验收证据)SHA-256:
```text
e1b39b3eb035175b79dd60dbe39496ea982c2dd6e2f1593fd60dd9630f393712
```
crash buffer 为空。
首次 TestRunner 编译暴露 6 个测试源码级 C++20 designated-initializer / protected-base conversion 问题;RDC 仅修正测试源码字段补齐和显式转换,未改变生产语义。修复后 Android C++ TestRunner build 与上述 filtered tests 均 PASS。
### 8.5 结论
STEP-101 的 Native 生命周期修复达到关闭条件:
1. RenderSource observer 在 owner teardown 前显式 detach;
2. readiness state 仍存活时显式销毁 renderSources;
3. source clear 前后 tagged work 双 drain;
4. glyph/image observer 同步 detach;
5. 20 次真实 Android renderer reset/recreate 无 destroyed-mutex;
6. 动态 GeoJSON、diagnostics 条件下仍安全;
7. STEP-100 locality 保持 PASS;
8. focused C++ tests PASS。
Jest:**NOT RUN**。
V19 candidate、NavSea 五次冷启动与正式 publish/finalize 属于后续发行 Gate,不改变本 Step Native 修复的 PASS 结论。

View File

@@ -0,0 +1,129 @@
# STEP-102 RenderSegment 无 Placement 段局部复用 Codex 完成报告 v1
## 1. 执行结论
**代码完成,等待独立构建与运行验证;STEP-102 尚非 PASS。** 已按任务书实现 full CPU placement-free Retained Segment 局部复用、逐段 fallback reason 和实际 main-buffer 执行诊断。C++ 与 Android 测试均只交付源码,未运行。没有编译、设备或视觉结果,不能据此宣称无 stale、Z-order 错乱或 crash。
## 2. Git 基线与工作树
- 工作区:`/Users/tei/dev/MapLibreParticleLab-step102`
- 当前机器:macOS 15.7.7 / Darwin x86_64;未连接或操作设备。
- 分支:`step102-placement-free-retained-locality`
- start HEAD:`6df21dac38f072c5ad35b8dfc7ec5217509602bc`
- end HEAD:仍为 `6df21dac38f072c5ad35b8dfc7ec5217509602bc`;本阶段未 commit、push、merge。
- 子模块:`git submodule status` 均以 `-` 开头,本 worktree 未初始化;未更改。
- 工作树:仅下列任务文件有本阶段差异;任务开始时已经未跟踪的 v2/v3 审查说明及 STEP-102 任务书未修改、未暂存。
- V19/V20 release worktree、`particle/main`、tag 与发布坐标未修改;无新 artifact。
## 3. 实际修改与新增文件
生产代码:
1. `include/mbgl/renderer/render_segment.hpp`:结构查询、placement gate、全局 live reason 辅助函数及 diagnostics 字段。
2. `src/mbgl/renderer/render_orchestrator.hpp`、`src/mbgl/renderer/render_orchestrator.cpp`:对 full CPU 提供结构查询和 placement transition 查询;旧动态查询保持原样。
3. `src/mbgl/renderer/renderer_impl.cpp`:逐段 gate/fallback、全局 live reason、实际执行记录。
4. `src/mbgl/renderer/retained_underlay_runtime_state.hpp`、`src/mbgl/renderer/render_segment_json.hpp`:只读快照与 JSON 字段。
5. `packages/maplibre-particle-rn/src/types.ts`:现有 diagnostics 返回类型 additive 扩展。
测试/Validation:
6. `test/renderer/retained_underlay_cache.test.cpp`:新增 `RenderSegmentPlacementFree.*` C++ 测试源码。
7. `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt`:STEP-102 场景菜单、Intent 入口、轮询及审计日志。
8. 新增 `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/Step102PlacementFixture.kt`:离线 R-C-R symbol/placement-free 两组 fixture。
文档:新增 `docs/50_Step记录/STEP-102_RenderSegment无Placement段局部复用_v1.md`、本报告;追加 `粒子开发记录.md`。
## 4. 实现与任务书逐项对照
- **结构能力**:扫描同一 style-layer 元数据中的 `layerType == "symbol"`;越界 range 返回 placement-capable 以 fail-closed。`retainedRangeUsesPlacement()` 的 `needsPlacement()` 动态语义未变。custom/custom-drawable 仍由原 unsupported gate 处理。
- **逐段 gate**:placement-free 返回通过;placement-bearing 要求 `!placementChanged && symbolFadeChange == 0 && !placementTransitionActive`。`symbolFadeChange==0` 只是沿用保守 gate 的条件,不命名为严格 stable。transition disabled 且 fade=1 仍不能让含 symbol 段复用。
- **逐段 fallback**:优先明确 source、global resource、placement、layer transition、legacy/unsupported 等本段理由。`static-placement` 只会由本段 gate 失败产生;不再拷贝 aggregate placement/transition 理由给邻段。
- **full CPU main-buffer**:全局 live 条件只删掉 aggregate `!retainedPlacementStable`,其他既有 3D、debug、非 Continuous MapMode、sprite、global resources、light transition 条件保留。原 `visitRenderSegmentExecution()` 和 Style 顺序不变。camera/viewport/pixelRatio、topology、content/global revision、resource/compositor failure 的原有失效路径未放宽。
- **兼容/安全边界**:aggregate `retainedStaticUsesPlacement`、`retainedPlacementStable`、prepared-tree/Fast Path eligibility 与 revision 观察继续原用;含 symbol 的 retained 仍 fail-closed;C-001、RN method surface、`setRenderSegmentPlan()` 输入未变。
与 v3 审查设计无架构差异。逐段 gate 额外显式查询当前 placement transition,属于对 placement-bearing 的更保守判定;原 `retainedSegmentIsStable()` 内仍保留既有 transition 检查。测试和 Android 场景均不修改 Placement 核心算法。
## 5. diagnostics 字段与真实执行语义
每段新增 `placementCapable`、`placementGatePassed`、`actualExecution`。前者来自 style-layer 结构,第二项表示本帧 full CPU placement cache gate;Continuous 段的 gate 为非阻塞值。`actualExecution` 在 main-buffer 全局 live 分支或 mixed executor 的 composite 回调实际发生后记录。即使 `cache.finalDecision=reuse`,全局门槛触发时仍记录 `actualExecution=live`。
全局新增 `placementChanged`、`symbolFadeChange`、`placementTransitionActive`、`crossSourceCollisions`、`mainBufferExecutionMode`、`globalLiveFallbackReason`。`mixed` 表示进入 Style 顺序的 mixed executor,可以包含某些 Retained live;`global-live` 表示整帧 live 分支。尚未渲染时 `mainBufferExecutionMode/actualExecution=not-rendered`。查询只拷贝已记录快照,不推进 revision;Android/iOS Shared Core 使用同一 JSON writer,RN TS 只补类型。
## 6. 测试源码覆盖矩阵
| 合同场景 | 新增/现有测试源码 | 尚待运行证明 |
| --- | --- | --- |
| A:R0 free、C live、R1 symbol live;Style 顺序 | `RenderSegmentPlacementFree.MixedExecutionKeepsFreeRangesInStyleOrder` | Android T1 真实 GPU composite/live 与视觉 Z-order |
| B:symbol 当前 placementData 为空仍 capable | `StructuralCapabilityAndConservativeGate` 直接输入 symbol style 结构,不依赖 placementData | Android 空 bucket/placementData 条件仍需设备审计 |
| C:两个 free Retained 复用 | `MixedExecutionKeepsFreeRangesInStyleOrder` 中 R0/R2;Android T2 | 60 秒 build/reuse/invalidation 窗口 |
| D:source-local unloaded/fading/mutation | 既有 `RenderSegmentLocality.ReadinessAndFadeFollowOnlyDependencies` 与本轮两 free cache 断言;Android T1 动态 symbol source | 设备 R0 计数不误增 |
| E:bearing 保守 gate | `StructuralCapabilityAndConservativeGate` changed/fade=1/transition 活跃组合 | transition disabled 场景的 GPU 行为 |
| F:真实全局门槛 | `RealGlobalGatesStillForceGlobalLive`;既有 revision/cache tests | style/context/image/glyph/light 等设备失效 |
| G:拓扑与 key | `TopologyAndCameraChangesCannotReuseOldRetainedKey`;既有 `OldCacheReleaseCannotChargeReplacementAtSameIndex` | 真正 GPU resource 释放及无 stale texture |
| H:reuse 但 global-live | `DiagnosticsRecordActualMainBufferAndDoNotMutateOnRead` | 设备日志中 cache/actual 分离 |
测试源码只验证可隔离的策略、cache 决策、diagnostics 和 mixed traversal;无法单凭这些单元测试替代真实 renderer/GPU 场景。
## 7. Android Validation 场景
Test App 的 STEP-093 菜单新增 `STEP-102 PLACEMENT LOCALITY`,也可用 Intent `step102_scenario` 启动:
- `T1_FREE_SYMBOL`:R0 background/fill(无 symbol)→ C0 持续粒子 → R1 symbol;每 500ms 更新 R1 GeoJSON point,让 placement/source 活跃。
- `T2_TWO_FREE`:相同 R0/C0,R1 改为 fill;两个 Retained 均结构上 placement-free。
每个 `STEP102_SAMPLE` 记录固定 camera、placement 四个全局字段、main-buffer mode/reason、每段 capability/gate/actual、cache decision、build/reuse/invalidation/fallback。tick 8/130 打窗口标记。日志字段用于验收,不在 App 中自行宣告 PASS。
## 8. 实际检查与 NOT RUN
- 已执行:`git status --short`、`git diff`/`rg` 只读审计;`git diff --check` **PASS**。三个新增未跟踪文件另以 `git diff --no-index --check /dev/null <文件>` 检查,无空白错误;该命令因有差异正常退出 1。
- **NOT RUN**:CMake/Ninja/Bazel configure/build/link、C++ GTest、Android Native TestRunner、Android Gradle、APK/AAR、codegen、Jest、ADB、设备/截图/logcat、iOS/Metal、NavSea、发布、commit、push。
- 无 APK/AAR、大小、SHA-256、运行日志或最终性能结果。没有编译失败或测试失败的事实;缺少编译/运行证据。
## 9. 后续精确验证命令与硬门槛
先由 RDC 在本工作区运行 host 定向测试;若当前 Mac `libuv` 环境仍阻塞,应记录首个真实 configure 错误,而非改动依赖:
```bash
cmake --preset macos-metal
cmake --build build-macos-metal --target mbgl-test-runner --parallel 3
build-macos-metal/mbgl-test-runner --gtest_filter='RenderSegmentPlacementFree.*:RenderSegmentLocality.*:RenderSegmentDiagnostics.*'
```
**Android Validation APK 只由用户手工构建**,使用项目固定入口:
```bash
cd /Users/tei/dev/MapLibreParticleLab-step102
./tools/particle_android_validation/build_validation_apk.sh
```
构建成功后由 RDC/用户核对 APK ZIP、ABI、`libmaplibre.so`、SHA-256、branch/commit/dirty 状态,再在选定设备上独立运行。下列 `<SERIAL>` 需替换为实际 `adb devices` 返回的 serial;每场景单独清日志、force-stop、启动并留存完整 logcat:
```bash
adb -s <SERIAL> install -r artifacts/maplibre-particle/android-validation/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk
adb -s <SERIAL> logcat -c
adb -s <SERIAL> shell am force-stop org.maplibre.android.testapp
adb -s <SERIAL> shell am start -n org.maplibre.android.testapp/.activity.particle.ParticleCoreLayerValidationActivity --es step102_scenario T1_FREE_SYMBOL
adb -s <SERIAL> logcat -v threadtime -d > /tmp/step102-t1-logcat.txt
rg 'STEP102_(SCENARIO_START|STYLE_READY|SAMPLE|WINDOW_MARKER)|Fatal signal|ANR' /tmp/step102-t1-logcat.txt
```
对 `T2_TWO_FREE` 重复 `logcat -c`、force-stop、启动、保存到 `/tmp/step102-t2-logcat.txt`。每组至少等待 tick 130(约 65 秒)后取最终日志。T1 硬门槛:固定 camera、`mainBufferExecutionMode=mixed` 的稳定窗口中 R0 `placementCapable=false`、`actualExecution=composite`、buildDelta=0、invalidationDelta=0、reuseDelta>0;R1 `placementCapable=true`,placement gate 失败期间 `actualExecution=live`,C0 live,Style Z-order 正确,无 stale/crash/ANR。T2 两个 Retained 均无 symbol,build 一次后持续 reuse/composite。若窗口内出现真实 global mutation,应结合 `globalLiveFallbackReason` 与 lastMutation 重新选择稳定窗口,不把合法 global invalidation 算作误伤。
还需独立做 STEP-100 source locality 与 STEP-101 teardown 回归,以及 global light/style/context/camera、topology 变动资源释放验证。iOS/Metal 只可在相同源码提交的 Mac/iOS 验收后声明通过。本阶段均未执行。
## 10. 风险、未完成事项与交接
- Android symbol glyph asset 与 placement 活跃窗口尚未由构建/设备核实;T1 若未出现 placement gate 失败,不构成主场景验收。
- 现有 C++ topology 测试验证 key/revision 无旧 cache reuse,不能证明真实 GPU 资源已释放;需设备/后端证据。
- `placementChanged` 与 `symbolFadeChange` 在 Fast Path 帧来自既有 prepared render tree;本 Step 没有改变 Fast Path 判定或语义。主验收只使用 `fullCpuFrame` 增长的 full CPU 窗口。
- 构建或运行失败应保留现场、回传首个真实错误及必要上下文;不得放宽测试或安全门槛。没有触及任务书要求 BLOCKED 的架构扩张条件。
本阶段未创建 Git commit,故无 implementation commit SHA;也未执行 merge、push 或远端 HEAD 回读。后续独立验收决定 scoped commit/merge 与发行流程。
## 11. V21 发行风险豁免记录(2026-10-08)
- 用户明确要求:V21 必须包含 STEP-102;本次发行不以正式 GTest、Android T1/T2 实机回归、iOS/Metal 运行态验收为前置条件,改由代码审查后执行完整发布流水线。
- 源码审查基线:`0ce551ad3791a21dbd8507e6cf8c607c270b6eee`。已检查结构性 symbol/Placement 分类、逐段 gate、真实全局 live 门槛、main-buffer 顺序、诊断数据和 Android Validation 场景;`git diff --check` 通过,未发现明确阻断发布的源码问题。
- 已有构建证据仅限 STEP-102 Metal Core 编译成功(Bazel 642/642),以及临时 helper smoke 10/10。正式 C++ GTest 受 `libuv` 依赖缺失阻塞,Android 与 iOS 运行态验收没有执行。
- **验收豁免不等于测试 PASS**:STEP-102 不标记 `CLOSED / PASS`,而按“源码审查后接受未验收风险发行 V21”记录。不能声称已经证明运行态无陈旧纹理、Z-order 错乱或崩溃。
- V21 Pipeline 的 prepare、build、publish、finalize 仍必须全部执行并以真实返回值、artifact 校验和公开回读为准;构建或发行阶段失败不可豁免。

View File

@@ -0,0 +1,64 @@
# STEP-104 官方 Native 13.6.1 升级阶段 A — Codex 完成报告 v1
## 1. 执行结论
**PARTIAL:官方 Native 13.6.1 + Particle .21 源码移植已完成三方合并,Android x86_64 OpenGL Native 编译链接 PASS;其他 ABI、GPU 视觉/行为、RN 与 iOS 未验收。** 不是正式发布结论。
## 2. 执行模型与人员分工
- Codex:`gpt-6.1-sol`,`high`,真实会话 `turn_context` 已由 RDC 独立核对。
- Codex 负责源码冲突、接口调整和静态核对;RDC 负责 Git 真实合并/index/commit、submodule 和 Native 构建;未切换其他模型。
- 所有操作在隔离工作树 `/Users/tei/dev/MapLibreParticleLab-upgrade-android-1361`,branch `upgrade/android-native-13.6.1-20261009`;未修改 NavSea、正式 .21、Integration 合同或 iOS 专用行为。
## 3. Git 基线与多个提交
- 官方新底座:Android Native 13.6.1,`c7506d6aff3800e946f89e1a51432fc22d1a6534`。
- 旧自研扩展:发布 .21 `630ec657687bad4200c059bbccbb950d9c6f7ce9`,完整历史及审计闭环 `b433775348373b10fba02dc0e1f728bacd72f9e7`。
- `e4c7af7c401aebc0fdb9d85309ad781e328baff4`:升级任务与根目录 `recoder_step.md` 的启动检查点。
- `f8378fd7113c4d230500f0b82902d2356907f4a9`:两父三方合并,将自研 Particle 与 RenderSegment 移植至官方 13.6.1(提交时未编译)。
- `a4b5f4eaa0eccb734e00d67adb5e750bba320404`:补充真实合并进度与风险记录。
- 本报告对应的构建发生在 `a4b5f4eaa0` 上。本文及后续 Gate 记录另作独立收尾 commit,不修改已验证的 Native 产品代码;最终 HEAD 和远端结果以实际 Git 命令回填。
## 4. 主要源码调整
- 自研 Field、Ingress、QBIN、WeatherColor、RasterParticle 代码迁移到官方 `include/mln`、`src/mln` 路径,不恢复旧 `mbgl` 产品目录。
- 合并官方与 .21 的 Source/Layer Factory、Shader manifest 与 OpenGL 建置注册,保留官方 CustomMVTVector 和现有 RasterArray。
- 适配 RenderLayer 新 `PaintParameters` 参数和 `renderableSize`,同步保留 RenderSegment/Retained、fast-path、revision、source-scoped fail-closed、observer 与资源清理。
- Android JNI 自研入口及官方 Feature State 入口的静态声明/注册核对,未重新定义 RN 公共 API。
## 5. 冲突与格式检查
- `git merge --no-ff --no-commit` 初始 76 个未合并路径;Codex 清除冲突标记,RDC 确认 `git ls-files -u` 为 0 后完成合并提交。
- 新版 Native 源码范围的 `git diff --check` PASS。整体 merge 中有 3 份历史文档保留自旧版的尾随空格,逐字节确认来自 .21 源提交,未篡改历史文档。
- 源码状态以本次 Git branch 和原生编译证据为准,静态检查不替代行为验收。
## 6. Native 构建记录
- 环境:Mac,Homebrew OpenJDK 17,Android SDK/NDK `28.2.13676358`,SDK CMake 3.31.6;ABI=`x86_64`,Renderer=OpenGL,BuildType=Debug。
- 标准命令(`platform/android`;先 export JAVA_HOME/ANDROID_HOME/ANDROID_SDK_ROOT):
```bash
./gradlew --no-daemon --max-workers=3 --console=plain -Pmaplibre.abis=x86_64 :MapLibreAndroid:externalNativeBuildOpenglDebug
```
- 首轮:CMake 因缺少 `vendor/maplibre-native-base/deps/cheap-ruler-cpp/include` 失败(新 worktree submodule 未初始化)。
- 第二轮:CMake 因 `maplibre-tile-spec/cpp/vendor/earcut/CMakeLists.txt` 和 `mbgl-vendor-supercluster` license 缺失失败。
- RDC 校验 top-level Native submodules 固定提交,恢复中断克隆导致的残缺 vendor 工作树;第三轮命令成功,Gradle `BUILD SUCCESSFUL in 22m 24s`,退出码 **0**。已执行真实 NDK 编译与动态库链接。
- 第三轮原始构建日志保存于 Mac `/tmp/step104_android_native_opengl_gradle_third.log`;前两轮错误日志保存于同目录对应 `gradle.log` 与 `gradle_retry.log` 文件。
## 7. 产物证据
- 完整路径:`/Users/tei/dev/MapLibreParticleLab-upgrade-android-1361/platform/android/MapLibreAndroid/build/intermediates/cmake/openglDebug/obj/x86_64/libmaplibre.so`。
- 文件类型:ELF 64-bit LSB shared object、x86-64、dynamically linked、with debug_info、not stripped。
- 大小:`377246848` bytes。
- SHA-256:`ff5a5eb45f84ff633a87fe385fb04ee39ba63ed3bc486003408e02cea78c8907`。
- 此产物未签名、未公开发布,不应作为 NavSea 正式依赖或全 ABI 发布件。
## 8. 实际测试与未测试范围
- PASS:三方合并无未解决冲突、Native 编译器完成 x86_64 OpenGL 工程构建、最终 libmaplibre.so 链接。
- NOT RUN:ARMv7、ARM64、其余 Android ABI、Android APK/实体机/虚拟机 GPU 视觉、QBIN/T0/T1 运行态、Pan/Zoom/Rotate、Style reset、RenderSegment retained 行为、Vulkan、RN 11.5.0 Feature State 联调、iOS Metal/XCFramework。
- 未执行 Jest;未以静态推断伪报运行通过。
## 9. 已知问题与阻塞
- GitHub 下载曾出现间歇性 DNS/HTTPS 超时;RDC 校正必要的 submodule HEAD 后完成编译。
- Gradle/CMake 输出 SDK XML 版本、Gradle 10 弃用提示;本轮未导致失败。长期工具链调整需单独设计,不并入当前移植 Gate。
- iOS/shared contract 更改不属于 Android 本轮权限;涉及跨平台共同语义须回 Integration 协调。
## 10. 下一阶段、停点与发布边界
建议在**Android 多 ABI(armeabi-v7a / arm64-v8a / x86 / x86_64)Native 验证 + Test Host GPU 功能回归**处设置下一 Gate。下一阶段再独立验证 RN 11.5.0 的公共桥接与 Feature State,iOS 由对应负责方验证。当前不发布 AAR、npm,不改 NavSea 主线。
## 11. 收尾事实
本次更新采用根目录 `recoder_step.md` append-only,并追加 STEP-104;Git 提交、远端分支、最终 HEAD、push 结果以 RDC 后续独立回读为准。未完成项如实保留。

View File

@@ -0,0 +1,59 @@
# STEP-105 Android Native 13.6.1 — FZG1-2 Validation APK 打包与安装 RDC 执行报告 v1
## 1. 结论
**APK_BUILD_PASS / FZG_INSTALL_PASS / DEVICE_APK_HASH_PASS / RUNTIME_NOT_RUN**。
本次在 Mac 使用官方 MapLibre Native Android 13.6.1 + Particle .21 升级候选打包 `MapLibreAndroidTestApp`,通过 FZG1-2 的 ADB 覆盖安装,并在设备端核对实际版本和完整 APK SHA-256。没有安装 NavSea,也没有声明粒子运行态通过。
## 2. 环境与版本
- Mac 目录:`/Users/tei/dev/MapLibreParticleLab-upgrade-android-1361`
- 源码分支:`upgrade/android-native-13.6.1-20261009`
- 构建源 HEAD:`30d0e6665eb16a258e47b3a8cc0d16932e43762b`
- 底座 Native:`android-v13.6.1`;OpenGL Debug,Native ABI `x86_64`
- Test App 包名:`org.maplibre.android.testapp`;新版本 `13.6.1`,`versionCode=14`,`targetSdk=35`。
- FZG:`FZG1-2` / Android 13 / `192.168.200.139:5555`,`ro.product.cpu.abi=x86_64`;另一台 Odin 不在修改范围。
- 工具:Mac JDK17、Android SDK/NDK、Gradle `--console=plain`;缺失的 Android SDK Platform 35 已经由 Gradle 获取。
## 3. APK 构建与失败恢复
使用项目原有 `tools/particle_android_validation/build_validation_apk.sh`。
1. 第一轮 Gradle `:MapLibreAndroidTestApp:assembleOpenglDebug` 编译 **BUILD SUCCESSFUL in 6m 48s**,但原 Validation 脚本要求 APK 全部 ABI 集合精确为 `x86_64`。实际 APK 其他 ABI 含有 Sentry 日志库 `libsentry.so` / `libsentry-android.so`,因此脚本按照 fail-closed 策略拒绝打包,未安装。
2. 调整 `tools/particle_android_validation/build_validation_apk.sh`:所有非目标 ABI 的文件只接受 `arm64-v8a`、`armeabi-v7a`、`x86` 下这两种 Sentry 库;其它意外 Native 库仍拒绝。额外确认 `lib/x86_64/libmaplibre.so`、`lib/x86_64/libexample-custom-layer.so` 存在;保持 APK 体积及 `libmaplibre.so` 体积上限。
3. 脚本通过 `bash -n`、`git diff --check`;增量 Gradle **BUILD SUCCESSFUL in 10s**,脚本报告 **BUILD SUCCESS**。
4. 修改脚本单独 Git commit:`73db0356ac5860366f314ddba23b716220e7c16a`。APK 的 `build-info.txt` 记录源码 HEAD `30d0e6665e` 且当时 `git_dirty=true`,因为脚本尚未提交;这里如实保留这一构建时事实,不能把后续 commit 当作已经编入 APK 的 C++ SHA。
## 4. APK 最终产物
- 相对路径:`artifacts/maplibre-particle/step105-native1361-fzg/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk`
- APK 字节数:`66,505,502`。
- `libmaplibre.so` 在 APK 内的字节数:`39,970,088`。
- SHA-256:`77bc0b238fb476494410a603443030b104d78f97a737307be52460bf5a68f5aa`。
- `aapt dump badging`:`org.maplibre.android.testapp` / `versionName=13.6.1`。
- `apksigner verify` PASS;校验日志中的非致命 META-INF 元信息警告不代表签名失败。
- APK 同时携带三种其它 ABI 的 *Sentry 辅助库*;`libmaplibre.so` 和 Test App Custom Layer 均仅为 x86_64。产物命名中的 x86_64 指 MapLibre Native 编译目标,不表示 APK 没有任何其它架构的 Sentry 依赖。
## 5. FZG 安装与设备端回读
- 安装前原版:`13.4.1-particle.21`,包名相同。
- 从设备拉取旧 APK,`apksigner verify --print-certs` 核对新旧证书 SHA-256 均为 `e3f8fae6451ed6322259d090dd8e8788df554ab25ed89a01c78014f1d5ef8236`,允许正常覆盖。
- 安装命令:`adb -s 192.168.200.139:5555 install -r <APK>`。
- ADB 明确返回 **Success**,完成时间 **2026-10-09 12:03:06 JST**。
- `dumpsys package`:`versionName=13.6.1`,`lastUpdateTime=2026-10-09 12:03:06`,`firstInstallTime=2026-09-22 07:34:56`,未卸载重装。
- `adb shell sha256sum /data/app/.../base.apk` 返回 `77bc0b238fb476494410a603443030b104d78f97a737307be52460bf5a68f5aa`,与 Mac 本地 APK 字节级一致。
- 安装后 FZG 前台仍是 `com.navsea.app/.MainActivity`。这不是 NavSea 更换 Native AAR/npm,也未更改 NavSea 本身。
## 6. 回退与未完成内容
- 安装前旧 APK 备份在(Git 忽略目录):`artifacts/maplibre-particle/step105-native1361-fzg/rollback/MapLibreAndroidTestApp-original-13.4.1-particle.21.apk`,SHA-256 `999f773276b29fffae05c1edc977e19df6cebecd94e4a4095508d0c5e97e07c2`。无需重新下载旧版 APK;尚未执行回退。
- **NOT RUN**:Test App 前台启动、GPU 粒子动画/QBIN/T0/T1、地图 pan/zoom/rotation、RenderSegment retained、Style/layer unload/reload、崩溃/帧性能、其它 ABI、RN 11.5.0 和 iOS。
- 下一阶段建议使用已安装的 FZG 测试 App 进行上述真实 GPU/生命周期回归,验收完成后再考虑升级分支合并或发布。
- 本任务通过 RDC 直接构建/安装,**没有调用 Codex 模型或替换 Codex 工作**。与此前 STEP-104 的 GPT-6.1 Sol/High 实施范围不同。
## 7. 记录与 Git
- Root `recoder_step.md` 追加事实,`docs/50_Step记录/` 单独记录,完成报告写入 `docs/报告/`。
- 脚本代码 commit `73db0356ac5860366f314ddba23b716220e7c16a`。本次文档提交与 push、远端 HEAD 由 RDC 单独验收,最终结果以实际 Git 回执为准。
- 只推送 `upgrade/android-native-13.6.1-20261009`;正式 `particle/main` 不更新。

View File

@@ -0,0 +1,57 @@
# STEP-105 FZG1-2 MapLibre 13.6.1 实机 ADB 验收报告 v1
## 1. 结论
整体状态:PARTIAL。Android x86_64 OpenGL 升级候选已在 FZG 上完成多组运行验收;STEP-102 T2_TWO_FREE 仍 FAIL。不得以已安装、可显示粒子和无崩溃代表升级全部 PASS。
## 2. 环境和范围
- 2026-10-09 JST;Mac RDC/ADB;FZG1-2 Android 13,serial 192.168.200.139:5555。
- Test App org.maplibre.android.testapp / versionName 13.6.1,已安装 APK SHA-256 为 77bc0b238fb476494410a603443030b104d78f97a737307be52460bf5a68f5aa。
- Git 升级分支 upgrade/android-native-13.6.1-20261009,测试源码 HEAD c30add4d335c5c02aadac5756c1606b5bc497269。
- 仅 ADB UI/手势/Intent/Logcat/截图;没有 Codex、Gradle、Jest、NavSea 修改、iOS、其他 ABI 或正式发布。
## 3. 验收表
| 实测项目 | 证据 | 结论 |
|---|---|---|
| 初始粒子显示 | 用户看到粒子;UI GLOBAL/ACTIVE/EAST/MIX0%/256;两帧截图 | PASS(初始显示) |
| Cache ON→OFF→ON | 状态回读,runtime-disabled 后恢复 CACHE ON | PASS |
| 地图平移/双击缩放 | App 存活;camera-or-boundary 缓存失效,后续复用 | PASS(基础运行) |
| STEP-101 T1 单次重建 | destroy enter/return、Native reset、new Renderer ready、DONE | PASS |
| STEP-101 T2 20 次重建 | 流式日志20请求、20 Native reset进入/完成、40 Render reset进入/完成、21 ready、crash buffer0 | PASS |
| STEP-099 T4 R-C-R | 71次动态源更新,R0 build2→2、reuse5696→9373、invalidation35→35 | PASS(R0 locality) |
| QBIN V4 Golden | T0/T1 ACCEPTED_INSERTED,6项播放控制 ACCEPTED | PASS(操作契约) |
| STEP-102 T1_FREE_SYMBOL | R0 composite reuse +3683;R1 symbol placement gate false,Live | PASS |
| STEP-102 T2_TWO_FREE | R0 reuse +3682;R1 placementCapable=true、Live/Fallback、reuse0 | FAIL(预期双 Retained) |
| 最终恢复 | 默认 GLOBAL/ACTIVE/EAST/MIX0%/256;前台 Test App 13.6.1;crash buffer0 | PASS |
## 4. 关键数字及诊断
STEP-101 T2 首轮虽完成20次但设备环形 Logcat 丢失了前15次。该轮不记完整 PASS。第二轮使用 Mac 实时流式日志,从场景启动前持续记录到 DONE,完整包含:20 RESET_REQUEST、20 MapView destroy enter、20 destroy return、20 nativeReset entered、20 nativeReset completed、40 resetRenderer entered、40 completed、21 NEW_RENDERER_READY、1 SCENARIO_DONE,Crash Buffer 0。
STEP-099 T4 R-C-R(底层 Retained/中央粒子 Continuous/上层动态 Retained)在 tick8 至 tick130:R0 build=2→2、reuse=5696→9373(+3677)、invalidation=35→35;动态 GeoJSON 共71次更新。上层 R1 因 static-placement 保守 Live 回退。该 PASS 仅针对独立 R0 的 Source-scoped 缓存隔离。
QBIN V4 Golden 录得 t0=ACCEPTED_INSERTED、t1=ACCEPTED_INSERTED,后续 action=3 Seek25、4 Seek75、1 Play、5 Speed2、2 Pause、7 Clear,均 result=ACCEPTED;最终 UI 显示 V4 CLEARED。这不是天气场颜色和方向的像素级数值证明。
## 5. T2_TWO_FREE 阻塞事实和归因限制
T1:R0 placementCapable=false/gate=true/actual=composite,build1→1、reuse196→3879、invalidation6→6;带 Symbol 的 R1 placementCapable=true/gate=false/actual=live,符合保守安全设计。
T2:R0 placementCapable=false/gate=true/actual=composite,build1→1、reuse197→3879、invalidation5→5;R1 即使 fixture 指定 Fill,仍 placementCapable=true、gate=false、actual=live、fallback=static-placement,build0→0、reuse0→0、invalidation202→3884。最终 symbolFadeChange≈0.997、placementTransitionActive=true、crossSourceCollisions=true。两窗口 tick8/130 一致;无 FATAL/ANR,Crash Buffer 0。
只读源码:renderSegmentHasPlacementCapableLayer 只要分段内出现类型 symbol 即判 true,而测试 fixture T2 的自定义上层为 Fill。应调查运行时完整 Style Layer 列表、默认 Annotation Symbol 注入、segment begin/end、source/layer 归属。其它场景的 dependency 中曾出现 org.maplibre.annotations,但尚未证明在 T2 中造成该问题。缺少旧 .21 的 T2 运行对照,因此不应把该差异直接断言为 13.6.1 新引入的回归。
现象是保守 Live/Fallback 与复用能力未达预期,不是已证实的错绘或 GPU 资源错误。禁止为凑 PASS 关闭 Placement 安全门。需先核实是场景/区段定义问题还是实现问题,再在授权范围内修复并重新验收。
## 6. 原始证据、范围与收尾
Mac Git 忽略目录:artifacts/maplibre-particle/step105-fzg-runtime-20261009/,共含 01-baseline、02-cache、03-camera、04-teardown-t1、05-teardown-t2、06-locality-t4、07-qbin-v4、08-step102-t1、09-step102-t2、10-restored;保存截图、UI XML、原始流式 Logcat 与 crash buffer。其中 STEP-101 T2 正式证据为 05-teardown-t2/stream-complete.log。
本轮未做严格像素对比、长时间性能曲线、bearing/pitch 数值校验、Vulkan、RN 11.5.0、iOS、NavSea SDK 接入或正式发布。
结束前将 FZG 的 Test App 重新冷启动至普通粒子状态 GLOBAL / ACTIVE / EAST / MIX 0% / 256,前台运行、版本仍 13.6.1,设备 Crash Buffer 为空;NavSea 没有被安装或覆盖。
下一阶段:STEP-102 T2 的只读诊断与旧版 .21 对照,确定是否默认 annotation layer 被归入 R1,必要时明确修正场景/索引或源码,并在用户手工 Android 编译后由 RDC 重跑 T1/T2、T4 R-C-R 与 STEP-101 20次 reset。未完成前 Android Native 功能 Gate 保持 PARTIAL。
此报告没有业务代码提交。根目录 recoder_step.md 追加事实,中文阶段记录与 Git 远端状态通过 RDC 单独收尾。

View File

@@ -0,0 +1,78 @@
# STEP-106 STEP-102 T2 Placement 边界修正 — RDC 实施报告 v1
## 1. 当前判定
**源码修正已提交、静态检查通过;Android/Kotlin 编译 NOT RUN、FZG 修正版设备验证 NOT RUN。**
本阶段专门处理 STEP-105 的 T2_TWO_FREE 未达到预期问题。保留原 STEP-105 PARTIAL 状态直至修正版 APK 手工编译和 FZG 定向运行 Gate 全部通过。没有改动核心 Renderer 的 Placement 容错判定。
## 2. 旧版同设备复现
设备 FZG1-2,Android 13,x86_64,ADB 192.168.200.139:5555。
先核对旧、新 APK 的包名相同为 org.maplibre.android.testapp、versionCode 均为14、证书 SHA-256 均为 e3f8fae6451ed6322259d090dd8e8788df554ab25ed89a01c78014f1d5ef8236。旧版文件 SHA-256 为 999f773276b29fffae05c1edc977e19df6cebecd94e4a4095508d0c5e97e07c2。
临时 adb install -r 安装旧版 13.4.1-particle.21,运行:
`adb -s 192.168.200.139:5555 shell am start -W -n org.maplibre.android.testapp/.activity.particle.ParticleCoreLayerValidationActivity --es step102_scenario T2_TWO_FREE`
流式 Logcat 在 tick29/30 记录:R0 placementCapable=false/gate=true/composite/reuse 正常;R1 placementCapable=true/gate=false/actual=live/fallback=static-placement/build0/reuse0。因而确认该现象旧 .21 **同样存在**,不是已证明由官方 Native 13.6.1 升级新引入。
立即 adb install -r 恢复已签名的新 13.6.1,返回 Success;设备已安装 base.apk 的 SHA-256 为 77bc0b238fb476494410a603443030b104d78f97a737307be52460bf5a68f5aa,和 Mac 现有新 APK 完全一致。随后重新启动不带 Extra 的 Particle Core Layer Validation Activity,版本仍 13.6.1。
证据位于 Git 忽略目录 `artifacts/maplibre-particle/step105-fzg-t2-rootcause-20261009/old21-t2-stream.log`,以及先前 `step105-fzg-runtime-20261009/09-step102-t2/stream.log`。
## 3. 可核对的源级原因
13.6.1 的 `src/mln/annotation/annotation_manager.cpp` 中,`AnnotationManager::updateStyle()` 会创建名为 `org.maplibre.annotations.points` 的 Symbol Layer 并追加至 Style。旧 .21 的 `src/mbgl/annotation/annotation_manager.cpp` 保留同样逻辑。
原测试计划为 R0 RETAINED → C0 CONTINUOUS 从 `step102-particle` 开始 → R1 RETAINED 从 `step102-upper` 开始并延伸到 Style 最后一层。测试 fixture 的 T2 `step102-upper` 是 Fill,但 R1 还包含默认追加的 Annotation Symbol。RenderSegment 层级的 `renderSegmentHasPlacementCapableLayer()` 只要在范围内看到 Symbol 即正确地判 true;在 fade/placement 期间 fallback `static-placement` 是安全行为,不能绕过。
这是对代码结构和两版设备现象的一致解释。真实 Style 的完整 `styleLayers` 数组先前没有输出,因此最终边界还要等待修正版新增诊断进一步核对;不得在这里宣称 Pixel/GPU 原因已由运行时完整证明。
## 4. 修改与保护边界
源码分支:`upgrade/android-native-13.6.1-20261009`。
代码提交:`86906c8a6af474a8d064c6f6d7d431e2a7e3efe6` — `test(android): isolate internal annotation symbol from STEP-102 retained ranges`。
两个文件:
1. `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/Step102PlacementFixture.kt`:为 T1、T2 共用计划增加最后一段 CONTINUOUS,startLayerId=`org.maplibre.annotations.points`,使原 R1 只包含自有上层。两场景保持相同边界。若默认 Layer 不存在,现有 Plan resolver 会因 boundary-layer-missing fail-closed,不会错误地忽略该层。
2. `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt`:在 tick8 输出一次 `STEP102_STYLE_LAYER_LAYOUT`,包含 Style Layer id/type/index 与四段 begin/end,用实际测试证据验证上层边界。
没有修改 `src/mln`、`include/mln`、Renderer、Shared Core、NavSea 或 iOS,也未改变任何公开 API/ABI。
新增 C2 使本测试由 R-C-R 变为 R-C-R-C,并可能失去“仅一个 Continuous”的 Particle fast-path 优化条件:这是仅用于证明两个 Retained 在真实内部 Annotation 层存在时安全局部复用的独立测试布局,不能当作生产性能验证或建议宿主一律使用四区段布局。
## 5. 当前检查结果
- `git diff --check` PASS。
- 静态合成 Style 解析:T1 的 R1 为 Symbol,T2 的 R1 为 Fill,Annotation Symbol 位于 C2;模拟边界覆盖完整且无空段,PASS(**非 Kotlin 构建、非真实 Runtime**)。
- Android Gradle/Kotlin Build:NOT RUN(用户手工编译)。
- 更新版 Validation APK:NOT BUILT。
- FZG 新计划的 T1/T2 tick8/130:NOT RUN。
- 其它 ABI / iOS / NavSea / Jest:NOT RUN。
## 6. 用户手工编译与 RDC 验收
Mac 终端:
```bash
cd /Users/tei/dev/MapLibreParticleLab-upgrade-android-1361
export JAVA_HOME=/usr/local/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home
export ANDROID_HOME=/Users/tei/Library/Android/sdk
export ANDROID_SDK_ROOT="$ANDROID_HOME"
export PATH="$JAVA_HOME/bin:$ANDROID_HOME/platform-tools:$PATH"
export MAPLIBRE_VALIDATION_OUT_DIR="$PWD/artifacts/maplibre-particle/step106-t2-fix"
./tools/particle_android_validation/build_validation_apk.sh
```
脚本自带 Gradle `--console=plain`、Native ABI/体积/ZIP 检查。用户编译后由 RDC 确认 Git 源码 SHA、包名、签名、APK SHA,再 adb install -r 到 FZG。
验收应分别运行 STEP-102 `T1_FREE_SYMBOL` 与 `T2_TWO_FREE`(明确传 `--es step102_scenario <SCENARIO>`),在 tick8 和 tick130 读取 `STEP102_STYLE_LAYER_LAYOUT` / `STEP102_SAMPLE` / `STEP102_WINDOW_MARKER`。对 T2 需要 R0 和 R1 同时 placementCapable=false、gate=true、actualExecution=composite;各自 buildDelta=0、invalidationDelta=0、reuseDelta>0;C2 live 且保持 Z-order。T1 的 R1 为 Symbol,应继续按现有安全 gate fallback;检查样本和崩溃日志。之后最小回归 STEP-099 T4、STEP-101 Native reset、QBIN V4 Golden,失败须保留现场。
## 7. Gate
**SOURCE_FIXED / STATIC_PASS / BUILD_PENDING / DEVICE_PENDING**。
任何未编译、未安装新版修正 APK 的设备日志不能被用来宣称 STEP-106 PASS。待 RDC 收到用户手工编译成功的制品后,才进入下一阶段设备验收和最终关闭。

View File

@@ -0,0 +1,100 @@
# STEP-106 STEP-102 T2 Placement 边界修正 — Mac 编译与 FZG 实机回归完成报告 v1
## 一、结论
**STEP-106 CLOSED/PASS(仅 FZG1-2 Android x86_64/OpenGL Test App 的 T2 问题及定向回归)。**
源码保留 RenderSegment Placement 安全规则,仅修复 STEP-102 Test App 的分段计划,将默认附加的 Annotation Symbol 从 R1 Retained 中隔离到末尾 Continuous C2。更新版经 Mac Gradle 打包、FZG 设备安装、两项 STEP-102 场景及 STEP-099/STEP-101/QBIN 回归,验收符合各自目标。
## 二、源码、构建、APK
- 工作区:/Users/tei/dev/MapLibreParticleLab-upgrade-android-1361
- 分支:upgrade/android-native-13.6.1-20261009
- 构建输入 HEAD:23f7b8a4d7b33d3fb63cd8691fc3a2f070936d03;构建时 git_dirty=false。
- 上游 Integration main 已经在本轮开始前同步到 80667d6c343411d03a760425438e3d292f452118。
- 构建:Mac,JDK 17,Android SDK/NDK,x86_64 OpenGL Debug,tools/particle_android_validation/build_validation_apk.sh(Gradle --console=plain);成功退出,BUILD SUCCESS,Kotlin/Java/Native 包装检查通过。
- APK:artifacts/maplibre-particle/step106-t2-fix/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk;66,505,495 bytes;lib/x86_64/libmaplibre.so=39,970,088 bytes。
- APK SHA-256:0ef3b033cd33139db07258745e9cd9d023170ce69767e3f8a5159821776ec9ef。
- 其它 ABI 带入的仅是 Validation 脚本明示允许的 Sentry 库;MapLibre Native 和测试 Custom Layer 是 x86_64。APK ZIP 检查、脚本 ABI/体积检查 PASS。
- 打包日志与 source lock:artifacts/maplibre-particle/step106-t2-fix/build.log、build-info.txt。
## 三、FZG 安装
- 设备:FZG1-2 / Android 13 / ADB 192.168.200.139:5555 / x86_64。
- 包名:org.maplibre.android.testapp;versionName=13.6.1,versionCode=14。
- 新旧证书 SHA-256 一致:e3f8fae6451ed6322259d090dd8e8788df554ab25ed89a01c78014f1d5ef8236。
- 2026-10-09 13:08:17 JST,adb install -r 返回 Success,保留 App 数据。
- 完成后设备内 base.apk SHA-256 与 Mac 完全一致;最后恢复默认页面时再次独立回读核实。
## 四、STEP-102 T1/T2 两窗口验收
窗口均从 STEP102_WINDOW_MARKER baseline tick8 测至 final tick130,期间持续 ADB Logcat 收集。
修正后的实际 Style/Segment 层级日志(两组均在 FZG 真实记录):
- 层 0:step102-background(background)
- 层 1:step102-static-fill(fill)
- 层 2:step102-particle(raster-particle)
- 层 3:step102-upper(T1 为 symbol,T2 为 fill)
- 层 4:org.maplibre.annotations.points(MapLibre 内部 symbol)
四段为 R0 RETAINED[0,2)、C0 CONTINUOUS[2,3)、R1 RETAINED[3,4)、C2 CONTINUOUS[4,5)。
### T1_FREE_SYMBOL — PASS
- R0:placementCapable=false、gate=true、actual=composite,build 1→1、reuse 180→3862(**+3682**)、invalidation 2→2。
- R1:placementCapable=true、gate=false、actual=live,fallback=static-placement,reuse0。这一安全退回是正确行为。
- C2:MapLibre 内部 Annotation Symbol 持续 Live。
- Crash Buffer=0,Style Plan 接受。
### T2_TWO_FREE — PASS,原阻塞解除
- R0:placementCapable=false、gate=true、actual=composite,build 1→1,reuse 195→3878(**+3683**)、invalidation 7→7。
- R1:placementCapable=false、gate=true、actual=composite,build 1→1,reuse 195→3878(**+3683**)、invalidation 7→7。
- C2:内部 Annotation Symbol 继续 Live,不破坏 Placement 安全。
- Crash Buffer=0,Style Plan 接受。
原失败表现(R1 placementCapable=true/fallback=static-placement)不再存在。之前对旧 13.4.1-particle.21 的同设备对照证明原 fixture 也有相同问题,不属于 13.6.1 新增回归。
## 五、定向回归
| 回归 | 实际设备证据 | 结论 |
|---|---|---|
| STEP-099 T4 R-C-R | 动态 GeoJSON 更新 69 次;tick8/130 R0 build 1→1,reuse 193→3868(+3675),invalidation 13→13;crash0 | PASS |
| STEP-101 T1 | request1、destroy enter/return1、nativeReset enter/complete1、新 Renderer ready2、DONE1;crash0 | PASS |
| STEP-101 T2 | request20、destroy enter/return20、nativeReset enter/complete20、Renderer reset enter/complete40、newReady21、DONE1;crash0 | PASS |
| QBIN V4 Golden | clear/color/particle/time=ACCEPTED;T0/T1 均 ACCEPTED_INSERTED,Runtime V4 READY,UI 显示 V4 GOLDEN | PASS(最小烟测) |
| 默认画面恢复 | GLOBAL/ACTIVE/EAST/MIX0%/256,Test App 前台,13.6.1,设备 APK SHA一致,crash0 | PASS |
特别说明:STEP-101 T2 从场景启动前至终态使用 Mac 持续流式 Logcat,避免 Android 环形 Logcat 溢出造成的假性少计数。
## 六、原始证据位置
所有文件保存在 Mac Git 忽略目录:
artifacts/maplibre-particle/step106-t2-fix/
- build.log 与 build-info.txt
- runtime-T1/stream.log、crash.log
- runtime-T2/stream.log、crash.log
- runtime-STEP099-T4/stream.log、crash.log
- runtime-STEP101-T1/stream.log、crash.log
- runtime-STEP101-T2/stream.log、crash.log
- runtime-V4-smoke/load.log、v4.xml
- runtime-restored/window.xml、frame.png、crash.log
未将大型原始 Logcat、截图或 APK 纳入 Git。
## 七、保留边界
本次完成的是升级候选 **Android x86_64/OpenGL Test App** 上的明确阻塞与相关回归。STEP-102 改成 R-C-R-C 的测试布局引入第二 Continuous 区段,不能用它宣称生产环境单 Continuous Particle fast-path 的性能通过。没有修改 Shared Core 的 Renderer/Placement API、NavSea Host 或 iOS。
Android ARM64、RN 11.5.0 接入、iOS Metal、Vulkan、AAR 发行与全链用户验收均仍需独立完成。QB​​IN V4 本轮仅复测 T0/T1 Golden 插入,不声称六个时间控制动作再次全部验证;上轮 STEP-105 的六项回归保持独立历史事实。
本轮没有运行 Jest,没有使用 Codex 模型;编译/安装按用户此轮显式授权由 RDC 在 Mac 执行。
## 八、阶段判定和 Git
**STEP-106 / Test App 修正闭环:CLOSED / PASS。**
代码修正提交 86906c8a6af474a8d064c6f6d7d431e2a7e3efe6,之前根因记录提交 23f7b8a4d7b33d3fb63cd8691fc3a2f070936d03。本轮追加 recoder_step.md 与中文阶段记录,报告提交/远端 Push 以实际 Git 结果为准。正式 particle/main 不修改。

View File

@@ -0,0 +1,623 @@
# UPSTREAM-001 MapLibre 官方升级兼容性架构审计 Codex 完成报告 v1
日期:2026-10-09(JST)。任务基线:`630ec657687bad4200c059bbccbb950d9c6f7ce9`。本报告只交付架构审计、三方干跑与后续建议,没有实施升级。
## 1. 结论摘要
**结论:CONDITIONAL GO。** 可以立项开展隔离迁移;不允许据本报告直接发布升级版本。必须先完成命名空间/接口迁移、Renderer 适配边界与两端单 SDK 收敛,再由 RDC/用户独立构建和运行验收。本次没有编译、运行、设备或发行 PASS。
- Particle 的 Field/Ingress/Binding 具备可移植基础,WeatherColor 与 Particle 为独立 RenderLayer;不需要重写引擎。但 GPU 实现在新增的 `render_particle_validation_layer.cpp` 内,仍依赖 MapLibre 内部 RenderTarget、LayerGroup、Heatmap 顶点结构、PaintParameters 和生命周期,不能把“新增文件”解释成“独立 SDK”。
- 长期维护的主要负担是 `Renderer::Impl` 与 `RenderOrchestrator` 中的缓存调度、Fast Path 输入签名、source/placement 失效及资源所有权。相对初始基线,两个 `.cpp` 分别增加/删除 **632/39**、**505/5** 行,已超过 thin-hook 的含义。
- 官方目标均发生 `mbgl` → `mln` 目录和 C++ 命名空间迁移。标准 dry-run:Android **76** 个冲突路径(31 content + 44 file location + 1 modify/delete);iOS **78** 个(33 + 44 + 1)。两者退出码均 **1:模拟完成且存在冲突**,不是执行失败,也不是升级成功。
- `.21` 相对初始基线共 **765** 个变化路径:680 新增、85 修改。两条官方升级线原路径交叉分别 **72/76**,其中可自动合并的交叉路径为 **40/42**。不能把 85、72、76 或旧说法中的“62 个修改文件”当作文本冲突数。
- 已读官方目标函数定义,确认 `RenderLayer::update()` 新增 `const PaintParameters&`、`PaintParameters` 增加 `renderableSize`、`RenderStaticData::backendSize` 被移除。新增粒子层、Fast Path 和 retained key 的调用必须适配;这是确定的源码接口差异,未执行编译,不能伪称已观察到编译报错。
- RN 11.5.0 必须与 Native 升级分开验收。当前 RN peer/dev/Podspec 锁 11.3.6,Android 插件强制 13.4.1/`.21`,iOS 借用 MLRN 私有 SPM helper。只升 npm 版本会留下版本约束与 API/二进制风险。
## 2. 核对的版本与 SHA
| 项目 | 本次核实结果 | 证据边界 |
| --- | --- | --- |
| 机器 | `Darwin Mac.lan 24.6.0`,x86_64 | `uname -a`,无设备操作 |
| 工作区 | `/Users/tei/dev/MapLibreParticleLab-upstream-audit-20261009` | 独立审计 worktree |
| 分支 / HEAD | `audit/upstream-native-20261009` / `630ec657687bad4200c059bbccbb950d9c6f7ce9` | 起点与收尾一致 |
| 本地远端跟踪引用 | `origin/particle/main` = 同上 SHA | `git ls-remote origin refs/heads/particle/main` 退出 128,DNS 失败;不能宣称实时远端 HEAD 已回读 |
| 初始 Core | `18545ca10d296704b2cba675b182ff2c8da24588` | HEAD 与两条目标各自的 merge-base 均为此 SHA,退出 0 |
| Android 目标 | `c7506d6aff3800e946f89e1a51432fc22d1a6534` | 本地 commit subject 为 Release MapLibre Android 13.6.1;任务书给定 tag 对应关系 |
| iOS 目标 | `01791ad02c1bfe3b22c42a97619b972aba962f82` | 本地 commit subject 为 Release MapLibre iOS 6.31.0;任务书给定 tag 对应关系 |
| 官方目标相互关系 | 两者 merge-base 为 Android 目标 SHA | Android 目标是 iOS 目标祖先;不能把它们当成两个无关 Core |
| 本地 tags | `android-v13.6.1^{commit}`、`ios-v6.31.0^{commit}` 均退出 128 | tag 引用未安装;以完整 commit SHA 复现,不伪称完成 tag 公网认证 |
| 当前 Android / RN | `13.4.1-particle.21` | `platform/android/VERSION`、RN package.json、release manifest |
| 当前 iOS | `6.28.0-particle.21`,Metal,模块 MapLibre | `release/maplibre-particle/ios/release-manifest.json` |
| `.21` 制品源码 | manifest 的 `sourceCommit=16a5d15f164dc93d220e3fac62de66a9c9527ccc` | 与审计 HEAD/发行记录提交是不同概念;未重新下载或核验制品 |
| 官方 RN | v11.5.0,release 页面短 SHA `059f46b`,2026-10-04 | 没有取得完整 RN tag checkout,不能声称审查了全部 RN 11.5.0 源码 |
| Integration | Mac 现存 `/Users/tei/dev/navsea-particle-integration` HEAD=`80667d6c343411d03a760425438e3d292f452118` | 只读 README/规则/COORD-005/C-001/C-002/状态;未访问 Linux 文件系统或修改合同 |
| Git / submodule | Git 2.54.0;非 shallow;39 个 submodule 均未初始化(`-`) | submodule status 退出 0;不构成构建环境就绪 |
根目录总则当前路线 v2 仍描述 `.3`,Integration 部分状态仍是旧开发状态,STEP-094 设计仍描述 source 全局失效;以 `.21` 代码与后续 STEP-100/102 实现事实为准,不回写历史文档。已阅读 STEP-098~102 记录及 STEP-094 设计;**本审计基线的 docs 中没有 STEP-103 文件**,因此不把其他 dirty worktree 或临时执行日志中的 STEP-103 当成 `.21` 已有能力。
## 3. 方法和数据可信度
### 3.1 执行范围
读取根规则、项目规范、四份有效总则、架构设计、任务书、相关 Step、实际源码与 base→HEAD diff。未启动子代理、第二个 Codex、后台构建、Jest、Gradle/APK/AAR、Xcode、ADB 或设备步骤。未真实 merge/rebase、未变更分支/index、未修改源码/依赖/构建脚本/Integration。任务书允许的两份文档中,本轮仅新增本报告,任务书保持原样。
证据临时目录:`/private/tmp/upstream-001-audit-20261009/`。Git object 写入也隔离于其 `objects/`,原共享对象库仅作只读 alternate。临时目录不是项目交付文件,RDC 应连同 JSONL/stdout/stderr 归档;本报告已嵌入冲突全表、命令与关键哈希,不依赖临时目录才能理解结论。
### 3.2 失败与恢复过程
| 操作 | 实际退出码 | 事实 |
| --- | --- | --- |
| 三个 `git merge-base HEAD <base/Android/iOS>` | 0 | 均为初始 Core SHA |
| 初次 `git diff --name-status base <Android/iOS>` | 各 128 | promisor 补取 `3354d3daaf97803cc42e43758177cb126a7f1671` 时 github.com DNS 失败 |
| 初次标准 `git merge-tree --write-tree --messages HEAD <目标>` | 各 128 | promisor 补取 `0e98150849597096c3fe2f1128b6e89884dcabdb` 时 DNS 失败;stdout 为空,不能计作零冲突 |
| 原对象目录、关闭 rename 的诊断干跑 | 各 128 | `unable to create temporary file: Operation not permitted` / `failure to merge` |
| `git diff --no-renames --name-status base <目标>` | 各 0 | 可得原路径交叉统计,但把移动表示为 D+A |
| 临时可写对象目录、标准 rename 干跑 | 各 1 | 完成,产生 tree 与冲突清单;未要求越过权限或修改原共享对象目录 |
| 同一临时对象目录标准干跑复跑 | 各 1 | 两次 stdout 字节完全一致,tree SHA 相同,stderr 为空 |
| 临时对象目录普通 `git diff --name-status` | 各 0 | rename-aware 清单取得成功 |
| 临时对象目录关闭 rename 的对照干跑 | 各 1 | Android 63、iOS 64 个路径;人为禁用目录迁移识别,**不是主结论** |
| 远端 HEAD / 本地 tag 验证 | 128 | 分别为 DNS 失败 / 本地引用不存在,尚待 RDC |
失败原始日志保留,没有把后一次完成倒写成首轮成功。成功使用的环境覆盖没有改 Git 配置或合并算法;没有使用 `-Xours`、`-Xtheirs` 或关闭冲突检测。没有证据证明网络后来恢复,不能从本地干跑成功推导网络已通。另有探索性旧路径读取、缺失测试文件名及 glob 查询失败,随后按实际新路径/文件定位;这些不是编译或测试失败。
### 3.3 统计定义
1. footprint:base→HEAD 的 Git 路径与 numstat,文档/fixture/测试/构建均分开说明。
2. 原路径交叉:关闭 rename 时两边变更路径集合的交集。Android 23 M+49 D=72;iOS 27 M+49 D=76。49 D 中 48 被 Git 识别为 rename,shader_manifest 为 modify/delete;不是 49 个独立算法冲突。
3. 冲突路径:标准 merge-tree stdout 第一段 stage 记录的路径去重;不把 stage 1/2/3 三条算三文件,也不靠 `Auto-merging` 文本计数。冲突类型另由 `CONFLICT (...)` 消息统计,恰与本轮路径数一致。
4. 自动合并交叉路径:交叉集合中,旧路径及其 `mbgl→mln` 对应路径均不在 unmerged 清单者。它仅说明文本可合并;不代表符号、ABI、shader、资源或视觉正确。
5. 行号默认是审计 HEAD。标注“目标”的 `src/mln/...` 行号来自指定官方 commit blob;审查用 namespace 归一 diff 只写临时文件,**未用归一文本作为正式干跑输入**。
## 4. 两条 Native 升级线冲突统计与具体文件
| 指标 | Android 13.6.1 | iOS 6.31.0 |
| --- | ---: | ---: |
| 官方 diff(rename-aware)路径数 | 2196 | 2250 |
| A / M / D / R | 91 / 709 / 27 / 1369 | 117 / 719 / 69 / 1345 |
| 官方 diff(no-renames)A / M / D | 1460 / 709 / 1396 | 1462 / 719 / 1414 |
| 与我方原路径交叉 | 72 | 76 |
| 交叉中冲突的官方既有文件 | 32 | 34 |
| 交叉中自动合并的官方既有文件 | 40 | 42 |
| 新增扩展的 file-location 冲突 | 44 | 44 |
| 全部 unmerged 路径 | **76** | **78** |
| content / file location / modify-delete | **31 / 44 / 1** | **33 / 44 / 1** |
| stage 条目数(不可当文件数) | 139 | 145 |
| 标准 dry-run 退出码 | **1** | **1** |
| 结果 tree | `9509597174b70c9eede21d6900b6f54fb092fefa` | `ae31097f803a49be28c27eca6291252baebfa4c0` |
iOS 比 Android 多出的文本冲突是 `platform/darwin/src/MLNStyleLayerManager.mm` 和 `src/mln/shaders/shader_source.cpp`。虽然目标名标注某个平台,比较对象是整个 Native 仓库,Android 干跑同样可能报告 iOS 文件冲突。
完整冲突路径见附录 A;全部 85 个官方修改文件及交叉标记见附录 B。自动合并不能豁免审查,尤其包括 `render_layer.hpp`、`paint_parameters.*`、`render_target.*`、`gfx/context.hpp`、`mtl/offscreen_texture.cpp`、`mtl/texture2d.cpp`。
### 4.1 目标源码证据与合并含义
| 位置 / 函数 | 已核实差异 | 迁移处理 |
| --- | --- | --- |
| 目标 `src/mln/renderer/render_layer.hpp:159`,`RenderLayer::update` | 新增 `const PaintParameters&` 参数;该官方文件本次文本自动合并 | 同步 Particle/WeatherColor override、声明、普通/hidden cleanup/Fast Path 调用;不能只修改 factory |
| 目标 `src/mln/renderer/renderer_impl.cpp:184`、`:224`、`:302` | 使用 `renderableSize` 构造 PaintParameters,并以其作为 UBO world size | retained viewport/key、scissor、target size 与主画布统一取当前 frame 数据 |
| 目标 `src/mln/renderer/render_static_data.hpp` | 删除 `backendSize`,增加 symbol geometry 方法 | `.21` renderer_impl.cpp:745、:766 等旧引用需适配;不能恢复旧字段掩盖所有权变化 |
| 目标 `src/mln/renderer/render_orchestrator.cpp`,`updateLayers` / `onSymbolError` | 传递新 PaintParameters,并增加 symbol error 转发 | 外提适配器须保留官方 observer 行为,包括 `.21` 自有的 source revision 和 teardown |
| 目标 `src/mln/renderer/render_source.cpp` / `include/mln/style/types.hpp` | 新增 CustomMVTVector 与 source factory 分支 | 合并保留官方新增 source 与自定义 RasterArray,source dependency 不认识的新类型需 fail closed |
| 目标 `src/mln/renderer/render_target.cpp`、`include/mln/gfx/context.hpp` | 审查的归一 diff 无其它差异;本地追加 isRenderable / depth-stencil 接口 | 可保留薄能力接口,仍做 GL/Metal clear、bind、恢复验证 |
| 目标 `src/mln/mtl/render_pass.cpp` | 保存 commandBuffer,并修改 encoder 构造附近代码 | 合并自有 clear/store 与 vertex texture 逻辑时同时保留官方 commandBuffer 生命周期 |
| 目标 `src/mln/mtl/offscreen_texture.cpp` | 官方也已把基类构造参数 `size` 修正为 `size_` | 删除重复维护的修复补丁;保留并单独审查自有 stencil/renderability 扩展 |
| 两条目标 shader_manifest | Git 不识别为 rename,旧头删除与我方追加冲突 | 按新 shader manifest/生成机制注册扩展,不能把旧头直接并排保留 |
44 个位置冲突解决为“搬到 mln”后,文件内容仍可能保留 `namespace mbgl` / `<mbgl/...>`。标准结果 tree 中还保留 **25 个 `/mbgl/` 路径**:24 个完全新增的 particle 子树文件及旧 shader_manifest。已直接读取模拟结果,确认搬到 `src/mln/renderer/layers/render_raster_particle_layer.hpp` 的内容仍是旧 namespace/include 和旧 update 签名。因此“解决冲突标记”不是完整升级;新增纯模块也需要机械命名迁移。
## 5. Particle 耦合清单
### 5.1 可保留的独立模块与实际边界
| 代码证据 | 独立性判断 | 适配重点 |
| --- | --- | --- |
| `src/mbgl/particle/field/field_runtime.cpp:173`,FieldSeries::submit;`:223`,resolve | Shared Core 内按 validTime 排序、候选集合原子校验后 swap;exact 时 T0/T1 指向同帧;插值检查批次身份;不依赖 renderer | 迁移 namespace/include,保留 C-002 八帧、拒绝零淘汰与单帧真实时刻语义 |
| `src/mbgl/particle/ingress/qbin_v2_decoder.cpp:75`,EncodedFieldIngress::decodeAndValidate | 字节解码→profile 校验→decoded frame,在 Core;未把 HTTP/provider 放进 renderer | 二进制/数值/错误枚举一致性;不得用升级机会改变 QBIN 公共契约 |
| `src/mbgl/style/sources/raster_array_source.cpp:431`,submitEncodedField | host metadata/contract/raw bytes→Ingress→Store→refreshV4RendererState;不在提交中偷偷改目标时间 | Source::Impl/observer 桥是版本适配层;建议把 Store/Projection 协调留在专用 runtime,不继续扩充官方 Map |
| `src/mbgl/renderer/layers/render_particle_validation_layer.cpp:1175`,prepare | 只消费 RenderRasterArraySource projection,绑定 T0/T1/mix;没有平台专属引擎 | 此 renderer 源文件实际实现正式 RenderRasterParticleLayer,不能按文件名把它当可删除测试 |
| 同文件 `ParticleGpuResources:320`、update:1211、GPU tweaker:524 | state/trail A/B、shader、texture、timeline 与 context 生命周期集中在新增文件;使用 gfx 资源 | 2136 行集成了 fixture/正式路径、GPU pass、时钟和诊断;P1 外提资源与 pass executor,保持 engine 一套 |
| `render_weather_color_layer.cpp:163`、prepare:197、update:229 | 与 Particle 有独立 class/resources,消费同一 projection;scalar/vector magnitude 分离 | 复用 `HeatmapTextureLayoutVertex`/RenderStaticData geometry(:274)是内部布局耦合,宜专用 quad adapter |
| `render_particle_validation_layer.cpp:1141`、:1157、:1223 | layerRemoved 移除注册 target;contextDestroyed 标志;清空 field 时清 drawable、解除 target/tweaker/resource 环 | 跨版本必须保持 render-thread 销毁;不能用任意 UI 线程 delete 或通用 shared_ptr 推断无环 |
| `src/mbgl/layermanager/raster_particle_layer_factory.cpp:19` | 创建专用 RenderRasterParticleLayer;default/Android/Darwin 仅注册类型 | factory 注册、SourceType、source switch 是真正应保留的薄 hook |
本次口径仅取 `src/` 与 `include/` 下所有 base→HEAD 变化:68 个新增文件、11438 新增行;47 个官方既有文件、2035 新增行/133 删除行。新增文件承载新增行比例 **84.90%**,不是目标“约 95%”;它是可复现的近似工程指标,不是全部平台/测试代码比例,更不能衡量语义独立性。附录 C 列出 68 个新增 Core 文件;另外 612 个新增路径主要为文档、平台/测试、RN、fixture、集成与工具,不可拿它们稀释核心耦合。
### 5.2 真正 thin hook、可外提和深耦合
- **不可避免的官方接入 hook**:LayerManager 三平台注册、SourceType/RenderSource factory、shader registry/enum/清单、repaint/hidden-source-cleanup 扩展点、Map runtime state 传递、PaintParameters target 边界重置。目标是窄调用和能力描述,不在 hook 中展开业务策略。
- **可外提的官方修改**:`style/conversion/source.cpp:206` 的 103 行 RasterArray parser 应移到专用 converter;`map/map_impl.cpp:115` 的 RasterArray 类型扫描/forecast tick 应由 source frame participant 适配器承担;JNI `native_map_view.cpp:1192` 的 field/layer 控制实现、MapLibreMap/MLNMapView diagnostics 可委托独立 facade。公开方法与生命周期所有者仍留在正式 SDK,不能以 global map registry 替代。
- **深耦合必须分步重构**:Renderer::Impl 直接组织段 key/revision/cache 与主 buffer;RenderOrchestrator 同时管理 topology、dependency、source readiness、placement 与快路径;MTL Texture2D::bind 对所有纹理镜像 vertex binding,影响所有官方层,宜改为 shader-stage-aware backend 能力。
- **通用 backend 修复应独立维护/争取上游化**:offscreen depth/stencil、clear/store、attachment-aware pipeline key。这些不能全塞入 Particle 私有 adapter,否则普通地图 target 仍可能不一致;保留在 gfx 的窄语义接口,并隔离成单独补丁与回归项。
- **Vulkan 尚不能宣称等价**:现有新增 shader 源及注册明确覆盖 GL/Metal;在 `src/mbgl/vulkan`、`include/mbgl/shaders/vulkan`、`cmake/vulkan.cmake` 未找到 ParticleGpuValidation/RetainedUnderlayComposite 注册。context 的 override 补齐不等于 Vulkan 粒子功能已实现。后续必须验证能力返回/fail-closed 与专用实现,不能继承早期普通 Vulkan 构建 PASS。
## 6. RenderSegment 耦合清单
| 主题 | `.21` 已实现事实 | 未来兼容约束 / 验收 |
| --- | --- | --- |
| 单一 topology | `render_segment_plan.hpp:32` 解析 explicit/legacy/continuous-range;`:160` 检查完整覆盖;全局 Style index 不重新编号 | boundary 删除、重排、hidden、新插层、非法 JSON 均重解;不能复用旧合法 cache 掩盖非法 plan |
| source→segment | `include/mbgl/renderer/render_segment.hpp:50` 从 Style metadata 统一推导依赖;`:114` RevisionBook;orchestrator:1172 查询 source loaded/fading | shared source 使多个段失效;无 source 的 background 不造依赖;custom/unknown/missing fail closed;remove/recreate 同 id 保留 revision 身份 |
| 分层失效 | renderer_impl:631–676 合并 source revision、layer fingerprint、pixelRatio,逐段 Build/Reuse/Fallback;orchestrator:260 保留全局 revision | source/tile/feature-state 走 source epoch;image/glyph/style/context 等共享事件走 global epoch;不能漏掉新的官方 mutation 入口 |
| loaded 与局部复用 | orchestrator:698 仍是 `styleLoaded && isLoaded()`;full CPU segment gate 用自己的 dependency/readiness | unrelated unloaded source 可阻塞 global loaded/快路径,不能据此禁用无关段的局部复用;也不能改 loaded 语义造 PASS |
| placement | `render_segment.hpp:75` 结构性 symbol 能力;renderer_impl:645–656 按段 gate | 无 symbol 段可在别段 placement 活跃时复用;含 symbol 段仍受 changed/fade/transition 约束;不是 segment-local placement 算法 |
| Fast Path | renderer.cpp:47 尝试快路径;:51 在全帧前释放 prepared tree;renderer_impl:199 起匹配签名/全局内容/拓扑/cache/稳定性;particle_fast_path.hpp:97 逐项 gate | singleContinuous 限制保持;sources/layers/images/light/font 等身份或参数变化必须回全帧;新增上游输入必须纳入签名,不能只检查 camera |
| 全局限制 | orchestrator:1155 的 retainedRangeIsStable 检查所有 source fading;快路径 dynamic state 含 pending/light/placement/非粒子 repaint/annotation | STEP-100/102 的 full CPU 局部复用不等于快路径局部化;多 Continuous 正常执行仍需 full CPU |
| Style / pass 顺序 | renderer_impl:805 构建 retained 段;:880/:904 opaque reverse/translucent forward;保留 layerGroup 原 ordinal 与全局 depthRange;:1005 顺序执行 composite/live | 半透明 fill/line/symbol、跨段遮挡与自定义层必须视觉对照;3D、debug、custom、legacy 等保守退回 live,不可简单按段局部重编号 |
| Top / Bottom | renderer_impl:506–524 按 segmentIndex 创建独立 cache;遇到首个 Continuous 后用 Top 兼容 role;cache:310 透明 clear,:286 禁 depth composite | Top/Bottom 是旧诊断兼容角色,不是只有两张 texture;多段以 segment diagnostics 为准,不能复用 Bottom texture 充当 Top |
| Context / target | paint_parameters.cpp:111 beginRenderTarget 清 stencil ID 和 tile mask;cache:246 depth+stencil offscreen、:310 clear、:320 present | 新目标 renderableSize、Metal attachment 格式/commandBuffer 与 GL FBO/stencil 恢复都要测;context generation 变化不得复用旧 texture |
| 所有权 / teardown | orchestrator:180–209 两次 tagged drain、中间 detach observer 并销毁 sources;render_source.cpp:74 nullObserver;renderer prepared tree 在替换前丢弃引用 | tagged drain 不等于排空独立 render jobs;reset 循环、source cancel 回调、style reload、后台恢复必须独立验证 |
建议内部抽出 `SegmentPlanner/DependencyTracker`(不持 GPU)、`RetainedSegmentExecutor`(持 cache、执行顺序与 target scope)、`FrameReuseAdapter`(官方 Update/Paint/Placement 输入映射)、`ParticleGpuResources/PassExecutor`(动画资源)。这些是建议职责,不是本轮新建 API。官方文件只传入明确 snapshot/事件并调用;资源生命周期和 Style 顺序必须保留在 renderer 所有权范围,不能外提成第二个 renderer。
## 7. RN 11.5.0 适配风险
### 7.1 官方信息与未取得材料
[RN v11.4.0 官方 release](https://github.com/maplibre/maplibre-react-native/releases/tag/v11.4.0) 明确升级 Android Native 13.6.1、iOS Native 6.31.0;[官方 release 列表](https://github.com/maplibre/maplibre-react-native/releases) 记载 v11.4.1 的 iOS SPM target 挂接修复;[v11.5.0 release](https://github.com/maplibre/maplibre-react-native/releases/tag/v11.5.0) 增加 feature state API。这是 release 证据,不是对 11.5.0 每个构建文件的逐行认证。
尝试 raw/GitHub 的 v11.5.0 android/build.gradle、Podspec 及 packages 子路径,返回 404 或 Cache miss,**未取得完整 RN 目标源码**。因此其私有 helper 签名、组件内部布局、Gradle property 名称是否保持均列为待核实,不伪造兼容结论。
### 7.2 当前包已核对的问题
| 文件与证据 | 风险与建议 |
| --- | --- |
| `packages/maplibre-particle-rn/package.json:34` / devDependencies | MLRN peer/dev 均精确 11.3.6;迁移时与 consumer lockfile 一起更新,经兼容 Gate 后锁定新版本,不能用宽泛 range 掩盖不支持 |
| `app.plugin.js:22–23` | 已有 marker 就提前返回;项目升级若保留旧生成块,可能继续锁旧 `.21`。建议版本化且幂等替换受管块,验证重复 prebuild;本轮没有运行 prebuild |
| `app.plugin.js:23` / `android/build.gradle:17` | substitution 只覆盖 `org.maplibre.gl:android-sdk-opengl`;另直接 implementation 自有 `.21`;nativeVersion=13.4.1、variant=opengl | 必须确认 MLRN 11.5 请求仍被替换,debug/release 每 configuration 仅一个 SDK、每 ABI 一个 libmaplibre.so;若官方改坐标/variant,旧替换可能漏掉。强制旧 SDK 也可能使 RN 新 API 缺失 |
| `MapLibreParticleRN.podspec:10–34` / `:47` | 依赖 MLRN 11.3.6,借 `$MLRN._add_spm_to_target` 与 `$MLRN_SPM_SPEC`,属于私有 helper 耦合 | 检查 v11.4.1 SPM 修复后 helper 的参数/调用顺序与 targets;只复用一套 MapLibre product,不另外加官方 Pod/XCFramework |
| `ios/WeatherRuntimeBridge.mm:103–118` | fresh Fabric registry→`MLRNMapViewComponentView`→contentView→`MLRNMapView`/MLNMapView;按类名识别内部组件 | 新 RN 组件名/包装结构变化即失效;用单独 MLRN adapter 集中适配,保留 stale tag/wrong tag 拒绝 |
| `android/.../WeatherRuntimeBridgeModule.kt:363–369` | Fabric resolveView、强类型 MLRNMapView、view.mapLibreMap | 核实 11.5 Kotlin 类/属性/可见性;attach owner 仍跟随 concrete MapLibreMap,不能用进程全局表绕过销毁 |
| `src/NativeWeatherRuntimeBridge.ts` / `RendererRuntime.ts` / 两端 bridge | typed TS→schema JSON→platform→Core;V4 submit/time、attach/detach、diagnostics | 维持公开签名/错误、JS safe integer 与平台 uint64 边界;codegen 构建由 RDC 后续执行 |
| `.21` Core orchestrator:1015–1046 | set/removeFeatureState 已推进 source revision | RN 11.5 新 feature-state 入口需证明实际命中这一链;不能仅验证方法调用成功,必须观察依赖段刷新与无关段 reuse |
功能验证必须覆盖:1)单 SDK 依赖树和制品身份;2)Fabric 新旧 map attach/detach、style reload、销毁后调用、20 次 reset;3)V4 单帧向量持续运动、标量无粒子、双帧 mix、八帧滚动、跨批次 unavailable、坏帧零副作用;4)RenderSegment R-C-R/C-R/R-C/多段、连续与 retained 中 feature-state/GeoJSON 更新;5)相机/pitch/wrap/resize、mask、透明度/颜色定量;6)GL 与 iOS Metal context loss/后台恢复和内存趋势。Android/iOS 各自提交日志/截图/计数,不互相替代。
## 8. 改造优先级矩阵
工作量为相对估计:S=局部少量文件,M=跨数个接口/模块,L=跨执行链和平台 Gate;不是承诺工期。P0 指迁移正确性前置,P1 指长期维护治理,P2 指后续优化。
| 级别 / 项目 | 路径与当前耦合证据 | 方案 | 风险 / 工作量 | 验收标准 | Android / iOS |
| --- | --- | --- | --- | --- | --- |
| P0 命名与构建移植 | 68 新增 Core 文件、44 location 冲突、24 particle 文件未随目录移走;附录 A/B/C | 独立机械迁移补丁处理路径/namespace/include/清单;删旧 shader_manifest 接法 | 漏引用/并存 namespace,M | 全部自定义符号单 namespace,生成清单一致;无旧 include、缺失 source 或重复 shader | 共用 Core,双端 |
| P0 帧接口适配 | render_layer.hpp 新 PaintParameters;renderer_impl 旧 backendSize;新增粒子 override | 建立 FrameReuseAdapter,先接全帧,再接 Fast Path;不恢复被官方移除状态 | 错 viewport/override/失效输入,M | 同帧 size/matrix 一致;普通/hidden/Fast 三入口完整;编译与 resize Gate | GL/Vulkan/Metal |
| P0 执行边界 | renderer_impl.cpp:501–1020 +632/-39,orchestrator.cpp +505/-5 | 先外提 segment 决策/执行与官方输入映射,行为保持;策略不继续嵌入官方主函数 | Z-order、placement、stale cache,L | retained on/off 图像对照;global index/pass 顺序;source/placement/资源失败逐项验证 | 双端必测 |
| P0 offscreen / MTL 生命周期 | gfx context overload、paint target reset、mtl render_pass clear 与新 commandBuffer | 窄 offscreen descriptor/target scope,保留官方所有权并独立迁移通用修复 | stencil 污染/格式错配/释放次序,M | GL stencil;Metal clear depth/stencil、pipeline format、device/simulator、context reset | Android GL;iOS/Metal |
| P0 单 SDK 收敛 | RN package/plugin/podspec 与 `.21` implementation | 同时更新支持锁、替换规则、SPM helper adapter 与发行 manifest | 双二进制/旧 API/生成块残留,M | Gradle/Pods/SPM 仅一个 Native;Symbols/headers 来自同一源码 | 两端分别验收 |
| P0 回归证据 | STEP-102 未完整运行验收即纳入 V21;STEP-103 本基线无文件 | 冻结旧版作对照;建立升级候选完整 Gate | 继承未知行为,M | 独立日志、同源制品 SHA、真实设备结果;无测试豁免冒充 PASS | 各平台明确状态 |
| P1 source dependency | render_segment.hpp:50 / RevisionBook;orchestrator:242/1172 | 从 diagnostics DTO 分离 typed dependency snapshot/event adapter,保持 shared/global/unknown | 新 source/feature-state 漏失效,M | 同 source 多段刷新,无关段 reuse,remove/recreate、unknown fail closed | 共用 |
| P1 GPU 模块外提 | render_particle_validation_layer.cpp 2136 行,Heatmap geometry 与资源环 | 专用 quad/资源/pass/lifecycle 模块,RenderLayer 只转发 | 跨 pass commit 与清理退化,M | 同样 state/trail generation、同帧推进一次、clear/reset 无泄漏 | GL/Metal;Vulkan另 Gate |
| P1 backend stage 抽象 | mtl/texture2d.cpp:262 全纹理镜像 vertex bind | 用 shader-stage/binding metadata 描述需要的 stage,通用修复尽量上游化 | 影响普通层 binding/cache,M | 既有地图 shader 与 Particle 都正确;无无效 stage 绑定 | iOS/Metal 主,Core接口共用 |
| P1 公共桥减重 | native_map_view.cpp:1192、MapLibreMap.java、MLNMapView.mm | 专用 Native facade/adapter 持实现,官方类保留方法与 map 生命周期 hook | JNI/ObjC API/销毁顺序,M | 方法签名不变,错误一致,stale tag/destroy callback 验证 | 两端 |
| P1 parser / 时钟薄接入 | style/conversion/source.cpp:206;map_impl.cpp:115 | RasterArray converter 外提;source frame participant tick | clock 改变错误/数据所有权,S–M | submit 不改目标时间;cadence/pause/background 正确 | 共用 |
| P1 Vulkan 能力闭环 | Vulkan 缺本任务 shader 注册证据 | 确认能力与 fail-closed;专用 backend 实现另立项 | 不支持被误报支持,L | Android Vulkan 粒子与 retained 实测;不能只编译普通地图 | Android Vulkan |
| P2 多 Continuous Fast Path | singleContinuousSegment / 全局 signature | 先保留 full CPU;待依赖模型和预算稳定再单独设计 | 跨段 placement/顺序/上传遗漏,L | 多段对照、source mutation/placement 全组合,必要时 RFC | 共用 |
| P2 footprint 预算与上游补丁 | 85 官方修改、47 Core 原文件 | 建 ledger、自动审计、补丁主题拆分、删除已上游化修复 | 日常维护成本,S | 每版本 diff/冲突/功能 gate 有独立可复现证据 | 共用 |
不是所有 P1 都应阻塞首个候选。Field/Ingress/Binding、专用 layer/factory 和窄注册点可以在机械迁移后直接移植;Renderer 调度与新帧接口、offscreen 生命周期、单 SDK 必须先界定并验证。不得先做多段高级优化再补基础升级验收。
## 9. 阶段性迁移与验收
### Gate 0:冻结与可回滚准备
RDC 回读 origin HEAD,认证两个官方 tag→SHA,归档 `.21` 的源码/manifest/制品;取得 RN 11.5.0 完整源码、11.3.6→11.5.0 diff。统一选择一个 Shared Core 候选:iOS 目标包含 Android 目标,但能否由该 commit 同时发行两端须构建验证,不能据祖先关系直接定版。本轮只给建议,不创建升级分支。
回滚点:保留 `.21` 不可变制品与 consumer 锁。任何 Gate 失败,停止推进;候选分支可丢弃,生产分支/旧制品不覆盖。需运行回退时可用既有 map-scoped retained enable 开关关闭优化,另保留完整旧版本回退;不把关闭功能当作新版本通过。
### Gate 1:行为保持的边界整理
在旧基线单独重构 segment executor / frame adapter / target scope;保持 C-001/C-002、Style 顺序与既有 fail-closed,不顺带提高 Fast Path 支持范围。RDC 完成旧基线等价回归后冻结此检查点。若无法保持行为,停下修复,不混进 namespace 迁移使定位困难。
### Gate 2:机械迁移与 Native 三方整合
从选定官方目标在隔离候选中按主题移植:Core/字段→类型注册→shader/backend→Renderer adapter→平台 bridge→测试/发行清单。先统一 mln namespace/include,适配 PaintParameters/renderableSize、source enum、symbol observer;处理 shader_manifest 删除和官方已有修复。保留官方新功能,禁止整文件选 ours/theirs。
RDC 记录每主题冲突解决、构建日志和 patch footprint;无冲突标记、无未注册新 shader/重复 namespace 后才进入功能 Gate。Android 和 iOS release tag 是同仓库不同发布点,不建立两套 Core fork。
### Gate 3:分 backend / 平台验证
由 RDC 在目标版本实际支持的 CMake/Bazel target 上配置/编译;本次没有替它运行。可复用旧仓库文档中的 host 路径仅作候选,目标改名后应以配置输出确定 runner,不能硬称 `mbgl-test-runner` 必然保留。已有 runner 的定向过滤器如下(由 RDC 设置真实路径):
```bash
"$UPSTREAM_AUDIT_TEST_RUNNER" --gtest_filter='Particle*.*:Source.RasterArray*:Retained*.*:ContinuousLayerRange.*:RenderSegment*.*:RenderOrchestratorTeardown.*'
```
该变量必须指向同候选源码构建的测试程序。额外执行官方基础地图回归。Android Gradle/APK/安装/ADB/实体机仍按用户手工规则;iOS/Metal host 编译不能替代 iOS 设备。GL、Vulkan、Metal 分别记录结果,不以某 backend 通过覆盖其它 backend。
硬门槛:R-C-R 动态 source 只刷依赖段;无关 source 永久 unloaded 时局部 retained 仍可复用;含 symbol / 无 symbol 的 placement 场景正确;global live fallback 不错过图层;feature-state set/remove 使依赖段更新;camera/pitch/wrap/resize/context reset 无旧纹理;20 次 teardown、clear/reload 无回调到已销毁对象;单帧/八帧 C-002 同两端语义;定量 WeatherColor 和统一 mask 不退化。记录实际 build/reuse/invalidation、actualExecution、sourceRevision、fastPath miss reason、日志与图像对照。
### Gate 4:RN 与发行
确认 Android 每个 debug/release dependency graph 中仅自有一个 Native SDK;由用户手工 Gradle 验证 dependencyInsight 和 APK so 唯一性。iOS 检查 Podfile.lock、Package.resolved、Pods/宿主 target 的同一个 MapLibre SPM product 与私有 helper 兼容。两端 Fabric bridge 功能通过后,再由授权发行任务升版本、build/publish/readback/finalize;不覆盖 `.21`,manifest 绑定同一源码。
必须回 Integration RFC/Contract 的情形:公共 API/返回值/错误、attach/detach 与资源所有权、QBIN/profile/time/window/mask 语义、Host/Native 责任边界、Android/iOS 公共行为产生分叉;或希望把多 Continuous/placement 新语义公开为能力。纯 namespace、内部模块外提和行为保持适配不自动要求新 Contract。
### 长期跟踪与 patch footprint budget(建议,未修改总则)
每个官方 release 单独审计 SHA/merge-base、rename-aware diff、三方冲突和自动合并后的行为清单。维护四组补丁:独立扩展、注册 hook、通用 backend 修复、平台/发行;每组有 owner、原因、上游替代情况和回归场景。不能只重放历史 Step 提交而不核对最终 diff。
建议预算:新增功能中 ≥95% 实现新增行进入专用模块(排除文档/fixture/generated/tests 的分母);官方函数内 hook 原则上一个调用、每处目标 ≤10 行;超过 30 行策略逻辑须评审外提;一次功能新增官方接点 >3 个须解释;本轮先让 47 个 Core 既有文件的修改规模不增长,重点把 renderer_impl/orchestrator 的新增策略行量减少至少一半,最终数字由行为保持 Gate 核定。预算是预警,不可为达数字拆碎代码或把复杂性藏进宏。
长期收益:把下一次官方 renderer 签名变化限制到 adapter/窄 hook;Field/GPU 逻辑继续复用。仍需承担 backend 与 Fabric 私有接口回归费用;“新增文件比例高”无法消除 API/ABI 和行为升级成本。
## 10. 阻塞和未知
- 本次没有实际编译/测试/设备/发布,所有升级运行验收为 **NOT RUN**;静态审计与 merge-tree 不等于功能 PASS。
- RN 11.5.0 目标源码未完整取得,私有 SPM helper/Fabric 细节待 RDC 审核;本地 Native tags 与实时 origin HEAD 未认证。
- `.21` STEP-102 记录明确以源码审查接受部分未跑 Gate 后发行;本轮不将其补写为运行 PASS。STEP-103 不在冻结基线,不能用未合入实现支持结论。
- Vulkan 粒子/retained 注册缺口、Metal vertex texture 全局绑定、资源环与 target clear 的跨设备行为需专项验证;没有测量内存/FPS,不给性能承诺。
- 完整 target source 不是全部逐文件审完;重点读取了本报告所列函数与自动合并热点,未下载到的 RN 文件已单列。单次三方模拟只能描述指定 SHA,不能预测所有未来上游版本。
- Git 收尾待 RDC 验收。未 commit/push,未收到执行器的最终 Git 回执。
## 11. 实际模型、退出状态与文件修改清单
实际配置来自当前会话 JSONL,不由默认 config.toml 或自称推断:
```text
文件:/Users/tei/.codex/sessions/2026/10/09/rollout-2026-10-09T08-48-37-01a11deb-3653-73b2-8b2d-43f0e59ccc3a.jsonl
第 1 行:session_meta
id=01a11deb-3653-73b2-8b2d-43f0e59ccc3a
cwd=/Users/tei/dev/MapLibreParticleLab-upstream-audit-20261009
originator=codex_exec; cli_version=0.161.0; source=exec; model_provider=openai
第 8 行:turn_context,时间 2026-10-08T23:48:46.536Z
model=gpt-6-astra
effort=high
collaboration_mode.settings.model=gpt-6-astra
collaboration_mode.settings.reasoning_effort=high
环境 CODEX_THREAD_ID 与上述 id 一致。
```
模型 Gate 符合 GPT-6 Astra High;未切换模型或推理档位。**本 Codex 执行器进程最终退出码在本轮结束前无法由本进程自证,待 RDC 从外层执行器回执填写。** 不把任意 shell 的 exit 0 或本报告写入成功当成 Codex 全任务退出 0;已观测的 dry-run exit 1、失败 exit 128 和检查退出状态见本报告及末尾收尾记录。
实际项目修改:只新增 `docs/报告/UPSTREAM-001_MapLibre官方升级兼容性架构审计_Codex完成报告_v1.md`。预先存在的未跟踪 `docs/40_任务/UPSTREAM-001_MapLibre官方升级兼容性架构审计_Codex任务_v1.md` 未修改。没有生成其它项目文档,因此没有更新 Step 或开发记录;本任务明确只允许这两份文档,优先于常规收尾规则。
独立验收需要:本报告、下列全路径表/命令/哈希、原始干跑 stdout/stderr、当前 JSONL 开始配置与外层结束回执、工作树 scoped diff、远端 HEAD 回读,以及后续单独授权的构建/设备证据。本轮可交付审计结论,不可交付新 SDK 功能 PASS。
## 附录 A:标准干跑完整冲突路径
路径为 merge-tree 的 unmerged 路径;`mln` 是模拟目标路径,并未创建到源码工作树。`—` 表示该升级线无此冲突。位置冲突不等于文本冲突。
| 路径 | Android | iOS |
| --- | --- | --- |
| `CMakeLists.txt` | 文本 | 文本 |
| `bazel/core.bzl` | 文本 | 文本 |
| `cmake/metal.cmake` | 文本 | 文本 |
| `cmake/opengl.cmake` | 文本 | 文本 |
| `include/mbgl/shaders/shader_manifest.hpp` | 修改/删除 | 修改/删除 |
| `include/mln/layermanager/particle_validation_layer_factory.hpp` | 位置 | 位置 |
| `include/mln/layermanager/raster_particle_layer_factory.hpp` | 位置 | 位置 |
| `include/mln/layermanager/weather_color_layer_factory.hpp` | 位置 | 位置 |
| `include/mln/map/map.hpp` | 文本 | 文本 |
| `include/mln/renderer/layers/weather_color_texture_lifecycle.hpp` | 位置 | 位置 |
| `include/mln/renderer/render_segment.hpp` | 位置 | 位置 |
| `include/mln/renderer/retained_underlay.hpp` | 位置 | 位置 |
| `include/mln/shaders/gl/particle_gpu_validation.hpp` | 位置 | 位置 |
| `include/mln/shaders/gl/retained_underlay_composite.hpp` | 位置 | 位置 |
| `include/mln/shaders/mtl/particle_gpu_validation.hpp` | 位置 | 位置 |
| `include/mln/shaders/mtl/retained_underlay_composite.hpp` | 位置 | 位置 |
| `include/mln/shaders/particle_gpu_validation_ubo.hpp` | 位置 | 位置 |
| `include/mln/style/layers/particle_validation_layer.hpp` | 位置 | 位置 |
| `include/mln/style/layers/raster_particle_layer.hpp` | 位置 | 位置 |
| `include/mln/style/layers/weather_color_layer.hpp` | 位置 | 位置 |
| `include/mln/style/layers/weather_color_stop.hpp` | 位置 | 位置 |
| `include/mln/style/sources/raster_array_source.hpp` | 位置 | 位置 |
| `include/mln/style/types.hpp` | 文本 | 文本 |
| `platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp` | 文本 | 文本 |
| `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/FeatureOverviewActivity.kt` | 文本 | 文本 |
| `platform/android/MapLibreAndroidTestApp/src/main/res/values/strings.xml` | 文本 | 文本 |
| `platform/android/VERSION` | 文本 | 文本 |
| `platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts` | 文本 | 文本 |
| `platform/darwin/src/MLNStyleLayerManager.mm` | — | 文本 |
| `platform/default/src/mln/layermanager/layer_manager.cpp` | 文本 | 文本 |
| `platform/ios/src/MLNMapView.mm` | 文本 | 文本 |
| `src/mln/gl/offscreen_texture.cpp` | 文本 | 文本 |
| `src/mln/layermanager/particle_validation_layer_factory.cpp` | 位置 | 位置 |
| `src/mln/layermanager/raster_particle_layer_factory.cpp` | 位置 | 位置 |
| `src/mln/layermanager/weather_color_layer_factory.cpp` | 位置 | 位置 |
| `src/mln/map/map_impl.cpp` | 文本 | 文本 |
| `src/mln/map/map_impl.hpp` | 文本 | 文本 |
| `src/mln/mtl/render_pass.cpp` | 文本 | 文本 |
| `src/mln/mtl/renderer_backend.cpp` | 文本 | 文本 |
| `src/mln/renderer/continuous_layer_range.hpp` | 位置 | 位置 |
| `src/mln/renderer/layers/render_particle_validation_layer.cpp` | 位置 | 位置 |
| `src/mln/renderer/layers/render_particle_validation_layer.hpp` | 位置 | 位置 |
| `src/mln/renderer/layers/render_raster_particle_layer.hpp` | 位置 | 位置 |
| `src/mln/renderer/layers/render_weather_color_layer.cpp` | 位置 | 位置 |
| `src/mln/renderer/layers/render_weather_color_layer.hpp` | 位置 | 位置 |
| `src/mln/renderer/particle_fast_path.hpp` | 位置 | 位置 |
| `src/mln/renderer/particle_viewport_reseed.hpp` | 位置 | 位置 |
| `src/mln/renderer/render_orchestrator.cpp` | 文本 | 文本 |
| `src/mln/renderer/render_orchestrator.hpp` | 文本 | 文本 |
| `src/mln/renderer/render_segment_json.hpp` | 位置 | 位置 |
| `src/mln/renderer/render_segment_plan.hpp` | 位置 | 位置 |
| `src/mln/renderer/render_source.cpp` | 文本 | 文本 |
| `src/mln/renderer/renderer.cpp` | 文本 | 文本 |
| `src/mln/renderer/renderer_impl.cpp` | 文本 | 文本 |
| `src/mln/renderer/renderer_impl.hpp` | 文本 | 文本 |
| `src/mln/renderer/retained_underlay_cache.cpp` | 位置 | 位置 |
| `src/mln/renderer/retained_underlay_cache.hpp` | 位置 | 位置 |
| `src/mln/renderer/retained_underlay_runtime_state.hpp` | 位置 | 位置 |
| `src/mln/renderer/sources/render_raster_array_source.hpp` | 位置 | 位置 |
| `src/mln/renderer/update_parameters.hpp` | 文本 | 文本 |
| `src/mln/shaders/mtl/particle_gpu_validation.cpp` | 位置 | 位置 |
| `src/mln/shaders/mtl/retained_underlay_composite.cpp` | 位置 | 位置 |
| `src/mln/shaders/mtl/shader_program.cpp` | 文本 | 文本 |
| `src/mln/shaders/shader_source.cpp` | — | 文本 |
| `src/mln/style/conversion/source.cpp` | 文本 | 文本 |
| `src/mln/style/layers/particle_render_layer_properties.hpp` | 位置 | 位置 |
| `src/mln/style/layers/particle_validation_layer.cpp` | 位置 | 位置 |
| `src/mln/style/layers/particle_validation_layer_impl.hpp` | 位置 | 位置 |
| `src/mln/style/layers/raster_particle_layer.cpp` | 位置 | 位置 |
| `src/mln/style/layers/raster_particle_layer_impl.hpp` | 位置 | 位置 |
| `src/mln/style/layers/weather_color_layer.cpp` | 位置 | 位置 |
| `src/mln/style/layers/weather_color_layer_impl.hpp` | 位置 | 位置 |
| `src/mln/style/sources/raster_array_source.cpp` | 位置 | 位置 |
| `src/mln/style/sources/raster_array_source_impl.hpp` | 位置 | 位置 |
| `test/CMakeLists.txt` | 文本 | 文本 |
| `test/gl/gl_functions.test.cpp` | 文本 | 文本 |
| `test/style/source.test.cpp` | 文本 | 文本 |
| `test/style/style_layer.test.cpp` | 文本 | 文本 |
## 附录 B:85 个官方既有修改文件逐项清单
`+/-` 来自 base→HEAD numstat;行号是首个修改 hunk 的 HEAD 起始行,详细函数解释见正文。主分类不抹除平台桥中的可外提逻辑。A/I:`C` 文本冲突、`D` 修改/删除、`净` 交叉但自动合并、`未交叉` 仅我方变动。旧路径迁移到 mln 后计同一文件。
| HEAD 路径:行 | +/- | 主分类 | 当前耦合/处理 | A / I |
| --- | --- | --- | --- | --- |
| `.gitignore:16` | +1/-0 | 构建/平台 | 忽略本地 artifact | 未交叉 / 净 |
| `CMakeLists.txt:183` | +54/-0 | 构建/平台 | 扩展 source/header/shader 清单接入 | C / C |
| `bazel/core.bzl:102` | +67/-0 | 构建/平台 | 扩展 source/header/shader 清单接入 | C / C |
| `cmake/metal.cmake:50` | +4/-0 | 构建/平台 | 扩展 source/header/shader 清单接入 | C / C |
| `cmake/opengl.cmake:40` | +1/-0 | 构建/平台 | 扩展 source/header/shader 清单接入 | C / C |
| `include/mbgl/gfx/context.hpp:85` | +4/-0 | 必要 hook | depth/stencil offscreen 虚接口 | 净 / 净 |
| `include/mbgl/map/map.hpp:17` | +10/-0 | 必要 hook | 公开 retained/segment API | C / C |
| `include/mbgl/mtl/context.hpp:109` | +4/-1 | 必要 hook | depth/stencil virtual override 声明 | 净 / 净 |
| `include/mbgl/mtl/render_pass.hpp:20` | +23/-2 | 深耦合 | 新增 clear helper、vertex texture/sampler 缓存 | 净 / 净 |
| `include/mbgl/renderer/render_target.hpp:37` | +3/-0 | 必要 hook | isRenderable 能力 | 净 / 净 |
| `include/mbgl/shaders/gl/shader_info.hpp:152` | +14/-0 | 必要 hook | 新增 shader/UBO/texture/attribute 注册;生成机制随目标迁移 | 净 / 净 |
| `include/mbgl/shaders/shader_defines.hpp:130` | +33/-0 | 必要 hook | 新增 shader/UBO/texture/attribute 注册;生成机制随目标迁移 | 净 / 净 |
| `include/mbgl/shaders/shader_manifest.hpp:27` | +2/-0 | 必要 hook | 新增 shader/UBO/texture/attribute 注册;生成机制随目标迁移 | D / D |
| `include/mbgl/shaders/shader_source.hpp:33` | +2/-0 | 必要 hook | 新增 shader/UBO/texture/attribute 注册;生成机制随目标迁移 | 净 / 净 |
| `include/mbgl/style/types.hpp:18` | +2/-1 | 必要 hook | RasterArray SourceType | C / C |
| `include/mbgl/vulkan/context.hpp:109` | +4/-1 | 必要 hook | depth/stencil virtual override 声明 | 净 / 净 |
| `include/mbgl/webgpu/context.hpp:46` | +4/-1 | 必要 hook | depth/stencil virtual override 声明 | 净 / 净 |
| `platform/android/MapLibreAndroid/src/cpp/map_renderer.cpp:198` | +4/-0 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 净 / 净 |
| `platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp:6` | +453/-0 | 构建/平台 | JNI field/layer/segment 实现可外提,官方类保留注册/生命周期 | C / C |
| `platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp:204` | +49/-0 | 构建/平台 | JNI facade 方法与签名 | 净 / 净 |
| `platform/android/MapLibreAndroid/src/cpp/style/layers/layer_manager.cpp:22` | +7/-0 | 构建/平台 | Android Core-only factory 薄注册 | 净 / 净 |
| `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java:15` | +243/-0 | 构建/平台 | runtime ownership、destroy listener、公开 facade,可外提实现 | 未交叉 / 未交叉 |
| `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java:142` | +60/-0 | 构建/平台 | Native 内部接口表 | 未交叉 / 未交叉 |
| `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java:656` | +221/-0 | 构建/平台 | state guard 与 Native JNI 转发 | 净 / 净 |
| `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/renderer/surfaceview/SurfaceViewMapRenderer.java:4` | +3/-0 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 未交叉 / 未交叉 |
| `platform/android/MapLibreAndroidTestApp/build.gradle.kts:19` | +6/-1 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 净 / 净 |
| `platform/android/MapLibreAndroidTestApp/src/main/AndroidManifest.xml:289` | +13/-0 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 净 / 净 |
| `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/FeatureOverviewActivity.kt:11` | +12/-0 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | C / C |
| `platform/android/MapLibreAndroidTestApp/src/main/res/layout/activity_feature_overview.xml:8` | +12/-1 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 未交叉 / 未交叉 |
| `platform/android/MapLibreAndroidTestApp/src/main/res/values/descriptions.xml:4` | +1/-0 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 净 / 净 |
| `platform/android/MapLibreAndroidTestApp/src/main/res/values/strings.xml:11` | +45/-0 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | C / C |
| `platform/android/MapLibreAndroidTestApp/src/main/res/values/titles.xml:28` | +1/-0 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 净 / 净 |
| `platform/android/VERSION:1` | +1/-1 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | C / C |
| `platform/android/buildSrc/src/main/kotlin/maplibre.artifact-settings.gradle.kts:1` | +6/-6 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 未交叉 / 未交叉 |
| `platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts:7` | +12/-0 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | C / C |
| `platform/darwin/src/MLNStyleLayerManager.mm:17` | +7/-0 | 构建/平台 | Darwin factory 薄注册 | 净 / C |
| `platform/default/src/mbgl/layermanager/layer_manager.cpp:13` | +7/-0 | 必要 hook | 注册三种新增 LayerFactory | C / C |
| `platform/default/src/mbgl/storage/offline_download.cpp:219` | +8/-0 | 必要 hook | RasterArray 无 offline tileset,switch 明确忽略 | 净 / 净 |
| `platform/ios/BUILD.bazel:152` | +0/-4 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 未交叉 / 未交叉 |
| `platform/ios/app/CMakeLists.txt:27` | +31/-0 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 未交叉 / 未交叉 |
| `platform/ios/app/MBXViewController.mm:19` | +741/-2 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 未交叉 / 净 |
| `platform/ios/bazel/files.bzl:8` | +2/-0 | 构建/平台 | 平台构建/发行/验证 App 或日志配套 | 未交叉 / 未交叉 |
| `platform/ios/src/MLNMapView.h:31` | +64/-0 | 构建/平台 | 公开诊断与 segment 方法 | 未交叉 / 未交叉 |
| `platform/ios/src/MLNMapView.mm:8` | +125/-0 | 构建/平台 | diagnostics ObjC 对象/JSON/Map 转发可委托专用 adapter | C / C |
| `platform/ios/src/Mapbox.h:45` | +1/-0 | 构建/平台 | 导出 MLNParticleFieldRuntime | 未交叉 / 净 |
| `shaders/manifest.json:147` | +14/-0 | 构建/平台 | 扩展 source/header/shader 清单接入 | 未交叉 / 净 |
| `src/mbgl/annotation/annotation_manager.cpp:224` | +6/-0 | 必要 hook | hasPendingChanges 持锁读取 dirty,快路径观察 | 净 / 净 |
| `src/mbgl/annotation/annotation_manager.hpp:45` | +1/-0 | 必要 hook | hasPendingChanges 声明 | 净 / 净 |
| `src/mbgl/gl/context.cpp:439` | +27/-1 | 可外提 | 通用 depth/stencil FBO 能力,独立 backend 补丁/上游化 | 净 / 净 |
| `src/mbgl/gl/context.hpp:137` | +6/-0 | 必要 hook | 通用 offscreen/FBO 声明 | 净 / 净 |
| `src/mbgl/gl/offscreen_texture.cpp:11` | +19/-4 | 可外提 | 通用 attachment 实现,独立 backend 补丁 | C / C |
| `src/mbgl/gl/offscreen_texture.hpp:15` | +3/-1 | 必要 hook | depth/stencil 构造参数 | 净 / 净 |
| `src/mbgl/gl/renderer_backend.cpp:138` | +2/-0 | 必要 hook | 新增 shader/UBO/texture/attribute 注册;生成机制随目标迁移 | 净 / 净 |
| `src/mbgl/map/map.cpp:97` | +32/-0 | 必要 hook | 公开配置/查询委托 runtime 并 onUpdate | 净 / 净 |
| `src/mbgl/map/map_impl.cpp:6` | +10/-0 | 可外提 | 直接识别 RasterArray 并 tickForecastClock | C / C |
| `src/mbgl/map/map_impl.hpp:16` | +3/-0 | 必要 hook | map-scoped runtime state 所有权 | C / C |
| `src/mbgl/mtl/offscreen_texture.cpp:8` | +60/-10 | 可外提 | 通用 attachment/renderability 修复;官方已有 size_ 修复 | 净 / 净 |
| `src/mbgl/mtl/render_pass.cpp:9` | +61/-13 | 深耦合 | clear/store/encoder/vertex binding 与官方 commandBuffer 合并 | C / C |
| `src/mbgl/mtl/renderer_backend.cpp:30` | +4/-0 | 必要 hook | 新增 shader/UBO/texture/attribute 注册;生成机制随目标迁移 | C / C |
| `src/mbgl/mtl/texture2d.cpp:260` | +4/-0 | 深耦合 | 所有 Texture2D::bind 镜像 vertex stage | 净 / 净 |
| `src/mbgl/renderer/layers/render_location_indicator_layer.hpp:47` | +1/-0 | 必要 hook | legacy rendering 分类 | 净 / 净 |
| `src/mbgl/renderer/paint_parameters.cpp:111` | +8/-0 | 必要 hook | beginRenderTarget 清 stencil id/mask cache | 净 / 净 |
| `src/mbgl/renderer/paint_parameters.hpp:115` | +3/-0 | 必要 hook | target boundary 声明 | 净 / 净 |
| `src/mbgl/renderer/render_layer.hpp:109` | +21/-0 | 必要 hook | repaint/粒子能力/legacy/hidden cleanup 默认虚函数 | 净 / 净 |
| `src/mbgl/renderer/render_orchestrator.cpp:2` | +505/-5 | 深耦合 | 依赖/revision/placement/readiness/teardown 与官方调度交织 | C / C |
| `src/mbgl/renderer/render_orchestrator.hpp:18` | +184/-1 | 深耦合 | 上述状态、事件、遍历方法与 mutex | C / C |
| `src/mbgl/renderer/render_source.cpp:11` | +5/-1 | 必要 hook | RasterArray factory 与 nullObserver 恢复 | C / C |
| `src/mbgl/renderer/render_source.hpp:14` | +21/-0 | 可外提 | readiness DTO/诊断方法与正式 source 类相连 | 净 / 净 |
| `src/mbgl/renderer/render_target.cpp:24` | +5/-3 | 必要 hook | isRenderable 与 target boundary | 净 / 净 |
| `src/mbgl/renderer/render_tree.hpp:102` | +11/-0 | 必要 hook | prepared tree 的快帧时间与 repaint 更新 | 净 / 净 |
| `src/mbgl/renderer/renderer.cpp:27` | +14/-1 | 必要 hook | 先快帧、全帧前释放引用树、提交 prepared tree | C / C |
| `src/mbgl/renderer/renderer_impl.cpp:4` | +632/-39 | 深耦合 | segment 决策/资源/执行与 Fast Path 主控制链 | C / C |
| `src/mbgl/renderer/renderer_impl.hpp:4` | +63/-1 | 深耦合 | cache/prepared tree、UpdateParameters 镜像签名所有权 | C / C |
| `src/mbgl/renderer/sources/render_tile_source.cpp:489` | +17/-0 | 可外提 | tilePyramid 计数诊断,可委托 source adapter | 净 / 净 |
| `src/mbgl/renderer/sources/render_tile_source.hpp:26` | +1/-0 | 必要 hook | readiness 查询 override | 净 / 净 |
| `src/mbgl/renderer/update_parameters.hpp:12` | +4/-0 | 必要 hook | 传递 map-scoped retained runtime state | C / C |
| `src/mbgl/shaders/gl/shader_info.cpp:290` | +27/-0 | 必要 hook | 新增 shader/UBO/texture/attribute 注册;生成机制随目标迁移 | 净 / 净 |
| `src/mbgl/shaders/mtl/shader_program.cpp:12` | +22/-9 | 可外提 | pipeline key 纳入 attachment format,独立通用修复 | C / C |
| `src/mbgl/shaders/shader_source.cpp:9` | +40/-37 | 必要 hook | 新增 shader/UBO/texture/attribute 注册;生成机制随目标迁移 | 净 / C |
| `src/mbgl/style/conversion/source.cpp:13` | +106/-0 | 可外提 | 103 行 RasterArray JSON parser 可独立 converter | C / C |
| `src/mbgl/style/types.cpp:15` | +2/-1 | 必要 hook | raster-array 字符串映射 | 净 / 净 |
| `test/CMakeLists.txt:21` | +16/-0 | 测试配套 | 新增类型/生命周期测试或平台条件;本轮未运行 | C / C |
| `test/gl/gl_functions.test.cpp:7` | +11/-0 | 测试配套 | 新增类型/生命周期测试或平台条件;本轮未运行 | C / C |
| `test/style/source.test.cpp:15` | +883/-0 | 测试配套 | 新增类型/生命周期测试或平台条件;本轮未运行 | C / C |
| `test/style/style_layer.test.cpp:19` | +106/-0 | 测试配套 | 新增类型/生命周期测试或平台条件;本轮未运行 | C / C |
分类合计:构建/平台 32;必要 hook 34;深耦合 7;可外提 8;测试配套 4。各类相加为 85;分类为审计判断,不代表冲突严重性排序。
## 附录 C:68 个纯新增 Core 扩展文件
“纯新增”是 Git 身份,独立程度仍按正文函数审计;GPU/RenderSegment 新文件也存在官方内部 API 耦合。以下为完整 `src/`、`include/` 新增清单(24 个 particle 子树文件、其余 44 个 layer/source/renderer/shader 等文件)。
```text
include/mbgl/layermanager/particle_validation_layer_factory.hpp
include/mbgl/layermanager/raster_particle_layer_factory.hpp
include/mbgl/layermanager/weather_color_layer_factory.hpp
include/mbgl/particle/field/field_binding.hpp
include/mbgl/particle/field/field_data_adapter.hpp
include/mbgl/particle/field/field_profile_contract.hpp
include/mbgl/particle/field/field_profile_contract_json.hpp
include/mbgl/particle/field/field_profile_validator.hpp
include/mbgl/particle/field/field_projection_materialization.hpp
include/mbgl/particle/field/field_runtime.hpp
include/mbgl/particle/field/local_particle_field_feed.hpp
include/mbgl/particle/field/particle_gpu_math.hpp
include/mbgl/particle/ingress/encoded_field_transport.hpp
include/mbgl/particle/ingress/qbin_v2_decoder.hpp
include/mbgl/particle/ingress/qbin_v3_decoder.hpp
include/mbgl/particle/renderer_debug_counters.hpp
include/mbgl/renderer/layers/weather_color_texture_lifecycle.hpp
include/mbgl/renderer/render_segment.hpp
include/mbgl/renderer/retained_underlay.hpp
include/mbgl/shaders/gl/particle_gpu_validation.hpp
include/mbgl/shaders/gl/retained_underlay_composite.hpp
include/mbgl/shaders/mtl/particle_gpu_validation.hpp
include/mbgl/shaders/mtl/retained_underlay_composite.hpp
include/mbgl/shaders/particle_gpu_validation_ubo.hpp
include/mbgl/style/layers/particle_validation_layer.hpp
include/mbgl/style/layers/raster_particle_layer.hpp
include/mbgl/style/layers/weather_color_layer.hpp
include/mbgl/style/layers/weather_color_stop.hpp
include/mbgl/style/sources/raster_array_source.hpp
src/mbgl/layermanager/particle_validation_layer_factory.cpp
src/mbgl/layermanager/raster_particle_layer_factory.cpp
src/mbgl/layermanager/weather_color_layer_factory.cpp
src/mbgl/particle/field/field_binding.cpp
src/mbgl/particle/field/field_data_adapter.cpp
src/mbgl/particle/field/field_profile_contract_json.cpp
src/mbgl/particle/field/field_profile_validator.cpp
src/mbgl/particle/field/field_projection_materialization.cpp
src/mbgl/particle/field/field_runtime.cpp
src/mbgl/particle/field/local_particle_field_feed.cpp
src/mbgl/particle/field/offline_fixture_particle_adapter.cpp
src/mbgl/particle/field/offline_fixture_particle_adapter.hpp
src/mbgl/particle/ingress/qbin_v2_decoder.cpp
src/mbgl/particle/ingress/qbin_v3_decoder.cpp
src/mbgl/renderer/continuous_layer_range.hpp
src/mbgl/renderer/layers/render_particle_validation_layer.cpp
src/mbgl/renderer/layers/render_particle_validation_layer.hpp
src/mbgl/renderer/layers/render_raster_particle_layer.hpp
src/mbgl/renderer/layers/render_weather_color_layer.cpp
src/mbgl/renderer/layers/render_weather_color_layer.hpp
src/mbgl/renderer/particle_fast_path.hpp
src/mbgl/renderer/particle_viewport_reseed.hpp
src/mbgl/renderer/render_segment_json.hpp
src/mbgl/renderer/render_segment_plan.hpp
src/mbgl/renderer/retained_underlay_cache.cpp
src/mbgl/renderer/retained_underlay_cache.hpp
src/mbgl/renderer/retained_underlay_runtime_state.hpp
src/mbgl/renderer/sources/render_raster_array_source.hpp
src/mbgl/shaders/mtl/particle_gpu_validation.cpp
src/mbgl/shaders/mtl/retained_underlay_composite.cpp
src/mbgl/style/layers/particle_render_layer_properties.hpp
src/mbgl/style/layers/particle_validation_layer.cpp
src/mbgl/style/layers/particle_validation_layer_impl.hpp
src/mbgl/style/layers/raster_particle_layer.cpp
src/mbgl/style/layers/raster_particle_layer_impl.hpp
src/mbgl/style/layers/weather_color_layer.cpp
src/mbgl/style/layers/weather_color_layer_impl.hpp
src/mbgl/style/sources/raster_array_source.cpp
src/mbgl/style/sources/raster_array_source_impl.hpp
```
## 附录 D:可复现命令、退出状态与证据摘要
以下 Python 仅执行 Git 读取和 merge-tree 干跑,并将输出/object 写入新临时目录,不执行真实 merge/rebase 或更新源码/index/ref。在同工作区与 Git 2.54.0 下运行;若原对象不足/网络不可用,保留退出码并报告阻塞,不将空 stdout 算零冲突。本轮未设置 merge.renames/directoryRenames/renameLimit 或 diff.renames/renameLimit 覆盖;检查这些配置未发现显式条目。
```python
import os, pathlib, subprocess, tempfile, json, re, collections, hashlib
BASE = "18545ca10d296704b2cba675b182ff2c8da24588"
OURS = "630ec657687bad4200c059bbccbb950d9c6f7ce9"
TARGETS = {
"android": "c7506d6aff3800e946f89e1a51432fc22d1a6534",
"ios": "01791ad02c1bfe3b22c42a97619b972aba962f82",
}
root = pathlib.Path(tempfile.mkdtemp(prefix="upstream-001-reproduce-"))
(root / "objects").mkdir()
original = subprocess.check_output([
"git", "rev-parse", "--path-format=absolute", "--git-path", "objects"
], text=True).strip()
env = dict(os.environ, GIT_OBJECT_DIRECTORY=str(root / "objects"),
GIT_ALTERNATE_OBJECT_DIRECTORIES=original)
def run(name, args):
r = subprocess.run(["git", *args], capture_output=True, env=env)
(root / (name + ".stdout")).write_bytes(r.stdout)
(root / (name + ".stderr")).write_bytes(r.stderr)
print(name, "exit", r.returncode,
"stdout-sha256", hashlib.sha256(r.stdout).hexdigest())
return r
def paths(r):
if r.returncode != 0:
raise RuntimeError("路径 diff 未完成,停止计数")
return {line.split("\t")[-1] for line in r.stdout.decode().splitlines()}
ours = paths(run("ours-paths", ["diff", "--no-renames", "--name-status", BASE, OURS]))
for label, target in TARGETS.items():
run(label + "-base", ["merge-base", OURS, target])
run(label + "-diff", ["diff", "--name-status", BASE, target])
upstream = paths(run(label + "-paths", ["diff", "--no-renames", "--name-status", BASE, target]))
overlap = ours & upstream
r = run(label + "-merge", ["merge-tree", "--write-tree", "--messages", OURS, target])
if r.returncode not in (0, 1) or not r.stdout:
print(label, "BLOCKED,冲突数未知")
continue
lines = r.stdout.decode().splitlines()
unmerged = {m.group(1) for line in lines
if (m := re.match(r"[0-7]{6} [0-9a-f]+ [123]\t(.+)$", line))}
kinds = collections.Counter(m.group(1) for line in lines
if (m := re.match(r"CONFLICT \(([^)]+)\)", line)))
clean = {p for p in overlap if p not in unmerged
and p.replace("/mbgl/", "/mln/") not in unmerged}
print(label, "tree", lines[0], "intersection", len(overlap),
"unmerged", len(unmerged), "types", dict(kinds), "clean-overlap", len(clean))
(root / (label + "-conflict-paths.txt")).write_text("\n".join(sorted(unmerged)) + "\n")
print("证据目录", root)
```
本轮临时对象库:`/private/tmp/upstream-001-audit-20261009/objects`;只读 alternate:`/Users/tei/dev/MapLibreParticleLab/.git/objects`。这是审计 worktree 原本共享的 Git object 来源,未操作其它工作树源码或状态。
| 证据文件(临时目录内) | SHA-256 | 说明 |
| --- | --- | --- |
| `ours-no-renames.txt` | `7e63240f4460f8c502dfec535b9fcbb0f11872ae221b87b550d68a05bb70bf48` | Git 路径证据 |
| `android-rename-aware.txt` | `fa42160229b3407eeaa13fd90d0dfb9c4d7425e8f0dfa860b01db1ff7f18984c` | Git 路径证据 |
| `ios-rename-aware.txt` | `e836b7699dc32c8300f8b0bfdcad16be17eeb526c48057d9a16cfa7734f32e61` | Git 路径证据 |
| `android-isolated-default.stdout` | `3526b74fc8152e61f72641d571c16e9055500deb1cd31540f2eacf26047b4fb6` | 标准干跑,exit 1;复跑一致 |
| `ios-isolated-default.stdout` | `d553091afaec4f381991bfbf6e60cd0d887177d5bccd172fac4f46e70f347261` | 标准干跑,exit 1;复跑一致 |
| `android-conflict-paths.txt` | `4c61654d97bee7bca76879d9b828db8ca5c1d4a0610e3cfb6d43edeb73029039` | Git 路径证据 |
| `ios-conflict-paths.txt` | `013ebe7121eaea79bf8491a1e3a55198e87acc7865b7b27bda6fdf81da993235` | Git 路径证据 |
首轮失败见 `android/ios-diff.stderr`、`android/ios-merge.stderr`;原目录权限失败见 `android/ios-merge-no-renames.stderr`;成功命令与 rc 见对应 `.json`;复跑比对见 `android/ios-repeat.json`。对照禁用 rename 的 tree 为 Android `59de9836b81e90c3fef4a5a0377454bd464f5ef9`、iOS `b419b471131eb4fa3244e5cc3082ee7f2bd8e1e9`,仅用于证明 rename 口径影响,不用于迁移决策。
已观察退出状态:标准干跑两线均 1(冲突),路径 diff/merge-base 0;原始失败 128;报告最终静态检查见下节。Codex 进程最终状态和 Git 发布回执由外层执行器/RDC 独立补证。
## 附录 E:最终静态收尾记录
- 报告内复现脚本已原样提取并执行,脚本退出 **0**;其中两次 merge-tree 各退出 **1**,Android 76 / iOS 78 个路径与正文完全一致。该脚本退出 0 只表示采集/计数完成,不是升级 PASS。复现临时目录 `/tmp/upstream-001-reproduce-58mf60um`,采集日志位于主证据目录 `embedded-reproduce.stdout/.stderr`。
- `git diff --check`:退出 **0**,无输出;tracked 与 staged 的 `git diff --name-only` 均为空,退出 0。
- 未跟踪报告另用 `git diff --no-index --check /dev/null <报告>` 检查:退出 **1**,stdout/stderr 均为空;这里 1 表示新增文件有差异,没有空白错误,不解释为测试失败或运行成功。
- 报告要求的 11 个章节齐全,Markdown 围栏闭合;完整本地路径:行引用的文件均存在。冲突附录为 78 个并集路径,官方修改清单 85 个,新增 Core 清单 68 个。
- 收尾 HEAD 仍为 `630ec657687bad4200c059bbccbb950d9c6f7ce9`;工作树只有以下两份未跟踪文档,没有源码或已跟踪文件改动:
```text
?? docs/40_任务/UPSTREAM-001_MapLibre官方升级兼容性架构审计_Codex任务_v1.md
?? docs/报告/UPSTREAM-001_MapLibre官方升级兼容性架构审计_Codex完成报告_v1.md
```
任务书 SHA-256:`2e2ba4b5b1e94bedf0846cea616611eab758467a3e9ffaf01a4c8691fc01c112`。本轮没有编辑任务书,未 commit/push。最终外层 Codex 进程退出码仍待执行器回执,**Git 收尾待 RDC 验收**。
## 附录 F:RDC Git 收尾回执(2026-10-09 JST)
本节为 Codex 完成后 RDC 独立验收补记;前述“Git 收尾待 RDC 验收”与“未 commit/push”均指 Codex 自身退出时的阶段事实,不再代表本附录写入后的状态。
- 审计结果:**PASS(仅只读架构审计与文档核验)**。目标升级结论仍为 **CONDITIONAL GO**,任何 Native/RN 构建、设备运行与发行均 **NOT RUN**。
- Codex 实际模型:**gpt-6-astra / high**;JSONL `turn.completed`,外部执行器退出码 **0**。
- 独立验收:报告 12 个必须章节存在;Android 76、iOS 78 条冲突复核一致;`git diff --check` 通过。
- 功能文档提交:`2b4075b60ba7c7265e39e18168522bf7089f3a60`。
- Commit message:`docs: audit upstream MapLibre Native upgrade compatibility`。
- 推送结果:**PASS**;`origin/particle/main` 从 `630ec657687bad4200c059bbccbb950d9c6f7ce9` 快进至上述文档提交,远端 SHA 回读一致。
- 本次补记作为后续独立文档提交推送;其最终 SHA 以远端 `origin/particle/main` 回读为准,不在提交内容中自引用。
- 本次没有修改任何产品源码、测试实现或用户原有 Mac 工作树。

View File

@@ -1,13 +1,13 @@
#include "expression_test_logger.hpp"
#include "expression_test_runner.hpp"
#include <mbgl/util/io.hpp>
#include <mbgl/util/string.hpp>
#include <mln/util/io.hpp>
#include <mln/util/string.hpp>
#include <sstream>
#include <filesystem>
using namespace mbgl;
using namespace mln;
using namespace std::literals;
namespace {

View File

@@ -4,12 +4,12 @@
#undef GetObject
#endif
#include <mbgl/util/io.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/variant.hpp>
#include <mbgl/style/conversion/function.hpp>
#include <mbgl/style/rapidjson_conversion.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
#include <mln/util/io.hpp>
#include <mln/util/logging.hpp>
#include <mln/util/variant.hpp>
#include <mln/style/conversion/function.hpp>
#include <mln/style/rapidjson_conversion.hpp>
#include <mln/style/expression/parsing_context.hpp>
#include <mapbox/geojson/rapidjson.hpp>
#include <rapidjson/writer.h>
@@ -20,9 +20,9 @@
#include <regex>
using namespace mbgl;
using namespace mbgl::style;
using namespace mbgl::style::conversion;
using namespace mln;
using namespace mln::style;
using namespace mln::style::conversion;
using namespace std::literals;
namespace {
@@ -407,7 +407,7 @@ std::optional<TestData> parseTestData(const std::filesystem::path& path) {
TestData data;
auto maybeJson = readJson(path.string());
if (!maybeJson.is<JSDocument>()) { // NOLINT
mbgl::Log::Error(mbgl::Event::General, "Cannot parse test '" + path.string() + "'.");
mln::Log::Error(mln::Event::General, "Cannot parse test '" + path.string() + "'.");
return std::nullopt;
}

View File

@@ -1,15 +1,15 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/util/rapidjson.hpp>
#include <mln/style/expression/expression.hpp>
#include <mln/util/feature.hpp>
#include <mln/util/rapidjson.hpp>
#include <set>
#include <string>
#include <vector>
#include <filesystem>
using namespace mbgl;
using namespace mln;
struct Input {
Input(std::optional<float> zoom_,

View File

@@ -3,7 +3,7 @@
#include "expression_test_parser.hpp"
#include "test_runner_common.hpp"
#include <mbgl/util/io.hpp>
#include <mln/util/io.hpp>
#include <rapidjson/writer.h>
#include <rapidjson/prettywriter.h>
@@ -105,7 +105,7 @@ TestRunOutput runExpressionTest(TestData& data, const std::string& rootPath, con
std::vector<Value> outputs;
if (!data.inputs.empty()) {
for (const auto& input : data.inputs) {
mbgl::style::expression::EvaluationResult evaluationResult;
mln::style::expression::EvaluationResult evaluationResult;
if (input.canonical) {
evaluationResult = expression->evaluate(
input.zoom, input.feature, input.heatmapDensity, input.availableImages, *input.canonical);

View File

@@ -2,7 +2,7 @@
#include "expression_test_runner.hpp"
#include "expression_test_logger.hpp"
#include <mbgl/util/logging.hpp>
#include <mln/util/logging.hpp>
#include <random>
#include <iostream>

View File

@@ -3,7 +3,7 @@
#include <cmath>
#include <regex>
using namespace mbgl;
using namespace mln;
// Strip precision for numbers, so that we can compare evaluated results with
// fixtures. Copied from JS expression harness.

View File

@@ -1,11 +1,11 @@
#pragma once
#include <mbgl/util/feature.hpp>
#include <mln/util/feature.hpp>
#include <string>
#include <vector>
using namespace mbgl;
using namespace mln;
Value stripPrecision(const Value& value);
std::vector<std::string> tokenize(std::string str);

View File

@@ -1,30 +0,0 @@
#pragma once
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/mtl/mtl_fwd.hpp>
#include <cstdlib>
namespace mbgl {
namespace mtl {
class RendererBackend;
class RenderableResource : public gfx::RenderableResource {
protected:
explicit RenderableResource() = default;
public:
virtual void swap() {
// Renderable resources that require a swap function to be called
// explicitly can override this method.
}
virtual const mbgl::mtl::RendererBackend& getBackend() const = 0;
virtual const mbgl::mtl::MTLCommandBufferPtr& getCommandBuffer() const = 0;
virtual mbgl::mtl::MTLBlitPassDescriptorPtr getUploadPassDescriptor() const = 0;
virtual const mbgl::mtl::MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const = 0;
};
} // namespace mtl
} // namespace mbgl

View File

@@ -1,69 +0,0 @@
#pragma once
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/mtl/mtl_fwd.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/size.hpp>
#include <mbgl/util/util.hpp>
#include <Foundation/NSSharedPtr.hpp>
#include <Metal/MTLDevice.hpp>
#include <Metal/MTLCommandQueue.hpp>
namespace mbgl {
class ProgramParameters;
namespace mtl {
using ProcAddress = void (*)();
using FramebufferID = uint32_t;
class RendererBackend : public gfx::RendererBackend {
public:
RendererBackend(gfx::ContextMode);
~RendererBackend() override;
/// Called prior to rendering to update the internally assumed MetalMetal state.
virtual void updateAssumedState() = 0;
/// One-time shader initialization
void initShaders(gfx::ShaderRegistry&, const ProgramParameters& programParameters) override;
const MTLDevicePtr& getDevice() const { return device; }
const MTLCommandQueuePtr& getCommandQueue() const { return commandQueue; }
bool isBaseVertexInstanceDrawingSupported() const { return baseVertexInstanceDrawingSupported; }
protected:
std::unique_ptr<gfx::Context> createContext() override;
/// Reads the color pixel data from the currently bound framebuffer.
PremultipliedImage readFramebuffer(const Size&);
/// A constant to signal that a framebuffer is bound, but with an unknown ID.
static constexpr const FramebufferID ImplicitFramebufferBinding = std::numeric_limits<FramebufferID>::max();
/// Tells the renderer that the Metal state has already been set by the windowing toolkit.
/// It sets the internal assumed state to the supplied values.
void assumeFramebufferBinding(FramebufferID fbo);
void assumeViewport(int32_t x, int32_t y, const Size&);
void assumeScissorTest(bool);
/// Returns true when assumed framebuffer binding hasn't changed from the implicit binding.
bool implicitFramebufferBound();
public:
/// Triggers a Metal state update if the internal assumed state doesn't
/// match the supplied values.
void setFramebufferBinding(FramebufferID fbo);
void setViewport(int32_t x, int32_t y, const Size&);
void setScissorTest(bool);
protected:
MTLDevicePtr device;
MTLCommandQueuePtr commandQueue;
bool baseVertexInstanceDrawingSupported = false;
};
} // namespace mtl
} // namespace mbgl

View File

@@ -1,112 +0,0 @@
#pragma once
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace mbgl {
enum class RenderSegmentStrategy : uint8_t { Retained, Continuous };
inline const char* renderSegmentStrategyText(RenderSegmentStrategy strategy) noexcept {
return strategy == RenderSegmentStrategy::Retained ? "RETAINED" : "CONTINUOUS";
}
struct RenderSegmentDefinition {
RenderSegmentStrategy strategy = RenderSegmentStrategy::Continuous;
std::optional<std::string> startLayerId;
bool operator==(const RenderSegmentDefinition&) const = default;
};
struct RenderSegmentPlan {
uint32_t schemaVersion = 1;
std::vector<RenderSegmentDefinition> segments;
bool operator==(const RenderSegmentPlan&) const = default;
};
struct StyleLayerDiagnostics {
int32_t layerIndex = -1;
std::string layerId;
std::string layerType;
bool visible = false;
std::optional<std::string> sourceId;
std::optional<std::string> sourceLayer;
bool operator==(const StyleLayerDiagnostics&) const = default;
};
struct RenderSegmentCacheDiagnostics {
std::string cacheState{"disabled"};
uint64_t contentRevision = 0;
uint64_t build = 0;
uint64_t reuse = 0;
uint64_t invalidation = 0;
std::string lastInvalidationReason{"none"};
uint64_t textureCreate = 0;
uint64_t compositeCreate = 0;
uint64_t resourceRelease = 0;
};
struct RenderSegmentDiagnosticsEntry {
uint32_t segmentIndex = 0;
RenderSegmentStrategy strategy = RenderSegmentStrategy::Continuous;
std::optional<std::string> configuredStartLayerId;
int32_t beginIndex = -1;
int32_t endExclusive = -1;
std::optional<std::string> resolvedStartLayerId;
std::optional<std::string> resolvedEndLayerId;
std::vector<StyleLayerDiagnostics> layers;
std::optional<RenderSegmentCacheDiagnostics> cache;
};
struct RenderSegmentDiagnostics {
uint32_t schemaVersion = 1;
bool enabled = true;
bool configured = false;
bool valid = false;
std::string configSource{"unconfigured/legacy"};
uint64_t configRevision = 0;
uint64_t topologyRevision = 0;
uint32_t styleLayerCount = 0;
uint32_t segmentCount = 0;
uint32_t retainedSegmentCount = 0;
uint32_t continuousSegmentCount = 0;
bool coverageComplete = false;
bool fallback = false;
std::string lastReason{"not-configured"};
bool fastPathEligible = false;
bool fastPathActive = false;
std::string fastPathFallbackReason{"no-prepared-tree"};
uint64_t fastPathHit = 0;
uint64_t fastPathMiss = 0;
uint64_t fullCpuFrame = 0;
std::vector<StyleLayerDiagnostics> styleLayers;
std::vector<RenderSegmentDiagnosticsEntry> segments;
};
struct ResolvedRenderSegment {
uint32_t segmentIndex = 0;
RenderSegmentStrategy strategy = RenderSegmentStrategy::Continuous;
std::optional<std::string> configuredStartLayerId;
int32_t beginIndex = 0;
int32_t endExclusive = 0;
bool operator==(const ResolvedRenderSegment&) const = default;
};
struct ResolvedRenderSegmentPlan {
bool configured = false;
bool valid = false;
std::string configSource{"unconfigured/legacy"};
uint64_t configRevision = 0;
std::string reason{"not-configured"};
int32_t layerCount = 0;
std::vector<ResolvedRenderSegment> segments;
bool operator==(const ResolvedRenderSegmentPlan&) const = default;
};
} // namespace mbgl

Some files were not shown because too many files have changed in this diff Show More