Files
open-wc/docs/modules/m2-animation-load-pipeline-state.md
T

9.7 KiB

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; animation eligibility and loading remain in StreamingWorldLoader, 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

flowchart LR
    Loader[StreamingWorldLoader] --> IO[ResourceLoader]
    Loader --> State[M2AnimationLoadPipelineState]
    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

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

stateDiagram-v2
    [*] --> Absent
    Absent --> Pending: remember
    Pending --> TerminalQueued: complete
    Pending --> Absent: discard or clear
    TerminalQueued --> Absent: pop or clear

Main sequence

sequenceDiagram
    participant L as StreamingWorldLoader
    participant R as ResourceLoader
    participant S as M2AnimationLoadPipelineState
    participant P as M2PrototypeCacheState
    L->>R: load_threaded_request(GLB)
    L->>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

flowchart TB
    Loader[StreamingWorldLoader] --> State[M2AnimationLoadPipelineState]
    Loader --> Resource[ResourceLoader]
    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 Loader No insertion; mark static Existing loader path 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 Filter 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
ResourceLoader and GLB selection Existing loader-owned Adjacent renderer tests 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_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 Eligibility, I/O, permits, instantiation and adoption
src/tools/verify_m2_animation_load_pipeline_state.gd Lifecycle/boundary/timing regression