Skip to content
Русский

Frame cost and look, on the low-end box

  • Low-end / older Windows iGPU box (§9), 1080p. Run the current release standalone, let it reach steady state, capture diagnostics.log. Report (a) fps holds ≥ 60 @ 1080p, and (b) steady-state working set + private commit. (This is Plan 0012 Phase 3, extracted; it also satisfies the identical Plan 0003 Phase 3 iGPU-60-fps carry-forward — same measurement.)
  • Second GPU vendor — Intel iGPU, if a box is available, 1080p. Same capture. The point is the footprint spread vs the AMD dev box — confirms whether the ~350 MB ceiling is AMD-specific.
  • The dual-live dissolve budget, on the low-end box. Plan 0023 made every preset switch a ~1 s dissolve, and its governor re-renders the outgoing preset live as well whenever the two presets hold independent GPU state and the smoothed frame time is under DUAL_LIVE_BUDGET_MS (core/src/render/mod.rs, currently 18.0 — the code calls it “the number to calibrate on a low-end rig”, and no capture can speak to it because a headless run collects no frame times and so never upgrades). Two things to report, both with the overlay on (F3) so the p99 is visible: (a) press Space repeatedly between light presets — does the frame time hold ≥ 60 fps through the dissolves, or does the governor’s threshold need to come down; (b) the heavy pair — dissolve an attractor preset into a reaction-diffusion one and back. That pair is the freeze fallback’s reason for existing; on this box it should either stay frozen (fine) or, if it upgrades, still hold the floor. (Plan 0023 Phase 4’s done-when and its budget-tuning risk, extracted at that plan’s close.)
  • The layered heavy pair (Plan 0076), on the low-end box, 1080p. A preset may now compose a second scene ([layer], ADR-0090), and Floor renders both layers by design — a two-layer world must not lose half its content on weak hardware. The deliberately heavy pairing is an attractor main with a reaction-diffusion layer, at both joins (under, and over with a blend — the over join adds a surface-sized Rgba16Float offscreen pair and one blend pass). With the overlay on (F3), load such a preset — the Plan 0076 close notes carry probe TOMLs, or write one from presets/README.md — and report (a) whether fps holds ≥ 60 at 1080p for each join and (b) the p99 against the attractor preset alone. (Plan 0076 Phase 4’s measured numbers are dev-box hardware figures, not iGPU evidence; this line is where that evidence comes from. If it fails, the response is authoring guidance — heavy-plus-heavy pairings are an authoring responsibility per ADR-0090 — not a tier change.)
  • Trails at native resolution, on the low-end box, 1080p. Plan 0033 made the two post stages size their internal grid from the render target instead of a fixed 1280x720 (ADR-0034). With trails active that is now a full-resolution Rgba16Float ping-pong read and write every frame where it used to be a 720p one — roughly 2.25x the feedback bandwidth at 1080p. Plan 0045 raised it again: the accumulation was always float, but the stage’s composited output and the fold’s source were the surface format and are now Rgba16Float too (ADR-0046), so every hand-off between stages moved from 4 to 8 bytes a texel. Composite bandwidth roughly doubled on top of the 2.25x. NFR §1’s ≥ 60 fps @ 1080p floor is exactly the claim at risk, and no headless capture can speak to it: WARP timings say nothing about an iGPU’s memory bandwidth. Load rose_trails — it binds trails around 0.78 and is the shipped preset that exercises this path (fragment_kaleido covers the fold). Let it settle with the overlay on (F3), and report (a) whether fps holds ≥ 60 and (b) the p99 against the same preset with trails = 0. (Plan 0033’s stated main exposure, widened by Plan 0045. If it fails, lower TierConfig::FLOOR.post_cap in core/src/render/tier.rs — the constant moved there in Plan 0044 — and do not re-fix the grids.)
  • Working-set delta from the post stages, including mid-dissolve. Re-stated for the float composite (Plan 0045). These numbers moved twice: Plan 0033 grew the composite from ~22 MB per chain to ~50 MB at the cap by sizing the grids from the target, and Plan 0045 took that to ~66 MB by moving every intermediate to Rgba16Float (8 bytes a texel, not 4). A dual-live dissolve holds two chains, so the transient peak is ~133 MB, and the worst case — dual-live, every stage on including bloom, ink on — is ~246 MB against NFR §12’s ~350 MB soft ceiling, which is mostly driver floor already. There is also a genuinely new surface-sized float buffer that exists on every frame regardless of preset: the tonemap’s input, 16.6 MB at 1080p. The full before/after table is in Non-functional requirements §12. Those figures are arithmetic from the texture descriptors, not a measurement. On the low-end box, report the steady-state working set with a trails preset active, and again while holding down preset switches so a dissolve is live, against the same numbers with trails = 0. Read rss_bytes, not gpu_bytes — the latter is a swapchain-only approximation (ADR-0008) that does not count the post stages’ offscreens, so it reads identically either way. Measured on the dev box after Plan 0033 landed: gpu_bytes unchanged at 16,588,800 (= 1920x1080 x 4 B x 2 — the swapchain exactly), and rss_bytes up only ~3 MB, because that box renders on a discrete GPU where the textures sit in VRAM and never enter the working set. That is exactly why this item needs the iGPU, where GPU memory is system memory — and why the doubled float footprint is unmeasured rather than known-harmless. (Plan 0033 Risks: “memory is a projection, not a measurement”. Same mitigation as above — the cap is one constant.)
  • Bloom on the low-end box, 1080p. Plan 0045 Phase 4 added a bright-pass, a blur pyramid and a recombine as a third PostStage. It is off by default (bloom_amount = 0 skips the stage entirely — no offscreens, no pyramid, no pipelines), so an ordinary run on most of the library measures none of it. Load star_lantern — it is the shipped preset built for this stage and binds all three params (bloom_amount around 0.95 rising on onset, bloom_threshold = 1.0, bloom_radius around 2.15), so no scratch RLX_PRESET_DIR is needed any more. When active the stage costs 4N passes at TierConfig::bloom_levels (Floor = 4, Rich = 6) plus its own grid-sized bloom-src offscreen and the pyramid — 16.6 + ~11 ≈ 28 MB at the floor cap (NFR §12). Report (a) whether fps holds ≥ 60 @ 1080p with bloom active on top of trails + the fold, and (b) the p99 against the same preset with bloom_amount = 0. If it misses, the lever is TierConfig::FLOOR.bloom_levels — a capacity, not a look, so it is a smaller decision than the other levers on this page, but the halo does visibly shorten. (Plan 0045 Phase 6 measured the Rich side on the dev box’s discrete GPU. Bloom is not what is expensive there: star_lantern runs 164 fps, p99 8.2 ms windowed — comfortably inside a 60 Hz frame — against attractor_clifford’s p99 19.9 ms and attractor_leviathan’s 19.0 ms on the same run, neither of which binds bloom at all. (Both attractor figures predate ADR-0140 and were taken at a flat 150 000 samples; see the Rich calibration item below.) So the cost that puts the heaviest shipped preset past a 60 Hz frame at Rich is the float composite plus the attractor, not this stage. Still owed on this page: the same star_lantern run at native fullscreen, the Floor-pinned sanity pass, and all of the low-end-box side.)
  • The reaction-diffusion present’s reconstruction cost, on the low-end box, 1080p. Plan 0033 replaced the RD present’s field sampling with a Catmull-Rom reconstruction to get the coral look. The present pass now calls sample_v five times per fragment, each at nine bilinear taps — roughly 45 texture fetches per fragment, over the whole screen, every frame. It shipped unmeasured on hardware: the WARP figure first reported was retracted as run-to-run noise (the same suite timed 193.6 / 224.2 / 105.2 s across three runs), and a software rasterizer says nothing about an iGPU’s texture-unit throughput anyway. Load reaction_reef (or any reaction_* preset), let it settle with the overlay on (F3), and report (a) whether fps holds ≥ 60 @ 1080p and (b) the p99. If it fails, that is a user call, not an automatic revert. The reconstruction is one function in the RD present shader and reverting it is cheap, but it costs the coral look outright — so route a failure to architect with the number, and let the look/perf tradeoff be decided rather than assumed. (Plan 0033 shipped this and never measured it; extracted at Plan 0035’s Phase 4.)
  • The swarm’s depth axis, on the low-end box, 1080p. Plan 0043 Phase 3 added per-particle depth math and a fourth vertex attribute inside a loop that runs 10 000 times per frame. Measured on the dev box over 5000 frames at 1920x1080: 1.03–1.09 ms/frame before, 1.56–1.58 ms after — about +0.5 ms. That is not fill rate (pinning the sprite scale flat still measures 1.60), so it is the depth math plus the wider instance, and it will not shrink on a slower box. Phase 3’s done-when named NFR §1/§9’s ≥ 60 fps @ 1080p floor as the acceptance criterion and that floor was never measured — it is defined on this box. Load swarm_dense.toml (the highest visible density of the three survivors, and the one whose field_freq ~5.2 keeps the most particles resolving separately), let it settle with the overlay on (F3), and report (a) whether fps holds ≥ 60 and (b) the p99. If it fails, the lever is TierConfig::FLOOR.swarm_particles (core/src/render/tier.rs — the constant moved there in Plan 0044) — and per Plan 0043’s own risk bullet that is a look decision that routes back to architect, not a constant to quietly lower. (Plan 0043 Phase 3’s done-when, extracted at that plan’s close.)
  • The analytic field’s escape-time budget, on the low-end box, 1080p. Plan 0163 added analytic_field, a fullscreen per-pixel loop whose cost is iterations per pixel on every pixel of the set’s interior, and capped it per tier with TierConfig::FLOOR.field_iterations = 64 — a number taken from arithmetic, not a measurement (the field’s doc comment in core/src/render/tier.rs carries it). No shipped preset draws the system yet, so point RLX_PRESET_DIR at docs/examples/field/ and load escape_time.toml; then write the heaviest frame the cap allows beside it — the same file with zoom = "3", pan_x = "-0.2", so the set’s interior fills the window and every pixel runs all 64 steps. Overlay on (F3), report (a) whether fps holds ≥ 60 @ 1080p on both, and (b) the p99. Load chladni.toml too: it is a closed form with no loop and should be the cheapest system in the engine, which is worth one line confirming. If the heavy frame misses, the lever is TierConfig::FLOOR.field_iterations — and lowering it changes what an escape-time preset looks like on this tier, not just how dense it is, so it routes to architect with the number rather than being quietly lowered. (Plan 0163 Phase 4 set the cap without target hardware; this is where the measurement comes from.)
  • The cellular system at the Floor caps, on the low-end box, 1080p. Plan 0164 added cellular, whose cost is one pass per generation over the grid — two for larger_than_life, whose neighbourhood is summed as a row pass and a column sum — and capped it per tier with TierConfig::FLOOR.cellular_grid = 512 and cellular_radius = 6, both from arithmetic, not a measurement (their doc comments in core/src/render/tier.rs carry it). No shipped preset draws the system yet, so point RLX_PRESET_DIR at docs/examples/cellular/ and load larger_than_life.toml; then write the heaviest frame the caps allow beside it — the same file with grid = 512 in its [cellular] table, radius = "6" and step_rate = "60". Overlay on (F3), report (a) whether fps holds ≥ 60 @ 1080p on both, and (b) the p99. Load life_like.toml and cyclic.toml too, which read eight neighbours and should cost a fraction of it. If the heavy frame misses, the levers are cellular_grid and cellular_radius — and lowering either changes what a preset looks like on this tier (a smaller grid draws every pattern larger; a smaller radius runs a different rule), so it routes to architect with the numbers. (Plan 0164 Phases 3 and 5 set both caps without target hardware.)
  • The cellular system’s look, any box. Load the three files in docs/examples/cellular/ and say, for each, whether it reads as structure or as noise: life_like.toml for whether the fading wake carries the history, larger_than_life.toml for whether its blobs visibly travel, cyclic.toml for whether the spirals are visible as spirals and rotate. Also run one same-system dissolve between two cellular presets: two presets of one system share one scene, so the dissolve holds the outgoing picture still while the incoming one runs (ADR-0198), and on this system that shows as a frozen automaton fading out — say whether it reads as a defect.
  • The plexus system at the Floor caps, on the low-end box, 1080p. Plan 0235 added plexus, whose cost is a pairwise test of every point on the CPU plus the fill of its lines, which an open aperture widens. Its Floor caps — plexus_points 600, plexus_edges 6000, max_coc_px 12 — were measured on the development box’s integrated GPU (under 4 ms a frame headless, release build), not on the low-end box. Load the shipped Synapse (cloud) and Storm Sea (sheet); then write the heaviest frame the caps allow beside them — docs/examples/plexus/sheet.toml with points = 600, link_distance = "0.6" and aperture = "24", the top of its declared range. Overlay on (F3), report (a) whether fps holds ≥ 60 @ 1080p on both, (b) the p99, and (c) what the standalone prints about the clamps. If the heavy frame misses, the levers are the three caps, and lowering plexus_points or max_coc_px changes what a preset looks like, so it routes to architect with the numbers.
  • The plexus system’s look, any box. Load cloud.toml and sheet.toml from docs/examples/plexus/ and say, for each, whether the depth reads: whether lines visibly soften away from the focal plane, whether links fade in and out rather than popping as the points drift, and, on the sheet, whether the ripple reads as cloth rather than as a mesh rewiring. Then bind aperture to a live control and sweep it, and say whether a blurred line dims as it spreads rather than flaring.

Built from 13c7582 at version 0.158.0. This site tracks main and is not versioned per release.