refactor(M03): extract M2 runtime mesh finalizer
Work-Package: M03-RND-M2-RUNTIME-MESH-FINALIZER-001 Agent: sindo-main-codex Tests: 37 headless renderer/coordinate contracts pass; checkpoint dry-run 7/7; documentation and coordination gates pass Fidelity: preserves refresh version 2, classifier, rebuild and fallback transitions; no visual parity claim
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
| M2 mesh load pipeline state | Implemented extraction | [`m2-mesh-load-pipeline-state.md`](m2-mesh-load-pipeline-state.md) |
|
||||
| M2 mesh resource cache state | Implemented extraction | [`m2-mesh-resource-cache-state.md`](m2-mesh-resource-cache-state.md) |
|
||||
| M2 mesh resource extractor | Implemented extraction | [`m2-mesh-resource-extractor.md`](m2-mesh-resource-extractor.md) |
|
||||
| M2 runtime mesh finalizer | Implemented extraction | [`m2-runtime-mesh-finalizer.md`](m2-runtime-mesh-finalizer.md) |
|
||||
| WMO placement resolver | Implemented extraction | [`wmo-placement-resolver.md`](wmo-placement-resolver.md) |
|
||||
| WMO placement registry | Implemented extraction | [`wmo-placement-registry.md`](wmo-placement-registry.md) |
|
||||
| WMO render build step planner | Implemented extraction | [`wmo-render-build-step-planner.md`](wmo-render-build-step-planner.md) |
|
||||
|
||||
@@ -87,7 +87,8 @@ flowchart TD
|
||||
Permit -->|no| FIFO
|
||||
Permit -->|yes| Pop[Pop oldest terminal record]
|
||||
Pop --> Finalize[Loader gets Resource and delegates first-Mesh extraction]
|
||||
Finalize --> Adopt[Loader prepares and adopts Mesh/missing state]
|
||||
Finalize --> Prepare[M2RuntimeMeshFinalizer prepares Mesh]
|
||||
Prepare --> Adopt[Loader adopts Mesh/missing state]
|
||||
```
|
||||
|
||||
## Lifecycle/state
|
||||
@@ -137,7 +138,7 @@ flowchart TB
|
||||
Loader --> Resource[ResourceLoader]
|
||||
Loader --> Budget[RenderBudgetScheduler]
|
||||
Loader --> MeshCache[M2 Mesh resource cache and shared missing cache]
|
||||
Loader --> Classifier[M2RuntimeMeshRebuildClassifier]
|
||||
Loader --> Finalizer[M2RuntimeMeshFinalizer]
|
||||
State -. no dependency .-> Resource
|
||||
State -. no dependency .-> Budget
|
||||
State -. no dependency .-> MeshCache
|
||||
@@ -148,8 +149,9 @@ flowchart TB
|
||||
- Main thread serializes all state mutation and snapshots.
|
||||
- State owns only request/finalize Dictionaries containing Strings and status integers.
|
||||
- Loader owns ResourceLoader request lifetime and drains active paths before shutdown clear.
|
||||
- `M2MeshResourceCacheState` owns prepared static Mesh references; the loader
|
||||
owns shared missing state, material refresh, M2Builder and other engine resources.
|
||||
- `M2MeshResourceCacheState` owns prepared static Mesh references and
|
||||
`M2RuntimeMeshFinalizer` owns refresh/rebuild/fallback. The loader owns shared
|
||||
missing state, raw I/O and remaining engine resources.
|
||||
- Snapshot and diagnostic records are detached; caller mutation cannot affect state.
|
||||
|
||||
## Errors, cancellation and recovery
|
||||
@@ -206,7 +208,8 @@ rebuild policy are unchanged; no migration or rebake is required.
|
||||
| ResourceLoader I/O | Existing loader-owned | Shutdown/material regressions | I/O adapter extraction optional |
|
||||
| Mesh cache | Implemented extraction | Mesh resource cache state verifier | Asset-backed memory/leak run pending |
|
||||
| First-Mesh extraction | Implemented extraction | Resource/order/lifetime verifier | Asset-backed corrupt-scene fixture pending |
|
||||
| Mesh materialization | Existing loader-owned | Renderer/material tests | Separate preparation finalizer pending |
|
||||
| Mesh preparation | Implemented extraction | Runtime finalizer transition/rebuild verifier | Asset-backed material comparison pending |
|
||||
| Mesh materialization | Existing loader-owned | Renderer/material tests | Further safe extraction pending |
|
||||
|
||||
## Known gaps and risks
|
||||
|
||||
@@ -222,6 +225,7 @@ rebuild policy are unchanged; no migration or rebake is required.
|
||||
| `src/render/m2/m2_mesh_load_pipeline_state.gd` | Pending records, terminal FIFO and metrics |
|
||||
| `src/render/m2/m2_mesh_resource_cache_state.gd` | Prepared static Mesh references and final clear |
|
||||
| `src/render/m2/m2_mesh_resource_extractor.gd` | First-Mesh selection and temporary PackedScene lifetime |
|
||||
| `src/render/m2/m2_runtime_mesh_finalizer.gd` | Refresh/rebuild/fallback preparation |
|
||||
| `src/scenes/streaming/streaming_world_loader.gd` | Cache path choice, I/O polling, permits and Mesh/missing adoption |
|
||||
| `src/render/m2/m2_runtime_mesh_rebuild_classifier.gd` | Downstream stale Mesh rebuild decision |
|
||||
| `src/tools/verify_m2_mesh_load_pipeline_state.gd` | Lifecycle/boundary/timing regression |
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
## Purpose
|
||||
|
||||
Own the runtime cache of prepared static M2 `Mesh` references outside
|
||||
`StreamingWorldLoader`. The loader remains responsible for finding, loading,
|
||||
extracting, refreshing and materializing each Mesh.
|
||||
`StreamingWorldLoader`. Dedicated services extract and prepare each Mesh; the
|
||||
loader remains responsible for finding, loading, adopting and materializing it.
|
||||
|
||||
## Non-goals
|
||||
|
||||
@@ -34,7 +34,7 @@ flowchart LR
|
||||
Loader --> Pipeline[M2MeshLoadPipelineState]
|
||||
Pipeline --> IO[ResourceLoader]
|
||||
IO --> Extract[M2MeshResourceExtractor]
|
||||
Extract --> Prepare[Loader runtime preparation]
|
||||
Extract --> Prepare[M2RuntimeMeshFinalizer]
|
||||
Prepare --> Cache
|
||||
Loader --> Build[M2 MultiMesh materialization]
|
||||
```
|
||||
@@ -74,7 +74,7 @@ flowchart TD
|
||||
Cached -->|no| Missing{Shared missing state?}
|
||||
Missing -->|yes| Null[Return null]
|
||||
Missing -->|no| Load[Loader request or synchronous fallback]
|
||||
Load --> Prepare[Loader extracts and prepares Mesh]
|
||||
Load --> Prepare[Extractor and runtime finalizer prepare Mesh]
|
||||
Prepare --> Valid{Prepared Mesh valid?}
|
||||
Valid -->|yes| Store[Store or replace cache entry]
|
||||
Valid -->|no| MarkMissing[Loader updates shared missing state]
|
||||
@@ -104,7 +104,7 @@ sequenceDiagram
|
||||
Loader->>Cache: find/has normalized path
|
||||
alt cache miss
|
||||
Loader->>Pipeline: request/poll/finalize record
|
||||
Loader->>Loader: ResourceLoader get + extract + prepare
|
||||
Loader->>Loader: ResourceLoader get; delegate extract + prepare
|
||||
Loader->>Cache: store_mesh(path, prepared Mesh)
|
||||
end
|
||||
Cache-->>Loader: exact retained Mesh
|
||||
@@ -117,7 +117,7 @@ sequenceDiagram
|
||||
flowchart TB
|
||||
Loader[StreamingWorldLoader] --> Cache[M2MeshResourceCacheState]
|
||||
Loader --> Pipeline[M2MeshLoadPipelineState]
|
||||
Loader --> Classifier[M2RuntimeMeshRebuildClassifier]
|
||||
Loader --> Finalizer[M2RuntimeMeshFinalizer]
|
||||
Loader --> Builder[M2Builder and MultiMesh]
|
||||
Cache --> Mesh[Godot Mesh Resource]
|
||||
Cache -. no dependency .-> Pipeline
|
||||
@@ -146,8 +146,9 @@ flowchart TB
|
||||
|
||||
## Configuration and capabilities
|
||||
|
||||
The module adds no setting, budget or profile branch. Cache path order,
|
||||
`M2_MATERIAL_REFRESH_VERSION`, finalize permits and batching remain loader-owned.
|
||||
The module adds no setting, budget or profile branch. Cache path order, finalize
|
||||
permits and batching remain loader-owned; refresh version `2` belongs to
|
||||
`M2RuntimeMeshFinalizer`.
|
||||
|
||||
## Persistence, cache and migration
|
||||
|
||||
@@ -173,8 +174,8 @@ the historical Mesh cache had no queue contribution or log site.
|
||||
|
||||
## Extension points
|
||||
|
||||
- A separate M2 Mesh resource finalizer may later return a prepared Mesh for
|
||||
`store_mesh` without changing cache ownership.
|
||||
- `M2RuntimeMeshFinalizer` returns a prepared Mesh for `store_mesh` without
|
||||
changing cache ownership.
|
||||
- Eviction requires measured memory pressure and explicit lifetime semantics.
|
||||
|
||||
## Capability status
|
||||
@@ -184,7 +185,7 @@ the historical Mesh cache had no queue contribution or log site.
|
||||
| Prepared static M2 Mesh cache | Implemented extraction | Contract/source/timing verifier | Asset-backed memory/leak run pending |
|
||||
| M2 Mesh request lifecycle | Implemented extraction | Pipeline state verifier | ResourceLoader I/O remains loader-owned |
|
||||
| M2 Mesh extraction | Implemented extraction | Resource/order/lifetime verifier | Asset-backed corrupt-scene fixture pending |
|
||||
| M2 Mesh preparation | Existing loader-owned | Material/classifier regressions | Separate finalizer extraction next |
|
||||
| M2 Mesh preparation | Implemented extraction | Runtime finalizer transition/rebuild verifier | Asset-backed material comparison pending |
|
||||
|
||||
## Known gaps and risks
|
||||
|
||||
@@ -200,7 +201,8 @@ the historical Mesh cache had no queue contribution or log site.
|
||||
|---|---|
|
||||
| `src/render/m2/m2_mesh_resource_cache_state.gd` | Prepared Mesh references and final clear |
|
||||
| `src/render/m2/m2_mesh_resource_extractor.gd` | First-Mesh selection and temporary PackedScene lifetime |
|
||||
| `src/scenes/streaming/streaming_world_loader.gd` | Normalization, I/O, preparation, missing state and materialization |
|
||||
| `src/scenes/streaming/streaming_world_loader.gd` | Normalization, raw/resource I/O, missing state and materialization |
|
||||
| `src/render/m2/m2_runtime_mesh_finalizer.gd` | Refresh/rebuild/fallback preparation |
|
||||
| `src/render/m2/m2_mesh_load_pipeline_state.gd` | Pending request and terminal finalize records |
|
||||
| `src/tools/verify_m2_mesh_resource_cache_state.gd` | Cache ownership/lifetime/boundary/timing regression |
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ flowchart LR
|
||||
Loader --> Resource[Loaded Mesh or PackedScene Resource]
|
||||
Resource --> Extractor[M2MeshResourceExtractor]
|
||||
Extractor -->|first Mesh or null| Loader
|
||||
Loader --> Prepare[Material refresh/rebuild]
|
||||
Loader --> Prepare[M2RuntimeMeshFinalizer]
|
||||
Prepare --> Cache[M2MeshResourceCacheState]
|
||||
Prototype[Existing M2 Node subtree] --> Extractor
|
||||
```
|
||||
@@ -116,7 +116,7 @@ flowchart TB
|
||||
Extractor --> Types[Resource / PackedScene / Node / Mesh]
|
||||
Loader --> Pipeline[M2MeshLoadPipelineState]
|
||||
Loader --> Cache[M2MeshResourceCacheState]
|
||||
Loader --> Classifier[M2RuntimeMeshRebuildClassifier]
|
||||
Loader --> Finalizer[M2RuntimeMeshFinalizer]
|
||||
Extractor -. no dependency .-> Pipeline
|
||||
Extractor -. no dependency .-> Cache
|
||||
Extractor -. no dependency .-> Classifier
|
||||
@@ -128,7 +128,8 @@ flowchart TB
|
||||
- Direct and subtree Mesh references are borrowed without duplication.
|
||||
- A PackedScene temporary root is extractor-owned and synchronously freed.
|
||||
- Existing prototype/rebuild subtrees remain caller-owned and are never mutated.
|
||||
- Cache retention and Mesh material preparation remain loader/service concerns.
|
||||
- Cache retention remains a cache-state concern; runtime material preparation
|
||||
belongs to `M2RuntimeMeshFinalizer`.
|
||||
|
||||
## Errors, cancellation and recovery
|
||||
|
||||
@@ -167,8 +168,8 @@ normalized M2 path. Its verifier measures traversal time and temporary Node coun
|
||||
|
||||
## Extension points
|
||||
|
||||
- Material refresh/rebuild can become a separate finalizer consuming the Mesh
|
||||
returned here and storing its result in `M2MeshResourceCacheState`.
|
||||
- `M2RuntimeMeshFinalizer` consumes the Mesh returned here and the loader stores
|
||||
its result in `M2MeshResourceCacheState`.
|
||||
- Broader generic scene traversal is intentionally excluded until another real
|
||||
consumer requires the same exact contract.
|
||||
|
||||
@@ -178,7 +179,7 @@ normalized M2 path. Its verifier measures traversal time and temporary Node coun
|
||||
|---|---|---|---|
|
||||
| Direct/PackedScene first-Mesh extraction | Implemented extraction | Resource/order/lifetime verifier | Asset-backed corrupt-scene fixture pending |
|
||||
| Prototype/rebuild subtree selection | Implemented extraction | Synthetic preorder verifier | Asset-backed M2 traversal pending |
|
||||
| Material refresh/rebuild finalization | Existing loader-owned | Classifier/material regressions | Separate finalizer extraction next |
|
||||
| Material refresh/rebuild finalization | Implemented extraction | Runtime finalizer transition/rebuild verifier | Asset-backed material comparison pending |
|
||||
|
||||
## Known gaps and risks
|
||||
|
||||
@@ -193,7 +194,8 @@ normalized M2 path. Its verifier measures traversal time and temporary Node coun
|
||||
| Path | Responsibility |
|
||||
|---|---|
|
||||
| `src/render/m2/m2_mesh_resource_extractor.gd` | First-Mesh traversal and temporary PackedScene lifetime |
|
||||
| `src/scenes/streaming/streaming_world_loader.gd` | ResourceLoader, preparation, caching, missing state and materialization |
|
||||
| `src/scenes/streaming/streaming_world_loader.gd` | ResourceLoader/raw I/O, caching, missing state and materialization |
|
||||
| `src/render/m2/m2_runtime_mesh_finalizer.gd` | Refresh/rebuild/fallback preparation |
|
||||
| `src/render/m2/m2_mesh_resource_cache_state.gd` | Prepared Mesh retention |
|
||||
| `src/tools/verify_m2_mesh_resource_extractor.gd` | Resource/order/lifetime/boundary/timing regression |
|
||||
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
# M2 Runtime Mesh Finalizer
|
||||
|
||||
## Metadata
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Status | Implemented extraction |
|
||||
| Target/work package | M03 / `M03-RND-M2-RUNTIME-MESH-FINALIZER-001` |
|
||||
| Owners | Stale Mesh refresh version, rebuild classification, M2Builder rebuild and fallback |
|
||||
| Last verified | Worktree `work/sindo-main-codex/m03-m2-runtime-mesh-finalizer`, 2026-07-17 |
|
||||
| Profiles/capabilities | Static cached and prototype M2 runtime material preparation |
|
||||
|
||||
## Purpose
|
||||
|
||||
Finalize an extracted static M2 Mesh for runtime use by accepting already-loaded
|
||||
raw M2 data, preserving material refresh version `2`, rebuilding only billboard/
|
||||
UV-rotation cases and returning the historical original-Mesh fallback.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Read raw `.m2` files or call ClassDB/FileAccess/ResourceLoader.
|
||||
- Own request/finalize queues, Mesh/missing/prototype caches or MultiMeshes.
|
||||
- Select cache paths or extract a Mesh from the originally loaded Resource.
|
||||
- Change classifier predicates, builder materials, refresh version or profiles.
|
||||
|
||||
## Context and boundaries
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Extractor[M2MeshResourceExtractor] --> Loader[StreamingWorldLoader]
|
||||
Loader -->|is raw data required?| Finalizer[M2RuntimeMeshFinalizer]
|
||||
Loader --> Raw[M2Loader raw Dictionary]
|
||||
Raw --> Finalizer
|
||||
Finalizer --> Classifier[M2RuntimeMeshRebuildClassifier]
|
||||
Finalizer --> Builder[M2Builder]
|
||||
Builder --> Subtree[M2MeshResourceExtractor]
|
||||
Finalizer -->|prepared Mesh| Cache[M2MeshResourceCacheState]
|
||||
```
|
||||
|
||||
The finalizer may use Mesh metadata, raw value Dictionaries, M2Builder and the
|
||||
two existing scene-free M2 services. Raw-file I/O, cache state, render permits,
|
||||
Nodes outside temporary rebuild roots and other application layers are forbidden.
|
||||
|
||||
## Public API
|
||||
|
||||
| Symbol | Kind | Purpose | Thread/lifetime | Errors |
|
||||
|---|---|---|---|---|
|
||||
| `requires_raw_data_for_refresh(mesh)` | Query | Tell loader whether stale Mesh needs raw-file lookup | Renderer main thread | Null/current false |
|
||||
| `finalize_mesh(path, mesh, raw_data, extracted_directory)` | Command/query | Return current, marked, rebuilt or fallback Mesh | Renderer main thread; one finalize operation | Null Mesh returns null; invalid rebuild falls back |
|
||||
| `clear()` | Command | Clear memoized classifier decisions | Map reset/final shutdown | Idempotent |
|
||||
| `cached_rebuild_decision_count()` | Diagnostic query | Expose memoized path-decision count | Tests/diagnostics | None |
|
||||
|
||||
## Inputs and outputs
|
||||
|
||||
| Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime |
|
||||
|---|---|---|---|---|---|
|
||||
| Input | Extracted Mesh and normalized M2 path | Loader/extractor adapter | Finalizer | Borrowed Mesh reference/String copy | One call |
|
||||
| Input | Already-loaded raw M2 Dictionary | Loader raw-file boundary | Classifier/M2Builder | Caller-owned value container | One call |
|
||||
| Input | Extracted directory path | Loader configuration | M2Builder texture resolution | Copied String | One rebuild |
|
||||
| Output | Original or rebuilt current Mesh | Finalizer | Cache/prototype adapter | Borrowed/new Resource reference | Cache may retain |
|
||||
|
||||
Side effects are Mesh refresh metadata, classifier memoization and temporary
|
||||
M2Builder prototype creation/destruction during required rebuilds.
|
||||
|
||||
## Data flow
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Mesh[Extracted Mesh] --> Current{Refresh version >= 2?}
|
||||
Current -->|yes| ReturnOriginal[Return original unchanged]
|
||||
Current -->|no| NeedRaw[Loader supplies raw M2 data]
|
||||
NeedRaw --> HasData{Raw data available?}
|
||||
HasData -->|no| Mark[Mark original version 2]
|
||||
HasData -->|yes| Classify{Billboard or UV rotation?}
|
||||
Classify -->|no| Mark
|
||||
Classify -->|yes| Build[M2Builder temporary prototype]
|
||||
Build --> Extract[M2MeshResourceExtractor first Mesh]
|
||||
Extract --> Rebuilt{Rebuilt Mesh exists?}
|
||||
Rebuilt -->|yes| ReturnRebuilt[Return rebuilt Mesh]
|
||||
Rebuilt -->|no| Mark
|
||||
Mark --> ReturnOriginal
|
||||
```
|
||||
|
||||
## Lifecycle/state
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Current: Mesh metadata >= 2
|
||||
[*] --> Stale: Mesh metadata < 2
|
||||
Stale --> Current: empty/ordinary data marks original
|
||||
Stale --> Rebuilding: classifier requires rebuild
|
||||
Rebuilding --> Current: rebuilt Mesh returned
|
||||
Rebuilding --> Current: failure marks original fallback
|
||||
Current --> Current: later preparation is no-op
|
||||
```
|
||||
|
||||
Classifier decisions are memoized per normalized path until either existing
|
||||
map/reset clear site calls `clear()`.
|
||||
|
||||
## Main sequence
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Loader as StreamingWorldLoader
|
||||
participant Finalizer as M2RuntimeMeshFinalizer
|
||||
participant Raw as M2Loader boundary
|
||||
participant Classifier as RebuildClassifier
|
||||
participant Builder as M2Builder
|
||||
Loader->>Finalizer: requires_raw_data_for_refresh(mesh)
|
||||
alt current Mesh
|
||||
Finalizer-->>Loader: false; reuse Mesh
|
||||
else stale Mesh
|
||||
Finalizer-->>Loader: true
|
||||
Loader->>Raw: load raw Dictionary
|
||||
Loader->>Finalizer: finalize_mesh(path, mesh, raw, extracted dir)
|
||||
Finalizer->>Classifier: needs_runtime_mesh_rebuild(path, raw)
|
||||
opt rebuild required
|
||||
Finalizer->>Builder: build(raw, extracted dir)
|
||||
Finalizer->>Finalizer: extract first Mesh; free prototype
|
||||
end
|
||||
Finalizer-->>Loader: rebuilt or marked fallback Mesh
|
||||
end
|
||||
```
|
||||
|
||||
## Dependency diagram
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Loader[StreamingWorldLoader] --> Finalizer[M2RuntimeMeshFinalizer]
|
||||
Finalizer --> Classifier[M2RuntimeMeshRebuildClassifier]
|
||||
Finalizer --> Extractor[M2MeshResourceExtractor]
|
||||
Finalizer --> Builder[M2Builder]
|
||||
Loader --> Raw[FileAccess / ClassDB M2Loader]
|
||||
Loader --> Cache[M2MeshResourceCacheState]
|
||||
Finalizer -. no dependency .-> Raw
|
||||
Finalizer -. no dependency .-> Cache
|
||||
```
|
||||
|
||||
## Ownership, threading and resources
|
||||
|
||||
- Renderer main thread executes metadata changes and M2Builder work.
|
||||
- Loader owns raw M2 file existence/load calls and supplies value data.
|
||||
- Finalizer owns classifier memoization and temporary rebuild prototype lifetime.
|
||||
- M2Builder owns construction rules; extractor selects the first rebuilt Mesh.
|
||||
- Cache/prototype adapters decide where the returned Mesh reference is retained.
|
||||
|
||||
## Errors, cancellation and recovery
|
||||
|
||||
| Failure/state | Detection | Behavior | Diagnostic | Recovery |
|
||||
|---|---|---|---|---|
|
||||
| Null Mesh | Guard | Return null | Contract verifier | Caller marks missing |
|
||||
| Current Mesh | Metadata query | Return exact reference; no raw load | Contract verifier | None needed |
|
||||
| Raw file/parse unavailable | Empty Dictionary from loader | Mark/reuse original | Existing renderer behavior | Source/cache repair |
|
||||
| Ordinary stale Mesh | Classifier false | Mark/reuse original | Classifier verifier | None needed |
|
||||
| Builder produces no Mesh | Extractor null | Mark/reuse original | Finalizer fallback fixture | Source/builder repair |
|
||||
| Reset/shutdown | Loader lifecycle | Clear classifier decisions | Source/clear verifier | Recompute next session |
|
||||
|
||||
## Configuration and capabilities
|
||||
|
||||
`MATERIAL_REFRESH_VERSION` remains `2` and is now owned by this finalizer.
|
||||
Finalize permits, cache paths, extracted directory configuration and quality
|
||||
profiles remain unchanged in the loader.
|
||||
|
||||
## Persistence, cache and migration
|
||||
|
||||
No new format is serialized. Existing Mesh metadata key
|
||||
`wow_m2_material_refresh_version`, M2Builder `MATERIAL_FORMAT_VERSION == 2` and
|
||||
`.tscn/.glb` caches are unchanged; no migration or rebake is introduced.
|
||||
|
||||
## Diagnostics and observability
|
||||
|
||||
`cached_rebuild_decision_count` exposes only a scalar count. Existing renderer
|
||||
logs/queue metrics are unchanged. Normalized M2 path remains the correlation key.
|
||||
|
||||
## Verification
|
||||
|
||||
- `verify_m2_runtime_mesh_finalizer.gd`: null/current/raw requirement, empty and
|
||||
ordinary marking, synthetic triangle billboard rebuild, rebuild failure
|
||||
fallback, refresh metadata, classifier clear, source boundary and 100-by-256
|
||||
bounded finalization.
|
||||
- Classifier/extractor/cache/pipeline/material/shutdown/M2 build regressions cover
|
||||
adjacent behavior. No asset-backed or original-client visual claim is made.
|
||||
|
||||
## Extension points
|
||||
|
||||
- Raw M2 file loading may later move behind a dedicated repository without
|
||||
changing the finalizer's value-data contract.
|
||||
- Refresh versions above `2` require explicit cache/fidelity evidence and docs.
|
||||
|
||||
## Capability status
|
||||
|
||||
| Capability | Status | Evidence | Gap/next step |
|
||||
|---|---|---|---|
|
||||
| Runtime Mesh refresh/fallback | Implemented extraction | Synthetic transition/rebuild verifier | Asset-backed corrupt/stale cache pending |
|
||||
| Rebuild predicate | Implemented extraction dependency | Classifier fixtures | Original-client material comparison pending |
|
||||
| Raw M2 refresh I/O | Existing loader-owned | Source boundary | Separate repository extraction optional |
|
||||
|
||||
## Known gaps and risks
|
||||
|
||||
- Required rebuild remains synchronous main-thread work behind existing permits.
|
||||
- Synthetic geometry proves transition/build behavior, not full asset materials.
|
||||
- No proprietary M2 traversal, descriptor-pressure/leak, p95/p99 or paired
|
||||
original-client capture is included.
|
||||
|
||||
## Source map
|
||||
|
||||
| Path | Responsibility |
|
||||
|---|---|
|
||||
| `src/render/m2/m2_runtime_mesh_finalizer.gd` | Refresh version, classification, rebuild and fallback |
|
||||
| `src/scenes/streaming/streaming_world_loader.gd` | Raw-file I/O and returned-Mesh adoption |
|
||||
| `src/render/m2/m2_runtime_mesh_rebuild_classifier.gd` | Memoized billboard/UV-rotation predicate |
|
||||
| `src/render/m2/m2_mesh_resource_extractor.gd` | First rebuilt-Mesh selection |
|
||||
| `src/tools/verify_m2_runtime_mesh_finalizer.gd` | Transition/rebuild/boundary/timing regression |
|
||||
|
||||
## Related decisions and references
|
||||
|
||||
- [`m2-runtime-mesh-rebuild-classifier.md`](m2-runtime-mesh-rebuild-classifier.md)
|
||||
- [`m2-mesh-resource-extractor.md`](m2-mesh-resource-extractor.md)
|
||||
- [`m2-mesh-resource-cache-state.md`](m2-mesh-resource-cache-state.md)
|
||||
- [`world-renderer.md`](world-renderer.md)
|
||||
- [`../../RENDER.md`](../../RENDER.md)
|
||||
- [`../../targets/roadmap/02-rendering-and-graphics.md`](../../targets/roadmap/02-rendering-and-graphics.md)
|
||||
@@ -29,13 +29,13 @@ runtime-cache lifetime.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Cache[Stale cached M2 Mesh] --> Loader[StreamingWorldLoader]
|
||||
Loader --> Raw[M2Loader raw Dictionary]
|
||||
Cache[Stale cached M2 Mesh] --> Finalizer[M2RuntimeMeshFinalizer]
|
||||
Loader[StreamingWorldLoader] --> Raw[M2Loader raw Dictionary]
|
||||
Raw --> Classifier[M2RuntimeMeshRebuildClassifier]
|
||||
Classifier --> Decision[Memoized rebuild boolean]
|
||||
Decision --> Loader
|
||||
Loader -->|true| Builder[M2Builder rebuild]
|
||||
Loader -->|false| Refresh[Mark material refresh version]
|
||||
Decision --> Finalizer
|
||||
Finalizer -->|true| Builder[M2Builder rebuild]
|
||||
Finalizer -->|false| Refresh[Mark material refresh version]
|
||||
```
|
||||
|
||||
Allowed dependencies are Dictionary/Array, `PackedInt32Array`, `Vector4` and
|
||||
@@ -57,7 +57,7 @@ WorkerThreadPool, Mesh/Node/RID ownership and other layers are forbidden.
|
||||
|---|---|---|---|---|---|
|
||||
| Input | Normalized M2 relative path | Loader cache lookup | Classifier cache key | String value copied | Until clear |
|
||||
| Input | Raw M2 batches/transforms/combos Dictionary | Native `M2Loader` adapter | Classifier | Borrowed; not mutated | First classification call per path |
|
||||
| Output | Rebuild-required boolean | Classifier | Loader material-refresh adapter | Scalar | Memoized until clear |
|
||||
| Output | Rebuild-required boolean | Classifier | Runtime Mesh finalizer | Scalar | Memoized until clear |
|
||||
| Output | Detached decision Dictionary | Classifier | Verifier/future diagnostics | Caller-owned copy | Snapshot lifetime |
|
||||
|
||||
Side effects are limited to inserting and clearing boolean memoization entries.
|
||||
@@ -103,16 +103,18 @@ stateDiagram-v2
|
||||
sequenceDiagram
|
||||
participant Loader as StreamingWorldLoader
|
||||
participant Native as M2Loader
|
||||
participant Finalizer as M2RuntimeMeshFinalizer
|
||||
participant Classifier as M2RuntimeMeshRebuildClassifier
|
||||
participant Builder as M2Builder
|
||||
Loader->>Native: load_m2(normalized path)
|
||||
Native-->>Loader: raw Dictionary
|
||||
Loader->>Classifier: needs_runtime_mesh_rebuild(path, data)
|
||||
Classifier-->>Loader: memoized boolean
|
||||
Loader->>Finalizer: finalize_mesh(path, mesh, data, dir)
|
||||
Finalizer->>Classifier: needs_runtime_mesh_rebuild(path, data)
|
||||
Classifier-->>Finalizer: memoized boolean
|
||||
alt rebuild required
|
||||
Loader->>Builder: rebuild mesh from raw data
|
||||
Finalizer->>Builder: rebuild mesh from raw data
|
||||
else no rebuild required
|
||||
Loader->>Loader: stamp material refresh version
|
||||
Finalizer->>Finalizer: stamp material refresh version
|
||||
end
|
||||
```
|
||||
|
||||
@@ -120,7 +122,8 @@ sequenceDiagram
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Loader[StreamingWorldLoader] --> Classifier[M2RuntimeMeshRebuildClassifier]
|
||||
Loader[StreamingWorldLoader] --> Finalizer[M2RuntimeMeshFinalizer]
|
||||
Finalizer --> Classifier[M2RuntimeMeshRebuildClassifier]
|
||||
Loader --> Native[M2Loader]
|
||||
Loader --> Builder[M2Builder]
|
||||
Loader --> Cache[M2 Mesh/Scene caches]
|
||||
@@ -132,8 +135,8 @@ flowchart TB
|
||||
## Ownership, threading and resources
|
||||
|
||||
- The classifier owns only normalized-path boolean entries.
|
||||
- The loader owns raw loading, cache/resource selection, Mesh replacement and
|
||||
material refresh metadata.
|
||||
- The finalizer owns classifier lifetime, rebuild decisions and refresh metadata.
|
||||
- The loader owns raw loading, cache/resource selection and Mesh adoption.
|
||||
- Raw Dictionaries are borrowed and never retained; only the computed boolean is cached.
|
||||
- Current calls and clears are serialized on the renderer main thread.
|
||||
- No Node, Resource, Mesh, material or RID reference crosses into the classifier.
|
||||
@@ -154,7 +157,7 @@ flowchart TB
|
||||
|---|---|---|---|---|
|
||||
| Maximum texture stages inspected | `4` | Existing M2 material path | No | Preserves historical four-stage shader boundary |
|
||||
| UV rotation-speed epsilon | `0.000001` exclusive | Existing M2 material path | No | Larger absolute speed requires rebuild |
|
||||
| `M2_MATERIAL_REFRESH_VERSION` | Loader constant `2` | All | Code version | Gates whether classifier is called |
|
||||
| `MATERIAL_REFRESH_VERSION` | Finalizer constant `2` | All | Code version | Gates whether classifier is called |
|
||||
|
||||
## Persistence, cache and migration
|
||||
|
||||
@@ -193,7 +196,7 @@ reset/shutdown sites. No persisted cache version or rebuild instruction changes.
|
||||
| Billboard rebuild classification | Implemented extraction | Flag/count fixtures | Asset-backed cache refresh timing pending |
|
||||
| UV-rotation rebuild classification | Implemented extraction | Combo/stage/threshold fixtures | More build-12340 material fixtures pending |
|
||||
| Runtime memoization lifetime | Implemented extraction | First-decision/clear/source fixtures | Byte/count runtime metric not exposed |
|
||||
| M2 mesh loading/finalization | Existing loader-owned | Material/shutdown regressions | Separate state extraction pending |
|
||||
| Runtime Mesh finalization | Implemented extraction | Finalizer transition/rebuild fixtures | Asset-backed material comparison pending |
|
||||
|
||||
## Known gaps and risks
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
| Status | Partial |
|
||||
| Target/work package | M00 baseline; `M01-RND-STREAMING-FOCUS-001`; `M01-QAR-SERVER-SPAWN-RENDERER-001`; M03 facade/planner/scheduler/internal-access/ground/environment/entity packages; M03 terrain packages; M03 M2 packages; M03 WMO placement package |
|
||||
| Owners | Renderer workstream / milestone integrator |
|
||||
| Last verified | Worktree `work/sindo-main-codex/m03-m2-mesh-resource-extractor`, 2026-07-17 |
|
||||
| Last verified | Worktree `work/sindo-main-codex/m03-m2-runtime-mesh-finalizer`, 2026-07-17 |
|
||||
| Profiles/capabilities | `Performance`, `Balanced`, `High`, `Custom`; Blizzlike fidelity incomplete |
|
||||
|
||||
## Purpose
|
||||
@@ -136,6 +136,7 @@ from externally reading/writing loader-private queue, task, cache and tile-state
|
||||
| `M2MeshLoadPipelineState` | Internal M2 async-state service | Owns static Mesh pending request records and terminal finalize FIFO | Renderer main thread; map/session | Empty/duplicate/unknown transitions rejected |
|
||||
| `M2MeshResourceCacheState` | Internal M2 Resource cache | Owns prepared static Mesh references by normalized path | Renderer main thread; final shutdown | Empty path/null Mesh rejected; same path replaces |
|
||||
| `M2MeshResourceExtractor` | Internal M2 scene/resource service | Selects first Mesh from direct Resource, PackedScene or Node subtree | Renderer main thread; stateless except temporary instance | Invalid/no Mesh returns null; temporary PackedScene root freed |
|
||||
| `M2RuntimeMeshFinalizer` | Internal M2 preparation service | Owns refresh version, rebuild classification, M2Builder rebuild and fallback | Renderer main thread; decisions cached until reset | Null returns null; missing/failed rebuild marks and reuses original Mesh |
|
||||
| `WmoPlacementResolver.normalize_relative_path/resolve_unique_key/resolve_world_transform` | Internal pure WMO service | Resolves cache key, registry identity and world transform | Main/any thread; stateless | Missing UID uses tile/index fallback; transform fields use historical defaults |
|
||||
| `WmoPlacementRegistry.add_reference/release_reference/contains/active_count/diagnostic_snapshot/clear` | Internal WMO service | Owns placement-key to tile/global reference sets | Renderer main thread; map session | Empty/unknown/non-owner input is rejected without mutation |
|
||||
| `WmoRenderBuildStepPlanner.plan_step` | Internal pure WMO service | Selects one mesh-first lightweight render-group operation and next cursors | Main/any thread; stateless | Raw integer comparisons are preserved without clamping |
|
||||
@@ -370,17 +371,20 @@ sequenceDiagram
|
||||
performs the existing ADTBuilder call, tile attach and optional recursive
|
||||
Editor ownership on the main thread without retaining the generated subtree.
|
||||
- `M2RuntimeMeshRebuildClassifier` owns only normalized-path boolean decisions
|
||||
for billboard/UV-rotation material refresh. The loader retains raw M2 loading,
|
||||
refresh-version checks, Mesh rebuild/adoption and both historical clear sites.
|
||||
for billboard/UV-rotation material refresh and is composed by the runtime Mesh
|
||||
finalizer. The loader retains raw M2 loading and returned-Mesh adoption.
|
||||
- `M2MeshLoadPipelineState` owns static M2 pending Resource paths, opaque
|
||||
terminal statuses and completion-order finalize FIFO. The loader retains cache
|
||||
path selection, ResourceLoader calls, permits, shared missing state and adoption.
|
||||
- `M2MeshResourceCacheState` owns prepared static Mesh references and releases
|
||||
them at the existing final-shutdown site. The loader retains material
|
||||
refresh/rebuild, missing/prototype state and materialization.
|
||||
them at the existing final-shutdown site. The loader retains missing/prototype
|
||||
state and materialization.
|
||||
- `M2MeshResourceExtractor` owns depth-first first-Mesh selection and temporary
|
||||
PackedScene instance destruction. The loader retains ResourceLoader I/O,
|
||||
runtime preparation, cache/missing adoption and materialization.
|
||||
cache/missing adoption and materialization.
|
||||
- `M2RuntimeMeshFinalizer` owns refresh version `2`, classifier lifetime,
|
||||
M2Builder rebuild and original-Mesh fallback. The loader loads raw data only
|
||||
after the finalizer reports that a cached Mesh is stale.
|
||||
- Rendered-ground query results and diagnostic snapshots are caller-owned values;
|
||||
the facade never returns Mesh, Node, tile-state or queue references.
|
||||
- Loaded-mesh ground sampling is renderer diagnostics, not authoritative gameplay
|
||||
@@ -585,6 +589,7 @@ Exact exported settings and cache versions remain documented in [`../../RENDER.m
|
||||
| `src/render/m2/m2_mesh_load_pipeline_state.gd` | Static M2 pending Resource paths, terminal statuses and finalize FIFO |
|
||||
| `src/render/m2/m2_mesh_resource_cache_state.gd` | Prepared static M2 Mesh references and final-shutdown release |
|
||||
| `src/render/m2/m2_mesh_resource_extractor.gd` | First-Mesh selection and temporary PackedScene instance lifetime |
|
||||
| `src/render/m2/m2_runtime_mesh_finalizer.gd` | Runtime refresh version, rebuild classification/build and fallback |
|
||||
| `src/render/streaming/streaming_target_planner.gd` | Scene-free wanted/retained ADT target calculation |
|
||||
| `src/render/streaming/streaming_target_policy.gd` | Immutable renderer radius/prefetch policy |
|
||||
| `src/render/streaming/streaming_target_plan.gd` | Immutable planner result with read-only tile-key sets |
|
||||
@@ -603,6 +608,7 @@ Exact exported settings and cache versions remain documented in [`../../RENDER.m
|
||||
| `src/tools/verify_m2_mesh_load_pipeline_state.gd` | Static M2 request/terminal/FIFO/boundary/timing regression |
|
||||
| `src/tools/verify_m2_mesh_resource_cache_state.gd` | Static M2 Mesh cache ownership/lifetime/boundary/timing regression |
|
||||
| `src/tools/verify_m2_mesh_resource_extractor.gd` | M2 direct/PackedScene/subtree order/lifetime/boundary/timing regression |
|
||||
| `src/tools/verify_m2_runtime_mesh_finalizer.gd` | M2 current/stale/rebuild/fallback/boundary/timing regression |
|
||||
| `src/tools/verify_streaming_target_planner.gd` | Planner behavior, dependency and bounded timing regression |
|
||||
| `src/tools/verify_render_budget_scheduler.gd` | Scheduler bounds, shared-lane priority, cancellation and timing regression |
|
||||
| `src/tools/verify_renderer_internal_access.gd` | Gameplay/EditorPlugin/registered renderer-tool boundary gate derived from private streamer fields |
|
||||
|
||||
Reference in New Issue
Block a user