226 lines
10 KiB
Markdown
226 lines
10 KiB
Markdown
# M2 Animation Load Pipeline State
|
|
|
|
## Metadata
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| Status | Implemented extraction |
|
|
| Target/work package | M03 / `M03-RND-M2-ANIMATION-LOAD-PIPELINE-001` |
|
|
| Owners | Animated M2 threaded request records and terminal finalize FIFO |
|
|
| Last verified | Worktree `work/sindo-main-codex/m03-m2-animation-load-pipeline`, 2026-07-17 |
|
|
| Profiles/capabilities | Existing optional cached-GLB animated M2 path |
|
|
|
|
## Purpose
|
|
|
|
Own cross-frame bookkeeping between a successful animated M2 ResourceLoader
|
|
request, terminal polling and budgeted main-thread scene finalization. This is
|
|
an exact state extraction; cached animation eligibility and request admission
|
|
belong to `M2CachedAnimationResourceObserver`, while scene finalization and
|
|
retained Node lifecycle belong to `M2AnimatedSceneFinalizer` and
|
|
`M2PrototypeCacheState`.
|
|
|
|
## Non-goals
|
|
|
|
- Select cache paths, interpret ResourceLoader statuses or perform I/O.
|
|
- Decide animated/static fallback or own prototype Nodes.
|
|
- Instantiate PackedScenes, repair materials or consume render permits.
|
|
- Merge the distinct animated and static-Mesh pipelines.
|
|
|
|
## Context and boundaries
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
Observer[M2CachedAnimationResourceObserver] --> IO[ResourceLoader request]
|
|
Observer --> State[M2AnimationLoadPipelineState]
|
|
Loader[StreamingWorldLoader] --> IO
|
|
Loader --> State
|
|
State -->|detached pending records| Loader
|
|
Loader -->|opaque terminal status| State
|
|
State -->|completion FIFO| Loader
|
|
Loader --> Budget[M2_ANIMATION_FINALIZE permit]
|
|
Loader --> Prototype[M2PrototypeCacheState]
|
|
```
|
|
|
|
Allowed dependencies are value containers, Strings and opaque integer statuses.
|
|
ResourceLoader, workers, scheduler, Node/Resource/Mesh ownership and other
|
|
renderer services are forbidden.
|
|
|
|
## Public API
|
|
|
|
| Symbol | Kind | Purpose | Thread/lifetime | Errors |
|
|
|---|---|---|---|---|
|
|
| `remember_request(normalized_relative_path, resource_path)` | Command/query | Insert one pending request | Renderer main thread; until transition/clear | Empty/duplicate false |
|
|
| `has_request(path)` | Query | Pending-request dedupe | Main thread | Empty/unknown false |
|
|
| `request_records_snapshot()` | Query | Detached pending records in insertion order | Main thread; caller-owned | None |
|
|
| `complete_request(path, terminal_status)` | Command/query | Move copied record into completion FIFO | Main thread after poll | Unknown false |
|
|
| `discard_request(path)` | Command/query | Remove without finalization | Main thread | Unknown false |
|
|
| `has_finalize_record()` / `pop_finalize_record()` | Query/command | Drain completion-order FIFO | Main-thread budget drain | Empty pop returns `{}` |
|
|
| `total_work_count()` | Query | Pending plus finalize metric | Main thread | None |
|
|
| `pending_request_count()` / `finalize_record_count()` | Query | Stage diagnostics | Main thread | None |
|
|
| `clear()` | Command | Drop bookkeeping after caller I/O drain/reset | Main thread | Idempotent; no I/O drain |
|
|
| `diagnostic_snapshot()` | Query | Detached paths/status records | Main thread | No Resources exposed |
|
|
|
|
## Inputs and outputs
|
|
|
|
| Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime |
|
|
|---|---|---|---|---|---|
|
|
| Input | Normalized M2 path and GLB Resource path | Loader request adapter | Pending map | Copied Strings | Until completion/discard/clear |
|
|
| Input | Opaque terminal status | Loader polling adapter | Finalize FIFO | Integer value | Until pop/clear |
|
|
| Output | Detached pending records | State | Loader poll/shutdown adapter | Caller-owned copies | One pass |
|
|
| Output | Oldest completion record | State | Loader finalizer | Transferred Dictionary | One finalize attempt |
|
|
| Output | Detached diagnostics | State | Verifier/future metrics | Caller-owned copies | Snapshot lifetime |
|
|
|
|
Side effects are limited to collection mutation and retaining String/integer values.
|
|
|
|
## Data flow
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
Start[Successful threaded request] --> Remember[Remember request]
|
|
Remember --> Poll[Loader polls detached snapshot]
|
|
Poll --> Terminal{Loaded or failed?}
|
|
Terminal -->|no| Poll
|
|
Terminal -->|yes| Complete[Complete with opaque status]
|
|
Complete --> FIFO[Finalize FIFO]
|
|
FIFO --> Permit{Permit available?}
|
|
Permit -->|no| FIFO
|
|
Permit -->|yes| Pop[Pop oldest record]
|
|
Pop --> Finalize[Loader loads/instantiates or marks static]
|
|
```
|
|
|
|
## Lifecycle/state
|
|
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> Absent
|
|
Absent --> Pending: remember
|
|
Pending --> TerminalQueued: complete
|
|
Pending --> Absent: discard or clear
|
|
TerminalQueued --> Absent: pop or clear
|
|
```
|
|
|
|
## Main sequence
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant O as CachedAnimationObserver
|
|
participant L as StreamingWorldLoader
|
|
participant R as ResourceLoader
|
|
participant S as M2AnimationLoadPipelineState
|
|
participant P as M2PrototypeCacheState
|
|
O->>R: load_threaded_request(GLB)
|
|
O->>S: remember_request(path, GLB)
|
|
loop frames
|
|
L->>S: request_records_snapshot()
|
|
L->>R: load_threaded_get_status(GLB)
|
|
end
|
|
L->>S: complete_request(path, status)
|
|
L->>S: pop_finalize_record() after permit
|
|
L->>R: load_threaded_get(GLB)
|
|
L->>P: adopt animated prototype or mark static
|
|
```
|
|
|
|
## Ownership, threading and resources
|
|
|
|
- Main thread serializes all mutation.
|
|
- State owns only request/finalize Dictionaries with copied paths and statuses.
|
|
- Loader drains pending ResourceLoader paths before orderly shutdown clear.
|
|
- Loader owns PackedScene instantiation and material repair; prototype state owns
|
|
accepted detached Node references and static-only outcomes.
|
|
|
|
## Dependency diagram
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
Observer[M2CachedAnimationResourceObserver] --> State[M2AnimationLoadPipelineState]
|
|
Observer --> Resource[ResourceLoader request]
|
|
Loader[StreamingWorldLoader] --> State[M2AnimationLoadPipelineState]
|
|
Loader --> Resource
|
|
Loader --> Budget[RenderBudgetScheduler]
|
|
Loader --> Prototype[M2PrototypeCacheState]
|
|
State -. no dependency .-> Resource
|
|
State -. no dependency .-> Budget
|
|
State -. no dependency .-> Prototype
|
|
```
|
|
|
|
## Errors, cancellation and recovery
|
|
|
|
| Failure | Detection | Behavior | Diagnostic | Recovery |
|
|
|---|---|---|---|---|
|
|
| Empty/duplicate request | State guard | Reject unchanged | Contract verifier | Correct caller or request later |
|
|
| Request start/cache miss | Cached observer | No insertion; mark static | Observer contract | Cache correction/reload |
|
|
| Non-terminal status | Loader | Keep pending | Existing metric | Poll next frame |
|
|
| Failed terminal load | Popped status | Loader marks static | Existing behavior | Future map/session reload |
|
|
| Empty defensive path | Loader poll | Discard and mark static | Source contract | Correct producer |
|
|
| Shutdown | Loader drains pending paths | Clear state | Source/shutdown regressions | New loader starts empty |
|
|
|
|
## Configuration and capabilities
|
|
|
|
| Setting/capability | Default | Profile | Runtime mutable | Effect |
|
|
|---|---|---|---|---|
|
|
| `enable_m2_animated_instances` | `true` | Existing renderer profile | Yes | Enables caller request path |
|
|
| `m2_animation_finalize_ops_per_tick` | `1` | Quality/custom | Yes | Bounds caller FIFO drain |
|
|
| Animated allow/deny/primitive rules | Existing values | Existing renderer profile | Yes | Observer filters before state insertion |
|
|
|
|
## Persistence, cache and migration
|
|
|
|
State is not serialized. Cache formats and prototype lifetimes are unchanged;
|
|
no rebake or migration is required.
|
|
|
|
## Diagnostics and observability
|
|
|
|
- `total_work_count()` preserves all three historical `m2_animation` metrics.
|
|
- Snapshots expose only paths and opaque statuses, never Resources or Nodes.
|
|
- Normalized M2 path is the correlation key; existing loader logs are unchanged.
|
|
|
|
## Verification
|
|
|
|
- `verify_m2_animation_load_pipeline_state.gd` covers validation, dedupe,
|
|
insertion order, completion FIFO, opaque status, discard, detached snapshots,
|
|
source boundaries and 100-by-256 timing.
|
|
- Adjacent renderer, scheduler, prototype and shutdown regressions cover callers.
|
|
- Fidelity evidence is exact state/lifecycle extraction; no visual 3.3.5a parity
|
|
or proprietary asset-backed claim is made.
|
|
- Performance budget: 25,600 request/complete/pop transitions under one second.
|
|
|
|
## Extension points
|
|
|
|
ResourceLoader polling may later move behind a separate adapter without
|
|
changing this value-only state contract. Animated-scene finalization is now a
|
|
sibling service.
|
|
|
|
## Capability status
|
|
|
|
| Capability | Status | Evidence | Gap/next step |
|
|
|---|---|---|---|
|
|
| Animated request/finalize state | Implemented extraction | Synthetic contract/source/timing verifier | Asset-backed traversal/leak/p95/p99 pending |
|
|
| Cached request admission and GLB selection | Implemented in observer | Policy/GLB/source verifier | Asset-backed traversal pending |
|
|
| Terminal ResourceLoader polling | Existing loader-owned | Shutdown/finalizer regressions | I/O adapter extraction optional |
|
|
| Animated prototype outcomes | Implemented extraction | Prototype cache verifier | Asset-backed animation fidelity pending |
|
|
|
|
## Known gaps and risks
|
|
|
|
- Dictionary records preserve the existing dynamic ResourceLoader boundary.
|
|
- `clear()` does not drain I/O; caller ordering remains mandatory.
|
|
- No private asset traversal, leak/descriptor-pressure or paired-client run is included.
|
|
|
|
## Source map
|
|
|
|
| Path | Responsibility |
|
|
|---|---|
|
|
| `src/render/m2/m2_animation_load_pipeline_state.gd` | Pending records, completion FIFO and metrics |
|
|
| `src/render/m2/m2_cached_animation_resource_observer.gd` | Eligibility, GLB selection and request admission |
|
|
| `src/render/m2/m2_animated_scene_finalizer.gd` | Candidate instantiation, material repair and player validation |
|
|
| `src/render/m2/m2_prototype_cache_state.gd` | Animated prototype/static-only outcomes |
|
|
| `src/scenes/streaming/streaming_world_loader.gd` | Native eligibility/build, polling, permits and adoption |
|
|
| `src/tools/verify_m2_animation_load_pipeline_state.gd` | Lifecycle/boundary/timing regression |
|
|
|
|
## Related decisions and references
|
|
|
|
- [`m2-animated-scene-finalizer.md`](m2-animated-scene-finalizer.md)
|
|
- [`m2-prototype-cache-state.md`](m2-prototype-cache-state.md)
|
|
- [`m2-mesh-load-pipeline-state.md`](m2-mesh-load-pipeline-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)
|