Files
gamedev-the-steward/docs/FEATURE_PRESENTATION_PERFORMANCE.md
T

121 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Feature slice: presentation, relevance, and weak-PC performance
Presentation is deliberately replaceable and bounded. The simulation can run
headless; loaded scenes provide geometry, navigation, animation, cues, and
input. This guide records the current performance controls and the evidence we
do and do not have.
## Loaded-world boundary
`ActiveWorldAdapter` owns a context identity `(world_id, location_id,
context_id)`, a `WorldTargetRegistry`, loaded resource spatial index, and
provider handles for resource/storage/activity/animal nodes. It is the only
place where a simulation target is paired with loaded geometry. Multiple
contexts must use separate ancestor containers; duplicate stable IDs are valid
only when they belong to different explicit contexts.
`WorldViewManager` owns active NPC visual instances and forwards target/arrival/
navigation callbacks. `NpcVisual`, `CreatureVisual`, and `AnimalNode` follow
authoritative positions. They do not own elapsed travel or saved quantities.
## Relevance and navigation budgets
`PresentationRelevancePolicy.select_detailed_visuals()` rejects foreign world,
context, or location candidates before ranking and returns at most 40 detailed
visuals. Explicit pins include named/important people, player-affecting
threats, situation/commitment participants, leaders, and unique owners. If
mandatory pins exceed the cap, the policy fails closed instead of silently
dropping identities. Decisions include score, distance, pin reasons, and
rejection traces.
`PresentationNavRequestBudget` admits at most two new navigation requests per
frame. It exposes pending/in-flight IDs and deterministic priority order. The
budget is a pure policy contract today; wiring it into every production visual
spawn is a next integration.
## Jajce quality profiles
`JajceWorld` owns reversible High, Balanced, and Low presentation profiles with
instance-local mutable environment/grass resources and viewport-scale ownership.
| Profile | 3D scale | Shadow distance | Volumetric/glow | Grass |
| --- | ---: | ---: | --- | --- |
| High | authored | authored (currently 180 m) | authored when renderer supports it | authored density/interactors |
| Balanced (default) | 0.85 cap | 120 m cap | authored ordinary lookdev; unsupported volumetric disabled | reduced spacing/interactors/update rate |
| Low | 0.70 cap | 80 m, orthogonal | volumetric/glow/adjustment disabled; ordinary fog retained | hidden/stopped, emitters off, shader interactors zero |
UI remains at native resolution. High/Low switches restore captured authored
values; viewport scale restoration is guarded by the current quality owner so a
second world cannot clobber the active owner. Compatibility/mobile feature
selection never forces unsupported volumetric fog on.
## Runtime hot paths already bounded
The woodland storybook art pass adds portable Blender animal meshes and an
opaque 35-triangle, seven-blade grass tuft. The existing camera-local grass
field and quality controls own its instance budget; four loaded path strips
provide disposable grass-clearance data after material isolation. Animal
appearance is derived from stable NPC IDs, shares mesh resources, and retains
profession tint, velocity-driven motion, inventory cues and death through the
existing presentation controllers. No saved state or navigation changes.
Characters and buildings use soft cel bands; tree crowns retain the shared
breeze with painted color patches. A static procedural cloud sky, cooler
ambient fill and warm sunlight follow the simulation day/night clock. The
cloud shader adds no volumetric pass, outline pass or screen-space postprocess.
See [the asset contract and rebuild commands](../assets/storybook/README.md).
`docs/baselines/storybook_*.png` records the native Metal review. The accompanying
`storybook_render_metrics.json` records a bounded local 1600×900 static-camera
sample on Apple M1 Max with six NPCs and High/Balanced/Low settings. Wall-frame
latency includes vsync and does not close the weak-PC evidence gap below.
- Player interaction and villager inspection probes are throttled/event-driven;
they no longer rebuild all candidate data every rendered frame.
- `LoadedResourceSpatialIndex` bounds finite-resource discovery.
- `SimulationPopulationView` gives stable-ID all/living/starving indexes once
per tick.
- `WorldTargetRegistry` gives O(1) target lookup and deterministic iteration.
- Creature path failures retain the failed target and use bounded backoff.
- Hostile hit flashes are health-change driven, not position-change driven.
- Day/night, status, time dial, storage/debug labels, and grass updates run at
human-readable rates or only on state changes.
- Regional scheduled work uses a due-job heap rather than a permanent scan.
## What the benchmarks prove
- Simulation baseline 03: 600 full-fidelity data-only NPC/combatant records at
about 90.6 ticks/s on the reviewed Apple M1 Max capture, with matching
checksums across samples.
- Loaded Resource Discovery 01: indexed 1,800-anchor queries preserve exact
selection checksums while reducing resolution work dramatically.
- Regional scale baseline 01: five settlements, 20 caravans, 2,000 named
people, 50,000 aggregate residents, 2,025 jobs, budget/checksum parity.
These are headless/structural measurements. They do **not** prove 600 rendered
visuals, a 30-day regional economy, or weak-PC GPU frame time.
## Remaining evidence gap
The project still needs a recorded reference weak-PC active-world workload at a
fixed gameplay camera, including High and Low p50/p95/p99 CPU/GPU frame time,
draw calls/primitives, memory/VRAM, active detailed visuals, and navigation
queue depth. The CI gate should keep structural profile assertions and the
two-request policy; hardware measurements belong in a reviewed benchmark
ledger, not brittle cross-machine CI thresholds.
## Performance extension rules
1. Measure a representative workload before optimizing.
2. Keep simulation and presentation results checksum-identical across loaded,
unloaded, and load/unload runs.
3. Add indexes, dirty sets, analytical updates, or scheduled jobs before adding
more per-frame scans.
4. Keep allocations out of render-frame probes and avoid sorting when a stable
bounded comparison is sufficient.
5. Any new visual must declare relevance/pin behavior and obey the navigation
request budget.
See [the benchmark ledger](benchmarks/README.md), [regional contract](REGIONAL_SIMULATION.md),
and [the build-in-public visual plan](BUILD_IN_PUBLIC_PLAN.md).