Files
open-wc/targets/03-renderer-facade.md
T

252 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M03 — Renderer Facade and Safe Extraction
<!-- OPENWC_TARGET:ACTIVE -->
## Outcome
Закрыть монолитный streamer стабильным API и постепенно извлечь тестируемые подсистемы без rewrite.
## Steps
- [x] Ввести `WorldRenderFacade` для focus, environment, entity visuals, ground query и metrics.
- [x] Запретить gameplay/editor доступ к внутренним очередям streamer.
- [x] Извлечь pure `StreamingTargetPlanner`.
- [x] Извлечь `RenderBudgetScheduler` с bounded queues/cancellation.
- [ ] Затем извлекать terrain, M2, WMO и liquid services по одному.
- [ ] Сохранить cache versioning и main-thread GPU finalization rules.
- [ ] Добавить dependency и performance regression checks.
## Fidelity evidence
Все baseline checkpoints сравниваются до/после; placement, visibility, animation и materials не меняются без отдельной fidelity-задачи.
## Exit criteria
Runtime и Editor используют facade; planner/scheduler тестируются без полного мира; p95/p99 и hitch budgets не хуже согласованного baseline.
## Evidence
- Date: 2026-07-17
- Revision/worktree: master merges `7ece2ab`, `7e35de7`, `80cb084`, `d6e5b53`, `c69abd6`, `606770c`, `630a0c1`, `f36fabb`, `24aef13`, `2342430`, `396be5e`, `f88bf97`, `3f84717`, `d2cb52f`, `f9e5a4f`, `c06aed5`, `a878e7c`, `60603e1`, `b4955d6`, `ada0fd9`, `f470775`, `874fd0f`, `38f831e`;
packages `M03-RND-SCHEDULER-001`, `M03-RND-INTERNAL-ACCESS-GATE-001`,
`M03-RND-FACADE-GROUND-QUERY-001`, `M03-RND-FACADE-ENVIRONMENT-001`,
`M03-RND-FACADE-ENTITY-001`, `M03-RND-TERRAIN-CACHE-SERVICE-001`,
`M03-RND-TERRAIN-LOD-PLANNER-001`, `M03-RND-TERRAIN-CHUNK-QUEUE-001`,
`M03-RND-M2-UNIQUE-REGISTRY-001`,
`M03-RND-M2-PLACEMENT-TRANSFORM-001`,
`M03-RND-M2-PLACEMENT-GROUPER-001`,
`M03-RND-M2-BUILD-BATCH-PLANNER-001`,
`M03-RND-WMO-PLACEMENT-RESOLVER-001`,
`M03-RND-WMO-PLACEMENT-REGISTRY-001`,
`M03-RND-WMO-RENDER-BUILD-PLANNER-001`,
`M03-RND-WMO-RENDER-BUILD-QUEUE-001`,
`M03-RND-WMO-RENDER-RESOURCE-CACHE-001`,
`M03-RND-WMO-SCENE-RESOURCE-CACHE-001`,
`M03-RND-ADT-WATER-LOAD-PIPELINE-001`,
`M03-RND-ADT-WATER-SCENE-FINALIZER-001`,
`M03-RND-M2-RUNTIME-REBUILD-CLASSIFIER-001`
- Commands: dedicated scheduler/planner/facade/focus/coordinate/manifest/shutdown
headless verifiers; Godot cold editor parse; coordination, documentation and diff gates.
- Results: scheduler `cases=6 iterations=20000 elapsed_ms=10.216`; planner
`cases=5 average_ms=1.804`; facade/focus passed; coordinate boundary
`files=111 consumers=6`; renderer manifest retained `7/7` checkpoints;
shutdown ownership and repository gates passed. Internal-access gate additionally
derived `43` private symbols and found no forbidden access across `7` gameplay
and `9` EditorPlugin-package sources plus the terrain probe. Ground facade passed
`delegation=5 ground_contract=2`; cold `RenderedGroundSample contract=3`;
environment integration passed cold snapshot `contract=5` and facade
`delegation=6 environment_contract=7`; dry-run retained all `7/7` plans and
applied the dusk checkpoint at `time=19.00`. Entity presentation passed
`snapshot_cases=8 lifecycle_cases=14 runtime_scenes=2`; facade expanded to
`delegation=9 entity_contract=6`, while character presentation remained `9/10/3/1`.
Terrain quality cache passed `contract_cases=15 loader_calls=3`; internal-access
inventory decreased to `42` because the loader no longer owns the LRU-order field.
Terrain chunk LOD planner passed `cases=7 iterations=250 elapsed_ms=12.630`;
post-merge facade, internal-access and `7/7` manifest gates remained green.
Terrain chunk geometry queue planner passed `cases=8 iterations=100
elapsed_ms=229.324`; internal-access remained `42` and post-merge facade and
`7/7` manifest gates stayed green.
M2 unique placement registry passed `cases=10 iterations=100 elapsed_ms=35.513`;
the historical `uid:11785` cross-tile smoke, internal-access `42`, facade and
`7/7` manifest gates remained green after merge.
M2 placement transform resolver passed `cases=9 iterations=10000
elapsed_ms=27.409`; post-merge M2 registry, internal-access `42`, facade,
`7/7` manifest, documentation and coordination gates remained green.
M2 placement grouper passed `cases=9 iterations=100 placements=256
elapsed_ms=67.104`; post-merge transform resolver, registry, internal-access
`42`, facade, `7/7` manifest, documentation and coordination gates remained green.
M2 build batch planner passed `cases=8 iterations=20000 elapsed_ms=14.532`;
post-merge grouper, transform resolver, registry, internal-access `42`, facade,
`7/7` manifest, documentation and coordination gates remained green.
WMO placement resolver passed `cases=9 iterations=20000 elapsed_ms=27.919`;
post-merge renderer materials, shutdown, internal-access `42`, facade,
`7/7` manifest, documentation and coordination gates remained green.
WMO placement registry passed `cases=10 iterations=100 elapsed_ms=53.941`;
all 21 adjacent WMO/M2/terrain/facade/scheduler/streaming/coordinate
regressions and the `7/7` checkpoint dry-run passed; post-merge registry
(`54.178ms`), resolver, shutdown, facade, documentation and coordination
gates remained green.
WMO render build step planner passed `cases=9 iterations=20000
elapsed_ms=11.914`; WMO registry/resolver/material/shutdown, 18 adjacent
regressions and the `7/7` checkpoint dry-run passed; post-merge planner
(`11.059ms`), registry, resolver, shutdown, facade, documentation and
coordination gates remained green.
WMO render build queue passed `cases=11 iterations=100 elapsed_ms=59.874`;
WMO planner/registry/resolver/material/shutdown, 18 adjacent regressions and
the `7/7` checkpoint dry-run passed. The first post-merge smoke exposed an
editor class-cache dependency; a fresh no-`.godot` run verified the fix
(`57.835ms`), and post-fix master passed queue (`56.454ms`), planner,
registry, resolver, shutdown, facade, documentation and coordination gates
without parse diagnostics.
WMO render Resource cache state passed `cases=10 iterations=100
elapsed_ms=58.727`; direct no-`.godot` service verification passed
(`45.361ms`), WMO queue/planner/registry/resolver/material/shutdown and 18
adjacent regressions passed, and the checkpoint dry-run retained `7/7` plans.
Post-merge cache state (`51.949ms`), shutdown, WMO queue/resolver, facade,
internal-access `41`, `7/7` manifest, documentation and coordination gates
remained green.
WMO scene Resource cache state passed `cases=11 iterations=100
elapsed_ms=40.768`; its initial direct no-`.godot` run passed (`43.636ms`),
render-cache state, WMO queue/planner/registry/resolver/material/shutdown and
18 adjacent regressions passed, and checkpoint dry-run retained `7/7` plans.
Post-merge scene state (`40.113ms`), render state (`43.434ms`), shutdown,
WMO queue/resolver, facade, internal-access `40`, `7/7` manifest,
documentation and coordination gates remained green.
ADT water load pipeline state passed `cases=12 iterations=100
elapsed_ms=86.170`; its initial direct no-`.godot` run passed (`94.576ms`),
WMO caches/queue/planner/registry/resolver/material/shutdown and 18 adjacent
M2/terrain/facade/scheduler/streaming/coordinate regressions passed, and the
checkpoint dry-run retained `7/7` plans. Post-merge water state (`86.935ms`),
shutdown, renderer materials, facade, internal-access `36`, `7/7` manifest,
documentation and coordination gates remained green.
ADT water scene finalizer passed `cases=8 iterations=100 elapsed_ms=0.042`
after an initial `0.024ms` run; synthetic data produced one four-vertex/
six-index liquid surface with exact tile attachment and recursive editor owner.
Water pipeline, WMO/M2/terrain/facade/scheduler/streaming/coordinate, material,
shutdown and 32 headless contract regressions passed; checkpoint dry-run
retained `7/7` plans. Post-merge finalizer (`0.025ms`), water pipeline
(`98.398ms`), shutdown, materials, facade, internal-access `36`, `7/7`
manifest, documentation and coordination gates remained green.
M2 runtime mesh rebuild classifier passed `cases=12 iterations=100
elapsed_ms=64.585` after an initial `35.461ms` run; billboard flag/count,
invalid variants/indices, UV rotation/speed/epsilon, four-stage cap,
memoization, detached diagnostics and both clear sites passed. Thirty-three
M2/WMO/liquid/terrain/facade/scheduler/streaming/coordinate/material/shutdown
regressions and checkpoint dry-run `7/7` passed. Post-merge classifier
(`45.439ms`), materials, shutdown, M2 batch planner, facade, internal-access
`35`, `7/7` manifest, documentation and coordination gates remained green.
M02 terrain-query regression
remained green (13 pre-existing expired M00 claim warnings).
- Fidelity comparison: all 16 historical operation limits and drain sites were
preserved; chunk removal/create retain their shared removal-first budget.
Defaults, quality presets, cache versions and visual rules are unchanged.
Rendered-ground diagnostics preserve the prior 5000-unit ray, 3x3 search and
`2/5/10/20/40`-unit nearby fallback while hiding mutable renderer state.
Environment snapshots preserve the prior fixed-clock assignments while DBC
profile/area/skybox selection, interpolation, fog, sun and shader rules remain unchanged.
Runtime produces no world-entity commands yet, so player/world output and all
baseline plans remain unchanged by the new present/remove ownership boundary.
Terrain revisit cache retains the same admitted/excluded sources, LRU touch/trim,
profile capacities and three loader adapter sites; no cache format changed.
Chunk LOD keeps horizontal XZ chunk-center distance, inclusive squared thresholds,
sparse-index omission and raw negative-radius squaring at both loader call sites.
Chunk operation planning preserves stable removals, nearest-first create sorting,
tile-LOD remove-all takeover, sparse tile-origin fallback and XZ-only distance;
loader still drains removals first through the shared `chunk_geometry` budget.
M2 positive `MDDF.uniqueId` retains `uid:<decimal>` first-owner semantics,
within-call duplicate suppression, cross-tile skip/retry and unkeyed pass-through.
M2 regular Euler, Elwynn cliff-rock shell correction, waterfall yaw/local-axis
twist, tall-waterfall anchor compensation, path normalization and caller scale
clamps are unchanged across worker grouping, placeholders and direct instances.
M2 worker grouping retains invalid-record filtering, case-sensitive lowercase
`.mdx/.mdl` conversion, first-seen group/per-group placement order, tile-local
origin subtraction and the `0.0001` scale clamp.
M2 build batching retains animated/static limit selection, minimum-one clamp,
remaining-transform cap and the exact offset/group-completion cursor rules.
WMO cache-key normalization, positive MODF identity with tile/index fallback
and world position/Euler/unclamped-scale transforms are unchanged across
lightweight render, cached-scene and live-prototype paths.
WMO first/idempotent/shared/non-owner/final/global reference behavior is
unchanged; the extracted registry owns only String reference sets while the
loader retains the parallel key-to-Node map and final-release cancellation/free.
Lightweight WMO render groups retain mesh-before-MultiMesh order, one cursor
increment and one budget permit per valid or null group; completion still
cancels the job after both raw integer cursor comparisons are exhausted.
Pending WMO render builds retain typed root/resource/cursors, FIFO order,
duplicate replacement, stale-front pop, first-occurrence cancel and three
idempotent clear sites. Queue release never frees engine objects; the loader
retains validity checks, materialization, permits and Node destruction.
Lightweight WMO render cache paths retain the same cached/pending/missing
transitions, retry behavior for absent files and map-reset versus final-shutdown
lifetime. `ResourceLoader`, script identity and `FORMAT_VERSION` validation
remain loader-owned before the extracted state accepts a Resource.
Cached WMO scene paths retain direct negative caching for missing/oversize/
request-start failures, terminal missing state for load/validation failures and
the prior transient-reset versus final-shutdown lifetime. File-size limits,
`PackedScene` probe instantiation, WMOBuilder metadata validation and probe-node
destruction remain loader-owned before state accepts a scene.
ADT water requests retain FIFO order and tile-key deduplication; tile release
removes pending requests without cancelling active work, task completion and
result publication order are unchanged, and the mutex remains limited to the
worker/main-thread mailbox. The loader still owns ADT parsing, concurrency and
profile limits, stale tile/path/root rejection, `WATER_FINALIZE` permits,
tile subtree lifetime and `water_loaded` timing.
Both raw-tile and delayed cached-tile water paths now call the same stateless
finalizer. It invokes the unchanged `ADTBuilder.build_tile_water_scene`,
attaches the returned root once and applies the existing optional recursive
Editor ownership; tile subtree lifetime and dry-root cleanup are unchanged.
M2 stale-cache rebuild selection retains the same positive billboard flag/
vertex-count tests, referenced non-identity UV rotation, exclusive
`0.000001` speed threshold, four-stage cap and first-decision-per-path cache
lifetime. Raw loading, material refresh version, M2Builder rebuild/fallback and
Mesh adoption remain loader-owned.
No new build-12340 parity claim is made; asset-backed visual/p95/p99 comparison remains pending.
- Changed files: scene-free scheduler and verifier; streamer budget composition/
permit delegation; scheduler module spec; world renderer/module registry/RENDER notes;
renderer-owned ground sample, facade/loader ground query, migrated terrain probe,
immutable environment snapshot, facade/sky adapter, migrated checkpoint time input,
contract-v1 entity snapshot, renderer-owned entity presenter, runtime composition,
scene-free terrain quality Mesh cache and loader store/restore/clear adapters,
immutable terrain chunk LOD policy, pure planner and both loader plan adapters,
pure terrain chunk geometry queue planner and loader queue-adoption adapter,
stateful M2 unique placement registry, loader reserve/release/clear adapters and
migrated historical dedupe smoke, stateless M2 placement transform resolver and
three transform consumers, stateless M2 placement grouper and worker adapter,
stateless M2 build batch planner and loader cursor adapter,
stateless WMO placement resolver and seven cache/identity/transform adapters,
stateful WMO placement registry and global/tile add/release/clear adapters,
stateless WMO render build step planner and loader cursor-adoption adapter,
typed WMO render build job/queue and loader enqueue/drain/cancel/clear adapters,
lightweight WMO render Resource/missing/request state and loader I/O/validation/
reset adapters,
cached WMO PackedScene/missing/request state and loader file-size/I/O/probe/
validation/reset adapters,
ADT water pending/task/result pipeline state and loader enqueue/start/publish/
drain/release/reset/shutdown/metrics adapters,
stateless ADT water scene finalizer and both loader build/attach adapters,
memoized M2 runtime mesh rebuild classifier and loader query/clear adapters,
expanded facade/internal-access/coordinate verifiers; work-package claims and this evidence.
- Remaining risks: worker concurrency and stale-result validation remain
streamer-owned; cancellation stops new permits but does not interrupt
in-flight work; the environment snapshot currently covers world time but not weather
or indoor state; entity PackedScene loading is synchronous and not accepted for
network-scale hot paths; terrain cache is entry-count bounded without Mesh-byte
metrics and the remaining terrain build/tasks/state/finalization stay monolithic;
chunk LOD asset-backed p95/p99 and visual acceptance remain pending;
chunk queue planning adds a second tile-state pass whose asset-backed p95/p99
still needs acceptance, while queue drains and geometry finalization remain monolithic;
private Azeroth data was absent for the asset-backed ADT placement probe; M2
asset-backed visual transform recheck, grouping/build/tasks/caches/finalization
and boundary traversal p95/p99 remain pending; path grouping is not yet
culling-driven spatial-cell grouping; M2 rebuild classification is separated,
but raw loading, resource/queue transitions and mesh finalization remain in
the loader; raw
WMO ResourceLoader/FileAccess I/O, live fallback and group materialization
remain in the loader;
asset-backed WMO placement/portal/material/leak/p95/p99 evidence remains pending;
ADT water parsing and active worker interruption remain loader-owned;
materialization is separated but remains synchronous main-thread work behind
the existing permit, and asset-backed MH2O/MCLQ traversal/leak/p95/p99/
original-client evidence is pending; M03 still needs further terrain/M2/WMO/
liquid service extraction and dependency/performance acceptance.