239 lines
12 KiB
Markdown
239 lines
12 KiB
Markdown
# M2 Build Resource Snapshot
|
|
|
|
## Metadata
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| Status | Implemented extraction |
|
|
| Target/work package | M03 / `M03-RND-M2-BUILD-RESOURCE-SNAPSHOT-001` |
|
|
| Owners | Per-build-step observed M2 resource references and outcome flags |
|
|
| Last verified | Worktree `work/sindo-main-codex/m03-m2-build-resource-snapshot`, 2026-07-18 |
|
|
| Profiles/capabilities | Existing static MultiMesh and animated-instance build paths |
|
|
|
|
## Purpose
|
|
|
|
Carry the resource observations for one M2 build operation as a typed contract:
|
|
normalized path, optional animated prototype, pending-animation state, optional
|
|
static Mesh and terminal missing-model state. The snapshot never owns engine lifetime.
|
|
|
|
## Non-goals
|
|
|
|
- Locate, request, load, validate or cache M2 resources.
|
|
- Decide dispatch action, batch count, queue order or permit consumption.
|
|
- Create, attach or free Nodes, Meshes, MultiMeshes or animated instances.
|
|
- Change animation allowlists, native candidate rules or cache paths/formats.
|
|
- Persist observations beyond one build operation.
|
|
|
|
## Context and boundaries
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
Native[StreamingWorldLoader native observation] --> Snapshot[M2BuildResourceSnapshot]
|
|
Cached[M2CachedAnimationResourceObserver] --> Snapshot
|
|
Static[M2StaticBuildResourceObserver] --> Snapshot
|
|
Snapshot --> Dispatch[M2BuildDispatchPlanner]
|
|
Snapshot --> Loader
|
|
Loader --> Animated[M2AnimatedInstanceMaterializer]
|
|
Loader --> Static[M2StaticBatchMaterializer]
|
|
```
|
|
|
|
The snapshot depends only on `RefCounted`, String, booleans and borrowed Node3D/
|
|
Mesh references. ResourceLoader, cache/pipeline state, SceneTree mutation,
|
|
RenderingServer/RIDs, files, workers, mutexes, gameplay, network and Editor APIs
|
|
are forbidden.
|
|
|
|
## Public API
|
|
|
|
| Symbol | Kind | Purpose | Thread/lifetime | Errors |
|
|
|---|---|---|---|---|
|
|
| Constructor `(normalized_path, animated_prototype, animation_pending)` | Command | Capture first-phase animation observation | Main thread; one build operation | Values retained exactly |
|
|
| `normalized_relative_path()` | Query | Return observed normalized path | Snapshot lifetime | None |
|
|
| `animated_prototype()` | Query | Borrow exact animated prototype | Main thread; no ownership transfer | May be null |
|
|
| `has_animated_prototype()` | Query | Report prototype availability | Any serialized caller | None |
|
|
| `animation_request_pending()` | Query | Report pending animation request | Any serialized caller | None |
|
|
| `adopt_static_observation(mesh, missing)` | Command | Replace second-phase static observation | Main thread | Values retained exactly, including contradictory inputs |
|
|
| `static_mesh()` | Query | Borrow exact prepared Mesh | Main thread; no ownership transfer | May be null |
|
|
| `has_static_mesh()` | Query | Report static Mesh availability | Any serialized caller | None |
|
|
| `static_model_missing()` | Query | Report terminal missing outcome | Any serialized caller | None |
|
|
| `diagnostic_snapshot()` | Query | Return detached path/availability flags | Any serialized caller | Omits engine references |
|
|
|
|
## Inputs and outputs
|
|
|
|
| Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime |
|
|
|---|---|---|---|---|---|
|
|
| Input | Normalized relative path | Loader path adapter | Snapshot/diagnostics | Copied String | Snapshot lifetime |
|
|
| Input | Optional animated prototype | Native/cached animation observer | Snapshot/materializer adapter | Borrowed exact Node3D reference | One build operation |
|
|
| Input | Animation request pending | Cached animation observer | Snapshot/dispatch planner | Boolean copy | One build operation |
|
|
| Input | Optional prepared static Mesh | Mesh cache/request path | Snapshot/materializer adapter | Borrowed exact Mesh reference | One build operation |
|
|
| Input | Static model terminally missing | Prototype cache state | Snapshot/dispatch planner | Boolean copy | One build operation |
|
|
| Output | Availability/pending/missing values | Snapshot | Dispatch planner | Scalar reads | One dispatch plan |
|
|
| Output | Borrowed prototype or Mesh | Snapshot | Loader materializer adapter | No ownership transfer | One materialization call |
|
|
| Output | Detached diagnostics | Snapshot | Tests/future metrics | Caller-owned Dictionary | Call result |
|
|
|
|
The snapshot is released after the build-loop operation. Releasing or replacing
|
|
it never frees the borrowed Node3D or Mesh.
|
|
|
|
## Data flow
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
Path[Normalized M2 path] --> Construct[Create snapshot]
|
|
Animated[Animated prototype or null] --> Construct
|
|
Pending[Animation request pending] --> Construct
|
|
Construct --> PendingCheck{Animation pending?}
|
|
PendingCheck -->|yes| Dispatch[Dispatch planner]
|
|
PendingCheck -->|no| Batch[Batch planner]
|
|
Batch --> StaticNeeded{Positive static batch?}
|
|
StaticNeeded -->|yes| Adopt[Adopt Mesh and missing observation]
|
|
StaticNeeded -->|no| Dispatch
|
|
Adopt --> Dispatch
|
|
Dispatch --> Borrow[Loader borrows selected resource]
|
|
```
|
|
|
|
## Lifecycle/state
|
|
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> AnimationObserved: construct
|
|
AnimationObserved --> AnimationObserved: animation pending or animated path
|
|
AnimationObserved --> StaticObserved: adopt static result
|
|
StaticObserved --> StaticObserved: replace static result
|
|
AnimationObserved --> Released: operation ends
|
|
StaticObserved --> Released: operation ends
|
|
Released --> [*]
|
|
```
|
|
|
|
## Main sequence
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant L as StreamingWorldLoader
|
|
participant S as M2BuildResourceSnapshot
|
|
participant B as M2BuildBatchPlanner
|
|
participant D as M2BuildDispatchPlanner
|
|
participant M as M2 materializer
|
|
L->>L: resolve native animated prototype
|
|
L->>S: construct native result
|
|
opt no native prototype
|
|
L->>L: delegate cached animation observer
|
|
L->>S: receive cached/pending snapshot
|
|
end
|
|
alt animation not pending
|
|
L->>B: plan batch using snapshot availability
|
|
opt positive static batch
|
|
L->>L: lookup/request static Mesh
|
|
L->>S: adopt_static_observation
|
|
end
|
|
end
|
|
L->>D: plan_step(batch count, snapshot)
|
|
D-->>L: action plan
|
|
opt materialization action
|
|
L->>S: borrow prototype or Mesh
|
|
L->>M: materialize selected slice
|
|
end
|
|
```
|
|
|
|
## Dependency diagram
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
Loader[StreamingWorldLoader] --> Snapshot[M2BuildResourceSnapshot]
|
|
Dispatch[M2BuildDispatchPlanner] --> Snapshot
|
|
Snapshot --> Values[String and booleans]
|
|
Snapshot --> Borrowed[Borrowed Node3D and Mesh]
|
|
Snapshot -. no dependency .-> IO[ResourceLoader / FileAccess]
|
|
Snapshot -. no dependency .-> State[Cache / pipeline / queue / scheduler]
|
|
Snapshot -. no dependency .-> Mutation[SceneTree / RenderingServer]
|
|
```
|
|
|
|
## Ownership, threading and resources
|
|
|
|
- Snapshot owns only copied scalar state and temporary references.
|
|
- Prototype/cache services retain resource state; loader owns native-first
|
|
observation order while cached/static observers own their phases.
|
|
- Scene roots remain loader/tile-owned; Mesh lifetime follows cache/resource refs.
|
|
- Dispatch planner reads only snapshot accessors and never mutates the snapshot.
|
|
- Current construction/adoption occurs on renderer main thread.
|
|
|
|
## Errors, cancellation and recovery
|
|
|
|
| Failure/state | Detection | Behavior | Diagnostic | Recovery |
|
|
|---|---|---|---|---|
|
|
| Empty path | Exact String retained | No validation or hidden normalization | Contract fixture | Loader already normalizes input |
|
|
| Null prototype/Mesh | Availability accessor false | Dispatch uses pending/missing state | Contract fixture | Loader request/cache path retries |
|
|
| Mesh and missing both true | Exact adoption | Both retained; dispatch gives ready Mesh priority | Contradiction fixture | Loader normally prevents combination |
|
|
| Static observation replaced | Explicit adoption | Latest Mesh/missing values win | Replacement fixture | None required |
|
|
| Borrowed Node externally freed | Outside snapshot | Loader validity/lifecycle gates remain authoritative | Shutdown regressions | Tile may cancel/requeue |
|
|
| Tile cancellation | Outside snapshot | Ephemeral snapshot releases references | Queue/shutdown regressions | Eligible tile may rebuild |
|
|
|
|
## Configuration and capabilities
|
|
|
|
The snapshot adds no setting. Existing animation enable/allow/deny rules, batch
|
|
limits, cache paths, render settings and scheduler permits remain external.
|
|
|
|
## Persistence, cache and migration
|
|
|
|
No observation is serialized. No ADT/M2 cache version changes and no rebake or
|
|
migration are required.
|
|
|
|
## Diagnostics and observability
|
|
|
|
`diagnostic_snapshot()` exposes normalized path and four availability/outcome
|
|
flags without Node/Mesh references. The module emits no logs. Existing loader
|
|
queue/hitch metrics remain unchanged.
|
|
|
|
## Verification
|
|
|
|
- `verify_m2_build_resource_snapshot.gd` covers exact path/reference identity,
|
|
defaults, static adoption/replacement/clear, contradictory flags, detached
|
|
diagnostics, engine lifetime, loader/dispatch boundaries and bounded timing.
|
|
- Dispatch, queue, batch, materializer, cache/pipeline, shutdown, facade,
|
|
internal-access and checkpoint regressions protect adjacent behavior.
|
|
- Fidelity evidence is exact observation transfer only; no private asset or
|
|
original-client visual claim is made.
|
|
|
|
## Extension points
|
|
|
|
`M2CachedAnimationResourceObserver` produces the cached animated phase and
|
|
`M2StaticBuildResourceObserver` produces the static phase. Native animation
|
|
observation remains loader-owned. The value contract stays independent of all
|
|
producers and of generic callback frameworks.
|
|
|
|
## Capability status
|
|
|
|
| Capability | Status | Evidence | Gap/next step |
|
|
|---|---|---|---|
|
|
| Typed per-step M2 resource observation | Implemented extraction | Identity/adoption/lifetime/source/timing verifier | Asset-backed traversal pending |
|
|
| Dispatch decision | Implemented separately | Dispatch planner verifier | Asset-backed traversal pending |
|
|
| Static lookup/request execution | Implemented separately | Static observer verifier | Asset-backed traversal pending |
|
|
| Cached animated lookup/request execution | Implemented separately | Cached observer verifier | Asset-backed traversal pending |
|
|
| Native animated lookup/build execution | Loader-owned | Native renderer regression | Service extraction pending |
|
|
| Engine lifetime/materialization | Loader/materializer-owned | Lifetime/materializer regressions | GPU/p95/p99 evidence pending |
|
|
|
|
## Known gaps and risks
|
|
|
|
- Static observation is mutable during its short two-phase construction.
|
|
- Raw Node3D/Mesh references remain necessary for current materializer APIs.
|
|
- Loader still owns synchronous native prototype attempts and terminal polling.
|
|
- Synthetic timing does not measure resource, Node or GPU work.
|
|
|
|
## Source map
|
|
|
|
| Path | Responsibility |
|
|
|---|---|
|
|
| `src/render/m2/m2_build_resource_snapshot.gd` | Typed per-step resource observations and diagnostics |
|
|
| `src/render/m2/m2_build_dispatch_planner.gd` | Snapshot-to-action planning |
|
|
| `src/render/m2/m2_static_build_resource_observer.gd` | Static snapshot production and requests |
|
|
| `src/render/m2/m2_cached_animation_resource_observer.gd` | Cached animated snapshot production and requests |
|
|
| `src/scenes/streaming/streaming_world_loader.gd` | Native animation observation and materializer borrowing |
|
|
| `src/tools/verify_m2_build_resource_snapshot.gd` | Identity/adoption/lifetime/boundary/timing regression |
|
|
|
|
## Related decisions and references
|
|
|
|
- [`m2-build-dispatch-planner.md`](m2-build-dispatch-planner.md)
|
|
- [`m2-build-batch-planner.md`](m2-build-batch-planner.md)
|
|
- [`m2-build-queue.md`](m2-build-queue.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)
|