docs(A.5 T27): spec + plan amendments for T22.5 + ship
Spec (2026-05-09-phase-a5-two-tier-streaming-design.md): - §2 acceptance metrics reshaped from absolute 240 FPS to refresh-rate-relative + per-preset (95th-pct ≤ 1000ms/refresh standstill; ≤ 1.5× walking) to match the Quality Preset reality. - New §4.10 Quality Preset System (T22.5): enum Low/Medium/High/Ultra, QualitySettings schema, canonical preset values table, env-var override table, wiring notes (GameWindow.OnLoad + ReapplyQualityPreset), MSAA mid-session unsupported caveat, file list, test count (12). - New §11 What was deferred: 8 items (Tier 1 cache, lifestone, JobKind plumbing, Tier 2/3, ToEntries alloc, InvalidateEntity wiring, High preset retest). Former §11 References renumbered to §12. Plan (2026-05-09-phase-a5-two-tier-streaming.md): - New Task 22.5 section inserted between T22 and T23: full inline spec with schema, preset table, env-var list, wiring steps, acceptance criteria, deferred items, commit SHAs. Includes file-name corrections (SettingsState → DisplaySettings, DisplayTab → SettingsPanel). - Self-review cross-check table: new §4.10 row pointing at T22.5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9b49009dd5
commit
a28a5b7583
2 changed files with 224 additions and 12 deletions
|
|
@ -37,21 +37,21 @@ The headline win: walking around Holtburg, the user sees a real horizon
|
|||
- 240 Hz @ 2560×1440 (verified via `Get-CimInstance Win32_VideoController`).
|
||||
- Frame budget: **4.166 ms** at vsync.
|
||||
|
||||
### Acceptance metrics (Q9 Option B — tiered)
|
||||
### Acceptance metrics (as shipped — revised with Quality Preset system)
|
||||
|
||||
1. **Build green; existing tests still green.** N.5b conformance sentinel
|
||||
passes (visual mesh Z = TerrainSurface.SampleZ within 1 mm).
|
||||
2. **Standstill at Holtburg dueling field, 30 s with `[WB-DIAG]` and `[TERRAIN-DIAG]`:**
|
||||
- Median frame time ≤ 4.166 ms (240 FPS sustained).
|
||||
- p99 ≤ 4.5 ms (no vsync misses).
|
||||
3. **Walking Holtburg → North Yanshi at run speed, 60 s trace:**
|
||||
- Median ≥ 144 FPS (≤ 6.94 ms).
|
||||
- p95 ≥ 120 FPS (≤ 8.33 ms).
|
||||
2. **Standstill at user's selected preset on user's hardware:**
|
||||
- 95% of frames hit ≤ (1000ms / monitor refresh rate).
|
||||
- No absolute FPS number is required — the Quality Preset system (§4.10)
|
||||
is the user's knob for trading quality vs frame budget.
|
||||
3. **Walking at user's selected preset:**
|
||||
- 95% of frames hit ≤ 1.5× (1000ms / monitor refresh rate).
|
||||
4. **First traversal into virgin region (cold mesh cache):**
|
||||
- Render thread frame time stays ≤ 8.33 ms throughout while the worker
|
||||
fills the far-tier horizon (~2.7 s of "horizon filling in" is OK).
|
||||
5. **Visual gate (user-driven):** user launches the client, walks
|
||||
Holtburg → North Yanshi, and confirms:
|
||||
- Render thread frame time stays within 2× the standstill budget while
|
||||
the worker fills the far-tier horizon (~2.7 s of "horizon filling in" is OK).
|
||||
5. **Visual gate (user-driven, same on all presets):** user launches the
|
||||
client, walks Holtburg → North Yanshi, and confirms:
|
||||
- Horizon visible at ~2.3 km.
|
||||
- Fog blend at N₁ smooths the scenery boundary (no harsh cliff).
|
||||
- Distant terrain does not shimmer (mipmaps work).
|
||||
|
|
@ -433,6 +433,106 @@ pass (it is, per `IsOpaque` returning true for ClipMap at line 738).
|
|||
If audit finds nothing wrong, ship a comment + a unit test that locks in
|
||||
the partition. Cheap insurance against future regression.
|
||||
|
||||
### 4.10 Quality Preset System (T22.5 — added mid-execution)
|
||||
|
||||
**Background:** Added between T22 (fog wiring) and T23 (DIAG budgets) at
|
||||
user's direction. The original spec had no preset concept; §2 was written
|
||||
against absolute 240 FPS on fixed N₁/N₂. T22.5 makes both radii and every
|
||||
quality knob user-controllable via a single enum. §2 was amended above to
|
||||
reflect the per-preset, refresh-rate-relative acceptance criteria.
|
||||
|
||||
#### Schema
|
||||
|
||||
```csharp
|
||||
public enum QualityPreset { Low, Medium, High, Ultra }
|
||||
|
||||
public readonly record struct QualitySettings(
|
||||
int NearRadius,
|
||||
int FarRadius,
|
||||
int MsaaSamples,
|
||||
int AnisotropicLevel,
|
||||
bool AlphaToCoverage,
|
||||
int MaxCompletionsPerFrame);
|
||||
```
|
||||
|
||||
`QualitySettings.From(preset)` returns the canonical values:
|
||||
|
||||
| Preset | NearRadius | FarRadius | MsaaSamples | AnisotropicLevel | AlphaToCoverage | MaxCompletionsPerFrame |
|
||||
|---|---|---|---|---|---|---|
|
||||
| Low | 2 | 5 | 0 | 4 | false | 2 |
|
||||
| Medium | 3 | 8 | 2 | 8 | false | 3 |
|
||||
| High | 4 | 12 | 4 | 16 | true | 4 |
|
||||
| Ultra | 5 | 15 | 4 | 16 | true | 6 |
|
||||
|
||||
`QualitySettings.WithEnvOverrides(baseSettings)` applies per-field env-var
|
||||
overrides (see §4.10.3).
|
||||
|
||||
#### Persistence and UI
|
||||
|
||||
`DisplaySettings.Quality` (type `QualityPreset`) persists via the existing
|
||||
`settings.json` infrastructure (Phase L.0). The Settings panel (F11) exposes
|
||||
a Quality dropdown in its Display tab (`SettingsPanel.RenderDisplayTab`).
|
||||
|
||||
#### Wiring (GameWindow.OnLoad + ReapplyQualityPreset)
|
||||
|
||||
1. `GameWindow.OnLoad` resolves the active `QualitySettings`:
|
||||
`QualitySettings.From(displaySettings.Quality).WithEnvOverrides(...)`.
|
||||
2. `StreamingController` and `LandblockStreamer` are built with the preset's
|
||||
`NearRadius` / `FarRadius`.
|
||||
3. `TerrainAtlas.SetAnisotropic(settings.AnisotropicLevel)` called once at
|
||||
load and again on reapply.
|
||||
4. `WindowOptions.Samples = settings.MsaaSamples` applied at window creation
|
||||
time only (MSAA mid-session change is structurally unsupported by OpenGL).
|
||||
5. `WbDrawDispatcher.AlphaToCoverage = settings.AlphaToCoverage`.
|
||||
6. `StreamingController.MaxCompletionsPerFrame = settings.MaxCompletionsPerFrame`.
|
||||
|
||||
Mid-session quality change (F11 dropdown change → Save):
|
||||
|
||||
- `GameWindow.ReapplyQualityPreset` rebuilds `StreamingController` +
|
||||
`LandblockStreamer` with the new radii, re-applies anisotropic and
|
||||
AlphaToCoverage.
|
||||
- If `MsaaSamples` changed, logs a warning that MSAA sample count cannot be
|
||||
changed mid-session; requires restart.
|
||||
|
||||
#### Env-var overrides (§4.10.3)
|
||||
|
||||
Applied by `QualitySettings.WithEnvOverrides` after the base preset is resolved.
|
||||
Each field has one env var; all are optional. Logged at startup.
|
||||
|
||||
| Env var | Field overridden |
|
||||
|---|---|
|
||||
| `ACDREAM_NEAR_RADIUS` | `NearRadius` |
|
||||
| `ACDREAM_FAR_RADIUS` | `FarRadius` |
|
||||
| `ACDREAM_MSAA_SAMPLES` | `MsaaSamples` |
|
||||
| `ACDREAM_ANISOTROPIC` | `AnisotropicLevel` |
|
||||
| `ACDREAM_A2C` | `AlphaToCoverage` (1/0/true/false) |
|
||||
| `ACDREAM_MAX_COMPLETIONS_PER_FRAME` | `MaxCompletionsPerFrame` |
|
||||
|
||||
#### Tests
|
||||
|
||||
12 tests in `tests/AcDream.UI.Abstractions.Tests/Settings/QualityPresetTests.cs`
|
||||
cover: canonical preset values per enum member; `WithEnvOverrides` no-op when
|
||||
no env vars set; `WithEnvOverrides` each override individually; invalid env-var
|
||||
value falls back to base setting.
|
||||
|
||||
#### Files
|
||||
|
||||
- `src/AcDream.UI.Abstractions/Settings/QualityPreset.cs` — new
|
||||
- `src/AcDream.UI.Abstractions/Settings/DisplaySettings.cs` — `Quality` field added
|
||||
- `src/AcDream.UI.Abstractions/Panels/Settings/SettingsPanel.cs` — Display tab
|
||||
Quality dropdown (`RenderDisplayTab` method)
|
||||
- `src/AcDream.App/Rendering/GameWindow.cs` — `ReapplyQualityPreset`,
|
||||
`OnLoad` preset wiring
|
||||
- `tests/AcDream.UI.Abstractions.Tests/Settings/QualityPresetTests.cs` — new (12 tests)
|
||||
|
||||
#### Out of scope (deferred)
|
||||
|
||||
- Auto-detect preset on first launch (Phase A.6 / N.6.5).
|
||||
- Adaptive runtime preset drop on budget miss.
|
||||
- Per-feature toggles below preset level.
|
||||
|
||||
Commits: `afa4200` (schema + tests), `28d2c60` (wiring).
|
||||
|
||||
---
|
||||
|
||||
## 5. Data flow
|
||||
|
|
@ -668,7 +768,49 @@ Per the brainstorm Q10 confirmation:
|
|||
|
||||
---
|
||||
|
||||
## 11. References
|
||||
## 11. What was deferred (post-A.5)
|
||||
|
||||
The following items were identified during A.5 development but deferred to
|
||||
post-A.5 phases. They are tracked as OPEN issues in `docs/ISSUES.md`.
|
||||
|
||||
1. **Tier 1 entity-classification cache** (commit `3639a6f` reverted at
|
||||
`9b49009`): First attempt cached `meshRef.PartTransform` which is mutated
|
||||
per frame for animated entities (skeletal pose). Next attempt needs:
|
||||
(a) audit AnimationSequencer + AnimationHookRouter to identify ALL
|
||||
per-frame mutations of MeshRef state; (b) redesign cache to bypass
|
||||
animated entities OR cache only the animation-invariant subset; (c) test
|
||||
specifically with a moving animated NPC on screen. (`docs/ISSUES.md` #53)
|
||||
|
||||
2. **Lifestone missing visual**: The Holtburg lifestone has not rendered since
|
||||
earlier in A.5 development. Possibly Bug A's far-tier strip incorrectly
|
||||
catching a near-tier entity, or a separate earlier regression.
|
||||
(`docs/ISSUES.md` #52)
|
||||
|
||||
3. **Plumb JobKind through BuildLandblockForStreaming**: Bug A's fix (commit
|
||||
`9217fd9`) strips entities post-load in the worker. Proper fix: skip the
|
||||
`LandBlockInfo` + scenery load entirely for far-tier jobs. ~30 min.
|
||||
(`docs/ISSUES.md` #54)
|
||||
|
||||
4. **Tier 2 — Static/dynamic split with persistent groups**: ~2-week phase.
|
||||
Avoids per-frame entity re-classification by maintaining stable groups
|
||||
keyed at spawn time. Roadmap doc at
|
||||
`docs/plans/2026-05-10-perf-tiers-2-3-roadmap.md`.
|
||||
|
||||
5. **Tier 3 — GPU-side culling via compute pre-pass**: ~1-month phase.
|
||||
Same roadmap doc.
|
||||
|
||||
6. **Eliminate ToEntries adapter allocation**: tiny win (~25 KB/frame).
|
||||
|
||||
7. **InvalidateEntity wiring on palette/ObjDesc events**: needed by the
|
||||
Tier 1 retry.
|
||||
|
||||
8. **Visual gate at full High preset**: never validated due to the
|
||||
GPU+CPU stack-up OS crash earlier in A.5. With Bug A fixed the crash
|
||||
likely won't recur; defer retest to post-A.5 perf polish.
|
||||
|
||||
---
|
||||
|
||||
## 12. References (formerly §11)
|
||||
|
||||
- **Handoff (cold-start):** [`docs/research/2026-05-10-phase-a5-handoff.md`](../../research/2026-05-10-phase-a5-handoff.md)
|
||||
- **N.5b handoff (predecessor):** [`docs/research/2026-05-09-phase-n5b-handoff.md`](../../research/2026-05-09-phase-n5b-handoff.md)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue