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:
2026-07-17 15:01:52 +04:00
parent 951bd54fff
commit ece7724a28
15 changed files with 626 additions and 85 deletions
@@ -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