At the end of the previous article we left a question: what exactly still separates a AAA game from running on mobile devices? The common answer is “performance optimization”, but that phrase is too vague to schedule work against. Taken apart, the gap is three ledgers: a budget ledger that fixes what each frame may spend; a scheduling ledger that fixes how a world far larger than memory flows in and out; and a cadence ledger that fixes the intervals at which frames reach the player’s eyes.
In a AAA studio these three ledgers are kept by dedicated teams: the engine group sets budgets, streaming and memory have their own keepers, a performance group runs regressions, and technical artists translate specifications for the content team. What we call “AAA quality” is, in large part, the output of this invisible organization — and it is precisely the part a small team cannot afford to hire. The mechanisms — render pipelines, virtualized geometry, open-world streaming — can all be bought from an engine today; what cannot be bought is the discipline that enforces the three ledgers. This article first lays the ledgers out, then answers the question from last time — knowing the target platform, how should art asset specifications and code structure be organized — and why this is moving from “highly paid engineering teams” to “infrastructure”.
Ledger 01 · The per-frame budget: accounting in many currencies
The surface currency of a frame budget is time: a frame is 16.6 ms at 60 fps, 8.3 ms at 120 Hz, 33.3 ms at 30 fps. But time is only the settlement unit. What actually gets spent are four other currencies: CPU milliseconds, GPU milliseconds, bandwidth and power — and on mobile, the last two are the hard walls.
| Constraint | Desktop workstation | Flagship phone |
|---|---|---|
| Memory bandwidth | Dedicated, on the order of 1 TB/s | Tens of GB/s, shared with the CPU |
| Power ceiling | Hundreds of watts for one GPU | Single-digit watts for the whole device, plus a thermal wall |
| Memory | Physical RAM mostly usable | The OS kills processes well below physical RAM |
| Sustained performance | ≈ peak performance | Peak holds for minutes; budget against sustained clocks |
This table explains why mobile GPUs are overwhelmingly tile-based: keep a small tile’s intermediate results in on-chip memory and finish there, because a round trip to main memory costs bandwidth and battery at once. It also sets the first lesson of porting — shipping the same assets straight down mails the desktop’s bandwidth bill to a phone: every extra texture sample, every extra load/store on a render target, every mid-pass resolve spends both of the scarcest currencies at once. And heat rewrites the denominator: 16.6 ms at benchmark clocks does not count; 16.6 ms at clocks the device can hold through forty minutes of play does.
For a budget to be enforceable it must be split into line items. “This frame gets 16.6 ms” is a wish; “shadows 1.5, opaque pass 4.5, lighting 2.5, transparents and FX 2.0, post 2.0, UI 0.8, streaming and misc 1.0, headroom 2.3” is a contract — an overrun points at a line item immediately, instead of “the game got slow”. The CPU side is the same: game thread, render submission and the worker pool each keep their own books.
How a budget exists decides whether it works. A budget on a wiki is remembered at review time, sometimes; an effective budget lives in the pipeline — assets validated on import, capture data reconciled against the ledger line by line, overruns blocked before merge. This is where the article returns at the end.
Ledger 02 · World streaming: the scheduler that follows the camera
An open world presumes the world is larger than memory, so “which assets are in memory right now” becomes a question answered anew every frame. The answer follows the camera: the world is cut into cells, the distance is stood in for by HLODs, and a resident set is maintained around the viewpoint. It sounds plain; in engineering terms it is a real scheduler with its own priority function and per-frame budgets.
Priority is not distance alone. Velocity joins the prediction — the prefetch ring should shift along the movement vector, because where the player is heading at speed deserves the IO more than what is behind them; visibility joins the ordering — cells behind a wall can arrive late; gameplay gets to cut the line — teleport targets and cinematic destinations should warm up before they trigger. The scheduler’s currencies tie straight back into the frame budget: IO requests in flight, decompress milliseconds per frame, upload megabytes per frame, and the resident pool’s watermarks. Big files are split across frames; eviction carries hysteresis, or the pool oscillates between evict and reload right at the waterline.
Mobile adds three special rules. First, the pool is smaller, so prediction quality directly becomes user experience — desktop can paper over misprediction with redundant residency, a phone cannot. Second, decompression is not free: consoles put it in hardware and PCs have NVMe plus DirectStorage behind them, while on a phone every decode burns into those few watts, so compression ratio versus decode cost must be re-balanced per platform. Third, streaming is not only about assets — the first time a new material enters the frame, pipeline compilation can hitch just the same, so PSO warmup belongs on the streaming schedule next to textures and meshes.
The acceptance test for this ledger is the same as the last one: never “feels smooth”. Fixed automated flythrough routes and long soak runs on real devices produce hitch counts, pop-in durations and pool watermark curves — those numbers are the scheduler’s report card.
Ledger 03 · Frame pacing: average FPS lies
The first two ledgers govern what each frame spends; the third governs the interval between frames — most of what a player feels, and exactly what average FPS cannot measure.
Cadence fails in two shapes. One is the hitch — an isolated long frame, with a leaderboard of causes that never changes: pipeline compilation triggered by a shader variant’s first appearance, synchronous IO landing on the critical path, allocation or GC spikes. The other is judder — no frame over budget, yet content step and display beat fall out of phase, and the image advances unevenly in a way the eye catches even at high frame rates. The first is fought by moving slow things off the critical path (PSO warmup, async IO, streaming inside its allowance); the classic answer to the second is fixed-timestep simulation with render interpolation, decoupling the simulation beat from the display beat.
The platform layer adds a set of mechanisms that must be done right per platform: swapchain depth trading latency against throughput; the Frame Pacing library aligning to Choreographer on Android; ProMotion on iOS not giving you 120 Hz unless the refresh-rate range is explicitly requested; variable refresh rescinding the “divide vsync evenly” rule — down to a floor, below which duplicated frames return. None of these is individually hard; the hard part is a dozen of them being right at once, and staying right on every new device generation.
And one more that testing misses most easily: thermal throttling. A game with perfect cadence for twenty minutes collapses in minute twenty-five as the SoC steps its clocks down — a thirty-second capture cannot see it; only a long on-device soak can. The cadence ledger is therefore an SLO sheet: it constrains the shape of the frame-time distribution across a whole play session. The mean does not even get a line item.
How three ledgers grow into the pipeline
Back to the two questions from last time. Knowing the target device and platform, organizing art specifications and code paths is, at bottom, moving the three ledgers out of documents and into the pipeline.
Art asset specifications, organized as data, not documents. One machine-readable spec per device tier: texture compression formats and size caps, mip and channel-packing conventions, LOD chain depth and decimation ratios, material complexity ceilings, the shader variant matrix. Validation happens at DCC export — a non-conforming asset is stopped the moment it is imported, not discovered three months later in an on-device capture; the cook produces per-tier variants from the same source asset. Nor must every variant be made by hand — take decimation: the spec states each LOD’s target triangle ratio and the features to preserve (silhouette, normals, UVs, skin weights), and an automatic decimator generates the whole chain per tier. Our toolchain already carries such a component: an attribute-aware QEM edge-collapse decimator that preserves boundaries and skinning and delivers to a target ratio. As for what defines a “device tier” — not a hand-kept handset list, but frame-time and bandwidth data captured on real hardware: tiers are measured, not guessed.
Code structure, organized around one abstraction seam. The platform-agnostic game and engine core on one side, each platform’s implementation in its own modules and directories, a clean graphics-and-systems abstraction layer between them; quality tiers expressed as data-driven scalability configuration rather than conditional compilation scattered through the code — the problem with an #ifdef forest is not that it is ugly, but that it quietly turns “one codebase” into a superposition of N, and the three ledgers stop reconciling. The direct price of organizing this way is the build matrix: the combinatorial explosion of platform × tier × configuration. That is exactly the cost distributed builds exist to eat — the IrisBuild cluster from the previous article, pressing UE editor shader-compile local fallbacks from 518 to 1 and the Unity IL2CPP stage from 236 s to 129 s, is paying precisely this bill.
Budgets as gates: the ledgers are enforced inside the loop. Spec validation stops non-conforming assets; the build matrix produces every platform and tier; the device matrix flies fixed routes and runs long soaks overnight; capture data reconciles against the three ledgers line by line; and an overrun is not an email — it is an attribution, landing on a specific commit or a specific asset, carried back to the workspace with evidence. The automated loop of the previous article closes here.
Democratizing creativity
With the three ledgers laid out, the question “can a small team ship platform-wide, high-quality games” can be answered honestly.
What infrastructure can flatten is the cost of discipline. Budget reconciliation, streaming acceptance, long-session cadence regression, the cross-platform build matrix, the device farm’s night shift — inside a AAA studio these map to a whole layer of highly paid engineering organization, and they are precisely the most automatable part: mechanisms rented from the engine, discipline subscribed from infrastructure. Ycode puts real devices, captures, automated replay and evidence-carrying AI triage into one workspace; IrisBuild lets the build matrix’s cost amortize across a cluster — together they turn that organizational layer into something subscribed by capacity.
What cannot be flattened is content and judgment. World, levels, feel, taste — content volume is still human time, and taste is still a human decision. But that is the point: a team of three to five used to face a brutal trade between “keeping the ledgers” and “making the game good”; now all of the human time can go to the latter. Engineers are not replaced — their discipline is written into the infrastructure, so it no longer has to be re-hired inside every team.
This is what we mean by democratizing creativity: more people taking part in making high-quality interactive works, with a work’s ceiling set by imagination and taste rather than by how many highly paid engineers one can afford. The three ledgers remain — they just no longer decide who gets to enter.
The road does not end at software. AI infrastructure is making “thinking” ever faster, and the bottleneck moves to the other side: agents must ultimately execute actions, and the heaviest actions in the loop — builds, baking, decimation, frame analysis — will eventually deserve dedicated silicon, just as compilation moved onto distributed clusters. We intend to build custom ASICs for game development and iteration, powering the production lines of real-time interactive worlds. The vision stays the same: players living other lives inside worlds woven from different imaginations, and more creativity reaching everyone in high-quality interactive form.
The entire game-development loop, on one AI-powered infrastructure.
Product page mixstudio.tech/product/ycode · Community Discord · Business [email protected]