# Platform, Performance & Tech

V5 is one Unreal Engine 5 open-world narrative universe — five playable ruleset
cells stitched together by a cross-cell Mind Palace — and it promises to run
that ambition across **nine launch platforms**, from a PS5 Pro pushing 4K/120
down to an iPad Pro running a touch-only Mind Palace. This page is the cluster
that turns that promise into something a platform holder can certify, an ops
team can profile, and a player can drive on whatever silicon they own. It is
also where V5's central honesty convention bites hardest. The repository is
**logic-and-manifest only**: V5 ships **zero binary `.uasset` files**, and the
game's modular content lives as **29 `.uplugin`** manifests over **74 C++
modules**. A repo with no cooked content cannot boot, cannot capture a GPU
trace, and cannot stand in a cert lab — so a manifest that _declares_ a 4K/60
frame budget or a passed TRC is declaration, not measurement, and this page says
which is which on every line.

The boundary runs cleanly. Some of this surface is **real, tested Unreal C++** —
the World Partition streaming subsystem and the triple-redundant save-generation
subsystem are substantive engine code with automation behind them, and the build
targets (dedicated server, arcade cabinet, listen server) are real `.Target.cs`
rules. Some is **machine-checked policy over JSON** — the per-platform
performance budgets and the crossplay/cross-progression policy are each enforced
by a Python validator _and_ an independent reader, and both pass green today.
The rest — cert checklists, the asset-size budget, VR/AR variants, peripheral
curves, store mappings, the companion app, and the persistent-world economy — is
authored intent in data, labeled as such wherever it appears. The section hub is
[../V5_features.md](../V5_features.md).

## What ships, honestly

It is worth stating the boundary up front so nothing below is oversold.

- **Open-world streaming is real, validated C++.** `UV5_Open_StreamingSubsystem`
  (`V5/ue/Source/V5Open/Private/V5OpenStreamingSubsystem.cpp`, 238 lines + an
  82-line header) is a `UWorldSubsystem` that implements Unreal's
  `IWorldPartitionStreamingSourceProvider`, registers the player / companions /
  mission markers as prioritized streaming sources, and computes the
  mission-start pre-warm grid — real engine integration, not a description of
  one.
- **Save redundancy and crash recovery are real C++.** `UV5_SaveGameSubsystem`
  (`V5/ue/Source/V5Core/Private/V5SaveGameSubsystem.cpp`) rotates three save
  generations (`Current` → `Previous` → `Fallback`), validates decrypt and JSON
  import on each, and recovers from a corrupt slot by rotating the first good
  generation back to current.
- **Performance budgets are a cross-validating gate, not decoration.**
  `V5/tools/performance/validate-performance-budgets.py` (223 lines) checks the
  11-profile catalog against exact budget tuples _and_ re-parses each platform's
  `.ini`; the UE test `V5.Tests.PerformanceBudgets` independently asserts the
  same catalog in-engine. Both pass today.
- **Crossplay and cross-progression are machine-checked policy.**
  `V5/crossplay/crossplay-progression-policy.json` is enforced by
  `V5/tools/crossplay/validate-crossplay.py` with a pytest harness that also
  runs a negative case. It passes today.
- **Build targets are real.** `V5DedicatedServer.Target.cs` is a lean
  `TargetType.Server` that strips ~28 client-only plugins;
  `V5ArcadeCabinet.Target.cs` is a kiosk SKU with coin-op economy compiled out;
  `V5ListenServer.Target.cs` is the host-migration path.
- **Cert, store, VR/AR, peripherals, companion app, and the world economy are
  declared intent.** They are honest checklist and entitlement data. A real TRC
  / Lotcheck / XR pass needs a cooked, bootable build the stand-in repo cannot
  produce — the same caveat the architecture companion
  [../architecture/observability-performance-testing-content-pipeline.md](../architecture/observability-performance-testing-content-pipeline.md)
  states in full.

## Platform support, fidelity & certification

### Nine platforms, one catalogue — and the arcade cabinet SKU

V5 targets PS5, PS5 Pro, Xbox Series X, Xbox Series S, Switch 2, Windows, macOS
(Apple Silicon), Steam Deck / Linux, and iPad Pro M3+. The parity rule is that
no cell, mode, or campaign is withheld behind a platform; the only principled
reductions are hardware reality, and they are encoded rather than promised. The
performance catalog marks the **Switch 2** profile with
`hardVacuumCookExcluded: true` — the Expanse-style spaceship cell is the
heaviest load in the game (dynamic gravity plus crew sim), and the handheld
drops it — and the **iPad Pro M3+** profile carries
`Nanite "Disabled outside Mind Palace"` and a `TouchOnlyMindPalace` restriction,
so the tablet ships the cross-cell deduction surface rather than the full open
world.

Beyond the nine consumer platforms, V5 cooks a distinct location-based SKU.
`V5ArcadeCabinet.Target.cs` is a real game target that adds the compile
definitions `V5_ARCADE_CABINET=1`, `V5_LOCAL_COOP_CABINET=1`,
`V5_CABINET_ONLINE_SERVICES=0`, and `V5_CABINET_COIN_OP_ECONOMY=0` — a
four-player local-co-op cabinet that compiles online services and any coin-op
economy _out_ of the binary, packaged through its own
`Platforms/ArcadeCabinet/Config/ArcadeCabinetEngine.ini` and profiled at 4K60.
It cooks only a curated roster (Spec Ops Co-op, Horde Defense, Fleet Co-op,
Hunter Card Game, Training Range) and hides open online/PvP rulesets behind the
build-target gate.

### Per-platform fidelity targets

The fidelity story is per-platform and explicit, because a Switch 2 and a
Windows-ultra rig do not share a frame-time reality. The launch-locked catalog
at `V5/ue/Content/V5Performance/Data/performance_platform_profiles.json`
(`schemaVersion: 1`, `contentLock: "launch-v5"`) carries **11 budget profiles
across 9 platform groups**, each declaring its upscaler, GI and Nanite strategy,
per-mode targets, and scalability knobs:

| Platform group              | Modes (target / frame budget)        | Upscaler           | GI / Nanite                                |
| --------------------------- | ------------------------------------ | ------------------ | ------------------------------------------ |
| PS5                         | quality 30/33.3 ms · perf 60/16.6 ms | TSR                | Full Lumen · Nanite                        |
| PS5 Pro                     | quality 60/16.6 ms · perf 120/8.3 ms | TSR                | Full Lumen · Nanite                        |
| Xbox Series X               | quality 30/33.3 ms · perf 60/16.6 ms | TSR                | Full Lumen · Nanite                        |
| Xbox Series S               | quality 30/33.3 ms · perf 60/16.6 ms | TSR                | Reduced Lumen · LOD-bias Nanite            |
| Switch 2                    | quality 30/33.3 ms · perf 60/16.6 ms | TSR mobile         | Reduced Lumen + SDF GI · Aggressive LOD    |
| Windows (low / rec / ultra) | 60/16.6 ms · 60/16.6 ms · 120/8.3 ms | TSR · DLSS/FSR/TSR | Reduced→Full Lumen                         |
| macOS Apple Silicon         | standard 60/16.6 ms                  | MetalFX            | Full Lumen where supported                 |
| Steam Deck                  | deck 30/33.3 ms                      | FSR/TSR            | Reduced Lumen · LOD-biased                 |
| iPad Pro M3+                | touch 60/16.6 ms                     | MetalFX mobile     | Mobile GI · Nanite off outside Mind Palace |

Memory budgets scale with the silicon — 8 GB on Series S, Switch 2, and the
Windows-low tier; 12 GB on PS5 and Series X; 13 GB on PS5 Pro; 16 GB on macOS,
Steam Deck, iPad, and Windows-recommended; and 32 GB on Windows-ultra. The
per-mode rows are not round numbers picked for marketing: the Switch 2 quality
mode is given a _fatter_ 28 ms GPU slice (against PS5's 22 ms) because the
handheld is GPU-bound and CPU-light, while its CPU budget drops to 5 ms.

Certification itself is the honest weak point: a real Sony TRC, Microsoft XR,
Nintendo Lotcheck, or Steam Deck Verified pass requires a cooked build to boot,
and this repo ships none. Cert status in V5 is therefore checklist intent, and
the launch-readiness gate refuses to count a platform cert-passed without
on-disk evidence behind it.

## Performance budgets

### The cross-validating gate

The catalog is enforced by two independent readers that must agree with the data
and with each other — which is how a budget gets _enforced_ rather than merely
documented. `validate-performance-budgets.py` is the CI reader, and it does
domain-specific verification a renamed-variable stub could not pass:

- It checks the profile inventory against an explicit `EXPECTED_PROFILE_IDS` set
  and the exact `(targetFps, frameBudgetMs, gpuBudgetMs, cpuBudgetMs)` tuple for
  every profile/mode against an `EXPECTED_BUDGETS` table.
- It asserts the special-platform flags — `switch-2` reduced-Lumen + SDF GI
  _and_ Hard-Vacuum cook excluded, `macos-apple-silicon` MetalFX, `steam-deck`
  Proton-verified, `ipad-pro-m3` touch-only Mind Palace.
- It requires `profiledFrameP95Ms ≤ frameBudgetMs` for every mode.
- It then **re-parses each platform's `.ini`** (e.g.
  `V5/ue/Platforms/PS5/Config/PS5Engine.ini`) and confirms the
  `[V5Performance.PS5]` section's `profileId`, memory budget, upscaler,
  GI/Nanite strategy, regression suite, and every per-mode FPS / budget /
  resolution match the JSON. The PS5 `.ini` block carries
  `quality.frameBudgetMs=33.3`, `performance.gpuBudgetMs=11.0`, and so on — the
  engine config and the budget catalog are kept in lockstep by the gate.

The matching UE automation test, `FV5PerformanceBudgetCatalogTest`
(`V5.Tests.PerformanceBudgets`, in
`V5/ue/Source/V5Tests/Private/Tests/V5TestsAutomation.cpp`), independently loads
the same catalog from the cooked content dir and asserts the 9 / 11 / 11 counts,
that every profile's profiled p95 stays within its frame budget, that each
profile blocks release through a regression suite, and that the four
special-platform flags are set. Eleven `regressionSuites` mirror the eleven
profiles, each `blocksRelease: true` and each bound to the
`Automation RunTests V5.Tests.PerformanceBudgets; Quit` command.

### What "profiled" honestly means here

The honest caveat is precise. Each profile carries a `profilingEvidence` block
that asserts `status: "profiled-and-tuned"`, `scenarioCount: 6`,
`captureMinutes: 10`, and a `traceArtifact` such as
`Saved/Profiling/V5/ps5.utrace`. No such `.utrace` exists — it cannot, in a text
repo with zero cooked content — and the validator does not claim it does: it
checks the artifact path _ends in_ `.utrace` and that the capture-minutes and
scenario counts clear a floor. So the gate enforces the **internal consistency
and the budget math** (every declared p95 sits under its declared budget; config
and catalog agree), not a real GPU capture on real hardware. That is the correct
shape for V5 today: the budgets are real engineering targets with real teeth
against drift, and the profiling evidence is declared intent awaiting a cooked
build.

### Asset budgets and the zero-`.uasset` reality

The features source publishes a per-cell asset budget — Urban Crime at 240 GB
geometry / 1.6 TB 4K textures / 38 GB audio, Sci-Fi the heaviest at 280 GB / 1.8
TB / 42 GB — as the _uncompressed authoring footprint_, before Oodle compression
and platform texture formats. These are planning estimates: with zero `.uasset`
authored, there is no measured footprint behind them, and they are honest scope
targets rather than a manifest of real bytes. The _streaming and install
mechanics_ they imply, by contrast, are concrete — World Partition cells,
per-cell content roots so a reduced SKU ships without an omitted cell's budget,
and chunked installs where a player can boot a cell's minimum-playable chunk
before the rest downloads.

## Technical features

### Open-world streaming: the real subsystem

This is the load-bearing real code of the cluster. `UV5_Open_StreamingSubsystem`
registers itself with the engine's `UWorldPartitionSubsystem` as a streaming
source provider on `Initialize` and `OnWorldBeginPlay`, and unregisters cleanly
on teardown. Gameplay code registers sources through `RegisterStreamingActor` (a
source that follows an actor) or `RegisterStreamingLocation` (a fixed point),
tagging each with a cell and an `EV5OpenStreamingSourceKind` of `Player`,
`Companion`, or `MissionMarker` — exactly the "streaming sources are the player,
companions, and active mission markers" the features doc names.

The priorities are real logic, not a constant. `ResolvePriority` returns
`Highest` for the player, `Normal` for companions, and `High` for a mission
marker — _except_ in the Sci-Fi cell, where a mission marker is promoted to
`Highest` because a hard-vacuum approach must stream the target before the
player arrives at burn speed. `GetSortedStreamingSourceDescriptors` orders
sources by priority, then kind, then name (a stable, deterministic sort), and
`GetStreamingSources` hands the engine real `FWorldPartitionStreamingSource`
objects with a radius converted from meters to centimeters, a debug color per
kind, and the activated target state. The class also exposes
`GetPrewarmCellsForMissionStart(MissionCenter, CellRadius = 1)`, which
floor-divides the mission center by the `PartitionCellSizeMeters = 256.0f` grid
and returns the `(2r+1)²` block of `FIntPoint` cells around it — the
implementation behind the "critical 3×3 cell area is pre-warmed at mission
start" claim — and `IsStreamingCompletedForV5Sources`, which delegates to the
engine's `IsStreamingCompleted` to gate a mission start on streaming readiness.

### Save redundancy, crash recovery, quick-resume & patching

Crash recovery is grounded in `UV5_SaveGameSubsystem`. A save is written across
three generations — `EV5SaveGeneration::Current`, `Previous`, and `Fallback` —
and the load path walks them in order: it reads each generation's envelope
bytes, rejects a generation that fails decrypt or whose JSON fails
`UV5_SaveGame::ImportFromJsonString`, logs the rejection, and on the first good
non-current generation rotates it back to `Current` so the next launch is clean.
That is the "triple-redundant (current, previous, fallback), corrupt save falls
back to the previous generation" behavior, implemented rather than asserted, and
because Mind Palace state is part of the save envelope, a deduction graph
survives a crash. The same `ImportFromJsonString` seam backs the Save-Slot
Archaeology flow that re-imports an older save into a New Game+ run.

The remaining recovery and update surface is documented process mirroring V4's
pipeline: a single binary day-one patch, then chunked `UnrealPak` iterative
delivery so a player downloads only changed chunks; CDN-served hot-fix data
(balance values, UI strings, live-service data) fetched at session start with no
binary patch; Xbox Series X|S Quick-Resume that revalidates session and online
state on wake; and a DRM posture of signed-execution checks only, **no
Denuvo-equivalent**, recorded in the decision log at
`V5/docs/decisions/0007-no-denuvo.md`.

### Server topology: dedicated, listen, and cabinet build targets

V5 makes dedicated-server client-server netcode the default for open-world PvP
and co-op, and the build targets make that real. `V5DedicatedServer.Target.cs`
is a `TargetType.Server` that defines `V5_DEDICATED_SERVER=1` and **disables ~28
client-only plugins** — Niagara, Metasound, the Chaos cloth/flesh modules,
CommonUI, EnhancedInput, MetaHumanRuntime, PCG, the geometry and IK toolsets,
and more — so the authoritative host compiles without rendering, audio, or input
weight. `V5ListenServer.Target.cs` (`V5_LISTEN_SERVER=1`) is the peer-hosted
path for the sub-2-second host-migration promise, and
`V5ArcadeCabinet.Target.cs` is the offline kiosk. The deeper netcode authority
and determinism design is owned by the architecture companion
[../architecture/observability-performance-testing-content-pipeline.md](../architecture/observability-performance-testing-content-pipeline.md)
and its netcode sibling.

### Crossplay & cross-progression

Cross-progression is machine-checked policy data today, not a running merge
service. `crossplay-progression-policy.json` declares one canonical `v5acct`
account with a single required account id, **9 platform credentials** (Steam
OAuth on Windows/Linux, Apple on Mac, Sign-in-with-Apple on iOS, PSN entitlement
subjects, Xbox `xuid`, and a Nintendo Account), and **four progression domains**
each with a named merge policy and offline reconcile: `profile`
(last-verified-write-wins), `cosmetics` (entitlement union), `bureauXp`
(monotonic ledger sum), and `mindPalace` (node last-writer-wins with accusations
append-only). Default crossplay is on for all nine platforms with exactly one
principled per-cell opt-out — Sci-Fi `mode.scifi.spaceship-pvp`, on
high-precision-input parity grounds. A signed, encrypted companion save-transfer
bundle carries those scopes plus `saveGames` between devices.

`validate-crossplay.py` enforces all of it — the nine required platforms, the
four required domains each with a service owner and offline reconcile, the
Sci-Fi opt-out targeting spaceship PvP, the signed-archive requirement, the save
scopes, and the QA-scenario coverage set — and `test_validate_crossplay.py` runs
it green against the live repo _and_ asserts it _fails_ when the Mind Palace
domain is removed (a negative test that proves the validator has teeth). The
honest framing: this is a contract with named service owners (`auth`,
`companion-app-bridge`, `mindpalace-cloud-sync`), validated for shape and policy
correctness, not an exercised cross-device merge.

```mermaid
flowchart TB
  subgraph real["Real, tested C++"]
    STREAM["UV5_Open_StreamingSubsystem<br/>World Partition source provider<br/>256 m cells · prewarm grid · priority"]
    SAVE["UV5_SaveGameSubsystem<br/>Current → Previous → Fallback<br/>decrypt + JSON validate + recover"]
    TGT["Build targets<br/>DedicatedServer (−28 plugins)<br/>ArcadeCabinet · ListenServer"]
  end
  subgraph gated["Machine-checked policy over JSON"]
    PERF["performance_platform_profiles.json<br/>11 profiles · 9 groups · 11 suites"]
    XP["crossplay-progression-policy.json<br/>9 creds · 4 domains · opt-out"]
  end
  subgraph declared["Authored intent (no cooked build)"]
    CERT["cert · store · region pricing"]
    XR["VR/AR variants · peripherals"]
    APP["companion app · world economy"]
  end
  PERF -->|validate-performance-budgets.py<br/>+ V5.Tests.PerformanceBudgets| GATE["build / launch gate"]
  XP -->|validate-crossplay.py + pytest| GATE
  STREAM --> CLIENT["V5 client"]
  SAVE --> CLIENT
  TGT --> CLIENT
  CERT --> GATE
```

### Adaptive difficulty, VR/AR, peripherals & live surfaces (declared intent)

The remaining technical surfaces are authored design rather than backing C++,
and are labeled so. The per-cell **AI Director** reads a rolling performance
signal (deaths, damage taken, objective time, accuracy) to keep each cell inside
its difficulty band — disabled in ranked PvP, Trials, and Speedrun so those stay
deterministic, and fully player-toggleable. **VR/AR** is curated to each
headset's strength: a seated PSVR2 cockpit for Hard Vacuum, a Quest 3 spectator
theater, a Vision Pro volumetric Mind Palace viewer, and a Hunter VR full-cell
manifest. **Peripherals** route through Enhanced Input and are fully remappable
— HOTAS, force-feedback wheels, PS5 Access / Xbox Adaptive controllers, and
DualSense weapon-specific triggers. The **store / region-pricing** surface is
PPP-adjusted per region with no campaign-gating editions; the **companion app**
is, by the features source's own admission, design-token mockups only
(`V5/companion/` holds one static `.swift` and one static `.kt` file, no
buildable project); and the **persistent-world economy** is
deterministic-given-seed save state, simulated coarsely while a cell is
inactive. None of these has a cooked build behind it, and the launch-readiness
gate keeps the cluster red until one exists.

## Where this connects

- **Sideways:**
  [Accessibility, Localization & Compliance](./accessibility-localization-and-compliance.md)
  owns the WCAG, parental-control, age-gating, and ratings surfaces that several
  of this page's launch gates and the telemetry opt-out depend on;
  [Production, Progression, World & Launch](./production-progression-world-and-launch.md)
  owns the account, save-archaeology, persistent-economy, and launch-readiness
  surfaces this page's save redundancy, crossplay scopes, and cert checklists
  feed.
- **Architecture companion:**
  [Observability, Performance, Testing & the Content Pipeline](../architecture/observability-performance-testing-content-pipeline.md)
  is the home of the performance-budget gate, the Gauntlet driver, the
  zero-`.uasset` content-pipeline accounting, and the fail-closed
  launch-readiness gate this page's budgets and policy validators compose into.
- The section hub: [../V5_features.md](../V5_features.md).
