refactor(M03): extract WMO scene resource cache state
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
| WMO render build step planner | Implemented extraction | [`wmo-render-build-step-planner.md`](wmo-render-build-step-planner.md) |
|
||||
| WMO render build queue | Implemented extraction | [`wmo-render-build-queue.md`](wmo-render-build-queue.md) |
|
||||
| WMO render Resource cache state | Implemented extraction | [`wmo-render-resource-cache-state.md`](wmo-render-resource-cache-state.md) |
|
||||
| WMO scene Resource cache state | Implemented extraction | [`wmo-scene-resource-cache-state.md`](wmo-scene-resource-cache-state.md) |
|
||||
| Third-person camera | Implemented | [`third-person-camera.md`](third-person-camera.md) |
|
||||
| Character presentation | Implemented boundary / Partial fidelity | [`character-presentation.md`](character-presentation.md) |
|
||||
| Renderer | Partial | [`world-renderer.md`](world-renderer.md), [`../../RENDER.md`](../../RENDER.md) |
|
||||
|
||||
@@ -179,8 +179,8 @@ states; Resource references and cache file paths are not exposed. No logs emit.
|
||||
|
||||
## Extension points
|
||||
|
||||
- Cached WMO scene request state can use a separate typed module because its
|
||||
size limit, PackedScene validation and missing-file behavior differ.
|
||||
- Cached WMO scene request state is a separate typed module because its size
|
||||
limit, PackedScene validation and missing-file behavior differ.
|
||||
- A later loader I/O adapter may consume the detached request snapshot while
|
||||
preserving this state contract and cache-version boundary.
|
||||
|
||||
@@ -190,7 +190,7 @@ states; Resource references and cache file paths are not exposed. No logs emit.
|
||||
|---|---|---|---|
|
||||
| Lightweight WMO render Resource state | Implemented extraction | Lifecycle/source/timing and shutdown verifiers | Asset-backed traversal/leak evidence pending |
|
||||
| Cache script/version validation | Preserved in loader | Source boundary and WMO regressions | Dedicated corrupt-cache fixture could follow |
|
||||
| Cached WMO scene state | Partial/loader-owned | Existing runtime behavior | Separate extraction |
|
||||
| Cached WMO scene state | Implemented extraction | Scene-cache lifecycle/source/timing verifier | Asset-backed traversal/leak evidence pending |
|
||||
| WMO materialization | Partial/loader-owned | Queue/planner regressions | Further safe extraction |
|
||||
|
||||
## Known gaps and risks
|
||||
@@ -213,6 +213,7 @@ states; Resource references and cache file paths are not exposed. No logs emit.
|
||||
## Related decisions and references
|
||||
|
||||
- [`wmo-render-build-queue.md`](wmo-render-build-queue.md)
|
||||
- [`wmo-scene-resource-cache-state.md`](wmo-scene-resource-cache-state.md)
|
||||
- [`wmo-placement-resolver.md`](wmo-placement-resolver.md)
|
||||
- [`world-renderer.md`](world-renderer.md)
|
||||
- [`../../RENDER.md`](../../RENDER.md)
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
# WMO Scene Resource Cache State
|
||||
|
||||
## Metadata
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Status | Implemented |
|
||||
| Target/work package | M03 / `M03-RND-WMO-SCENE-RESOURCE-CACHE-001` |
|
||||
| Owners | Validated cached-WMO PackedScenes, negative cache and pending request paths |
|
||||
| Last verified | Worktree `work/sindo-main-codex/m03-wmo-scene-resource-cache`, 2026-07-17 |
|
||||
| Profiles/capabilities | Cached WMO `.tscn` fallback; profile-independent state |
|
||||
|
||||
## Purpose
|
||||
|
||||
Own mutually exclusive cached, missing and pending states for normalized WMO
|
||||
scene paths. The state accepts only caller-validated `PackedScene` references and
|
||||
records `.tscn` paths for threaded requests whose I/O, size limit and cache
|
||||
metadata validation remain in `StreamingWorldLoader`.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Normalize WMO paths, build `.tscn` paths or measure files.
|
||||
- Call ResourceLoader/FileAccess, instantiate scenes or validate cache metadata.
|
||||
- Own live prototypes, placement/build jobs, instantiated Nodes or RIDs.
|
||||
- Change missing, oversize, request-error, retry or fallback behavior.
|
||||
- Persist, migrate or build WMO caches.
|
||||
|
||||
## Context and boundaries
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Lookup[Normalized WMO scene lookup] --> Loader[StreamingWorldLoader]
|
||||
Loader --> State[WmoSceneResourceCacheState]
|
||||
Loader --> Size[File existence and size limit]
|
||||
Size --> ResourceLoader[Godot ResourceLoader]
|
||||
ResourceLoader --> Loader
|
||||
Loader --> Probe[Instantiate, metadata/version check, free]
|
||||
Probe -->|accepted PackedScene or missing| State
|
||||
Loader --> Live[Live-prototype fallback]
|
||||
```
|
||||
|
||||
The module retains validated PackedScenes and copied paths only. ResourceLoader,
|
||||
FileAccess, WMOBuilder, Node, RID, worker, gameplay, network and editor concerns
|
||||
remain outside it.
|
||||
|
||||
## Public API
|
||||
|
||||
| Symbol | Kind | Purpose | Thread/lifetime | Errors |
|
||||
|---|---|---|---|---|
|
||||
| `scene_for(path)` / `contains_scene(path)` | Query | Borrow/test validated PackedScene | Renderer main thread; until full clear | Empty/unknown returns null/false |
|
||||
| `is_missing(path)` / `has_request(path)` | Query | Test negative/pending state | Renderer main thread | Empty returns false |
|
||||
| `remember_request(path, cache_path)` | Command/query | Record loader-started request | Until terminal/reset | Invalid/occupied returns false |
|
||||
| `mark_missing(path)` | Command/query | Record absent/oversize/request-start failure without pending state | Until transient/full clear | Invalid/occupied returns false |
|
||||
| `request_paths_snapshot()` | Query | Copy pending normalized/cache-path mapping | Poll/shutdown drain | Detached Dictionary |
|
||||
| `complete_request_with_scene(path, scene)` | Command/query | Remove pending and adopt validated PackedScene | Terminal poll | Unknown/null returns false |
|
||||
| `complete_request_as_missing(path)` | Command/query | Remove pending and adopt negative state | Terminal poll | Unknown returns false |
|
||||
| `clear_transient_state()` | Command | Clear pending/missing and retain scenes | Map reset/request drain | Idempotent |
|
||||
| `clear_all()` | Command | Release scenes and transient state | Final runtime-cache release | Idempotent |
|
||||
| `pending_request_count()` | Query | Preserve renderer queue metric | Diagnostics | None |
|
||||
| `diagnostic_snapshot()` | Query | Return sorted detached scalar keys | Tests/diagnostics | No PackedScene exposure |
|
||||
|
||||
## Inputs and outputs
|
||||
|
||||
| Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime |
|
||||
|---|---|---|---|---|---|
|
||||
| Input | Normalized WMO path | Placement resolver through loader | State | Copied String | Cache lifetime |
|
||||
| Input | `.tscn` path after accepted request start | Loader | Pending state | Copied String | Until terminal/reset |
|
||||
| Input | Metadata/version-validated PackedScene | Loader probe adapter | Scene cache | Strong reference | Until full clear |
|
||||
| Input | Missing decision | Loader file/size/request/load/validation adapters | Negative cache | Boolean membership | Until transient/full clear |
|
||||
| Output | Borrowed PackedScene | State | Loader scene instantiation | State retains reference | Lookup/instantiate call |
|
||||
| Output | Detached request snapshot | State | Loader polling/shutdown | Caller-owned Dictionary | One drain pass |
|
||||
|
||||
## Data flow
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Lookup --> Known{Cached, missing or pending?}
|
||||
Known -->|cached| Return[Return PackedScene]
|
||||
Known -->|missing/pending| Null[Return null]
|
||||
Known -->|absent| Check[Loader checks file and size]
|
||||
Check -->|missing/oversize| Mark[mark_missing]
|
||||
Check -->|allowed| Request[Start threaded request]
|
||||
Request -->|error| Mark
|
||||
Request -->|accepted| Remember[remember_request]
|
||||
Remember --> Poll[Loader polls snapshot]
|
||||
Poll -->|failure| CompleteMissing[complete as missing]
|
||||
Poll -->|loaded| Validate[Instantiate and validate cache metadata]
|
||||
Validate -->|valid| CompleteScene[complete with scene]
|
||||
Validate -->|invalid| CompleteMissing
|
||||
```
|
||||
|
||||
## Lifecycle/state
|
||||
|
||||
Each normalized path is `Absent`, `Pending`, `Cached` or `Missing`. Direct file,
|
||||
size and request-start rejection moves `Absent` directly to `Missing`; terminal
|
||||
loads move `Pending` to `Cached` or `Missing`. Transient clear retains `Cached`,
|
||||
while full clear returns every path to `Absent`.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Absent
|
||||
Absent --> Pending: accepted request
|
||||
Absent --> Missing: absent, oversize or request error
|
||||
Pending --> Cached: validated PackedScene
|
||||
Pending --> Missing: load or validation failure
|
||||
Pending --> Absent: transient/full clear
|
||||
Missing --> Absent: transient/full clear
|
||||
Cached --> Absent: full clear
|
||||
```
|
||||
|
||||
## Main sequence
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Loader as StreamingWorldLoader
|
||||
participant State as WmoSceneResourceCacheState
|
||||
participant RL as ResourceLoader
|
||||
Loader->>State: cached/missing/pending queries
|
||||
Loader->>Loader: exists and wmo_max_runtime_scene_mb check
|
||||
Loader->>RL: load_threaded_request(.tscn)
|
||||
Loader->>State: remember_request(normalized, path)
|
||||
loop renderer tick
|
||||
Loader->>State: request_paths_snapshot()
|
||||
Loader->>RL: load_threaded_get_status(path)
|
||||
end
|
||||
Loader->>RL: load_threaded_get(path)
|
||||
Loader->>Loader: instantiate, validate WMO metadata, free probe
|
||||
Loader->>State: complete with scene or as missing
|
||||
```
|
||||
|
||||
## Ownership, threading and resources
|
||||
|
||||
- State owns three Dictionaries and strong references to accepted PackedScenes.
|
||||
- Loader owns paths, file measurement, requests, validation and all Node lifetime.
|
||||
- All mutation is serialized on the renderer main thread; no mutex is required.
|
||||
- Detached request snapshots allow terminal removal while polling.
|
||||
- Scene instantiation borrows the PackedScene and does not transfer cache ownership.
|
||||
|
||||
## Errors, cancellation and recovery
|
||||
|
||||
| Failure/state | Detection | Behavior | Recovery |
|
||||
|---|---|---|---|
|
||||
| Missing `.tscn` | Loader ResourceLoader existence check | Direct missing state | Transient reset permits later retry |
|
||||
| Oversize `.tscn` | Loader byte limit | Missing plus unchanged debug log | Raise limit/rebuild, then reset |
|
||||
| Request-start/load failure | Loader error/status | Direct or terminal missing | Reset and retry later |
|
||||
| Wrong type/stale metadata | Loader PackedScene/probe validation | Terminal missing; probe freed | Rebuild cache and reset |
|
||||
| Shutdown while pending | Loader drains snapshot | Clear transient, then full cache release | New loader starts absent |
|
||||
|
||||
## Configuration and capabilities
|
||||
|
||||
No setting is added. `wmo_cache_dir`, `wmo_max_runtime_scene_mb`, request timing,
|
||||
quality profiles and WMO build budgets stay loader-owned.
|
||||
|
||||
## Persistence, cache and migration
|
||||
|
||||
The module is runtime-only. Existing WMOBuilder cache metadata/version checks
|
||||
remain unchanged and execute before state adoption. No cache format, migration or
|
||||
rebuild is introduced.
|
||||
|
||||
## Diagnostics and observability
|
||||
|
||||
Pending count preserves the existing `wmobuild` metric contribution. The snapshot
|
||||
exposes sorted scene/missing/request keys only. Existing oversize logging remains
|
||||
in the loader; the state emits no logs.
|
||||
|
||||
## Verification
|
||||
|
||||
- `verify_wmo_scene_resource_cache_state.gd`: invalid input, direct missing,
|
||||
exclusivity, request completion, partial/full reset, diagnostics, boundaries
|
||||
and bounded timing.
|
||||
- `verify_render_runtime_cache_shutdown.gd`: loader full release of scenes,
|
||||
negative and pending state.
|
||||
- Adjacent WMO/renderer regressions verify unchanged lookup/fallback behavior.
|
||||
This extraction makes no visual or build-12340 parity claim.
|
||||
|
||||
## Extension points
|
||||
|
||||
- A later I/O adapter may consume request snapshots while retaining this contract.
|
||||
- Scene instantiation/material preparation can be extracted separately because it
|
||||
owns Nodes and main-thread side effects rather than cache state.
|
||||
|
||||
## Capability status
|
||||
|
||||
| Capability | Status | Evidence | Gap/next step |
|
||||
|---|---|---|---|
|
||||
| Cached WMO PackedScene state | Implemented extraction | Lifecycle/source/timing and shutdown verifiers | Asset-backed traversal/leak evidence pending |
|
||||
| Size and cache metadata validation | Preserved in loader | Source boundary and WMO regressions | Oversize/stale asset fixtures could follow |
|
||||
| ResourceLoader I/O and live fallback | Partial/loader-owned | Existing runtime behavior | Separate extraction if justified |
|
||||
|
||||
## Known gaps and risks
|
||||
|
||||
- PackedScenes remain strongly referenced until final shutdown cache release.
|
||||
- Negative caching suppresses retries until transient reset, matching prior behavior.
|
||||
- No proprietary WMO corpus, stale/oversize asset fixture, leak run, traversal
|
||||
p95/p99 or paired original-client capture is included.
|
||||
|
||||
## Source map
|
||||
|
||||
| Path | Responsibility |
|
||||
|---|---|
|
||||
| `src/render/wmo/wmo_scene_resource_cache_state.gd` | Scene/missing/request state and resets |
|
||||
| `src/scenes/streaming/streaming_world_loader.gd` | Paths, file limit, requests, validation, fallback and Node lifetime |
|
||||
| `src/tools/verify_wmo_scene_resource_cache_state.gd` | State, boundary and timing regression |
|
||||
| `src/tools/verify_render_runtime_cache_shutdown.gd` | Loader final cache ownership regression |
|
||||
|
||||
## Related decisions and references
|
||||
|
||||
- [`wmo-render-resource-cache-state.md`](wmo-render-resource-cache-state.md)
|
||||
- [`wmo-render-build-queue.md`](wmo-render-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)
|
||||
@@ -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-wmo-render-resource-cache`, 2026-07-17 |
|
||||
| Last verified | Worktree `work/sindo-main-codex/m03-wmo-scene-resource-cache`, 2026-07-17 |
|
||||
| Profiles/capabilities | `Performance`, `Balanced`, `High`, `Custom`; Blizzlike fidelity incomplete |
|
||||
|
||||
## Purpose
|
||||
@@ -137,6 +137,7 @@ from externally reading/writing loader-private queue, task, cache and tile-state
|
||||
| `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 |
|
||||
| `WmoRenderBuildQueue` / `WmoRenderBuildJob` | Internal WMO pending-state service | Owns typed root/resource/cursor jobs and FIFO placement keys | Renderer main thread; map session | Invalid enqueue rejected; duplicate/stale behavior preserved |
|
||||
| `WmoRenderResourceCacheState` | Internal WMO cache-state service | Owns validated Resources, negative entries and pending cache paths | Renderer main thread; map/cache session | Invalid/occupied request and unknown completion are rejected |
|
||||
| `WmoSceneResourceCacheState` | Internal WMO cache-state service | Owns validated PackedScenes, negative entries and pending `.tscn` paths | Renderer main thread; map/cache session | Direct missing and terminal request transitions remain distinct |
|
||||
|
||||
Публичным contract не считаются `StreamingWorldLoader` methods/properties,
|
||||
внутренние dictionaries, queues, job records и generated node names. Scene-owned
|
||||
@@ -170,6 +171,7 @@ loader configuration remains transitional composition data, not a caller API.
|
||||
| Internal WMO build step | Mesh/MultiMesh counts and job cursors | Loader / `WmoRenderBuildStepPlanner` | Loader materialization/cursor adapter | Fresh scalar Dictionary | One group operation |
|
||||
| Internal WMO pending build | Placement key, Node3D root, WMO Resource and cursors | Loader / `WmoRenderBuildQueue` | Loader drain and step planner adapter | Queue-owned job and strong references | Until cancel/clear/replacement |
|
||||
| Internal WMO render cache | Normalized path, cache path and validated Resource | Loader / `WmoRenderResourceCacheState` | Loader lookup, ResourceLoader poll and build queue | State-owned Resource/path references; detached request snapshots | Until transient/full clear |
|
||||
| Internal WMO scene cache | Normalized path, `.tscn` path and validated PackedScene | Loader / `WmoSceneResourceCacheState` | Loader lookup, request poll and scene instantiation | State-owned PackedScene/path references; detached request snapshots | Until transient/full clear |
|
||||
| Output | Desired tile/detail operations | Streamer plan application | Finalize queues | Loader-owned | Cross-frame |
|
||||
| Output | Terrain/M2/WMO/liquid instances | Loader/builders | Godot world/renderer | Loader/world owner | Main-thread attach |
|
||||
| Output | Detached renderer metrics | `WorldRenderFacade` | Capture/baseline tools | Caller-owned deep copy | On demand |
|
||||
@@ -350,9 +352,10 @@ sequenceDiagram
|
||||
and cursor plan. `WmoRenderBuildQueue` owns typed pending jobs, FIFO keys and
|
||||
strong root/resource references without freeing engine objects.
|
||||
`WmoRenderResourceCacheState` owns validated render Resources, negative entries
|
||||
and pending cache paths. The loader retains ResourceLoader I/O, script/version
|
||||
validation, cached-scene/live fallback, materialization, permits, validity
|
||||
reactions and every Node lifecycle action.
|
||||
and pending cache paths. `WmoSceneResourceCacheState` similarly owns validated
|
||||
PackedScenes, negative entries and pending `.tscn` paths. The loader retains
|
||||
ResourceLoader/FileAccess I/O, size and cache-version validation, live fallback,
|
||||
materialization, permits, validity reactions and every Node lifecycle action.
|
||||
- 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
|
||||
@@ -455,6 +458,9 @@ Exact exported settings and cache versions remain documented in [`../../RENDER.m
|
||||
- WMO render Resource cache contract: invalid/duplicate request rejection,
|
||||
validated/missing terminal transitions, transient/full reset, detached sorted
|
||||
diagnostics, loader-owned version validation and bounded timing.
|
||||
- WMO scene Resource cache contract: direct missing sources, pending terminal
|
||||
transitions, transient/full reset, detached diagnostics, loader-owned size/
|
||||
metadata validation and bounded timing.
|
||||
- Budget scheduler contract: exact lane exhaustion, shared chunk removal/create
|
||||
priority, independent lanes, frame reset, invalid limits, terminal cancellation,
|
||||
dependency boundaries and bounded permit timing without loading a world scene.
|
||||
@@ -492,7 +498,8 @@ Exact exported settings and cache versions remain documented in [`../../RENDER.m
|
||||
| WMO placement registry | Implemented extraction | Scene-free ownership/lifecycle/source/timing contract | Build/resource state and asset-backed cross-tile corpus pending |
|
||||
| WMO render build step planner | Implemented extraction | Scene-free order/cursor/source/timing contract | Asset-backed traversal p95/p99 pending |
|
||||
| WMO render build queue | Implemented extraction | Typed lifecycle/order/ownership/source/timing contract | Materialization and asset-backed traversal/leak evidence pending |
|
||||
| WMO render Resource cache state | Implemented extraction | Scene-free lifecycle/exclusivity/source/timing plus shutdown contract | Cached-scene/I/O extraction and asset-backed traversal/leak evidence pending |
|
||||
| WMO render Resource cache state | Implemented extraction | Scene-free lifecycle/exclusivity/source/timing plus shutdown contract | ResourceLoader I/O and asset-backed traversal/leak evidence pending |
|
||||
| WMO scene Resource cache state | Implemented extraction | Scene-free lifecycle/direct-missing/source/timing plus shutdown contract | ResourceLoader/live-fallback extraction and asset-backed traversal/leak evidence pending |
|
||||
| WMO rendering | Partial | Cached group rendering | Portals/rooms/material parity |
|
||||
| Liquids | Partial | MH2O/MLIQ paths | LiquidType/depth/shore fidelity |
|
||||
| Sky/light | Partial | DBC controller/logs | Zone transition paired validation |
|
||||
|
||||
Reference in New Issue
Block a user