Terrain Quality Mesh Cache
Metadata
| Field |
Value |
| Status |
Implemented extraction |
| Target/work package |
M03 / M03-RND-TERRAIN-CACHE-SERVICE-001 |
| Owners |
Full-quality terrain revisit Mesh retention and LRU policy |
| Last verified |
Worktree work/sindo-main-codex/m03-terrain-quality-cache, 2026-07-16 |
| Profiles/capabilities |
Performance/Balanced/High/Custom capacity; session-memory only |
Purpose
Retain eligible full-quality terrain Mesh references after ADT tile state unload,
so a revisit can restore quality without flashing to a lower-quality fallback,
while bounding retained references with the existing least-recently-used policy.
Non-goals
- Parse/build terrain, own tile state or schedule quality-upgrade tasks.
- Create/finalize Nodes or RIDs, mutate materials or choose terrain LOD.
- Persist cache entries or change baked/control-splat/splat format versions.
- Cache control-splat/splat sources whose active radius has separate ownership.
- Provide a generic cache framework or change profile capacity defaults.
Context and boundaries
Allowed dependencies: Mesh, Dictionary/Array scalar containers and the loader
adapter. Forbidden dependencies: Node/SceneTree/RID, tasks/mutexes, ADT parsing,
gameplay/network/editor UI, files and persistent Resource cache ownership.
Public API
| Symbol |
Kind |
Purpose |
Thread/lifetime |
Errors |
TerrainQualityMeshCache.store(tile_key, mesh, source, capacity) |
Command |
Admit/touch a Mesh and trim oldest entries |
Owning renderer thread/session |
Returns false for rejected input or immediate zero-capacity eviction |
TerrainQualityMeshCache.restore(tile_key) |
Query/touch |
Return a fresh Mesh/source record and mark newest |
Owning renderer thread |
Empty on miss; invalid record is removed |
TerrainQualityMeshCache.clear() |
Lifecycle command |
Release all retained Mesh references and LRU keys |
Reset/shutdown |
Idempotent |
TerrainQualityMeshCache.diagnostic_snapshot() |
Read model |
Detached count and oldest-to-newest key/source list |
Caller-owned result |
Never exposes Mesh references |
Inputs and outputs
| Direction |
Contract/data |
Producer |
Consumer |
Ownership |
Thread/lifetime |
| Input |
Tile key |
Streamer tile catalog/state |
Cache index |
Copied string |
Map session |
| Input |
Full-quality Mesh |
Baked upgrade/fallback path |
Cache |
Retained shared reference |
Until eviction/clear |
| Input |
Quality source |
Streamer quality adapter |
Admission/restore |
Copied string |
Entry lifetime |
| Input |
Current capacity |
Active renderer profile |
Store trim |
Scalar copy |
One store |
| Output |
Fresh {mesh, source} record |
Cache |
Loader state adapter |
Caller dictionary; shared Mesh reference |
One restore |
| Output |
Detached diagnostics |
Cache |
Tests/future metrics |
Caller-owned scalars |
One query |
Side effects are limited to retained reference and LRU container mutation. There
is no scene, GPU, task, file, database, network or persistent-cache mutation.
Data flow
Lifecycle/state
Main sequence
Ownership, threading and resources
- The cache owns its dictionary, ordered tile keys and retained Mesh references.
- The loader retains tile state, async tasks/results, quality selection and all
Node/RID/material finalization.
- Returned records are new dictionaries; their Mesh is a shared reference.
- Calls currently occur on the main renderer thread. The service has no lock and
must not be mutated concurrently.
clear deterministically drops references during the existing world reset path.
Errors, cancellation and recovery
| Failure |
Detection |
Behavior |
Diagnostic |
Recovery |
| Empty key/null Mesh |
Store guard |
Reject unchanged |
Boolean/test |
Fix caller result |
| Splat/control source |
Admission list |
Reject unchanged |
Boolean/test |
Keep source in active-radius ownership |
| Zero/negative capacity |
Clamp and trim |
Entry immediately evicted; cache empty |
Snapshot/count |
Increase profile capacity |
| Miss/invalid entry |
Restore validation |
Remove invalid and return empty |
Empty record |
Existing loader fallback/rebuild |
| World reset/shutdown |
Loader lifecycle |
Clear every reference/key |
Shutdown regression |
Refill during next session |
There is no asynchronous work or cancellation token inside this service.
Configuration and capabilities
| Setting/capability |
Default |
Profile |
Runtime mutable |
Effect |
terrain_quality_mesh_cache_limit |
Existing loader value |
0/24/48 in current presets |
Read on every store |
Maximum retained entries |
| Admitted source |
Non-splat (currently baked_full) |
All |
No hidden override |
Revisit retention |
| Excluded sources |
control_splat_cache, splat_cache, splat |
All |
No |
Preserve active quality ownership |
Persistence, cache and migration
- This is an in-memory reference cache, not a serialized cache format.
REQUIRED_BAKED_TILE_FORMAT_VERSION=5, control splat v3 and splat v1 remain
loader/resource validation contracts and are unchanged.
- No migration or rebuild is required. Entry keys retain the existing tile-key form.
Diagnostics and observability
- Detached diagnostics report count and oldest-to-newest tile key/source entries.
- Mesh, material, Node and RID references are deliberately absent.
- Performance is bounded dictionary lookup plus one ordered-array erase/append;
no new optimization or scale claim is made.
Verification
verify_terrain_quality_mesh_cache.gd: admission, exclusions, Mesh identity,
source, LRU touch/eviction, detached diagnostics, negative capacity and clear.
- Loader source boundary proves cache composition/delegation and removal of its
former LRU array/touch/trim implementation.
- Existing shutdown, facade, internal-access, manifest, planner and scheduler
regressions remain required.
- Fidelity: source rules, capacities and three loader adapter sites are unchanged;
no visible terrain or build-12340 parity change is claimed.
Extension points
- Expose scalar cache counts through facade metrics when needed.
- Move additional terrain responsibilities only as separate bounded services.
- Replace ordered-array LRU only after measured scale evidence.
Capability status
| Capability |
Status |
Evidence |
Gap/next step |
| Bounded quality Mesh retention |
Implemented extraction |
Contract/LRU fixtures |
Asset-backed memory/revisit timing pending |
| Deterministic reset ownership |
Implemented |
Clear path plus shutdown regression |
Full terrain service still monolithic |
| Persistent terrain cache formats |
Unchanged |
Loader version constants |
Separate acceptance audit remains |
Known gaps and risks
- Ordered-array touch is linear in entry count, matching prior behavior.
- Mesh memory size is not measured; capacity remains entry-count based.
- Only revisit Mesh ownership moved; build/tasks/state/finalization remain loader-owned.
- Asset-backed flash/revisit timing and p95/p99 evidence remain pending.
Source map
| Path |
Responsibility |
src/render/terrain/terrain_quality_mesh_cache.gd |
Session cache entries, LRU and admission |
src/scenes/streaming/streaming_world_loader.gd |
Store/restore state adapter and reset lifecycle |
src/tools/verify_terrain_quality_mesh_cache.gd |
Scene-free cache and loader-boundary regression |
Related decisions and references