Files
onion-mc/analysis/client-perf/research/r7-sable-create-client.md
T
logan 611a1a5952 docs: client-perf analysis, bench harness and work journal
Everything the next agent needs to run the Phase 2 optimisation loop on a
machine that can launch the client:

- analysis/client-perf/: LEVERS (ranked levers + corrections), BENCH-MATRIX
  (world, scenes, config IDs, blocks B0-B14 with decision rules),
  PLAYER-TUNING, SPAWN-TUNING, research briefs, the jar scanner and its
  output, observed default configs, and proposed-configs/ (build.py
  generates tiers and bench variants and fails on unknown keys;
  apply_variant.py applies a variant and merges options.txt).
- analysis/client-perf/bench/onion-bench/: bench-world datapack (scene
  teleports, Create grid, mob pen, sound storm, 120 s teleport tour).
- analysis/audit/: the static recipe/dependency audit, including gen_fixes.py,
  which generates the shipped Paxi datapack and was never tracked.
- phase0/: per-machine measurement harness (Steam Deck, 7700K/1060,
  6700K/1080 Ti).
- .pi/journal.md: running work log; read it first.

All of it is packwizignored, so nothing here ships to players.
2026-10-14 18:15:32 -04:00

107 lines
24 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.
# Research: Client rendering cost of the Create/Sable stack (r7)
Scope: Sable 2.0.5, Create Aeronautics bundled 1.3.2 (aeronautics 1.3.2 + simulated 1.3.2 + offroad 1.3.2), SSRD 1.8.7, Sable: Physics Compat 1.3.0, Create 6.0.10 + Flywheel 1.0.6 (jar-in-jar), Slice & Dice, Dragons Plus, Enchantment Industry — on 1.21.1 NeoForge, Sodium 0.8.13, Iris 1.8.14-beta.1, DH.
Tag legend: **VERIFIED** = confirmed against the exact pinned jars in this repo (bytecode/config inspection) or an official spec; **DOCUMENTED** = official issue tracker/changelog/mod page; **COMMUNITY** = reddit/user comments; **INFERENCE** = my reasoning.
## Summary
Sable does not have its own renderer — its only sub-level renderer (`SODIUM_REACHAROUND`) re-drives **Sodium's own chunk renderer once per sub-level** (own viewport, frustum, section meshing, layered draws), so each airship is effectively a small second terrain pass, and cost scales with *number of sub-levels × their meshed section count*, not with world render distance. The two biggest *client* levers are (1) shaderpacks: Flywheel's `indirect` **and** `instancing` backends both self-disable while a shaderpack is active (and this pack ships **no** Iris Flywheel Compat), dropping Create contraption rendering onto the vanilla block-entity path, and (2) per-frame pathological interactions (log spam on the render thread, per-tick sub-level-aware sound distance math) that produce the "FPS decays over 30–60 min" reports. Known FPS bugs in the trackers are mostly either fixed by our pinned versions (burner-sound degradation fixed in Aeronautics 1.3.0) or still open and unconfirmed on 2.0.5/1.3.2 (gradual decay while sub-levels exist).
## Findings
### A. How a Sable sub-level renders, and how it scales
1. **Sable's sub-level renderer is a Sodium "reach-around", not a separate engine.** `sable-client.toml` exposes exactly one renderer: `sub_level_renderer = "SODIUM_REACHAROUND"` (sole allowed value). Bytecode of `mixin/sublevel_render/impl/sodium/SodiumWorldRendererMixin` shows per sub-level: build a Sodium `Viewport` from the camera + sub-level container, `compileSections` (chunk mesh builds) honoring Sodium's `performance.chunkBuildDeferMode`/`PrioritizeChunkUpdates`, then draw via `ChunkRenderMatrices` + layered render types (`VeilRenderType.LayeredRenderType`) with `ShaderInstance.setDefaultUniforms`. Sub-levels also have their own frustum (`cullingFrustum`) and per-frame culling update. — **VERIFIED** (jar inspection; keys cross-checked in `analysis/client-perf/data/observed-default-configs/sable-client.toml`; Sodium integration also described in Sable's own README: https://github.com/ryanhcode/sable)
2. **Cost model.** Per frame each visible sub-level costs: one frustum+cull update, draws for all compiled sections in it (≈ ceil(blocks/16)³ worst case, typically the hull), plus matrix-only transform (movement itself is cheap — it's a pose, not a re-mesh). Re-meshing happens when blocks on the sub-level change (also piston/contraption edits). Scaling is roughly linear in *count of rendered sub-levels* and in *meshed section count per sub-level*, additive to normal world terrain cost; SSRD then decides how far away this pipeline runs. — **VERIFIED** (mechanism) / **INFERENCE** (exact per-sub-level ms; no public benchmark found)
3. **Sable patches the shader stack it runs on.** Sable 2.0.5 ships overrides of **Flywheel's internal shaders** (`assets/flywheel/flywheel/internal/*`, plus `light/flat.glsl`, `light/smooth.glsl`, `light/smooth_when_embedded.glsl`) so Create Flywheel visuals can be embedded in sub-levels; it has a `sublevel_render.fancy.ProgramMixin` and `compatibility.flywheel.ShaderSourcesMixin`. The *vanilla* core-shader override in the Sable stack is only `worldborder.*` from the nested Veil 4.3.2 jar (4 files) — the static scan's "sable overrides vanilla core shaders" is real but tiny in file count; the runtime shader patching (Veil/Flywheel) is the substantive interference surface. Iris compat exists explicitly (`SableIrisCompat`, `compatibility.iris.ExtendedShaderMixin`), and the pack additionally ships `irisveil-0.3.0` (Iris Veil Compat). — **VERIFIED** (jar inspection; static scan in `analysis/client-perf/data/jarscan-report.md`)
4. **Sable does not disable Sodium optimizations** — the opposite: it *requires* Sodium (SSRD hard-requires it too) and *reads* Sodium settings (`PerformanceSettings.chunkBuildDeferMode`, `PrioritizeChunkUpdates`) to decide how sub-level rebuilds are queued; it changes no `sodium-options.json` keys. Known Sodium visual conflicts with Sable were fixed over time ("Fix some visual issues with Sodium on AMD machines" in 2.0.0; "Update Sodium compatibility to 0.8.13 alpha" in 2.0.0). — **VERIFIED** (jar inspection) + **DOCUMENTED** (https://api.modrinth.com/v2/project/T9PomCSv/version)
5. **Client-cost toggles that exist in Sable 2.0.5** (all keys verified in `SableClientConfig` / observed defaults):
| key | default | perf relevance |
|---|---|---|
| `sub_level_dynamic_shading` | `true` | adds `dynamic_directional_shading` mixins into `ModelBlockRenderer`/`AmbientOcclusionFace`/`SectionCompiler` (meshing-side cost for sub-levels) |
| `sub_level_skylight_shadows` | `false` | if enabled, sub-levels cast world shadows — leave off |
| `sub_level_water_occlusion` | `true` | hooks `FogRenderer`/`GameRenderer`/`Camera` |
| `sub_level_snapshot_interpolation_delay_ticks` | `1.5` (0–100) | interpolation buffer, not render cost |
| `sub_level_renderer` | `SODIUM_REACHAROUND` | only value; no vanilla fallback to pick |
| `attempt_udp_networking` | `true` | client side of UDP movement channel (disabling = "worse performance and latency" per common-config comment) |
Common config (`SableConfig`): `sub_level_tracking_range` (network distance of sub-levels to players), `sub_levels_with_players_cannot_unload`, `sub_level_splitting*`, `disable_udp_pipeline`, `verbose_serialization_logging`. — **VERIFIED** (jar inspection). Community advice to raise tracking range to 1280 (default 320) is about *server→client streaming* of sub-levels, not client frame cost: **COMMUNITY** (https://www.reddit.com/r/CreateMod/comments/1tdil1p/limiting_sublevel_render_distance_in_sable/ — key name `sub_level_tracking_range` verified in jar)
### B. Known FPS issues / fixes in the Sable & Aeronautics trackers
6. **Render-thread log spam can collapse FPS near any sub-level (Sable #881, open).** A mod calling `getEntityLookedAt()` every frame produced huge AABBs against Sable's entity getter; Sable logged `Aborting entity get for abnormally large AABB` hundreds of times/sec, log4j ate ~75% of the render thread, 30→9–12 FPS. Root cause is the *triggering mod* (LegendarySurvivalOverhaul — **not in our pack**; only `legendary-tooltips` is, which does no entity lookups). Lesson for us: any per-frame entity/clip query mod can detonate on sub-levels; watch client logs for repeated Sable errors. — **DOCUMENTED** (https://github.com/ryanhcode/sable/issues/881)
7. **"FPS decays over 20–60 min while a sub-level exists" (Sable #1011, open; Simulated-Project #746/#1204).** Two distinct reported causes: (a) #1011 — gradual decay mitigated temporarily by F3+T (texture reload) or world rejoin, smells like a render-resource leak (Sable 1.2.2 era, unconfirmed on 2.0.5); (b) #746/#1204 — `BalloonBurnerSoundInstance` (`aeronautics:block.hot_air_burner.head`, `aeronautics:block.steam_vent.head`) re-played ~20×/s, each tick doing `distanceSquaredWithSubLevels → projectOutOfSubLevel → getContaining → getLocalPlot → getChunk/getBlockEntity` — hundreds of× vanilla cost; master volume 0 or blocking the two sound IDs stabilizes FPS. **Fixed upstream:** Aeronautics 1.3.0 changelog has "Fix performance degradation with Adjustable Burner sounds" → our 1.3.2 pin includes the fix. Caveat: 1.3.2 still contains `BalloonBurnerSoundInstance` with `distanceSquaredWithSubLevels` and `AeroSoundDistUtil.tickGlobalBurnerSound` — the sub-level-aware per-tick distance math is structurally still there, so treat "burners on many airships" as a known stressor. — **DOCUMENTED** (https://github.com/ryanhcode/sable/issues/1011, https://github.com/Creators-of-Aeronautics/Simulated-Project/issues/746, https://github.com/Creators-of-Aeronautics/Simulated-Project/issues/1204, https://api.modrinth.com/v2/project/oWaK0Q19/version) + **VERIFIED** (1.3.2 jar inspection)
8. **Iris shader artifacts with sub-levels — affects our exact stack (Iris #3164, open).** With Iris 1.8.14-beta.1 + Sable 2.0.x + Aeronautics 1.3.x + Sodium 0.8.13, physics structures render incorrectly *with shaders enabled*; artifact scales with structure size; any shaderpack; goes away with shaders off; specifically triggered by shader **real-time shadows** (Complementary/Miniature: disable shadows; Solas: disable SSAO). Root cause attributed to Veil; a community fix exists but is unmerged. Our `shaderpacks/` = **Complementary Reimagined + Makeup–Ultra-Fast**, i.e. the affected families (Makeup–Ultra-Fast is also named in SSRD #50 "SSRD not working with Shaders"). — **DOCUMENTED** (https://github.com/IrisShaders/Iris/issues/3164, https://github.com/RanoldStranold/SSRD/issues/50)
9. **Other tracker items (context, mostly visual or fixed):** sub-levels invisible behind DH LODs at distance when tracking range > view distance (Sable #376); "Visual bugs with Sodium" world-invisible report (Sable #331, older Sable); Iris tessellation-shader geometry invisible with Aeronautics (Simulated-Project #308); IFC + `flywheel:DEFAULT` → invisible/transparent cogs & shafts (iris-flw-compat #244); resource leak of Contraption Diagram fixed in Aeronautics 1.1.0. — **DOCUMENTED** (https://github.com/ryanhcode/sable/issues/376, https://github.com/ryanhcode/sable/issues/331, https://github.com/Creators-of-Aeronautics/Simulated-Project/issues/308, https://github.com/leon-o/iris-flw-compat/issues/244, https://api.modrinth.com/v2/project/oWaK0Q19/version)
### C. SSRD (1.8.7) — what it changes on the client
10. **Config surface:** a "Sub-Level Render Distance" **slider injected into Sodium's video settings** (below Simulation Distance); slider max is dynamically capped by your DH/Voxy LOD distance or the server maximum; server caps via `/gamerule ssrdMaxRenderDistance` (**default 128 chunks**) and `/gamerule ssrdForceloadLimit` (**default 2 per player**). SSRD 1.8+ **requires Sodium 0.8** (we have 0.8.13 ✓) and DH or Voxy on the client. — **DOCUMENTED** (https://modrinth.com/project/fJ183v3D)
11. **Cost & bugs:** raising the slider = more sub-levels rendered by the full Sable/Sodium pipeline at distance (frame cost scales with visible sections, culling still applies), plus server-side force-loading pressure. Known issues: sub-levels visible through LODs with certain shaderpacks (Modrinth warning), DH fade-out also fades sub-levels (#64), zoom glitching (#66), Colorwheel incompatibility (#62, closed), various forceload/unload bugs (mostly closed as of 1.8.7). Mixins confirm the hooks: `RenderSectionManagerMixin`, `SodiumConfigBuilderMixin` (the slider), `VanillaFrustumMixin`/`SodiumViewportMixin`, `RenderSystemFogMixin`, DH `DHShaderSourceMixin`/`FrameUniformsMixin`, plus visual-distance mixins on contraption/entity/block-entity visuals. — **DOCUMENTED** (https://modrinth.com/project/fJ183v3D, https://github.com/RanoldStranold/SSRD/issues?q=is%3Aissue) + **VERIFIED** (`SSRD-1.8.7-1.21.1.jar` mixin list)
12. **sablecompat** (`Sable: Physics Compat` 1.3.0) only provides tags for modded blocks — no rendering behavior. `Create Aeronautics: Compatibility` 1.1.3 likewise compat glue. Neither is a perf surface. — **DOCUMENTED** (https://modrinth.com/project/sZbcIrJb; jar metadata)
### D. Flywheel backend choice (Pascal NVIDIA vs Mesa RADV, with Iris)
13. **Backend IDs & requirements (Flywheel 1.0.6, verified in source + jar):** `flywheel:off`, `flywheel:instancing` (GL 3.3 + `ARB_shader_bit_encoding`; priority 500), `flywheel:indirect` (GL 4.6 + compute/DSA/`ARB_multi_draw_indirect`/SSBO/etc.; priority 1000 — GPU-driven culling with a depth pyramid + MDI; uses `GL_KHR_shader_subgroup`). `DEFAULT` picks the highest-priority *supported* backend, with a fallback log "Flywheel backend fell back from '{}' to '{}'". **Driver special-case: `Driver.INTEL` gets indirect priority 1** ("Intel has very poor performance with indirect rendering, and on top of that has graphics bugs") — irrelevant to our fleet (NVIDIA Pascal, AMD/Mesa RADV). Both Pascal (GTX 10xx) and Steam Deck RADV advertise GL 4.6 + the required ARBs, so **`DEFAULT` → `indirect` on all three machines when no shaders**. — **VERIFIED** (Flywheel `Backends.java` @ Engine-Room/Flywheel branch 1.21.1/dev, and bytecode in `create-1.21.1-6.0.10.jar` → nested `flywheel-neoforge-1.21.1-1.0.6.jar`)
14. **With a shaderpack active, both backends self-disable:** `supported() = … && !ShadersModHelper.isShaderPackInUse()` on *both* `instancing` and `indirect` → `DEFAULT` falls back to `flywheel:off` (vanilla block-entity path for all Create visuals). This is why the pack has no working Create-instancing under Iris. The documented fix is **Iris & Oculus Flywheel Compat (IFC)**: "Flywheel will disable its optimizations when you are using shaderpacks. This mod forces Flywheel's optimizations to be enabled… render Create's entities using Flywheel Instancing with shaderpack enabled… significantly improve fps" — IFC 2.3.x supports **Create 6.0.9 + Flywheel 1.0.6**, needs **Iris ≥ 1.8.1** (we have 1.8.14-beta.1 ✓); Create **6.0.10 is newer than the last tested 6.0.9** → verify before shipping. **Our pack does not include IFC.** — **VERIFIED** (Flywheel source) + **DOCUMENTED** (https://modrinth.com/mod/iris-flw-compat, https://github.com/leon-o/iris-flw-compat/issues)
15. **Driver risk notes for indirect:** AMD *Windows* has a confirmed driver crash in Flywheel's indirect path (`atio6axx.dll`, `glBindBuffersRange`/MDI; GPUOpen-Drivers #89, acknowledged in Create/Flywheel repos) — **does not apply** to our fleet (no AMD Windows machine; Steam Deck is Mesa RADV, which Flywheel explicitly detects as `Driver.MESA` and supports); Create #10191 reports indirect crashes with elevator pulleys on one user setup (fix: `instancing`), and some users report indirect crashes with Create 6 + certain setups. Pascal is generally the safest indirect platform; treat any "Create block crash" on a client as "switch `backend` to `flywheel:instancing` or `flywheel:off` first". — **DOCUMENTED** (https://github.com/GPUOpen-Drivers/AMD-Gfx-Drivers/issues/89, https://github.com/Creators-of-Create/Create/issues/10191, https://www.reddit.com/r/CreateMod/comments/1pogo4t/create_6_crashing_when_placing_a_block_other/)
16. **flywheel-client.toml (verified defaults in pack):** `backend = "DEFAULT"`, `limitUpdates = true` ("instance update limiting with distance" — keeps distant contraptions from updating instances; leave on), `workerThreads = -1` (0–4; parallelizes instance updates, needs restart; 4-core Zen2 Deck vs 8-thread 7700K/6700K → explicit `2` on Deck if update-thread contention shows up is a testable knob), `[flw_backends] lightSmoothness = "SMOOTH"` (values FLAT, TRI_LINEAR, SMOOTH, SMOOTH_INNER_FACE_CORRECTED; config comment: "**May have a large performance impact**" — SMOOTH adds per-vertex light interpolation in Flywheel's uber-shaders; FLAT is the cheap end; each value changes compiled shader permutations). — **VERIFIED** (`observed-default-configs/flywheel-client.toml`, `LightSmoothness.class` bytecode)
### E. Create contraption rendering cost & the addons
17. **Create 6 = Flywheel 1.0** (official changelog: "Now using Flywheel 1.0"); contraption/kinetic visuals are instances batched per material; `indirect` adds GPU culling+MDI so cost scales with *visible* instances, `instancing` costs CPU draw calls per material (fine for tens of contraptions, and it's what IFC re-enables under shaders). Without Flywheel (backend off, e.g. under shaders without IFC) every kinetic/contraption visual becomes a vanilla block-entity render — the classic "Create + shaders = CPU death" mode. — **DOCUMENTED** (https://wiki.createmod.net/users/changelogs/6.0.0) + **VERIFIED** (backend mechanics, above)
18. **Sable × Create integration adds its own frame mixins:** Sable 2.0.5 has 30+ `compatibility.create.*` mixins (ContraptionVisual, CarriageContraptionVisual, VisualizationEventHandler, flywheel Engine/RenderDispatcher/EmbeddedEnvironment/VisualManager mixins) so contraptions riding sub-levels render inside the sub-level pass with embedded lighting — contraptions on airships are therefore *both* Flywheel instances and embedded-environment draws; a big airship factory is the worst-case render target. — **VERIFIED** (`sable-neoforge.mixins.json`, jarscan: create-aeronautics 20 frame mixins, sable 127)
19. **Slice & Dice, Dragons Plus, Enchantment Industry:** no client-perf issue reports found in their trackers for 1.21.1/Create 6 (S&D mostly touches RenderLevelStage/Gui events per jarscan; no lag/fps issues surfaced). They add ordinary instance/BER content; cost scales with placed blocks like any Create addon. — **DOCUMENTED (absence of evidence)** — treat as "no known client perf issues found" for these three.
20. **Sound-adjacent sanity note:** Create 6.0.0 already caps boiler sounds ("Play at most four steam engine sounds at once per side"), but Aeronautics adds its own global sound instances; combined with Sable's sub-level-aware distance math (Finding 7) the sound engine is a real client-tick cost center on all machines — an easy benchmark axis (master volume 0 vs 100). — **DOCUMENTED** (https://wiki.createmod.net/users/changelogs/6.0.0) + Finding 7
## Top levers (ranked)
| # | Lever | Impact | Machine(s) | Risk | Confidence |
|---|---|---|---|---|---|
| 1 | Add **Iris Flywheel Compat 2.3.x** (test vs Create 6.0.10) or accept `flywheel:off` under shaders knowingly | **H** — restores GPU instancing for all Create visuals under shaders; without it shader users pay vanilla-BER cost for every cog/contraption | All, biggest on 7700K+1060 (CPU-bound) and Deck (4-core Zen2) | M — IFC lists Create 6.0.9 as last tested; visual glitches possible per iris-flw-compat #244 | High (Flywheel source-verified behavior + IFC docs) |
| 2 | In shaderpack settings, **disable real-time shadows/SSAO** (Complementary Reimagined, Makeup–Ultra-Fast) or accept #3164 artifacts | **H** — removes documented sub-level rendering corruption *and* shadow-pass cost; shadows are the confirmed trigger | All shader users | L — pure shader setting | High (Iris #3164 reproduces on our exact versions) |
| 3 | Keep **SSRD slider modest** (e.g. start at 8–16 chunks, not the 128-chunk server cap) and don't forceload broadly | **M–H** — directly bounds how many sub-level sections the per-sub-level Sodium pass draws; also server load | Deck (GPU/VRAM-limited) & 1060 6GB first | L — slider is the intended knob; gamerule cap on server | Medium-High (mechanism verified; magnitude unbenchmarked) |
| 4 | Prefer `flywheel:indirect` (DEFAULT) **without** shaders; only drop to `flywheel:instancing` on crash; consider `lightSmoothness = "FLAT"`/`TRI_LINEAR` on Deck if Flywheel shader cost shows in F1 | **M** — indirect = GPU-culled MDI; FLAT removes per-vertex light smoothing cost ("large performance impact" per config) | Deck (RADV) and 1060 for lightSmoothness; indirect OK on Pascal & RADV | L–M — changing lightSmoothness alters visuals (block light smoothing) | Medium-High (config semantics verified; perf delta unbenchmarked) |
| 5 | Keep `sub_level_skylight_shadows=false`, keep `limitUpdates=true`, keep UDP networking on; watch client logs for Sable "Aborting entity get" spam (Finding 6 class) | **M** — avoids enabling the shadow pass; avoids the documented render-thread log-stall class | All | L | High (defaults verified; #881 mechanism documented) |
| 6 | If gradual FPS decay reproduces on 2.0.5: test F3+T / master-volume-0 as diagnostics (sound-engine vs render-resource); keep an eye on Sable #1011 | **M** — separates the two documented decay causes cheaply before deeper profiling | All; 8GB-RAM 1080 Ti machine most sensitive to leaks | L — diagnostics only | Medium (both causes documented on adjacent versions; 1.3.2 fixed the burner one) |
## Open questions to verify by benchmark
1. ms/frame cost of **one** idle sub-level vs an identical static structure in the world (isolates the per-sub-level Sodium re-drive overhead), and the marginal cost of the 2nd, 3rd, 4th sub-level (linearity of Finding 2).
2. Cost of a **moving + rotating** sub-level with `sub_level_dynamic_shading=true` vs `false` (does rotation re-mesh? how often?) — deck vs 1060.
3. Frame cost of the **same airship under shaders with IFC on vs off** (instancing-merged vs vanilla-BER fallback) on 7700K/1060 and Deck.
4. `flywheel:indirect` vs `flywheel:instancing` vs `off` on **RADV/Steam Deck specifically** (Mesa GL4.6 MDI perf is the wildcard; also VRAM headroom vs the 1080 Ti's 8 GB-free-RAM host).
5. SSRD slider sweep (4/16/32/64 chunks) with DH LODs: frame-time and chunk-build queue behavior (Sable reads `chunkBuildDeferMode=ALWAYS` — does sub-level remeshing starve behind deferred world builds?).
6. Sound-engine axis: master volume 0 vs 100 near N burners/steam vents on 1.3.2 (residual per-tick `distanceSquaredWithSubLevels` cost, Finding 7).
7. Long-run decay test (45+ min, sub-levels present, #1011 class) on Sable 2.0.5 — does it still exist? Track client RAM/VRAM and F3+T recovery.
8. IFC 2.3.x × Create 6.0.10 × Iris 1.8.14-beta.1 compatibility spot-check (invisible cogs #244 class) before adding it to the pack.
## Sources
**Kept:**
- Sable repo/README (https://github.com/ryanhcode/sable) — primary source; mixin list & Sodium integration verified against jar
- Sable issues #881, #1011, #376, #331 (github.com/ryanhcode/sable) — documented FPS failure modes
- Simulated-Project #746 + #1204 (github.com/Creators-of-Aeronautics) — sound-engine FPS decay, spark profiles, bytecode-level root cause
- Aeronautics changelog API (https://api.modrinth.com/v2/project/oWaK0Q19/version) — "Fix performance degradation with Adjustable Burner sounds" in 1.3.0
- SSRD Modrinth page + GitHub issues (https://modrinth.com/project/fJ183v3D, https://github.com/RanoldStranold/SSRD/issues) — config/gamerules, Sodium-0.8 requirement, shader caveats
- Iris #3164 (https://github.com/IrisShaders/Iris/issues/3164) — repro on our exact version stack; shadow trigger
- Iris Flywheel Compat Modrinth page (https://modrinth.com/mod/iris-flw-compat) — shader-mode Flywheel behavior + IFC support matrix
- Flywheel `Backends.java` (raw.githubusercontent.com/Engine-Room/Flywheel/1.21.1/dev) — backend support conditions, Intel deprioritization
- GPUOpen-Drivers/AMD-Gfx-Drivers #89, Create #10191, r/CreateMod threads — driver-level indirect risks
- Create 6.0.0 changelog (https://wiki.createmod.net/users/changelogs/6.0.0) — Flywheel 1.0 baseline
- Local pinned-jar inspection: sable 2.0.5 (+ nested veil 4.3.2), create 6.0.10 (+ nested flywheel 1.0.6), aeronautics bundled 1.3.2, SSRD 1.8.7, observed default configs (`analysis/client-perf/data/observed-default-configs/`)
**Dropped:**
- Modders-of-Create/Create-Aeronautics #14 "Gradual drop in fps" (404 — repo/issue no longer resolvable; superseded by Simulated-Project #746/#1204)
- r/CreateMod "Limiting sublevel render distance in Sable" full thread (login-walled; snippet retained only as COMMUNITY corroboration; its `ticking_range` key name is stale — actual key verified as `sub_level_tracking_range`)
- mcmod.cn Flywheel page (secondary aggregator; its AMD-Windows advice superseded by GPUOpen issue #89)
- 9minecraft/deepwiki Flywheel articles (SEO/aggregator content, no unique facts)
## Gaps
- No public benchmark quantifies per-sub-level frame cost or scaling with count/size — the cost model in Finding 2 is mechanism-derived, not measured.
- Could not confirm whether Sable #1011 (gradual decay, F3+T-reset) still reproduces on Sable 2.0.5 — issue is open but filed against 1.2.2; no maintainer root-cause posted.
- IFC compatibility with Create **6.0.10** specifically (last tested 6.0.9) is unverified; nor is IFC × Sable 2.0.5 embedding (Sable overrides Flywheel shaders, IFC also patches them — interaction untested publicly).
- Shaderpack-specific behavior of *Makeup–Ultra-Fast* with SSRD (#50) and Complementary Reimagined with #3164 is reported for sibling packs (Makeup–Ultra-Fast plain, Complementary Unbound); Reimagined itself untested in those threads.
- Steam Deck (RADV) Flywheel-indirect reports are anecdotal in either direction; no RADV-specific issue was found, which is weak evidence of health, not proof.