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.
This commit is contained in:
logan committed 2026-10-14 18:15:32 -04:00
1 parent d80f85b3f6
commit 611a1a5952
102 files changed
+25853

No files matched your search

@@ -0,0 +1,278 @@
# Research: Core render stack levers
Scope: client-side render stack for **Onion MC** — Minecraft 1.21.1 / NeoForge 21.1.251, ~212 mods, ~10 players, server view-distance 8.
Fleet: **P0** Steam Deck (Zen2 8CU RDNA2 iGPU, 16 GB shared, 1280×800, Mesa/RADV) · **P1** i7-7700K + GTX 1060 **6 GB** (VRAM-bound) · **P2** i7-6700K + GTX 1080 Ti 11 GB with only ~8 GB free RAM (CPU/heap-bound).
Confidence tags used throughout:
- **VERIFIED** — read in the pinned mod's source/config code or its own shipped defaults.
- **DOCUMENTED** — official README / wiki / changelog / mod-author description.
- **COMMUNITY** — forum/Reddit/third-party guide.
- **INFERENCE** — my reasoning, no direct source.
Every non-inference claim has a URL. Config keys are only named where I actually saw them in source or a shipped properties file.
---
## Summary
The single biggest client-side render lever in this pack is **Iris/shaders, not Sodium**: with any shaderpack active, Flywheel 1.0.x marks *both* of its GPU backends unsupported, so Create 6 falls back to per-block-entity rendering and shader packs re-draw that content in the shadow pass; on top of that, DH's shadow pass is auto-enabled and renders *all* DH chunks. Sodium itself is already near-optimal on 0.8.13 (most impactful options — animate-only-visible-textures, fog occlusion, entity culling, block face culling, no-error GL context — are **on by default** and built into Sodium, no add-on needed). The remaining cheap wins are shader-quality knobs (shadow distance/quality, SSAO, entity shadows, volumetric clouds), ModernFix `mixin.perf.dynamic_resources=true` for the RAM-starved P2, mipmap-level reduction for the VRAM-bound P1, and Fresh-Animations/EMF animation throttles.
---
## Findings
### 1. Sodium 0.8.13 (`mc1.21.1-0.8.13`) — options that matter, and their real defaults
Sodium 0.8.13 is the 1.21.1 backport of Sodium 0.8; its changelog (0.8.12, the base of this line) claims **"up to +115%"** world-render improvement, reduced chunk-update micro-stutter, and slightly faster entity/particle rendering, and states compatibility "Create Aeronautics works as of 1.3.0, Sable as of 2.0.0, Veil works as of 4.1.2, Iris works as of 1.8.13". [Modrinth version page](https://modrinth.com/mod/sodium/version/mc1.21.1-0.8.12-neoforge) — **DOCUMENTED**. (Confirms the pack's version matrix is a supported one; it also warns Sodium is *not* compatible with "Sodium Options API".)
**Option exposure: everything in the task list is in Sodium's own Video Settings — no add-on required.** The 0.8.13 1.21.1 config builder registers pages *General / Quality / Performance / Advanced* and puts chunk-update threads, chunk-updates (defer), block face culling, fog occlusion, entity culling, animate-only-visible-textures, block-transparency-limits and **Use No Error Context on the Performance page**, and persistent-mapping + CPU render-ahead limit on Advanced. [SodiumConfigBuilder @ mc1.21.1-0.8.13](https://github.com/CaffeineMC/sodium/blob/mc1.21.1-0.8.13/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumConfigBuilder.java) — **VERIFIED**.
Defaults are hard-coded in `PerformanceSettings` / `QualitySettings` / `AdvancedSettings` in [SodiumOptions.java @ mc1.21.1-0.8.13](https://github.com/CaffeineMC/sodium/blob/mc1.21.1-0.8.13/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumOptions.java) — **VERIFIED**:
| Video option (label) | Config field | Default | Impact as labelled | Notes |
|---|---|---|---|---|
| Chunk Update Threads | `performance.chunkBuilderThreads` | `0` = auto | High | `0` resolves to `clamp(max(cores/3, cores−6), 1, 10)` → **2 threads on every 4C/8T fleet machine** ([ChunkBuilder.java](https://github.com/CaffeineMC/sodium/blob/mc1.21.1-0.8.13/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkBuilder.java)). Range is 0..`availableProcessors`. Requires renderer reload. |
| Chunk Updates | `performance.chunkBuildDeferMode` | `DeferMode.ALWAYS` ("Deferred") | High | Other values `ONE_FRAME` ("Soon"), `ZERO_FRAMES` ("Immediate"). Already at the frame-rate-friendliest setting. |
| Animate Only Visible Textures | `performance.animateOnlyVisibleTextures` | **`true`** | High | Already on. Tooltip: "significant performance improvement on some hardware, especially with heavier resource packs". |
| Use Fog Occlusion | `performance.useFogOcclusion` | **`true`** | Medium | Already on. |
| Use Entity Culling | `performance.useEntityCulling` | **`true`** | Medium | Already on. |
| Use Block Face Culling | `performance.useBlockFaceCulling` | **`true`** | Medium | Already on. |
| Block Transparency Limits (quad splitting) | `performance.quadSplittingMode` | `SAFE` | Medium | `BASIC`/`SAFE`/`UNLIMITED`. Controller: translucency sorting. |
| Use No Error Context | `performance.useNoErrorGLContext` | **`true`** | Low | Only enable-able on GL 4.6 / `GL_KHR_no_error`; needs game restart. Effect is "slight". |
| CPU Render-Ahead Limit | `advanced.cpuRenderAheadLimit` | `3` | (debug) | Docs say don't touch. |
| Use Persistent Mapping | `advanced.useAdvancedStagingBuffers` | `true` | (debug) | — |
| Entity Sorting | `quality.useClosestPointEntitySort` | `false` | Medium | "Enhanced" costs a little CPU. |
| Leaves | `quality.leavesQuality` (vanilla `cutoutLeaves`) | default/fancy | Medium | Fast = opaque, cullable leaves. |
| Mipmap Levels / Biome Blend / Entity Distance / Entity Shadows | vanilla-backed (`mipmapLevels`, `biomeBlendRadius`, `entityDistanceScaling`, `entityShadows`) | vanilla defaults | Med / Low / High / Medium | See §6. |
Two options people commonly cite (**"Hidden Fluid Culling"**, **"Improved Fluid Shaping"**, **"Texel Interpolation / pixel filtering mode"**) are **not present in the 0.8.13 / 1.21.1 build** — their lang keys exist only on Sodium `dev` (26.x). Do not look for them in-game on this version. [compare dev lang](https://github.com/CaffeineMC/sodium/blob/dev/common/src/main/resources/assets/sodium/lang/en_us.json) vs [0.8.13 lang](https://github.com/CaffeineMC/sodium/blob/mc1.21.1-0.8.13/common/src/main/resources/assets/sodium/lang/en_us.json) — **VERIFIED**.
**Add-on boundary (what is *not* in Sodium):** fog-type toggles, cloud height, particle-culling detail, and "turn off all fog" are Sodium-Extra/Extras features. [Sodium Extras description](https://modrinth.com/mod/sodium-extras) — **DOCUMENTED**. None of the options in this task's list requires an add-on; Sodium Extra is optional polish. (Neither Sodium Extra nor Sodium Extras is in the current pack.)
### 2. Iris 1.8.14-beta.1 + the two shaderpacks
**Complementary Reimagined r5.9.3** exposes a *Profile* selector plus per-setting overrides. The profile table and default shadow distances are shipped in the pack's `shaders.properties` (read from the author's repo, `main` branch — treat the exact numbers as "current author defaults, verify in-game for r5.9.3"): [ComplementaryReimagined/shaders/shaders.properties](https://github.com/ComplementaryDevelopment/ComplementaryReimagined/blob/main/shaders/shaders.properties) — **DOCUMENTED**.
| Profile | `SHADOW_QUALITY` | `shadowDistance` | `ENTITY_SHADOW` | `CLOUD_QUALITY` | `RAIN_PUDDLES` |
|---|---|---|---|---|---|
| POTATO | −1 (OFF) | 64 (4 ch) | −1 (off) | 1 | 0 |
| VERYLOW / LOW | 0 (Very Low) | 64 / 96 | off | 1 / 2 | 0 |
| MEDIUM | 2 (Medium) | 128 (8 ch) | off | 2 | 0 |
| HIGH | 2 (Medium) | **192 (12 ch)** | 1 | 2 | 0 |
| VERYHIGH | 2 | 192 | 1 | 2 | 2 |
| ULTRA | 2 | 224 (14 ch) | 1 | 3 | 2 |
| COMPLEMENTARY | 3 (High) | 256 (16 ch) | 1 | 3 | 2 |
Author-supplied cost notes in the pack's own lang file (same source) — **DOCUMENTED**:
- **Entity Shadows** — "impact performance way more than expected, costing **more than 50% of your fps in some cases**". This is the single biggest per-setting cost in the pack, and it is **off in every profile except HIGH and above**.
- **Colored Lighting** (ACT/voxel floodfill) — "each increment can cost more than twice the performance of the previous tier".
- **Shadow Distance** — "lower values may cause excessive Light Shaft leaking" (visual, not perf).
- Informational panel tells users to keep render distance "2–4 chunks higher than the shadow distance of the Profile", e.g. 16 chunks RD for the HIGH profile — i.e. **at server view-distance 8, no profile above MEDIUM's 8-chunk shadow distance is even productive**.
- Rain Puddles and volumetric clouds are called out as expensive.
**MakeUp Ultra Fast 9.5f** — its settings screen and defaults are in the pack's `shaders.properties` (open source): [MakeUpUltraFast/shaders/shaders.properties](https://github.com/javiergcim/MakeUpUltraFast/blob/master/shaders/shaders.properties) — **VERIFIED**. Relevant keys and shipped profile values:
| Key | Meaning | Values seen in shipped profiles |
|---|---|---|
| `SHADOW_CASTING` | shadows on/off | `no_effects` / `shadowless_*` profiles have `!SHADOW_CASTING` (off); `low`…`extremeplus` have it on |
| `SHADOW_DISTANCE_SLIDER` | slider | 0 (low), 1 (medium), 2 (high/extremeplus) |
| `SHADOW_QTY_SLIDER` | slider | 1 / 2 / 3 |
| `REFLECTION_SLIDER` | water/block reflections | 0–2 |
| `AO` / `AOSTEPS` / `AO_STRENGTH` | AO on/off and steps | `AOSTEPS=5` |
| `V_CLOUDS` / `CLOUD_STEPS_AVG` / `CLOUD_VOL_STYLE` | volumetric clouds | `CLOUD_STEPS_AVG=10` |
| `BLOOM` / `BLOOM_SAMPLES`, `VOL_LIGHT`, `CHROMA_ABER`, `AA_TYPE`, `DOF` | post | author notes Bloom/DoF/Shadows are the heaviest effects |
| `dhShadow.enabled` | DH shadow pass | **`false`** in MakeUp |
MakeUp also sets `shadow.culling = true`. Its README positions it as "Intended for low-spec computers … FAST!", with optional shadows/volumetric clouds/DoF/bloom. [MakeUp README](https://github.com/javiergcim/MakeUpUltraFast) — **DOCUMENTED**.
**Comparative cost:** I could not find any *primary/measured* head-to-head between these exact two packs; every comparison I found is COMMUNITY (e.g. "MakeUp Ultra Fast … gives better fps tho", [r/minecraftshaders](https://www.reddit.com/r/minecraftshaders/comments/1m9c569/any_nice_looking_shaders_that_run_well/)). The defensible statement is structural and comes from the profiles themselves: MakeUp's *default* profile ships with lower shadow distance/quality and `dhShadow` off, whereas Complementary's HIGH-and-above profiles enable entity shadows and 12–16-chunk shadows. That gap — especially **Entity Shadows** — is where the FPS difference will come from, not from the shader's core lighting. **INFERENCE**, with **DOCUMENTED** inputs.
**Iris-level knobs:** Iris exposes each pack's own options, and the shader-lab community wiki describes the shader-selection-menu sliders ("Render Quality", "Shadow Quality", "Antialiasing") as OptiFine-only and says baseline render distance with shaders should stay under 16 chunks. [shaderLABS Performance Tips](https://shaderlabs.org/wiki/Performance_Tips) — **COMMUNITY/DOCUMENTED** (page is old; treat as directional only).
### 3. Iris + Distant Horizons (mandatory in this pack)
- DH + Iris requires **Iris 1.7+** and a shaderpack *built for DH*; DH itself says most shaderpacks will not work. [DH Modrinth description](https://modrinth.com/mod/distanthorizons) — **DOCUMENTED**.
- Iris adds `dh_terrain`, `dh_water`, `dh_shadow` programs, and **"The DH shadow pass is automatically enabled … Distant Horizons has no set shadow distance; all chunks will be rendered."** [Iris docs — Distant Horizons](https://shaders.properties/current/reference/mod-support/distant_horizons/) — **DOCUMENTED**. This is the key interaction cost: *your shadow pass covers DH's full LOD distance*, not the vanilla 8 chunks.
- DH's own config (read from the current core repo) — **VERIFIED** keys/defaults: `Client.Advanced.Graphics.Quality.lodChunkRenderDistanceRadius` (min/default/max **32/256/4096** chunks), `maxHorizontalResolution` default **BLOCK** (256 LODs per chunk — the "Fanciest"), `horizontalQuality` default **MEDIUM**, `verticalQuality` default **MEDIUM**, `Client.Advanced.Culling.overdrawPrevention` default **−1 (auto)**, `reduceOverdrawWithFastMovement` default **true**, `enableCaveCulling` default **true**, `Client.Advanced.Graphics.Quality.transparency` default **COMPLETE**, `vanillaFadeMode` default **DOUBLE_PASS** ("Slowest … provides the smoothest transition"), `lodBiomeBlending` default **3** ("anything above 0 will slow down LOD loading time"), `enableNoiseTexture` default **true**, far-fog `farFogStart` 0.4 / `farFogEnd` 1.0. Quality preset default `MEDIUM`, thread preset default `BALANCED`. [distant-horizons-core Config.java](https://gitlab.com/distant-horizons-team/distant-horizons-core/-/blob/main/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java) — **VERIFIED**.
- DH's official stutter advice, in order: use a concurrent GC (ZGC/Shenandoah), allocate 6–8 GB for 4–8 core CPUs, **lower DH's CPU load**, disable **Distant Generation**, lower the **Graphics Preset**. [DH Modrinth description](https://modrinth.com/mod/distanthorizons) — **DOCUMENTED**. Note "6–8 GB allocated" directly conflicts with P2's ~8 GB free RAM — that machine will be the DH-stutter canary.
### 4. Create 6.0.10 / Flywheel 1.0.6 with Iris shaders — **it falls back**
This is the most important verified finding. In Flywheel's 1.21.1 branch, both GPU backends declare themselves unsupported whenever a shaderpack is in use:
```java
INSTANCING: .supported(() -> GlCompat.SUPPORTS_INSTANCING && InstancingPrograms.allLoaded()
&& !ShadersModHelper.isShaderPackInUse())
INDIRECT : .supported(() -> GlCompat.SUPPORTS_INDIRECT && IndirectPrograms.allLoaded()
&& !ShadersModHelper.isShaderPackInUse())
```
[Flywheel Backends.java @ 1.21.1/dev](https://github.com/Engine-Room/Flywheel/blob/1.21.1/dev/common/src/backend/java/dev/engine_room/flywheel/backend/Backends.java) — **VERIFIED**; the same guard is present at the 1.21.1 `mc1.21.1/v1.0.5` tag, the nearest tagged release below the pack's 1.0.6 — **VERIFIED**. `ShadersModHelper` is Iris-backed (`IrisApi.isShaderPackInUse()`), and this is exactly what `IrisCompat` exists for. [IrisCompat.java](https://github.com/Engine-Room/Flywheel/blob/1.21.1/dev/common/src/main/java/dev/engine_room/flywheel/impl/compat/IrisCompat.java) — **VERIFIED**.
When neither backend is supported, `BackendManagerImpl.chooseBackend()` falls through to `OFF_BACKEND` (`flywheel:off`) and logs `"Flywheel backend fell back from '…' to 'flywheel:off'"`. [BackendManagerImpl.java](https://github.com/Engine-Room/Flywheel/blob/1.21.1/dev/common/src/main/java/dev/engine_room/flywheel/impl/BackendManagerImpl.java) — **VERIFIED**.
What that costs, confirmed in Create's own code: Create 6's kinetic/contraption renderers are *guarded* by Flywheel visualization availability —
```java
protected void renderSafe(T be, …) {
if (VisualizationManager.supportsVisualization(be.getLevel())) return;
…
}
```
[Create KineticBlockEntityRenderer @ mc1.21.1/dev](https://github.com/Creators-of-Create/Create/blob/mc1.21.1/dev/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityRenderer.java) — **VERIFIED** (same pattern in `ShaftRenderer`). So with shaders on, every shaft/cog/gear/belt is drawn as an ordinary per-block-entity draw instead of one instanced/indirect batch. Iris's own tracking issue states this in plain terms: *"Create through Flywheel uses a highly-optimized rendering engine normally, but when Iris is enabled it has to use a slower fallback … Iris also has to render the Create content **twice** using this slower fallback path with most shader packs to implement dynamic shadows."* [Iris issue #1414](https://github.com/IrisShaders/Iris/issues/1414) — **DOCUMENTED** (coderbot16, Iris maintainer), corroborated by the Ocuwheel description: *"When Iris/Oculus shaderpacks are active, Flywheel can disable its GPU-instancing backend and fall back to CPU rendering."* [Ocuwheel](https://www.curseforge.com/minecraft/mc-mods/ocuwheel-oculus-flywheel-compat) — **DOCUMENTED**.
Mitigations exist but are third-party and not listed in the pack: **Iris Flywheel Compat** (`irisflw` / backend id seen in the wild as `irisflw:iris_instancing`) and the newer **Colorwheel**, which claims better compatibility. Iris maintainers explicitly warn the former "isn't supported by either team, and almost always breaks on a Create or Iris update. It's a brute force method". [Iris issue #1414 comments](https://github.com/IrisShaders/Iris/issues/1414) — **DOCUMENTED**. Also note Sodium's own 0.8.12 changelog lists **"Create Aeronautics works as of 1.3.0"** and **"Sable works as of 2.0.0"** — so the aeronautics half of Create *is* version-aligned, it is specifically the Flywheel backend gate that costs you. **INFERENCE** from DOCUMENTED inputs.
**Flywheel config levers (NeoForge client config, `flw_backends` section)** — [NeoForgeFlwConfig.java](https://github.com/Engine-Room/Flywheel/blob/1.21.1/dev/neoforge/src/main/java/dev/engine_room/flywheel/impl/NeoForgeFlwConfig.java) — **VERIFIED**:
- `backend` (default `"DEFAULT"`) — you can force `flywheel:instancing` / `flywheel:indirect` / `flywheel:off`, but the `supported()` test still gates it.
- `limitUpdates` (default `true`) — instance-update limiting by distance.
- `workerThreads` (default `-1` = auto, `0` = no parallelism, needs restart).
- `flw_backends.lightSmoothness` (default `SMOOTH`) — "May have a large performance impact"; **irrelevant while a shaderpack is active**, because the Flywheel engine is off.
There is also a `/flywheel backend` client command. **VERIFIED** (BackendArgument exists in the repo). [BackendArgument.java](https://github.com/Engine-Room/Flywheel/blob/1.21.1/dev/common/src/main/java/dev/engine_room/flywheel/impl/BackendArgument.java)
### 5. Veil + irisveil (Iris Veil Compat 0.3.0)
- Veil is a rendering SDK; **Create: Aeronautics and Sable are the prominent consumers** (Aeronautics "uses Veil for its airplane wings, glass panels, contrails, and other visual effects"). [iris-veil-compat README](https://github.com/leon-o/iris-veil-compat) — **DOCUMENTED**.
- Without a bridge, "Veil-rendered visuals bypass the shaderpack's pipeline entirely, causing them to appear broken or missing" — i.e. irisveil is a *correctness* mod first.
- Mechanism/overhead: it mixin-intercepts Veil shader compilation, **caches the processed shader source**, and at render time does **AST-level patching (glsl-transformer)** to inject Veil logic into the shaderpack's gbuffer vertex/fragment programs, then **creates an extra Iris `ShaderInstance`** to replace the original Veil shader. Cache invalidates on shaderpack switch/reload. [README](https://github.com/leon-o/iris-veil-compat) — **DOCUMENTED**.
- Cost profile (**INFERENCE** from that mechanism): a one-time compile/patch cost per shaderpack load, plus one extra ShaderInstance and its draw path per Veil object; not a per-frame CPU cost of the same order as the Flywheel fallback. It requires Iris 1.8.1+, Sodium, Veil 4.0.0+, and was tested against **Sable 2.0.6**.
- Note its pinned dev baseline is *exactly* this pack's stack: Iris 1.8.14-beta.1+1.21.1, Sodium 0.8.13+mc1.21.1, Veil 4.5.1, Flywheel 1.0.6, Create Aeronautics 1.3.2, Sable 2.0.6, NeoForge 21.1.255 (min 21.1.228). The README mentions "the existing **Iris Flywheel Compat** missing-access-transformer warning remains in the log" — i.e. the tested configuration *did* include Iris Flywheel Compat, which the pack does not list. [iris-veil-compat README](https://github.com/leon-o/iris-veil-compat) — **DOCUMENTED**. Worth confirming against the pack manifest.
### 6. ImmediatelyFast · EntityCulling · ModernFix · FerriteCore
**ImmediatelyFast 1.6.14** — batches immediate-mode draws (entities, block entities, particles, text, GUI/HUD, other mods' immediate rendering) and replaces vanilla map/HUD/text paths. Author's own benchmark table (Ryzen 5 1600 + GTX 1060 — close to P1) claims ~2× FPS for entity-heavy scenes, ~1.4× HUD, ~2× text, ~5× maps; notably the *same* test with **Iris+Sodium** only improved 60 → 76 FPS (1.27×) on 1000 cows, because the GPU bound. [ImmediatelyFast README](https://github.com/RaphiMC/ImmediatelyFast/blob/1.21/README.md) — **DOCUMENTED**. Shipped defaults (all "regular" options on): `font_atlas_resizing`, `map_atlas_generation`, `hud_batching`, `fast_text_lookup`, `fast_buffer_upload` = **true**; experimental (`experimental_disable_error_checking`, `experimental_disable_resource_pack_conflict_handling`, `experimental_sign_text_buffering`, `experimental_screen_batching`) = **false**. [ImmediatelyFastConfig.java @ 1.21](https://github.com/RaphiMC/ImmediatelyFast/blob/1.21/common/src/main/java/net/raphimc/immediatelyfast/feature/core/ImmediatelyFastConfig.java) — **VERIFIED**. Practical read: with shaders on, ImmediatelyFast mostly buys back CPU headroom, not GPU frames.
**EntityCulling 1.11.2** — asynchronous path-traced occlusion culling on spare CPU threads, plus entity tick culling; "Fully configurable … Whitelist entities and block entities that should not be culled or tick-culled", and there is a "treat leaves as solid blocks for Entity Culling" option to help in forests. [EntityCulling README](https://github.com/tr7zw/EntityCulling/blob/main/README.md) — **DOCUMENTED**. Shipped defaults (`config/entityculling.json`, configVersion 9) — [Config.java](https://github.com/tr7zw/EntityCulling/blob/main/EntityCulling-Versionless/src/main/java/dev/tr7zw/entityculling/versionless/Config.java) — **VERIFIED**:
| Key | Default | Comment |
|---|---|---|
| `safeMode` | `true` | — |
| `tracingDistance` | `128` | blocks of ray-tracing range |
| `tickCulling` | `true` | entity tick culling on |
| `captureRate` | `5` | how often visibility is recomputed |
| `hitboxLimit` | `50` | don't cull when too many hitboxes on screen |
| `sleepDelay` | `10` | thread sleep |
| `blockEntityFrustumCulling` | `true` | — |
| `solidLeaves` | `false` | "treat leaves as solid" — relevant with fast/cullable leaves |
| `skipEntityCulling` / `skipBlockEntityCulling` | `false` | global off-switches |
| `forceDisplayCulling` | `false` | — |
| `renderNametagsThroughWalls` | `true` | cosmetic |
| `blockEntityWhitelist` / `entityWhitelist` / `tickCullingWhitelist` | populated | **`tickCullingWhitelist` already contains `create:contraption`, `create:carriage_contraption`, `create:gantry_contraption`, `create:stationary_contraption` and `alexscaves:gum_worm`/`gum_worm_segment`** — i.e. this pack's Create + Alex's Caves content is already protected from tick-culling. **VERIFIED** |
**ModernFix 5.27.24 — defaults on NeoForge 1.21.1.** Options default to **enabled unless overridden**; the explicit override map is in source. [ModernFixEarlyConfig.java @ 1.21.1](https://github.com/embeddedt/ModernFix/blob/1.21.1/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java) — **VERIFIED**:
| Option (`mixin.*` in `config/modernfix-mixins.properties`) | Default | Why it matters here |
|---|---|---|
| `perf.dynamic_resources` | **false** | The big one: dynamic/on-demand model loading. Author's wiki: **1.7 GB → 945 MB (−55%)** on a modpack that *already had FerriteCore*. Off by default only for compat risk (startup crash / missing textures). |
| `perf.dynamic_entity_renderers` | **false** | (Option retained in the 1.21.1 defaults map; no matching mixin exists on this branch.) |
| `perf.faster_texture_stitching` | **true** (not overridden) | Speeds atlas stitching at load — valuable with Chipped/Rechiseled/Macaw's texture counts. Auto-disabled if OptiFine present. |
| `perf.faster_item_rendering` | **false** | Off by default. |
| `perf.deduplicate_location`, `perf.deduplicate_climate_parameters`, `perf.clear_mixin_classinfo` | **false** | Off by default. |
| `bugfix.packet_leak`, `bugfix.skip_redundant_saves`, `bugfix.missing_block_entities`, `feature.direct_stack_trace`, `feature.stalled_chunk_load_detection`, `feature.blockentity_incorrect_thread`, `feature.spam_thread_dump`, `feature.remove_chat_signing`, `bugfix.restore_old_dragon_movement` | **false** | Off by default. |
| `feature.integrated_server_watchdog`, `feature.snapshot_easter_egg`, `feature.warn_missing_perf_mods`, `feature.log_stdout_in_log_files` | **true** | — |
| `bugfix.fix_config_crashes`, `feature.registry_event_progress` | **true** on non-Fabric | NeoForge-only. |
| (implicit) `perf.thread_priorities` / `perf.boost_worker_count` | **true** | Sets the system property **`max.bg.threads = availableProcessors − 3`** (reserving server thread + client thread + GC). On the fleet's 4C/8T that's **5**. Can be overridden by `-Dmax.bg.threads`, and is auto-disabled when Smooth Boot / ThreadTweak are present. **VERIFIED** |
The dynamic_resources win is documented by the author as "disabled by default **to maximize compatibility**", with the failure modes being a startup crash or missing textures, and the recommendation that packs which test it should turn it on. [Dynamic Resources FAQ](https://github.com/embeddedt/ModernFix/wiki/Dynamic-Resources-FAQ) — **DOCUMENTED**.
**FerriteCore 7.0.3** — a memory mod (RAM savings, mostly client-side blockstate/model objects). Config file is **`config/ferritecore-mixin.toml`** (built from `Constants.MODID + "-mixin.toml"`). [ConfigFileHandler.java @ 1.21.1](https://github.com/malte0811/FerriteCore/blob/1.21.1/NeoForge/src/main/java/malte0811/ferritecore/mixin/platform/ConfigFileHandler.java) — **VERIFIED**. Options and defaults — [FerriteConfig.java @ 1.21.1](https://github.com/malte0811/FerriteCore/blob/1.21.1/Common/src/main/java/malte0811/ferritecore/mixin/config/FerriteConfig.java) — **VERIFIED**:
| Key | Default |
|---|---|
| `replaceNeighborLookup` | true |
| `replacePropertyMap` (requires the above) | true |
| `cacheMultipartPredicates` | true |
| `modelResourceLocations` | true |
| `multipartDeduplication` (requires predicates) | true |
| `blockstateCacheDeduplication` | true |
| `bakedQuadDeduplication` | true |
| `modelSides` | true |
| `dataComponentPatch` | true |
| `useSmallThreadingDetector` | **false** — "very rare and very hard-to-reproduce crashes, use at your own risk" |
| `compactFastMap` | **false** — "slightly more compact, but also slightly slower representation" |
| `populateNeighborTable` | **false** — "slightly increases memory usage" |
Its own `summary.md` quantifies the mechanism (e.g. ~600 MB of `Table` neighbor structures → ~7 MB of `FastMap`s in a 2020-era pack), i.e. FerriteCore is a bet that pays in **heap**, which is exactly P2's binding constraint. [FerriteCore summary.md](https://github.com/malte0811/FerriteCore/blob/1.21.1/summary.md) — **DOCUMENTED**. Turning on `compactFastMap` trades CPU for a little more RAM — the wrong direction on a 4C/8T main-thread-bound machine; **INFERENCE**.
### 7. Mipmaps, atlas/VRAM, biome blend, Better Leaves, Fresh Animations
**Mipmaps.** Vanilla caps usable mipmap levels at **4**, which is the "full pyramid" level for a 16×16 texture; "Anything higher than that will have incomplete mipmaps", and the optimal level scales with pack resolution (16 → 4, 32 → 5, 64 → 6 …). Because Minecraft stitches every block texture into one atlas, "the maximum mipmap level of this atlas is the smallest maximum mipmap level of any individual texture … a single left-over 16x16 texture will limit the atlas to 4 mipmap levels". [Better Mipmaps](https://modrinth.com/mod/better-mipmaps) — **DOCUMENTED**. Consequences, and the raw VRAM maths, are **INFERENCE**: a mipmap pyramid adds ≈ 1 + ¼ + 1/16 + … ≈ **+33 %** over the base atlas, and that multiplier applies to a *large* base once Chipped / Rechiseled / Macaw's / handcrafted are in play (these add thousands of models, and animated textures occupy atlas space for *every* frame of the animation). Sodium's own tooltip already warns that raising mipmaps "could adversely affect performance with resource packs that use many animated textures", and that the option requires an asset reload. [Sodium 0.8.13 lang](https://github.com/CaffeineMC/sodium/blob/mc1.21.1-0.8.13/common/src/main/resources/assets/sodium/lang/en_us.json) — **VERIFIED**. I could not find a *primary* measured figure for atlas size/VRAM of a 212-mod pack; treat "lower mipmap levels = less VRAM + less asset reload time, biggest for 6 GB P1" as a hypothesis to measure.
**Biome blend.** Sodium's tooltip: default **5×5**; "Higher values will **greatly increase the amount of time it takes to load or update chunks**, for diminishing improvements in quality." [Sodium 0.8.13 lang](https://github.com/CaffeineMC/sodium/blob/mc1.21.1-0.8.13/common/src/main/resources/assets/sodium/lang/en_us.json) — **VERIFIED**. This is a **chunk-build/micro-stutter** cost, not a steady-state FPS cost — relevant on all three machines (all 4C/8T), and it composes with Sodium's 2 chunk-builder threads and DH's `lodBiomeBlending` (default 3). The shaderLABS wiki notes vanilla's implementation is naive and that the fastest reliable reduction is simply lowering it. [shaderLABS](https://shaderlabs.org/wiki/Performance_Tips) — **COMMUNITY**.
**Better Leaves (Motschen's) 9.6.** "Better Leaves adds additional layers to leaf blocks, making them appear more bushy, dense and natural." Version 9.0 pre-generates textures per leaf type for performance; the pack explicitly says: *"I strongly recommend installing the **Cull Leaves** mod alongside Sodium/Embeddium to get more FPS."* [Motschen's Better Leaves](https://modrinth.com/project/uvpymuxq) — **DOCUMENTED**. Read: it *increases* per-leaf-block geometry (more quads → more mesh work + more overdraw) and relies on face culling to pay for it. Sodium's own `Leaves` setting ("Fast = transparent vs opaque") is the vanilla-side lever; Sodium 0.8.12's changelog warns **"sodiumleafculling does not work"** on this line, so don't plan on a Sodium leaf-culling add-on. [Sodium 0.8.12 changelog](https://modrinth.com/mod/sodium/version/mc1.21.1-0.8.12-neoforge) — **DOCUMENTED**. EntityCulling's `solidLeaves` option exists for exactly this scenario. **Cull Leaves is not in the pack.** [Community reports](https://www.reddit.com/r/Minecraft/comments/42glrg/leaves_causing_fps_issues_fixed_with_a_resource/) of leaves dominating FPS in forested/jungle areas are **COMMUNITY** but consistent with the pack's own geometry change.
**Fresh Animations 1.10.4 + EMF 3.3.9 + ETF 7.2.4.** Fresh Animations requires EMF/ETF on 1.19+. [Fresh Animations](https://modrinth.com/resourcepack/fresh-animations) — **DOCUMENTED**. Reported cost ~5–10 FPS in mob-dense areas [mcmodhub](https://mcmodhub.com/resource-packs/fresh-animations) — **COMMUNITY**; there is also a mod-side bug report of "Huge FPS drops with Fresh Animations and the mods needed for it (EMF/ETF)" [easy-villagers #243](https://github.com/henkelmax/easy-villagers/issues/243) — **DOCUMENTED (bug report)**. EMF exposes throttles (**VERIFIED** from [EMFConfig.java](https://github.com/Traben-0/Entity_Model_Features/blob/master/src/main/java/traben/entity_model_features/config/EMFConfig.java)): `animationLODDistance` (**default 20**), `modelUpdateFrequency` (**default `UpdateFrequency.Average`**), `animationFrameSkipDuringIrisShadowPass` (**default `true`** — a real shader-specific saving), `retainDetailOnLowFps` (true), `retainDetailOnLargerMobs` (true), `renderModeChoice` (`NORMAL`), `allowedCEM` (`ALL`). The shadow-pass frame-skip being on by default is worth noting given §3: it is one of the few places Iris+EMF already cooperate.
**Fusion/Athena CTM (1.3.15b / 4.0.6)** and **Chipped/Rechiseled/Macaw's** appear in this stack as texture/model-count amplifiers (atlas + model bake + D4). Fusion CTM is the 1.21.1 successor to the old "CTM" path that ModernFix's `dynamic_resources` explicitly carries compat mixins for (`dynamic_resources/ctm/…`, `…/ldlib/…`). [ModernFix tree @ 1.21.1](https://github.com/embeddedt/ModernFix/tree/1.21.1/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources) — **VERIFIED** presence of those compat patches; whether Fusion specifically is covered is **INFERENCE / to verify**.
---
## Top levers (ranked)
| # | Lever | Expected impact | Machine it helps | Risk | Confidence |
|---|---|---|---|---|---|
| 1 | **Decide whether shaders are mandatory per machine.** With shaders on, Flywheel's instancing/indirect backends are unavailable → Create kinetics render per-BE *and* twice for shadows. Running Complementary only on P1/P2 (or all-off) is the largest single swing. | **High** | all, especially P0 | none (policy) | **VERIFIED** (source) |
| 2 | **Add a Flywheel↔Iris bridge** (Iris Flywheel Compat / Colorwheel) if Create throughput matters with shaders. | **High** | P1/P2 (CPU), P0 | **High** (both are unofficial, "almost always breaks on a Create or Iris update") | **DOCUMENTED** |
| 3 | **Complementary profile ≤ MEDIUM + Shadow Distance ≤ 8, Entity Shadows OFF.** Entity shadows are author-flagged as >50 % FPS in some cases; profiles above MEDIUM push shadow distance past the server's 8-chunk view distance. | **High** | all, esp. P0 | none (visual) | **DOCUMENTED** |
| 4 | **DH settings + shaders:** lower DH `lodChunkRenderDistanceRadius` (default 256), consider `maxHorizontalResolution` below `BLOCK`, `horizontalQuality`/`verticalQuality` below MEDIUM, `vanillaFadeMode` off `DOUBLE_PASS`, `lodBiomeBlending` 3→0, and the DH *CPU/thread preset* down from BALANCED. Remember the DH shadow pass renders **all** DH chunks. | **High** | all; P2 (RAM/CPU) most | low–med (visual bands, DH border) | **VERIFIED** (defaults) + **DOCUMENTED** (behaviour) |
| 5 | **ModernFix `mixin.perf.dynamic_resources=true`** — the biggest documented memory/launch win (−55 % in the author's test *with* FerriteCore), default-off only for compat. | **High** (RAM/load) | **P2** (8 GB free) | Med (startup crash / missing textures) | **DOCUMENTED** + **VERIFIED** (default) |
| 6 | **Lower `mipmapLevels` 4 → 2/3** and/or trim high-res overlays: cuts the ~+33 % mipmap VRAM multiplier on an atlas inflated by Chipped/Rechiseled/Macaw's plus animated-texture frames. | **Med** | **P1** (6 GB VRAM), P0 | low (slight shimmer) | **INFERENCE** on the numbers; **DOCUMENTED** on the mechanism |
| 7 | **Verify Sodium's high-impact options are actually on**: `animateOnlyVisibleTextures`, `useFogOcclusion`, `useEntityCulling`, `useBlockFaceCulling`, `useNoErrorGLContext` — all default `true`, and all are the pack's most animated-texture/RP-heavy-mod sensitive ones. | **Med** | all, P0 (iGPU) most | none | **VERIFIED** (defaults) |
| 8 | **Sodium `chunkBuilderThreads` and `chunkBuildDeferMode`:** default auto = **2 threads** on all three 4C/8T machines with "Deferred" already selected. Try 3–4 threads on P1/P2; expect faster chunk fill, riskier frame times. | **Med** | P1/P2 (chunk-bound) | low–med (frame-time variance) | **VERIFIED** (formula) |
| 9 | **Biome blend 2 → 0/1** (and DH `lodBiomeBlending` 3 → 0) — pure chunk-load/micro-stutter lever, cheap to test. | **Med** | all (4C/8T) | none (visual) | **VERIFIED** (tooltip) |
| 10 | **EMF throttles:** raise `modelUpdateFrequency` toward slower, raise/lower `animationLODDistance`, keep `animationFrameSkipDuringIrisShadowPass=true`. | **Med** | P0/P1 | low (animation quality) | **VERIFIED** (keys/defaults) |
| 11 | **Better Leaves 9.6 + no Cull Leaves = paid geometry.** Add a leaf-culling mod (Cull Leaves) or drop the RP; set EntityCulling `solidLeaves=true` if leaves are opaque. Note `sodiumleafculling does not work` on this Sodium line. | **Med** | all, P0 | low–med | **DOCUMENTED** + **VERIFIED** (Sodium changelog/EntityCulling key) |
| 12 | **ModernFix `max.bg.threads` = cores−3** is already being set; if `-Dmax.bg.threads` is being passed in JVM args, confirm it isn't fighting this. | **Low–Med** | P1/P2 | low | **VERIFIED** |
| 13 | **FerriteCore: leave defaults.** Don't enable `compactFastMap` (CPU for RAM) on a main-thread-bound fleet. | **Low** | P2 only | low | **VERIFIED** (source) |
| 14 | **ImmediatelyFast:** leave defaults; the author's own bench shows only 1.27× under Iris+Sodium. | **Low** | P1/P2 (CPU) | none | **DOCUMENTED** |
---
## Open questions to verify by benchmark
1. **Does the pack actually ship an Iris↔Flywheel bridge?** The provided mod list has `irisveil` but no Iris Flywheel Compat / Colorwheel — yet irisveil's own validated baseline includes Iris Flywheel Compat. Check `mods/` and the log for `Flywheel backend fell back from 'flywheel:indirect' to 'flywheel:off'` and for `irisflw:iris_instancing`. **This single log line decides levers #1/#2.**
2. **What is the actual block-atlas size and VRAM on P1?** (Atlas texture allocation, plus mipmap multiplier.) Only answerable by measurement (e.g. a VRAM/F3 or driver-level capture) — needed before trusting lever #6.
3. **Complementary Reimagined r5.9.3's shipped default profile** — the repo table is authoritative for the settings, but the *default* profile on a fresh install should be read in-game (the repo has a `COMPLEMENTARY` profile the older docs predate).
4. **Whether MakeUp Ultra Fast 9.5f actually beats Complementary at equivalent visual settings** on P0/P1 — no primary comparison exists; measure.
5. **DH's real cost with the chosen shaderpack**: measure with DH rendering on/off, and with DH's shadow pass (`dhShadow.enabled`) forced off, to separate the DH-shadow cost from DH-terrain cost.
6. **ModernFix `dynamic_resources=true` compatibility with Fusion CTM / Athena / Chipped / Rechiseled / Macaw's** on this exact pack — author lists CTM-style compat patches but not these mods by name; test with a resource reload and a look for missing textures.
7. **Does `Animate Only Visible Textures` actually hold up with Fresh Animations + FA All Extensions + Better Leaves' generated textures** (author warns of "issues with some textures not being animated")?
8. **EntityCulling block-entity whitelist adequacy for this pack** — Create contraptions are tick-cull-whitelisted, but check whether specific Create/Alex's Caves block entities pop or vanish (the config is a plain JSON list and is safe to extend).
9. **Whether Sodium's `QuadSplittingMode = SAFE` is limiting translucency correctness/instability** in a Chipped/Rechiseled/glass-heavy base — the tooltip says `UNLIMITED` imposes no geometry cap but risks instability; only worth testing if sorting artifacts are visible.
10. **P2 memory headroom specifically**: with ~8 GB free, does DH's "6–8 GB allocated" recommendation plus ModernFix `dynamic_resources` fit, and does a concurrent GC (ZGC) change the micro-stutter picture?
---
## Sources
**Kept**
- Sodium, `mc1.21.1-0.8.13` source — `SodiumConfigBuilder.java`, `SodiumOptions.java`, `ChunkBuilder.java`, `lang/en_us.json`. https://github.com/CaffeineMC/sodium/tree/mc1.21.1-0.8.13 — the authoritative option set **and defaults** for the pinned version.
- Sodium version page / changelog, `mc1.21.1-0.8.12-neoforge` (the base of the 0.8.13 line). https://modrinth.com/mod/sodium/version/mc1.21.1-0.8.12-neoforge — perf claims + official mod-compat matrix.
- Flywheel 1.21.1 branch: `Backends.java`, `BackendManagerImpl.java`, `IrisCompat.java`, `ShadersModHelper.java`, `NeoForgeFlwConfig.java`. https://github.com/Engine-Room/Flywheel/tree/1.21.1/dev — proves the Iris→backend fallback and gives the real NeoForge config keys.
- Flywheel tag `mc1.21.1/v1.0.5`. https://github.com/Engine-Room/Flywheel/blob/mc1.21.1/v1.0.5/common/src/backend/java/dev/engine_room/flywheel/backend/Backends.java — confirms the shader gate predates 1.0.6.
- Iris issue #1414 ("Flywheel is not supported"), includes maintainer statement. https://github.com/IrisShaders/Iris/issues/1414
- Create `mc1.21.1/dev`: `KineticBlockEntityRenderer.java` (+ `ShaftRenderer.java`). https://github.com/Creators-of-Create/Create/blob/mc1.21.1/dev/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityRenderer.java — proves the non-Flywheel fallback path exists and is used when visualization is unsupported.
- Iris docs — Distant Horizons integration (`dh_terrain`/`dh_water`/`dh_shadow`, auto-enabled shadow pass, no shadow distance). https://shaders.properties/current/reference/mod-support/distant_horizons/
- Distant Horizons core `Config.java` (current main). https://gitlab.com/distant-horizons-team/distant-horizons-core/-/blob/main/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java — verified config keys + defaults.
- Distant Horizons Modrinth description (shader requirements, stutter checklist). https://modrinth.com/mod/distanthorizons
- Complementary Reimagined `shaders.properties` + `lang/en_US.lang` (author repo). https://github.com/ComplementaryDevelopment/ComplementaryReimagined — profile table, shadow distances, and the author's own perf warnings.
- MakeUp Ultra Fast `shaders.properties` + README (author repo). https://github.com/javiergcim/MakeUpUltraFast — verified option keys, shipped profile values, `dhShadow.enabled=false`.
- Iris Veil Compat README (mechanism, overhead, tested baseline). https://github.com/leon-o/iris-veil-compat
- ModernFix `ModernFixEarlyConfig.java` @ 1.21.1 (default table). https://github.com/embeddedt/ModernFix/blob/1.21.1/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java
- ModernFix Dynamic Resources FAQ. https://github.com/embeddedt/ModernFix/wiki/Dynamic-Resources-FAQ — 1.7 GB → 945 MB with FerriteCore already installed; why it's off by default.
- FerriteCore `FerriteConfig.java`, `ConfigFileHandler.java`, `summary.md` @ 1.21.1. https://github.com/malte0811/FerriteCore/tree/1.21.1
- EntityCulling `Config.java` (configVersion 9 defaults + whitelists). https://github.com/tr7zw/EntityCulling/blob/main/EntityCulling-Versionless/src/main/java/dev/tr7zw/entityculling/versionless/Config.java
- ImmediatelyFast `ImmediatelyFastConfig.java` + README bench table. https://github.com/RaphiMC/ImmediatelyFast/blob/1.21/common/src/main/java/net/raphimc/immediatelyfast/feature/core/ImmediatelyFastConfig.java
- EMF `EMFConfig.java` (animation throttles incl. `animationFrameSkipDuringIrisShadowPass`). https://github.com/Traben-0/Entity_Model_Features/blob/master/src/main/java/traben/entity_model_features/config/EMFConfig.java
- Better Mipmaps description (vanilla 4-level cap, atlas-wide minimum, resolution↔level table). https://modrinth.com/mod/better-mipmaps
- Motschen's Better Leaves description (geometry change, Cull Leaves recommendation, v9 perf rework). https://modrinth.com/project/uvpymuxq
- shaderLABS Performance Tips wiki (biome blend, shader menu sliders, RAM guidance). https://shaderlabs.org/wiki/Performance_Tips
- Ocuwheel description (explicit "Flywheel disables GPU instancing under shaders, falls back to CPU rendering"). https://www.curseforge.com/minecraft/mc-mods/ocuwheel-oculus-flywheel-compat
- Sodium Extras description (which options are *not* in Sodium — fog toggles etc.). https://modrinth.com/mod/sodium-extras
**Dropped**
- shadersmods.com / mc-mods.com / mcmodhub "Complementary Reimagined review" pages — SEO content, and their profile tables describe r2.1 (2023). Used only as a secondary lead; superseded by the author's own `shaders.properties`.
- irisshaders.org / minecrafthub.io / mctoolbox.net guides — unverifiable marketing-style guides, no version-specific claims worth keeping.
- r/feedthebeast, r/minecraftshaders, r/Minecraft threads on MakeUp-vs-Complementary FPS — anecdotal, no controlled comparison.
- Sodium `dev`-branch lang file as a *description of 0.8.13* — kept only to demonstrate which options (hidden fluid culling etc.) are **absent** on 1.21.1.
- minecraft.wiki/w/Options.txt — returned HTTP 403, so the vanilla `mipmapLevels`/`biomeBlendRadius` defaults are stated from Sodium's own language file ("Default is 5x5" for biome blend) rather than the wiki.
@@ -0,0 +1,185 @@
# Research: Distant Horizons 3.3.x (client) + Xaero's Minimap 26.5.0 / World Map 1.46.0 — client-side performance
Pack context: Onion MC, MC 1.21.1 / NeoForge 21.1.251, pinned `DistantHorizons-3.3.2-1.21.1-fabric-neoforge.jar`, `xaerominimap-neoforge-1.21.1-26.5.0.jar`, `xaeroworldmap-neoforge-1.21.1-1.46.0.jar` (verified against `mods/*.pw.toml` in this repo). Dedicated server with DH; Iris 1.8.14-beta.1; shaderpacks Complementary Reimagined r5.9.3 + MakeUp Ultra Fast 9.5f. All 3 fleet machines are 4C/8T.
## Summary
DH 3.3.2's client cost splits into (a) CPU: LOD building/generation threads (thread preset; on 8 logical CPUs BALANCED = 4 threads, Minimal = 1), and (b) GPU/VRAM: LOD render distance × quality preset (distance is the dominant term; DH docs say >512 chunks gets "difficult due to high VRAM/GPU usage"; a 1.x-era dev-tracker data point put 1024 chunks at ~4 GB VRAM). In multiplayer the client cannot generate LODs at all — the server sends them (default 500 KB/s per player) — so client-side "distant generation" settings are singleplayer-only; server pregen via `/dh pregen` is the officially recommended path, and running Chunky alongside DH generation is explicitly warned against (holes). Xaero's pair is cheap: the minimap reuses world-map textures by default, world-map disk data grows with exploration but in-RAM region cache is bounded (cappable via a "max loaded regions" setting added in 1.41.2), and the map screen skips world rendering by default.
## Findings — Distant Horizons 3.3.2
### 1. What each client setting actually costs (keys verified from the pinned jar's `assets/distanthorizons/lang/en_us.json` + DH core source)
GUI path and TOML key names below were read from the 3.3.2 jar and DH core `Config.java`; every listed key exists in 3.3.2. [Config.java (DH core, main/3.3.x line)](https://gitlab.com/distant-horizons-team/distant-horizons-core/-/raw/main/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java), [lang file in jar 3.3.2](https://modrinth.com/mod/distanthorizons/version/3.3.2-1.21.1)
| Concern | Key (GUI path) | Verified facts |
|---|---|---|
| LOD render distance | `client.advanced.graphics.quality.lodChunkRenderDistanceRadius` | min 32 / **default 256** / max 4096 chunks; "best effort" number [Config.java](https://gitlab.com/distant-horizons-team/distant-horizons-core/-/raw/main/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java); official gallery: "By default DH renders 256 chunks wide… anything above 512 may become difficult due to high VRAM/GPU usage" [Modrinth gallery](https://modrinth.com/mod/distanthorizons/gallery) |
| Quality preset | `client.qualityPresetSetting` (MINIMUM/LOW/MEDIUM/HIGH/EXTREME) | Preset just sets the sub-options below; **generation is independent** — "DH will always generate LODs at the maximum possible quality so you can use any Quality preset you want later" (no regen needed) [DH FAQ General](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/1-general/General) |
| Horizontal quality / resolution | `…quality.horizontalQuality`, `…quality.maxHorizontalResolution` | "Higher settings will … increase memory and GPU usage"; resolution BLOCK = 256 LODs/chunk (fanciest) vs CHUNK = 1 LOD/chunk (fastest) [Config.java](https://gitlab.com/distant-horizons-team/distant-horizons-core/-/raw/main/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java) |
| Vertical quality | `…quality.verticalQuality` | HEIGHT_MAP (cheapest) → PIXEL_ART; "higher options … increase memory and GPU usage"; too-low vertical quality causes flat/discolored LODs [Config.java + Problems & Solutions](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions) |
| Transparency | `…quality.transparency` | Only `DISABLED` or `COMPLETE` in 3.3.2 (fake transparency removed in 3.1.0-b); DISABLED = opaque LODs = cheaper; **3.1.1-b+ forces transparency ON when Iris is present** [changelog 3.1.0-b/3.1.1-b](https://modrinth.com/mod/distanthorizons/version/3.1.1-b-1.21.1) |
| Cave culling | `…culling.enableCaveCulling`, `…culling.caveCullingHeight` (default 60) | "culls all faces with skylight value of 0 under the cave culling height" — big face-count saver in mountains/overhangs [lang tooltip, jar 3.3.2] |
| Overdraw | `…culling.overdrawPrevention` (default −1 = auto), `…culling.reduceOverdrawWithFastMovement` | % of vanilla RD where DH starts rendering behind vanilla terrain; −1 auto-scales; holes-at-edge tradeoff documented; auto reduce while flying [Config.java + P&S quick guide](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions) |
| Frustum culling | `…culling.disableFrustumCulling` (default false = culling ON), `…culling.disableShadowPassFrustumCulling` | Culling "increasing GPU performance"; leave enabled (disabled only if LODs pop at screen corners) [lang tooltip] |
| Vanilla fade mode | `…quality.vanillaFadeMode` (NONE/SINGLE_PASS/DOUBLE_PASS) | NONE "Fastest… pronounced border"; DOUBLE_PASS "Slowest… smoothest" (MEDIUM+ default) [Config.java] |
| DH SSAO / AA | `client.advanced.graphics.enableSsao`, `…enableAntiAliasing` | 3.3.0 added TAA; SSAO/AA off in MINIMUM/LOW presets [changelog 3.3.0](https://modrinth.com/mod/distanthorizons/version/3.3.0-1.21.1) + preset handler source |
| LOD textures | `…texture.enableTexturedLods`, `maxTexturedLodDetailLevel` | 3.2.0 feature; "Only available for base DH rendering, **Iris shaders will render LODs as untextured**" → no shader cost under Iris either way [changelog 3.2.0-b](https://modrinth.com/mod/distanthorizons/version/3.2.0-b-1.21.1) |
| DH clouds/beacons | `…genericRendering.enableCloudRendering`, `enableMultiLayerClouds`, `enableBeaconRendering` | DH renders its own 3-layer clouds; GPU filler; Complementary sets `dhClouds = off` (see §4) |
| Zoom quality | `…quality.increaseQualityWhenZoomedIn`, `maxZoomQualityIncrease` (default 4) | Loading crisper LODs while zoomed costs CPU/memory while zoomed [Config.java; 3.3.0 fixed "massive lag when zoomed in and spinning the camera"] |
| CPU threads | `client.threadPresetSetting` → `common.multiThreading.numberOfThreads`, `threadRunTimeRatio`, `threadPriority`, `useC2meThreadCount` | Preset = % of **logical** CPUs (source has table: 1.0 ⇒ 8 threads on 8 logical) + runtime ratio [ThreadPresetConfigEventHandler](https://gitlab.com/distant-horizons-team/distant-horizons-core/-/raw/main/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/ThreadPresetConfigEventHandler.java) |
| LOD storage | `common.lodBuilding.dataCompression` (LZ4/ZSTD…), `worldCompression` (MERGE_SAME_BLOCKS/VISUALLY_EQUAL), `databaseSyncMode` (FULL/NORMAL/OFF), `disableUnchangedChunkCheck` | LODs live in SQLite (`.minecraft/Distant_Horizons_server_data/<server>/` in MP); NORMAL sync default since 3.3.0 cut disk work ~50%; OFF risks corruption on power loss [General FAQ](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/1-general/General), [changelog 3.3.0](https://modrinth.com/mod/distanthorizons/version/3.3.0-1.21.1) |
| World gen (SP only) | `common.worldGenerator.enableDistantGeneration`, `generatorPlan` (SURFACE_THEN_CHUNKS/SURFACE_ONLY/CHUNKS_ONLY/DISABLED), `chunkGeneratorMode` (…/SURFACE/FEATURES/INTERNAL_SERVER), `enableFastSurfaceGenerator`, `limitIfServerUnhealthy`, `pauseIfMovingQuickly` | 3.3.0 added fast surface gen + "pause world gen if server thread overloaded or moving quickly — both options can be toggled… if faster world gen is desired over smoothness" [changelog 3.3.0](https://modrinth.com/mod/distanthorizons/version/3.3.0-1.21.1) |
Quality preset → what it sets (from [RenderQualityPresetConfigEventHandler.java](https://gitlab.com/distant-horizons-team/distant-horizons-core/-/raw/main/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/presets/RenderQualityPresetConfigEventHandler.java)) — note the trap that **HIGH/EXTREME turn cave culling OFF**:
| Preset | maxHorizRes | Vertical | Horizontal | Transparency | SSAO | AA | Vanilla fade | Cave culling | Biome blending |
|---|---|---|---|---|---|---|---|---|---|
| Minimum | 2-block | Height map | Lowest | Disabled | off | off | None | on | 0 |
| Low | Block | Low | Low | Disabled | off | on | Single pass | on | 1 |
| Medium | Block | Medium | Medium | Complete | on | on | Double pass | on | 3 |
| High | Block | High | High | Complete | on | on | Double pass | **off** | 3 |
| Extreme | Block | Extreme | Extreme | Complete | on | on | Double pass | **off** | 3 |
Thread presets on the fleet's 4C/8T (source: `ThreadPresetConfigEventHandler` — percentages of `availableProcessors` = 8 logical):
| Preset | Threads | Runtime ratio |
|---|---|---|
| Minimal Impact | 1 | 0.5 |
| Low Impact | 2 | 1.0 |
| Balanced (default) | 4 | 1.0 |
| Aggressive | 6 | 1.0 |
| I Paid For The Whole CPU | 8 | 1.0 |
### 2. GPU upload settings — removed in 3.x
The old 2.x-era `gpuUploadMethod` (Direct / Single draw / Multi draw / Buffer storage) **no longer exists in 3.3.2**: the full option list in the pinned jar contains no upload-method key, and the 3.0.0-b changelog states "Remove instanced rendering config option — instanced rendering will always be used if available". The only related control left is `client.advanced.graphics.experimental.renderingEngine` (Auto / OpenGL / Blaze3D); Blaze3D is only for newer MC — on 1.21.1 it's effectively OpenGL/Auto, and DH ≥3.3 renders with reverse-Z depth. [jar lang file](https://modrinth.com/mod/distanthorizons/version/3.3.2-1.21.1), [changelog 3.0.0-b](https://modrinth.com/mod/distanthorizons/version/3.0.0-b-1.21.1), [changelog 3.1.0-b](https://modrinth.com/mod/distanthorizons/version/3.1.0-b-1.21.1). VERIFIED.
### 3. VRAM / RAM vs distance (no first-party table exists)
- Official qualitative: memory & GPU usage rise with horizontal/vertical quality, max resolution and LOD distance (config comments); >512 chunks "difficult due to high VRAM/GPU usage" [Config.java](https://gitlab.com/distant-horizons-team/distant-horizons-core/-/raw/main/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java), [Modrinth gallery](https://modrinth.com/mod/distanthorizons/gallery). DOCUMENTED.
- Only quantitative tracker data point is old (DH 1.x, 2022): "1024 with default settings uses ~4 GB VRAM and more than 8 GB RAM should be allocated to JRE or else there will be intense stuttering" [GitLab issue #157](https://gitlab.com/distant-horizons-team/distant-horizons/-/issues/157). COMMUNITY/dev-tracker, dated — treat as order-of-magnitude only.
- Heap guidance is first-party: 4–8 core CPUs → allocate 6–8 GB; 10+ cores → 12–16 GB; prefer ZGC (`-XX:+UseZGC`) over G1GC on Java 21 "known to cause stuttering"; DH even warns in-chat if G1GC is used [DH FAQ General](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/1-general/General), [P&S](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions). VERIFIED.
- Community starting profile for mid hardware: LOD 96–192 chunks at Medium quality [distanthorizonsguide calculator](https://distanthorizonsguide.com/calculator). COMMUNITY.
- Official troubleshooting maps symptom→setting: CPU pegged → lower CPU preset or disable world gen; GPU pegged → lower quality preset or LOD distance; VRAM pegged → same [P&S](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions). VERIFIED.
### 4. Iris shader cost & which packs support DH
- Iris ≥1.7 required; DH terrain renders through dedicated `dh_terrain`, `dh_water` and `dh_shadow` programs defined by the shaderpack — i.e. LODs are drawn with full shader effects, so shader cost scales to the LOD distance too; the DH shadow pass can be toggled per-pack via `dhShadow.enabled` [Iris docs — Distant Horizons](https://shaders.properties/current/reference/mod-support/distant_horizons/). VERIFIED.
- **Complementary Reimagined r5.x supports DH**: its `shaders.properties` has a `#ifdef DISTANT_HORIZONS` block with `blend.dh_water=…` and, importantly, `dhShadow.enabled = false` + `dhClouds = off` — the DH shadow pass and DH clouds are disabled, trimming shader work over distant terrain [Complementary Reimagined source](https://raw.githubusercontent.com/ComplementaryDevelopment/ComplementaryReimagined/main/shaders/shaders.properties). VERIFIED.
- **MakeUp Ultra Fast also has DH support**: `#ifdef DISTANT_HORIZONS: dhShadow.enabled = false; blend.dh_water=…` [MakeUp Ultra Fast source](https://raw.githubusercontent.com/javiergcim/MakeUpUltraFast/master/shaders/shaders.properties). VERIFIED. Both pack shaders therefore avoid the most expensive DH-over-shader path (DH shadows render *all* chunks into the shadow map).
- Shaders that don't support DH prevent LODs from rendering entirely [P&S](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions). VERIFIED.
### 5. Client-generated vs server-provided LODs (this pack: server-provided)
- In multiplayer, clients **cannot** generate LODs: "Can clients generate instead? No, world generation is coupled with server-side logic" — the client requests and receives LODs (normal generation), gets real-time updates near players, and sync-on-load with timestamps [Server Owners wiki](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/5-server-owners/Server-Owners). VERIFIED.
- Server must have the same DH version; `Distant Generator Plan` must not be `DISABLED` on either side. Defaults allow **500 KB/s (4 Mbit/s) per player** of LOD traffic (`server.playerBandwidthLimit`); other keys: `generationRequestRateLimit`, `maxGenerationRequestDistance`, `enableRealTimeUpdates` + `realTimeUpdateDistanceRadiusInChunks`, `synchronizeOnLoad` + `syncOnLoadRateLimit` + `maxSyncOnLoadRequestDistance`, `globalBandwidthLimit`, `enableAdaptiveTransferSpeed` [Server Owners wiki + jar lang](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/5-server-owners/Server-Owners). VERIFIED. Client-side keys: `client.advanced.multiplayer.serverFolderNameMode` (local LOD DB naming).
- "Pre-generating LODs is strongly recommended to avoid performance issues" — command `/dh pregen start <dimension> <origin> <chunkRadius>`; avoid pregen on a live server. Client-side pregen alternative: copy server world, generate AFK, ship the SQLite DB back [Server Owners wiki](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/5-server-owners/Server-Owners). VERIFIED.
- World-gen mode notes: default `FEATURES` mode doesn't save generated chunks, so trees/structures can pop in/out at LOD borders; `INTERNAL_SERVER`/`FULL` prevents it [P&S](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions). VERIFIED.
### 6. Known warnings relevant to this pack
- **DH + Chunky**: "Running Chunky will also generate & update LODs, but it's not recommended to rely on this… by loading a lot of chunks quickly you risk overloading DH and ending up with a lot of holes. Either use DH's pre-generation, or temporarily disable the mod entirely" [Server Owners wiki](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/5-server-owners/Server-Owners). DH 3.3.x also changed thread linking: "Don't link DH thread count to C2ME unless Chunky is also present… Using Chunky and DH isn't recommended due to the possibility of holes" [changelog 3.3.0](https://modrinth.com/mod/distanthorizons/version/3.3.0-1.21.1); 3.3.3 added auto-disable of DH worldgen while Chunky worldgen runs (3.3.2 does **not** have that guard). VERIFIED.
- **DH + Alex's Caves**: LODs fail to render; fix = set `biome_ambient_light_coloring = false` in `config/alexscaves-client.toml` (DH bug tracker issue #566) [DH wiki Mod Support](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/4-mod-support/Mod-Support). VERIFIED.
- **DH 3.3.2 + SSRD**: "Mark SSRD (Separate Sable Render Distance) 1.8.6 and below as incompatible — due to DH's change to rendering with Reverse Z depth". Pack has SSRD 1.8.7 → OK, but don't downgrade it [changelog 3.3.2](https://modrinth.com/mod/distanthorizons/version/3.3.2-1.21.1). VERIFIED.
- **Steam Deck / Mesa**: DH+ Sodium crash on Linux AMD/Intel Mesa GPUs → disable Sodium's "Use No Error context" (and delete DH config once) [P&S](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions). DH 3.2.0 raised min OpenGL 3.2→3.3 (AMD fix) [changelog 3.2.0-b](https://modrinth.com/mod/distanthorizons/version/3.2.0-b-1.21.1). VERIFIED. Deck players run 128–256 LOD with Iris shaders at 30–40 FPS at 1200×800 [r/DistantHorizons](https://www.reddit.com/r/DistantHorizons/comments/1by5v4u/how_to_get_distant_horizons_working_on_steam_deck/), [r/SteamDeck](https://www.reddit.com/r/SteamDeck/comments/1lak2s5/how_i_got_minecraft_running_with_distant_horizons/). COMMUNITY.
- Black LODs from light-map mods; "Mod Compatibility Warnings" exist at `Advanced → Logging → Warnings` if a known-bad combo is present [P&S + jar lang]. VERIFIED (key exists).
### 7. Recommended starting settings per fleet machine
All values use verified keys; distances assume server VD 8 (vanilla) and server-side pregen so the client isn't starved of LODs. (INFERENCE from the verified mechanics + community profiles above.)
| Setting | (a) Steam Deck (RDNA2 8CU, 1280×800, shared RAM) | (b) P1 GTX 1060 6GB (VRAM-bound) | (c) P2 4C + ~8GB free RAM (heap-bound) |
|---|---|---|---|
| LOD render distance | 96–128 | 128–192 (step up slowly; shaders over 512-chunk LODs is where VRAM dies) | 96–128 (lower if heap spikes) |
| Quality preset | LOW | LOW–MEDIUM (watch VRAM; MEDIUM re-enables transparency+SSAO) | MEDIUM or LOW (quality is render-only cost; cheap to lower) |
| Cave culling | ON (do **not** use HIGH/EXTREME presets without re-enabling) | ON | ON |
| Thread preset | Minimal/Low Impact (leave headroom for Deck's APU) | Low Impact/Balanced | Balanced (4 threads) while playing; Minimal if stutter |
| SSAO / DH anti-aliasing | off (LOW preset) | off unless headroom | default |
| Transparency | Disabled (if no shader) | forced Complete under Iris | forced Complete under Iris |
| Vanilla fade mode | Single pass | Double pass (visual seam vs GPU) | Double pass |
| DH clouds/beacons | off if GPU-bound (Complementary already disables DH clouds) | off | default |
| JVM heap | 6–8 GB `-Xmx` + `-XX:+UseZGC` (wiki guidance) | 6–8 GB | ≤6 GB; prefer cutting LOD distance over heap |
| Generation | server provides LODs; keep `enableDistantGeneration` irrelevant in MP | same | same; keep client DB sync NORMAL |
## Findings — Xaero's Minimap 26.5.0 / World Map 1.46.0
### 8. Where the cost is, and the verified settings that control it
Field names below were extracted from the pinned jars' settings classes (`xaero/common/settings/ModSettings.class`, `xaero/map/settings/ModSettings.class`) — the mods are closed-source but NeoForge builds ship Mojang-mapped symbols. VERIFIED (jar extraction).
| Cost center | Mechanism | Relevant verified settings/keys |
|---|---|---|
| Minimap terrain | Chunk-to-pixel updates as you move; renders into its own FBO (`MinimapFBORenderer`, `bufferSize`) | `minimapSize` (bigger = more fill rate), `zoom`, `caveZoom` |
| Cave mode | Renders below-ground slices; needs roof search + extra depth scanning | `caveMaps` (on/off), `caveMapsDepth`, `caveMapsDisabled`, `manualCaveModeStart`, `autoCaveMode` (WM), per-dimension `defaultCaveModeType`, `legibleCaveMaps` |
| Shading | Extra per-chunk color math | `terrainDepth`, `terrainSlopes`, `biomeBlending`, `blockColours`, `ambientLightColored` |
| Entity radar | Per-frame entity scan + icon rendering (model-based icons are pre-rendered; heavy entity mods = more types) | `entityRadar`, `mainEntityAs`, `dotsStyle`, `smoothDots`, `radarHideInvisibleEntities`, display-names toggles; categories in `xaero/minimap` config |
| Overlays | Extra scans | `displayRedstone`, `displayStainedGlass`, `slimeChunks`, `lightOverlay*` |
| World Map rendering | Full-screen map; **skips world rendering by default while the map is open** — turning that off "significantly reduces your framerate" (official changelog) | world-map-screen "world render skip" option; `openMapAnimation`, `zoomButtons` |
| World Map writing | Client converts explored chunks into region data; "Optimized map writing… less useless chunk iteration" (26.2.0/1.42.0) | `mapWritingDistance` (limit writing distance; option exists since 1.35.0), **"Force Fast Writing"** — official: "Bad for game performance" |
Official changelog anchors: world map 1.42.0 (fast-writing "bad for game performance", world-render skip, optimized map writing), 1.41.2 ("Added a new option… for setting the **maximum number of loaded regions**"), 1.35.0 (map writing distance option), 1.37.2 ("Slightly optimised region unloading"); minimap 26.2.0 ("Optimized map writing"), 25.3.12 (BatchableBufferSource / ImmediatelyFast interplay) — [chocolateminecraft update pages](https://chocolateminecraft.com/update.php?mod_id=2) and [mod_id=0](https://chocolateminecraft.com/update.php?mod_id=0). DOCUMENTED.
### 9. Does world map memory scale with explored area?
- **On disk: yes, unbounded-ish** — regions are saved as `.zip` files per dimension/map under `xaero/world-map/…` (plus separate cache folders the FAQ says can be deleted) [Modrinth FAQ](https://modrinth.com/mod/xaeros-world-map). VERIFIED.
- **In RAM: bounded** — the mod keeps a *region cache* (region-cache fields exist in 1.46.0 bytecode; "Reload Regions"/"Reload All Regions" options manage the cache), region unloading is automatic, and since world map 1.41.2 there is a user setting for the **maximum number of loaded regions** (present in 1.46.0) — so heap use is a function of that cap + zoom level, not of total exploration [changelog 1.41.2](https://chocolateminecraft.com/update.php?mod_id=2). VERIFIED (mechanism) — a third-party benchmark measured roughly flat ~45–85 MB for the pair even with heavy exploration [Oreate guide](https://create.oreateai.com/create/performance-vs-features-the-real-difference-between-journeymap-and-xaeros). COMMUNITY (small blog, directionally consistent with the bounded-cache design).
- Resource pack changes force a full map regeneration (disk churn) [Modrinth description](https://modrinth.com/mod/xaeros-world-map). DOCUMENTED.
### 10. Minimap↔world map integration (perf-positive, keep defaults)
"By default uses the map textures generated by the world map mod instead of generating its own. This improves performance when using both mods" [Minimap description](https://modrinth.com/mod/xaeros-minimap). Also, config moved to `/config/xaero/minimap`, `/config/xaero/world-map`, shared `/config/xaero/lib` (25.3.2/1.40.2 config rework) — the pack can ship enforced defaults per machine there [changelog 25.3.2](https://chocolateminecraft.com/update.php?mod_id=0). VERIFIED. The world map screen's default world-render skipping + auto framerate limit (~625 fps cap) when skipped is another official perf behavior [changelog 1.42.0](https://chocolateminecraft.com/update.php?mod_id=2). VERIFIED.
### 11. Alternatives, briefly
- Community consensus ranks Xaero's as the lightest full-featured pair; JourneyMap is "slightly heavier on system resources" with more RAM/CPU headroom needed; FTB Chunks is often called the most performant but feature-poor and its map/claim data lives in the server world save (server TPS exposure) [r/feedthebeast comparison](https://www.reddit.com/r/feedthebeast/comments/1pnr3bo/for_modded_minecraft_which_minimap_has_more/), [Enigmatica6 issue #1340](https://github.com/EnigmaticaModpacks/Enigmatica6/issues/1340), [Astroworld guide](https://guide.astroworldmc.com/best-minecraft-minimap-mods). COMMUNITY — no first-party benchmarks either way; keep Xaero's.
## Sources
Kept:
- DH GitLab wiki (Server Owners; Problems & Solutions; Mod Support; General FAQ) — primary, maintained by the mod author. https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/home
- DH core source (Config.java, preset handlers, enums) — authoritative key/behavior definitions. https://gitlab.com/distant-horizons-team/distant-horizons-core
- Pinned jars' embedded lang/setting symbols (DH 3.3.2, XaeroMinimap 26.5.0, XaeroWorldMap 1.46.0) — exact-version config surface. https://modrinth.com/mod/distanthorizons/version/3.3.2-1.21.1
- Iris docs, DH mod-support reference — how shaderpacks integrate DH passes. https://shaders.properties/current/reference/mod-support/distant_horizons/
- Complementary Reimagined + MakeUp Ultra Fast `shaders.properties` — proof of DH support and of disabled DH shadow pass. (GitHub raw links above)
- Xaero's official descriptions + chocolateminecraft changelogs — feature/perf changes per version. https://chocolateminecraft.com/update.php?mod_id=2
- GitLab issues #157 (RAM/VRAM data point), #566 (Alex's Caves fix via wiki) — tracker history.
Dropped:
- distanthorizonsguide.com — useful but third-party SEO-adjacent; kept only its calculator profile as one COMMUNITY data point.
- Sportskeeda/best-settings listicles — no original data, stale version references.
- Steveplays28 shader-compat gist — 1.19.2-era, superseded by per-pack source verification.
- Older Reddit optimization threads (DH 1.18.2 era) — settings names/values changed in 3.x.
## Gaps
- No first-party per-distance VRAM/RAM table for DH 3.3.x exists; the only numbers are 2022-era (issue #157) and community profiles. Benchmark: F3 overlay + RTSS/`radeontop` at 64/128/256 chunks × LOW/MEDIUM with each shaderpack, per machine.
- Actual FPS/VRAM delta of Complementary's DH programs (`dh_terrain`/`dh_water`) vs base renderer, and whether its disabled `dhShadow` fully avoids DH shadow cost (it should by contract, but verify).
- Xaero's minimap cost with heavy entity mods (Alex's Mobs etc.) and with cave mode on — no measurements found; icon pre-rendering burst at first-encounter may stutter on Deck.
- World map "maximum number of loaded regions" default value on 1.46.0 and its heap effect (setting exists; default not visible without running the game).
- Whether the pack's server actually enables `enableRealTimeUpdates`/sync radius ≤ client LOD distance (affects client bandwidth/CPU when riding Create trains).
## Top levers
| # | Lever | Expected impact | Helps | Risk | Confidence |
|---|---|---|---|---|---|
| 1 | Cut DH LOD render distance to 96–128 (Deck/P2) or 128–192 (P1) — keep ≤512 always | High (GPU+VRAM+CPU all scale with it) | All three; most on P1 VRAM & Deck | Visual only | High |
| 2 | Quality preset LOW/MEDIUM **with cave culling re-checked ON** (never leave HIGH/EXTREME presets' culling-off in mountains) | High on GPU-heavy scenes, Med general | Deck, P1 | Slightly flatter distant terrain | High (preset mapping verified) |
| 3 | Server-side `/dh pregen` + keep per-player LOD bandwidth/rate limits (500 KB/s default) so clients stream prebuilt LODs instead of stressing CPU | High (client smoothness), Med (server) | All three; P2 CPU | Server disk/IO during pregen; don't pregen while playing | High |
| 4 | Thread preset: Minimal/Low while exploring fast, Balanced otherwise; keep `pauseIfMovingQuickly`/`limitIfServerUnhealthy` on | Med (stutter elimination on 4C/8T) | P2, Deck | Slower LOD fill-in | High |
| 5 | Heap: `-Xmx6–8G` + `-XX:+UseZGC` (≤6G on P2), keep DH DB sync NORMAL | Med (stutter/GC) | P2 most, Deck (shared RAM) | Lower heap on P2 may thrash if LOD RD kept high | High (official guidance) |
| 6 | Steam Deck: Sodium "Use No Error context" OFF (Mesa fix) + stay on OpenGL rendering engine | Med (crash/stability, some perf) | Deck | None | High (official wiki) |
| 7 | Xaero's: cap world-map "max loaded regions" + keep `mapWritingDistance` default; never enable Force Fast Writing; keep world-render skip ON | Low–Med (heap spikes on P2 when opening map) | P2, Deck | Slower mapping while flying fast | Med |
| 8 | Xaero's minimap: modest `minimapSize`, radar to dots + hide invisible entities, cave mode off above ground for users who don't need it | Low | Deck, P2 | Feature loss (QoL) | Low–Med (mechanism verified, magnitude not) |
| 9 | Keep both shaderpacks' built-in DH integration (dhShadow off) — do not swap in packs without `DISTANT_HORIZONS` support | Prevents catastrophic regressions | All | None (status quo) | High |
| 10 | Pack fixes: Alex's Caves `biome_ambient_light_coloring = false`; pin SSRD ≥1.8.7 with DH 3.3.2 | Prevents broken LODs/rendering | All | AC loses biome tint ambience | High |
## Open questions to verify by benchmark
1. VRAM at 128 vs 192 vs 256 LOD chunks with Complementary Reimagined r5.9.3 on the GTX 1060 6GB — where does the 6 GB budget break?
2. Steam Deck: 30 fps target — LOW preset @128 LOD vs MEDIUM @96 LOD with MakeUp Ultra Fast (which is cheaper per visual quality?).
3. Client thread occupancy (F3 "Show Thread Pools") with thread preset Minimal vs Balanced during flight — does P2's main thread still stutter at 4 DH threads?
4. Heap profile on P2 (8 GB free): peak JVM RSS with ZGC `-Xmx5G` at 128 LOD + world map opened after 2h exploration vs DH SQLite flush behavior.
5. Xaero's: minimap FPS cost with entity radar ON vs OFF in a mob-dense Alex's Caves area; cave-mode ON cost while caving.
6. Bandwidth/latency: server LOD streaming rate when teleporting (Create train) with `realTimeUpdateDistanceRadiusInChunks` at default vs reduced — any client hitching from sync-on-load bursts?
7. Does `enableFastSurfaceGenerator` on the server reduce time-to-filled-horizon for new areas enough to matter for clients joining fresh regions?
@@ -0,0 +1,485 @@
# Research: Entity & Animation Rendering Cost (client-side)
Scope: Minecraft 1.21.1 / NeoForge 21.1.251, Onion MC pack pins. Purely client-side
render/main-thread and heap cost of entity models, animations and dynamic lights.
Tags: **VERIFIED** = read in source/config code, **DOCUMENTED** = official
README/wiki/changelog, **COMMUNITY** = user reports/forums, **INFERENCE** = my reasoning.
---
## Summary
Entity/animation cost in this pack is dominated by three independent CPU-side pipelines
that **do not share configuration**: (1) EMF/CEM custom models driven by Fresh Animations
(`animationLODDistance`, `modelUpdateFrequency`), (2) GeckoLib 4.x models used by Mowzie's,
Fowlplay, dragons, etc. (no user-facing perf config in GeckoLib itself), and (3)
player-animation mods (Better Combat / playerAnimator / Emotecraft) layered on EMF. Only
pipeline (1) is throttled by the EMF knobs most guides mention; the biggest confirmed
per-mob cost multiplier is **Iris shadow-pass re-animation**, which EMF already skips by
default in this version. Dynamic lights (LambDynamicLights 4.8.x) are a separate risk
because each moving light source forces **chunk mesh rebuilds**, which is far more
expensive than animation math. Entity**Culling** (already in pack) and the vanilla
**Entity Distance** slider are the two levers that reduce the *number* of entities hitting
any of these pipelines, and are therefore the highest-leverage, lowest-risk changes.
---
## Findings
### A. EMF 3.x + ETF 7.x with Fresh Animations (+ All Extensions)
1. **EMF exposes exactly five performance-relevant settings.** From `EMFConfig.java`
(repo master = mod_version **3.3.11**; the pack's 3.3.9 is the same config surface):
`animationLODDistance` (int, default **20**, range 0–65), `retainDetailOnLowFps`
(default true), `retainDetailOnLargerMobs` (default true),
`animationFrameSkipDuringIrisShadowPass` (default true), and `modelUpdateFrequency`
(type `ETFConfig.UpdateFrequency`, default `Average`). `asmMaths` ("Compiled animation
math", default true) is the compiled-maths fast path. [VERIFIED]
https://github.com/Traben-0/Entity_Model_Features/blob/master/src/main/java/traben/entity_model_features/config/EMFConfig.java
2. **`animationLODDistance` is frame-skipping keyed to distance from the client player.**
Official tooltip: "Sets the distance at which animations will begin to skip frames,
lower the Level of Detail (LOD) … None = no frame skipping; 16 = will skip 1 frame for
every 16 blocks distance from player. Lower numbers mean more skipped frames and more
performance gain." Default is 20; 0 = the "None" entry on the slider. [DOCUMENTED —
mod lang file, same repo]
https://github.com/Traben-0/Entity_Model_Features/blob/master/src/main/resources/assets/entity_model_features/lang/en_us.json
The setting was introduced in the 1.3 changelog and the size-aware variant
(`retainDetailOnLargerMobs`) in the 2.0 changelog. [DOCUMENTED — CHANGELOG.MD]
https://github.com/Traben-0/Entity_Model_Features/blob/master/CHANGELOG.MD
3. **`retainDetailOnLowFps` and `retainDetailOnLargerMobs` deliberately soften the LOD
effect** (less skipping below 60 fps; less skipping on big mobs). Tooltips: "reduce the
Level of Detail (LOD) impact of the above setting according to the mobs size" / "…
according to your fps. Only applies when below 60 fps." Turning these **off** makes the
LOD slider do more work (more aggressive skipping). [DOCUMENTED — mod lang file]
https://github.com/Traben-0/Entity_Model_Features/blob/master/src/main/resources/assets/entity_model_features/lang/en_us.json
4. **`animationFrameSkipDuringIrisShadowPass` is the single most important EMF option and
is already ON.** Changelog 2.1.1: "added an optimization option that will skip
recalculating entity model animations during the iris shadow pass, on by default, and
**should always stay on**". With shaders, each animated model would otherwise be
animated a second time for the shadow pass. **Verify this is still `true` on all three
fleet machines** — it is the difference between 1× and 2× animation cost per frame.
[VERIFIED — config + DOCUMENTED — changelog]
https://github.com/Traben-0/Entity_Model_Features/blob/master/CHANGELOG.MD
5. **EMF 3.2+ already contains a large animation-speed fix.** Changelog 3.2: "significant
performance improvement for custom animations (**more than doubling frames** when many
animated entities are present)". The pack's EMF 3.3.9 includes this; do not "fix" FA
cost by downgrading. [DOCUMENTED]
https://github.com/Traben-0/Entity_Model_Features/blob/master/CHANGELOG.MD
6. **`modelUpdateFrequency` only controls *model refresh* (health/age/child-state
changes), not per-frame animation.** Tooltip: "Sets how often a mobs model will update
for changes like health & age. Never = never update, Slow = 3-5 seconds, Average =
about 1 second, Fast = less than a second, Instant = instant (possible lag with
hundred of mobs)". Default `Average`. Lowering it to `Slow`/`Never` is a cheap,
low-visual-impact win on busy farms/villager halls. [VERIFIED — config; DOCUMENTED —
lang file]
7. **Per-model opt-out exists** via `modelsNamesDisabled` (a `Set<String>` of
`<name>.jem`), exposed in the GUI as "Enable model" per .jem file. This lets you kill
the most expensive FA models (e.g. villager layers) without dropping FA globally.
[VERIFIED — config]
https://github.com/Traben-0/Entity_Model_Features/blob/master/src/main/java/traben/entity_model_features/config/EMFConfig.java
8. **`allowedCEM` gates which model namespaces EMF touches** (`All` / `Known only (mostly
vanilla/OptiFine)` / `Unknown only (mostly modded)` / `Off`). Setting it to
`Known only` stops EMF from building CEM models for modded mobs — useful if FA-derived
models on modded entities are the hot path. [VERIFIED — config]
9. **Measured Fresh-Animations cost is large and shader-amplified.** On the EMF issue
tracker, a user reported on 1.21.11 + Sodium/Iris: 50 cows on screen = 400+ fps (no
mods) → 110–130 fps with Fresh Animations → **30–40 fps with shaders + FA**; vanilla
animations on the same scene = 300–350 fps / 180–200 fps with shaders. The EMF author
replied the numbers are "more than I'd expect" but that FA "animations are just so
involved compared to vanilla" and you "aren't going to be easily pushing past 200 fps
with fresh animations on ever". A second reporter on 1.20.1 saw 165→40 fps with 30 cows
+ Beefier Bovine x FA + Complementary. The issue was closed as fixed in a later
release. [COMMUNITY — user reports on mod's own tracker; DOCUMENTED — maintainer reply]
https://github.com/Traben-0/Entity_Model_Features/issues/443
10. **Independent corroboration that FA + EMF/ETF drops FPS on villager-heavy scenes:**
easy-villagers #243 "Huge FPS drops with Fresh Animations and the mods needed for it
(EMF/ETF). Seems to be trying to run the animations even tho there's no animation
seen." [COMMUNITY]
https://github.com/henkelmax/easy-villagers/issues/243
11. **EMF recommends EntityCulling specifically for animation-heavy packs.** EMF README:
"Entity Culling … does wonders for reducing entity rendering lag, doing even more than
Sodium's included entity culling. This is very beneficial when using animation heavy
packs like Fresh Animations." [DOCUMENTED — official README]
https://github.com/Traben-0/Entity_Model_Features
12. **ETF: the cost-bearing knobs are the texture-update frequency and emissive/skin
toggles.** From `ETFConfig.java`: `textureUpdateFrequency_V2` (enum `UpdateFrequency`:
`Never` = -1, `Slow` = 80 t, `Average` = 20 t, `Fast` = 5 t, `Instant` = 1; **default
`Fast`**), `enableCustomTextures`, `enableEmissiveTextures`, `enableEmissiveBlockEntities`,
`emissiveRenderMode` (`DULL`/`BRIGHT`), `enableEnchantedTextures`, `enableArmorAndTrims`,
`enableBlinking`, `blinkFrequency` (150), `blinkLength` (1), `skinFeaturesEnabled`,
`skinTransparencyMode`, `use3DSkinLayerPatch`, `alwaysCheckVanillaEmissiveSuffix`,
`advanced_IncreaseCacheSizeModifier` (1.0), `enableFullBodyWardenTextures`,
per-entity override maps (`entityEmissiveOverrides`, `entityRandomOverrides`,
`entityEmissiveBrightOverrides`, `entityRenderLayerOverrides`, `entityLightOverrides`).
`UpdateFrequency` is a **tick delay** for re-evaluating random/variant properties, so
moving `Fast` (5 t, 4 Hz per entity) → `Average` (20 t, 1 Hz) cuts per-entity texture
bookkeeping 4×. [VERIFIED — source]
https://github.com/Traben-0/Entity_Texture_Features/blob/ETF-Main/src/main/java/traben/entity_texture_features/config/ETFConfig.java
13. **ETF rates misbehaving packs as a lag source.** README FAQ: "If you are experiencing
lag please check your most recent log file to see if any errors are being logged,
sometimes an incorrectly written properties file or missing textures may lag the
system." Relevant because FA All Extensions ships many `.properties` files — a single
mis-pathed texture can multiply cost. [DOCUMENTED]
https://github.com/Traben-0/Entity_Texture_Features/blob/ETF-Main/.github/README.md
14. **ETF emissive conflicts with Complementary shaders.** ETF FAQ: "Complimentary shaders
has its own in-built emissive textures that usually work fine but will conflict with
some resource packs. You can either disable Complimentary's emissives or ETF's
emissives to fix this." Relevant because the pack runs Complementary Reimagined r5.9.3.
[DOCUMENTED]
https://github.com/Traben-0/Entity_Texture_Features/blob/ETF-Main/.github/README.md
15. **Known pack-relevant interaction: ImmediatelyFast 1.6.14 vs FA All Extensions.**
ImmediatelyFast issue #180 (still open, last comment Dec 2025): ImmediatelyFast breaks
the custom models of Fresh Animations Extensions. The reporter's working set was
ETF + EMF + Embeddium(+extra) + FreshAnimations + FA+All_Extensions; adding
ImmediatelyFast broke entity rendering. Maintainer: "I added this as a low priority
issue to my todo list." The pack carries ImmediatelyFast 1.6.14 + FA All Extensions
1.8.1 — worth an A/B on entity visuals/cost. [COMMUNITY/DOCUMENTED — mod tracker]
https://github.com/RaphiMC/ImmediatelyFast/issues/180
16. **FA All Extensions is a bundle of official sub-packs** (details, creeper/spider
edits, emissive add-on, quivers, classic horses), i.e. it *adds* cost on top of base
FA rather than being neutral. [DOCUMENTED — mod description]
https://www.curseforge.com/minecraft/texture-packs/fresh-animations-extensions
### B. GeckoLib 4.x (Mowzie's, Fowlplay, dragons, Doggy Talents, etc.)
17. **GeckoLib is a library, and the pack's GeckoLib 4.9.3 has no end-user performance
config.** The official README documents no client perf options — its `wiki.geckolib.com`
is modder documentation (controllers, molang, render layers). Per-entity animation
cost is therefore set by each *consumer mod*, not by a config the pack can tune.
[VERIFIED — README has no config section]
https://github.com/bernie-g/geckolib
18. **Mowzie's Mobs genuinely requires GeckoLib 4.9.3 on 1.21.1 NeoForge** — reproduced in
a 1.21.1/NeoForge 21.1.248 + Mowzie's 1.8.2 + GeckoLib 4.9.3 report. So the pack's
GeckoLib load is not optional. [COMMUNITY/DOCUMENTED — mod repo issue]
https://github.com/BobMowzie/MowziesMobs-Public/issues/64
19. **Third-party GeckoLib optimizers exist and are directly relevant to 1.21.1 NeoForge.**
"GeckoLib Animation Optimizer" requires GeckoLib 4.9.0+ on 1.21.1 NeoForge; its
description claims configurable distance-based animation optimisation and camera
visibility culling enabled by default, block-occlusion culling and player optimisation
disabled by default, "fully client-side". "GeckolibBetterFPS" claims ~"25% faster
rendering of GeckoLib entities" and "reduces micro stutters when multiple GeckoLib
entities are present", but it is a MoePus mod historically targeted at 1.20.1 — check
1.21.1 build availability before proposing. [COMMUNITY — mod listings; treat the
percentages as vendor claims, not verified]
https://www.curseforge.com/minecraft/mc-mods/geckolib-animation-optimizer ,
https://modrinth.com/project/CZyWdBUo
20. **Important negative finding: EMF's animation LOD does NOT throttle GeckoLib.**
EMF only handles OptiFine CEM `.jem` models; GeckoLib renders through its own pipeline.
**INFERENCE**: the `animationLODDistance` lever benefits vanilla-mob/FA content only;
for GeckoLib-heavy scenes the only EMF-independent levers are EntityCulling, the
Entity Distance slider, and reducing the number of GeckoLib entities (spawn/mob count).
21. **Citadel (Alex's Mobs / Alex's Caves) is a different library from GeckoLib.** The
widely-reported Alex's Mobs perf complaints are about **server/world-gen and chunk
loading**, not client rendering — Citadel issue #156 is titled "Alex's Mobs X Citadel:
Slow Chunk loading", and r/feedthebeast discussion is about worldgen/chunky comparison.
A separate community "Alex's Mobs: Tweaks [Performance Optimization]" (AMT) addon
claims to "fix several expensive Alex's Mobs and Citadel hot paths". Treat client-side
Citadel cost as driven mainly by entity *count* and its own model complexity.
[COMMUNITY]
https://github.com/AlexModGuy/Citadel/issues/156 ,
https://www.curseforge.com/minecraft/mc-mods/amt
### C. 3D Skin Layers (1.11.3)
22. **3D Skin Layers already has a built-in distance LOD.** README: "The mod automatically
switches back to vanilla-style 2D rendering when players are more than **12 blocks
away**". The config option is "Level Of Detail Distance" — "The distance at which the
model will switch to a lower level of detail (vanilla 2d)". [DOCUMENTED — README;
VERIFIED — lang file]
https://github.com/tr7zw/3d-Skin-Layers ,
https://github.com/tr7zw/3d-Skin-Layers/blob/main/src/main/resources/assets/skinlayers3d/lang/en_us.json
23. **Per-limb and per-feature toggles let you buy cost back cheaply.** Lang keys observed:
"3D Hat", "3D Jacket", "3D Left/Right Sleeve", "3D Left/Right Pants", "3D Skulls",
"3D Skull Items", plus cost/quality knobs "Voxel Size", "Head Voxel Size", "Body Voxel
Height", "Torso Voxel Width", "Skull Voxel Size", "First Person Voxel Size", "Fast
Render" ("render the 3D models as fast as possible, this may cause some graphical
glitches with transparency"). [VERIFIED — lang file]
https://github.com/tr7zw/3d-Skin-Layers/blob/main/src/main/resources/assets/skinlayers3d/lang/en_us.json
24. **3D Skin Layers is explicitly integrated with EMF and with playerAnimator.**
Repo contains `EMFModelPartMixin.java`; README lists Player Animator as supported
("This means mods that use it like Better Combat and Emotecraft"). ETF in turn exposes
`use3DSkinLayerPatch` which is only shown when `ETF.SKIN_LAYERS_DETECTED`. So EMF/ETF,
3D Skin Layers and playerAnimator form one chained render path on players.
[VERIFIED — source files; DOCUMENTED — README]
https://github.com/tr7zw/3d-Skin-Layers/blob/main/src/main/java/dev/tr7zw/skinlayers/mixin/EMFModelPartMixin.java
25. **Compat/quality switches that trade correctness for cost:** "Compatibility Mode",
"Iris Compatibility Mode" ("fixes weird shadows/colors when using Iris shaders … Will
break the corner connections"), "Sodium Workaround". Only enable as needed. [VERIFIED —
lang file]
26. **Cost is bounded by player count, not mob count.** 3D Skin Layers only affects player
models/heads. On a 10-player server, worst case is 9 remote players within 12 blocks.
[INFERENCE]
### D. Player-animation stack: Better Combat + playerAnimator + Emotecraft
27. **Better Combat requires playerAnimator, and its animation code runs on *every*
player entity, not just yourself.** Its client package contains
`PlayerAttackAnimatable` and `CustomAnimationPlayer` under
`common/…/client/animation/`, i.e. it is a `Player`-model mixin path, and Better Combat
synchronises attacks so remote players' swings animate too (community reports of
multiplayer animation bugs confirm remote-player animation is rendered).
[VERIFIED — repo file tree; COMMUNITY — multiplayer reports]
https://github.com/ZsoltMolnarrr/BetterCombat/tree/1.21.1/common/src/main/java/net/bettercombat/client/animation
28. **Better Combat client-side cost knobs are few but real.** `ClientConfig.java` fields
include `isShowingWeaponTrails` (**default true** — the slash/trail particle system in
`client/particle/TrailParticles.java` and `SlashParticleUtil.java`),
`isSweepingParticleEnabled` (default false), `isShowingArmsInFirstPerson` (false),
`firstPersonAnimations` (TriStateAuto.AUTO), `legAnimationThreshold` (0). Turning off
weapon trails removes a per-swing particle + geometry cost without touching animation
math. [VERIFIED — source]
https://github.com/ZsoltMolnarrr/BetterCombat/blob/1.21.1/common/src/main/java/net/bettercombat/config/ClientConfig.java
29. **There is a first-class EMF ⇄ playerAnimator conflict, and a purpose-built fix.**
"Entity Player Compat" (MIT, client-side, published for **1.21.1 NeoForge/Fabric**,
requires EMF + PlayerAnimator) exists because EMF's custom player models and
playerAnimator both write player part transforms. It does per-part blending
("Automatically detects which specific body parts … are being animated by PlayerAnimator
and only pauses EMF animations for the specific parts currently in use"), a "virtual
follow" limb re-parenting system, and claims "high-performance tick-based caching …
does its work in a handful of hooks per frame." It explicitly lists Better Combat,
FA: Player Extension and GeckoLib/AzureLib armors as tested. [DOCUMENTED — mod page]
https://modrinth.com/mod/entity-player-compat
**INFERENCE**: without it, EMF will animate the player model *and* playerAnimator will
animate it again each frame — double work on every visible player, the exact class of
waste `animationFrameSkipDuringIrisShadowPass` was built to avoid. This is a strong
candidate lever for the 10-player use case.
30. **Emotecraft is built on playerAnimator and is client-side-required.** Emotecraft needs
the client half; the server half is optional, and features stay inactive without a
sync path. Emote animation is transient (only while an emote plays), so steady-state
cost is low; the risk is many simultaneous emotes near the player. [DOCUMENTED —
Emotecraft/playerAnimator listings]
https://minecrafthub.io/mods/emotecraft , https://minecrafthub.io/mods/playeranimator
31. **EMF has explicit Emotecraft integration** — changelog 3.0.7 added
`registerPauseCondition(Function<EMFEntity,Boolean> shouldPause)` to
`EMFAnimationApi` specifically so mods like EmoteCraft stop mixing in, and 3.3.4
"updated emote craft emote pausing support in EMF". So EMF+Emotecraft is a supported
path; the pack's EMF 3.3.9 is new enough. [DOCUMENTED — CHANGELOG.MD]
https://github.com/Traben-0/Entity_Model_Features/blob/master/CHANGELOG.MD
### E. LambDynamicLights 4.8.x on Sodium
32. **Dynamic lights cost is chunk rebuilds, not per-frame shading.** Official
"How does it work": "To apply the dynamic lighting we have to request the affected
chunks a rebuild to rebuild the lightmap, **which is the most critical part
performance-wise**. Rebuilding a chunk cost performances, that's why there's multiple
mode: FASTEST, FAST and FANCY. The fast modes will limit the update." The mod computes
dynamic light over a radius of 7.75 blocks, "which is still a lot" of touched chunks,
and hooks `WorldRenderer#setupTerrain` (or its Sodium equivalent) to schedule rebuilds.
[DOCUMENTED — official doc]
https://github.com/LambdAurora/LambDynamicLights/blob/1.21/HOW_DOES_IT_WORK.md
33. **Exact 1.21-branch config keys (this branch is `@version 4.8.0`, matching pack 4.8.11),
config file `config/lambdynlights.toml`:** `mode` (enum `off`/`fastest`/`fast`/`fancy`,
**default `fancy`**), `chunk_rebuild_scheduler` (`culling` **default** / `immediate`),
`adaptive_ticking.slow` (**5** chunks), `adaptive_ticking.slower` (**8** chunks),
`adaptive_ticking.background_sleep` (**true**), `light_sources.entities` (true),
`light_sources.self` (true), `light_sources.water_sensitive_check` (true),
`light_sources.beam` (true), `light_sources.guardian_laser` (true),
`light_sources.sonic_boom` (true), `light_sources.glowing_effect` (true),
`light_sources.creeper` (`simple`), `light_sources.tnt` (`off`), plus `debug.*`.
[VERIFIED — source]
https://github.com/LambdAurora/LambDynamicLights/blob/1.21/src/main/java/dev/lambdaurora/lambdynlights/DynamicLightsConfig.java
34. **The quality mode maps to a tick mode, not to radius.** `DynamicLightsMode` in the
1.21 branch: `FANCY → TickMode.REAL_TIME`, `FAST → TickMode.SLOW`,
`FASTEST → TickMode.SLOWER`, `OFF → REAL_TIME` (disabled). So `fastest`/`fast` throttle
**how often light updates are applied** (fewer chunk rebuilds/second), which is the
correct lever for stutter, and `fancy` gives real-time smoothness at full rebuild cost.
[VERIFIED — source]
https://github.com/LambdAurora/LambDynamicLights/blob/1.21/src/main/java/dev/lambdaurora/lambdynlights/DynamicLightsMode.java
35. **The 4.8.x line added two dedicated cost mitigations vs older guides.** `chunk_rebuild_scheduler`
(`culling` default vs `immediate`) and the adaptive-ticking distance pair
(`adaptive_ticking.slow` / `.slower`, in **chunks**) plus `background_sleep` under
`adaptive_ticking`. These are the 1.21-branch additions that the widely-copy-pasted
"Light Range / updateInterval / entitiesGlowing" advice (which cites keys that do not
exist in the 1.21 branch source) does not mention. [VERIFIED — source vs the third-party
guide] https://lambdynamiclights.com/configuring-lambdynamiclights-for-peak-performance/
36. **Per-category light-source toggles map to real feature costs.**
`light_sources.entities=false` removes all burning-mob/glow-squid/entity-carried-light
sources (the biggest moving-light population in a survival world);
`light_sources.self=false` removes the first-person player light;
`light_sources.beam`/`guardian_laser`/`sonic_boom`/`glowing_effect` cover beacon beams,
guardian beams, sonic booms and the Glowing effect. Disabling `entities` while keeping
`self` is the usual "I still want my torch to glow, but not 200 burning zombies"
compromise. [VERIFIED — source]
https://github.com/LambdAurora/LambDynamicLights/blob/1.21/src/main/java/dev/lambdaurora/lambdynlights/DynamicLightsConfig.java
37. **Sodium interop is explicit, not accidental.** `HOW_DOES_IT_WORK.md`: "we inject at
`WorldRenderer#setupTerrain` (`WorldRenderer#render` at `WorldRenderer#setupTerrain`
invoke **if Sodium is present**)". So LDD 4.8.x is Sodium-aware by design; the classic
"dynamic lights cause chunk rebuild stutter on Sodium" claim needs to be re-measured
on this version rather than assumed. [DOCUMENTED]
https://github.com/LambdAurora/LambDynamicLights/blob/1.21/HOW_DOES_IT_WORK.md
### F. EntityCulling (1.11.2) interplay
38. **Independently useful alongside Sodium's own culling.** README: "I have 'Use Entity
Culling' enabled in Sodium — does this still help? Yes! … Sodium performs basic
visibility checks based on loaded chunks, this mod goes further. It analyzes the
actual line-of-sight visibility, skipping entities that are within visible chunks but
not actually visible to the player." [DOCUMENTED — official README]
https://github.com/tr7zw/EntityCulling
39. **It has a client-side entity *tick* culling feature, not just render culling.**
`Config.java` (config version 9): `tickCulling` (**true**), with a separate
`tickCullingWhitelist`. This reduces main-thread entity tick cost — relevant to P2's
main-thread bottleneck. [VERIFIED — source]
https://github.com/tr7zw/EntityCulling/blob/main/EntityCulling-Versionless/src/main/java/dev/tr7zw/entityculling/versionless/Config.java
40. **Exact config keys/defaults** (`config/entityculling.json`): `tracingDistance` **128**
(path-trace range), `sleepDelay` **10**, `hitboxLimit` **50**, `captureRate` **5**,
`tickCulling` **true**, `skipEntityCulling` false, `skipBlockEntityCulling` false,
`blockEntityFrustumCulling` **true**, `forceDisplayCulling` false, `solidLeaves`
**false** ("treat leaves as solid blocks … help to increase the performance in
forested areas" — directly relevant with Better Leaves 9.6 in pack), `safeMode` true,
`renderNametagsThroughWalls` true, plus `entityWhitelist` / `blockEntityWhitelist` /
`tickCullingWhitelist`. [VERIFIED — source; DOCUMENTED — README for `solidLeaves`]
41. **Known interaction: client-side/mod "display" entities and far-bounds block entities
need whitelisting** — "Client-side entities, commonly used by magic mods for
animations, may not behave as expected. Whitelist the relevant entities via the config
screen for tick culling and/or entity culling … You'll also need to whitelist block
entities that render well beyond their normal bounds. Examples include the vanilla
beacon, pulleys from Create…". **INFERENCE**: relevant to this pack's Create/Flywheel
contraptions and Veil-based mods; verify no visual regressions before recommending any
change. [DOCUMENTED — README]
42. **Mild CPU trade-off on very weak CPUs.** README: "Consider [disabling] when playing on
a really old computer … When the CPU is already maxed out, there is no spare CPU time
to run the visibility calculations." None of the fleet's CPUs are in that class, but
the Steam Deck's shared power budget makes this worth watching. [DOCUMENTED — README]
43. **Author-provided test reference:** the README's comparison screenshot was captured
with "Sodium, Iris and ImmediatelyFast … alongside EntityCulling" — i.e. exactly the
pack's stack. [DOCUMENTED — README]
44. **Also provide a F3-adjacent debug toggle.** "In the controls menu, you can bind a
debug key to toggle the mod on and off on the fly" — this is the cleanest in-situ
benchmark control for entity cost. [DOCUMENTED — README]
### G. Entity-count drivers and the Entity Distance slider
45. **Clumps is a server-side aggregation mod, so its client benefit is indirect but real.**
"Clumps groups XP orbs together into a single entity to reduce lag when there are many
in a small area." On 1.17+ it is a **server** mod: "For a multiplayer world on 1.17 or
newer, the jar goes on the server rather than on each player's client." Fewer orb
entities on the server → fewer orb entities synchronised → less client render/tick and
(with LDD) fewer dynamic-light sources. Verify it is installed server-side.
[DOCUMENTED — mod listings]
https://modrinth.com/mod/clumps/versions , https://minecrafthub.io/mods/clumps
46. **The vanilla "Entity Distance" video setting is the bluntest client lever.** The
Minecraft Wiki's simulation-distance article states the client does not render entities
based only on Render Distance but on "both 'Render distance' and 'Entity distance'
video settings"; it is a percentage slider scaling entity render distance.
[DOCUMENTED — Minecraft Wiki]
https://minecraft.wiki/w/Simulation_distance
*(A community write-up explicitly frames it: "This setting directly impacts client-side
performance … Setting the rendering distance to its maximum allows all entities to be
visually displayed at the full extent of their tracking distance.")* [COMMUNITY]
https://www.curseforge.com/minecraft/mc-mods/entity-distance-1-12-2
47. **Item entities are the other unbounded count driver.** No mod in the pack aggregates or
culls dropped items; a farm/hopper overflow or an explosion drops hundreds of
`ItemEntity`s, each costing an `ItemRenderer` submission and (with Better Leaves +
FA) potentially full model evaluation for held-block mobs. [INFERENCE]
48. **EMF/ETF+FA cost scales with *visible* model count, which EntityCulling and Entity
Distance both reduce.** Since `animationLODDistance` skips frames as a function of
distance from the player, `Entity Distance` and the LOD slider are multiplicative:
shrinking entity distance removes far models entirely, and the LOD slider makes the
remaining middle-distance models cheaper. [INFERENCE]
---
## Sources
Kept:
- EMF `EMFConfig.java` (master, v3.3.11) — authoritative list of every EMF config key and
defaults. https://github.com/Traben-0/Entity_Model_Features/blob/master/src/main/java/traben/entity_model_features/config/EMFConfig.java
- EMF `lang/en_us.json` — exact tooltip wording for `lod`, `low_fps_lod`, `large_mob_lod`,
`update`, `asmmaths`. https://github.com/Traben-0/Entity_Model_Features/blob/master/src/main/resources/assets/entity_model_features/lang/en_us.json
- EMF `CHANGELOG.MD` — 3.2 "doubling frames", 2.1.1 Iris shadow skip, 1.3/2.0 LOD
history, EmoteCraft integration. https://github.com/Traben-0/Entity_Model_Features/blob/master/CHANGELOG.MD
- EMF README — FA confirmed supported; EntityCulling recommendation.
https://github.com/Traben-0/Entity_Model_Features
- EMF issue #443 — quantified FA/shader cost, maintainer response.
https://github.com/Traben-0/Entity_Model_Features/issues/443
- ETF `ETFConfig.java` — all ETF keys incl. `textureUpdateFrequency_V2` enum ticks.
https://github.com/Traben-0/Entity_Texture_Features/blob/ETF-Main/src/main/java/traben/entity_texture_features/config/ETFConfig.java
- ETF README — emissive/Complementary conflict, "lagging" FAQ.
https://github.com/Traben-0/Entity_Texture_Features/blob/ETF-Main/.github/README.md
- LambDynamicLights `HOW_DOES_IT_WORK.md`, `DynamicLightsConfig.java`,
`DynamicLightsMode.java` (1.21 branch = v4.8.0, matching pack 4.8.11) — chunk-rebuild
cost model and exact keys/enums.
https://github.com/LambdAurora/LambDynamicLights/blob/1.21/HOW_DOES_IT_WORK.md
- EntityCulling `Config.java` + README — exact keys/defaults, tick culling, `solidLeaves`,
whitelist caveats. https://github.com/tr7zw/EntityCulling/blob/main/EntityCulling-Versionless/src/main/java/dev/tr7zw/entityculling/versionless/Config.java
- 3D Skin Layers README + `lang/en_us.json` + repo tree — 12-block LOD default, per-limb
toggles, EMF/playerAnimator integration.
https://github.com/tr7zw/3d-Skin-Layers/blob/main/src/main/resources/assets/skinlayers3d/lang/en_us.json
- Better Combat `ClientConfig.java` + client package tree — weapon trails default, animation
is per-Player.
https://github.com/ZsoltMolnarrr/BetterCombat/blob/1.21.1/common/src/main/java/net/bettercombat/config/ClientConfig.java
- Entity Player Compat mod page — EMF⇄playerAnimator conflict and its fix, 1.21.1 NeoForge.
https://modrinth.com/mod/entity-player-compat
- GeckoLib README — confirms absence of user perf config.
https://github.com/bernie-g/geckolib
- Minecraft Wiki (simulation distance) — Entity Distance affects client entity rendering.
https://minecraft.wiki/w/Simulation_distance
Dropped:
- `bravith.com`, `mythiq.net`, `skinmc.net`, `9minecraft`, `modbay`, `minecrafthub`,
`modrinth.com/mod/geckolib-animation-optimizer` (404) — SEO/aggregator pages; superseded
by the GitHub source I read directly. Used only where no primary source exists (GeckoLib
optimizer, Clumps, Emotecraft) and flagged as vendor/community claims.
- `lambdynamiclights.com/configuring-…` — cites config keys (`updateInterval`,
`lightSourceRenderRange`, `entitiesGlowing`) that **do not exist** in the 1.21-branch
source; treated as unreliable, kept only as an example of bad advice.
- Reddit threads on FA cost — replaced by the two mod-tracker issues which are primary and
quantified.
- ImmediatelyFast issue #180 — kept as a *caveat* only, not as an entity-cost source.
---
## Top levers (ranked)
| # | Lever | Expected impact | Fleet machine | Risk | Confidence |
|---|---|---|---|---|---|
| 1 | Confirm `animationFrameSkipDuringIrisShadowPass=true` in EMF on all 3 machines | **High** when shaders on (halves animation work) | P0, P2 (also P1) | None (default; wrong value is the bug) | High — VERIFIED default + maintainer "should always stay on" |
| 2 | Install **Entity Player Compat** (EMF+playerAnimator bridge) for the Better Combat / Emotecraft / FA-Player path | **High** on player-dense scenes; removes double animation of every visible player | P0, P2 | Med — third-party mod, unofficial fork; test for arm/armor desync | Med — DOCUMENTED mod page; mechanism plausible but percentage unverified |
| 3 | Lower EMF `animationLODDistance` 20 → 8–12 | **Med–High** in mob/animal areas | P0, P2 (CPU-bound); P1 mild | Low — visible low-framerate animations up close | High — VERIFIED semantics; magnitude needs A/B |
| 4 | Iris shader choice: shaders + FA is the dominant cost (issue #443: 110–130 → 30–40 fps) | **High** | P0 (RDNA2 iGPU) most, P1 (VRAM) too | Med — visual (loss of shaders on Deck) | High — consistent across two independent reports |
| 5 | LambDynamicLights `mode` `fancy` → `fast`/`fastest` on the CPU-bound boxes | **Med–High** where fires/burning mobs/held torches are common | P2 (main-thread bound), P0 | Low — slightly less responsive light | High — VERIFIED tick-mode mapping |
| 6 | LambDynamicLights `light_sources.entities=false` (keep `light_sources.self=true`) | **Med** in busy survival areas | P2, P0 | Low–Med (losing burning-mob glow) | High — VERIFIED key exists |
| 7 | EMF `modelUpdateFrequency` `average` → `slow`/`never` | **Med** in villager halls/farms | P0, P2 | Low | Med–High — VERIFIED key; magnitude unmeasured |
| 8 | Vanilla **Entity Distance** slider 100% → 75–80% | **Med** everywhere, scales all pipelines | All three, esp. P0 | Low | Med — documented mechanism, pack-specific magnitude unknown |
| 9 | ETF `textureUpdateFrequency_V2` `fast`(5t) → `average`(20t) | **Med** with random/variant packs | P0, P2 | Low — slower variant swaps | Med–High — VERIFIED ticks |
| 10 | GeckoLib Animation Optimizer (needs GeckoLib ≥4.9.0) | **Med** if GeckoLib mobs are common | P0, P2 | Med–High — third-party, can break animations | Low — vendor claim only, no independent test |
| 11 | Better Combat `isShowingWeaponTrails=false` | **Low–Med** | P2, P0 | Low (visual) | Med — VERIFIED key/default; magnitude small |
| 12 | Reduce 3D Skin Layers "Level Of Detail Distance" below 12 / disable 3D Skulls | **Low** (≤9 players, tightly bounded) | P1 VRAM-mostly | Low | Low–Med |
| 13 | EntityCulling `solidLeaves=true` in forested bases (Better Leaves present) | **Low–Med** in forests | All | Med — leaves stop occluding incorrectly / leaves may hide entities visually | Med — DOCUMENTED option, no pack-specific measurement |
| 14 | Verify Clumps is deployed **server-side** | **Low–Med** on XP-heavy scenes | All (indirect) | Low | Med — DOCUMENTED placement requirement |
---
## Open questions to verify by benchmark
1. **Is `animationFrameSkipDuringIrisShadowPass` actually `true` in the shipped `emf.json`/config?**
Cheapest possible check; if a pack preset or copy flipped it, every shader scene is
paying 2× animation.
2. **What is the real fps delta from EMF `animationLODDistance` 20 vs 8 vs 0-on vs LOD-off**
on a fixed FA mob cluster (e.g. 30–50 animals) on P0 and P2? Issue #443 gives the
magnitude for the FA/shaders *combination* but not for the LOD slider alone.
3. **Does Entity Player Compat measurably help on the 10-player server**, and does it break
FA: Player Extension or armor alignment? Requires ≥2 players within view, attacking.
4. **LambDynamicLights `fancy` vs `fast` chunk-rebuild count** — use the mod's own
`debug.display_dynamic_lighting_chunk_rebuild` and `debug.active_dynamic_lighting_cells`
options (both exist as keys) to count rebuilds per second, then correlate with 1% lows.
Also test whether `chunk_rebuild_scheduler=culling` is genuinely better than `immediate`
on Sodium 0.8.13.
5. **Do the LambDynamicLights `adaptive_ticking.slow`/`.slower` distances (5 / 8 chunks)
default interact badly with shaders?** Not covered by the mod docs beyond the tick-mode
description.
6. **GeckoLib entity share:** measure with a profiler how much main-thread time GeckoLib
models occupy on P2 (Mowzie's boss fights, Fowlplay birds, dragons). If it is <2 %,
GeckoLib optimizers are not worth the risk.
7. **ImmediatelyFast 1.6.14 vs FA All Extensions 1.8.1 (issue #180)** — does the pack
exhibit it? A/B entity visuals with ImmediatelyFast disabled.
8. **ETF emissive vs Complementary Reimagined built-in emissives** — which to disable, and
does disabling one measurably reduce frame time or just fix z-fighting?
9. **`solidLeaves` under Better Leaves 9.6** — measure in forested areas and inspect for
entities disappearing behind custom leaves.
10. **Entity Distance slider calibration** — find the % where mobs stop being visibly
affected at the pack's server view-distance 8 with Distant Horizons mandatory.
11. **Heap/GC effect on P2 (only ~8 GB free):** quantify the RAM cost of FA + FA All
Extensions + Best Leaves textures and EMF's model cache; test whether ETF
`advanced_IncreaseCacheSizeModifier` changes GC pause frequency (it trades RAM for CPU,
likely the wrong direction on P2).
@@ -0,0 +1,194 @@
# Research: Effects / audio / HUD & GUI / "flavour" client mods — frame time, tick time, RAM/VRAM, startup cost (MC 1.21.1 NeoForge, Onion MC)
## Summary
Most of this category is cheap at idle: the mods with real, recurring cost are **Sound Physics Remastered** (CPU raytracing per sound, + a cloned-chunk cache for RAM), **WATUT** (network + CPU rendering other players' GUIs, with a *known dynamic-GUI breakage when Twilight Forest is installed*), **Twilight Forest's client effects** (Aurora shader, cloud precipitation — both have config toggles), **Alex's Caves' biome fog/lighting overrides** (documented "may conflict with shaders"; community key `biome_ambient_light_coloring` to disable), **Perception's chromatic-aberration post pass** (fires on explosions/warden sounds) and **Immersion Paintings/Exposure** (texture/VRAM + capture-time hitches). Everything else (tooltips, plaques, titles, Ping Wheel, Sooty Chimneys, Inventory Particles, Controlify) is event-driven HUD/particle work that only costs when visible — keep, don't tune. Fusion + Athena both being loaded means **two CTM/model engines** initialized at startup; at least one is a candidate for removal depending on which resourcepacks the pack actually ships.
## Findings
### 1. Sound Physics Remastered 1.5.1 — the biggest CPU lever in this category (VERIFIED, config source)
All keys below read from `SoundPhysicsConfig.java` on the repo's `1.21.1` branch (same file/keys as the pinned 1.5.1 line):
[SoundPhysicsConfig.java (branch 1.21.1)](https://github.com/henkelmax/sound-physics-remastered/blob/1.21.1/common/src/main/java/com/sonicether/soundphysics/config/SoundPhysicsConfig.java)
| Key (file `sound-physics-remastered.toml`) | Default | Note |
|---|---|---|
| `environment_evaluation_ray_count` | 32 (range 8–64) | Config comment: *"Decrease this value if you experience lag spikes when sounds play"* |
| `environment_evaluation_ray_bounces` | 4 (range 2–64) | Same comment — reverb bounces per sound |
| `max_occlusion_rays` | 16 (range 1–128) | occlusion ray count per sound |
| `strict_occlusion` | false | if true, occlusion uses **1 path instead of 9** — big CPU cut, slight accuracy loss |
| `sound_direction_evaluation` | true | reflection-based stereo redirection |
| `evaluate_ambient_sounds` | false | cave/nether/underwater ambients are NOT processed by default (good for the AmbientSounds stack) |
| `update_moving_sounds` / `sound_update_interval` | false / 5 | re-evaluation of discs/long sounds; interval comment: "Lower values ... more lag" |
| `max_sound_processing_distance` | 512 | sounds beyond this are not processed |
| `unsafe_level_access` | false | if true, disables the **level clone & cache** (falls back to main-thread access — slower but no clone memory) |
| `level_clone_range` / `level_clone_max_retain_ticks` / `level_clone_max_retain_block_distance` | 4 / 20 / 16 | size and lifetime of the cloned-chunk cache (RAM lever) |
- There is also a **per-sound rate config** (a generated properties file listing every registered sound event). Verified from `SoundRateConfig.java`: values are *"Max sounds per tick. Set to '-1' for unlimited, '0' to disable sound physics for that sound, >=1 to cap"* with the stated purpose *"can help prevent lag when some mod or mechanism produces hundreds of sounds per tick"*; rain, rain-above, thunder and goat horns are disabled (`0`) by default. [SoundRateConfig.java](https://github.com/henkelmax/sound-physics-remastered/blob/1.21.1/common/src/main/java/com/sonicether/soundphysics/config/SoundRateConfig.java) — this is the right lever for noisy Create/mob-farm sounds.
- Cost model: per-sound CPU raytracing (threaded, `TaskProfiler`/`performance_logging` exists to measure it — VERIFIED key `performance_logging`). Cost scales with number of simultaneous sounds, so a Create factory floor or mob farm is the worst case. [SoundPhysics.java / profiling package](https://github.com/henkelmax/sound-physics-remastered/tree/1.21.1/common/src/main/java/com/sonicether/soundphysics)
- Fork README documents a 10× sound-processing improvement over original Sound Physics (context for "it's already optimized"). [README](https://github.com/henkelmax/sound-physics-remastered#changes-to-the-original-mod)
- **Recommendation: keep + tune.** Lower `environment_evaluation_ray_count` → 16 and `ray_bounces` → 2–3, enable `strict_occlusion`, and cap the noisiest modded sounds in the sound-rates file. Helps P2 (CPU) and P0 (4C Zen2) most. Low risk, easily reversible.
### 2. AmbientSounds 6.3.8 (CreativeMD) — audio streaming & mixing, client-side (DOCUMENTED)
- Client-side mod, requires CreativeCore; config via `/cmdclientconfig`; `/ambient-debug` shows which sounds are playing. [Modrinth](https://modrinth.com/mod/ambientsounds)
- Changelog shows features are per-biome/dimension "engines" with spawn conditions (e.g., "silent dimension configuration", min-count fixes for grass/ice/rock/sand features). [CurseForge changelog](https://www.curseforge.com/minecraft/mc-mods/ambientsounds/files/6400880)
- Cost: memory for its sound library/streamed buffers + audio mixing; essentially no render cost. Community reports of lag are rare/anecdotal (COMMUNITY).
- **Recommendation: keep.** If RAM-tight on P2, reducing played sound density via its config is the lever (no specific key verified — do not guess; check `/cmdclientconfig` in-game).
### 3. Subtle Effects 1.14.3 — particle floods, but ships its own mitigations (DOCUMENTED)
- "All features can be disabled in the config menu"; documented config sections: `Entities/Dust Clouds` (dust clouds) and `Items/Item Rarity` → `Particle Display Type` = `OFF` (item rarity dots). [Modrinth FAQ](https://modrinth.com/mod/subtle-effects) / [Wiki Home](https://github.com/MincraftEinstein/SubtleEffects/wiki)
- Built-in **particle culling and particle render distance** (Modrinth description) — the mod already culls its own particles. [Modrinth](https://modrinth.com/mod/subtle-effects)
- Feature list (fireflies, pollen, sculk dust, slimes/slime trails, spark sources on torches/campfires/furnaces, replacing vanilla smoke/steam) is large but each is individually toggleable: [Wiki: Particles](https://github.com/MincraftEinstein/SubtleEffects/wiki/Particles)
- Known incompatibility to watch: fires off `Particles` video setting (features silently stop if particle setting = minimal). Coexists with other particle mods per FAQ. [Modrinth FAQ](https://modrinth.com/mod/subtle-effects)
- **Recommendation: keep + tune on P0/P1.** Dust clouds + fireflies + item rarity dots are the highest-volume effects; turn off per section if 800p Deck GPU or fill-rate-bound P1 dips. Low risk.
### 4. Perception 0.2.1 (+ OctoLib) — trails + screen shake + a real post-effect (VERIFIED config; issues)
- Source (branch 1.21.1) has three modules: `trail`, `shake`, `chromatic_aberration`. Chromatic aberration is a **fullscreen post-effect triggered by loud sounds** (explosions, warden, dragon, wither...) with per-sound `duration`/`strength`; trails are a per-entity map (`entityTrails`, `particleTrails`) that includes `minecraft:experience_orb`, arrows, allay, vex, phantom etc. Config keys verified: [ChromaticAberrationConfig.java](https://github.com/Octo-Studios/perception/blob/1.21.1/common/src/main/java/it/hurts/octostudios/perception/common/modules/chromatic_aberration/config/ChromaticAberrationConfig.java), [TrailConfig.java](https://github.com/Octo-Studios/perception/blob/1.21.1/common/src/main/java/it/hurts/octostudios/perception/common/modules/trail/config/TrailConfig.java), [module tree](https://github.com/Octo-Studios/perception/tree/1.21.1)
- Known bug (fixed line): 0.1.0.2 changelog — *"Fixed FPS leak with arrows stuck in player model"*, *"Fixed render conditions of particle trails"*. Pinned 0.2.1 postdates this. [Modrinth version notes](https://modrinth.com/mod/perception/version/9QZB1Ivx)
- Cost: trails = extra particles per moving entity (XP orbs in a Create mob/XP farm are the realistic burst case); CA = one post pass during effect duration; shake = cheap matrix offset.
- **Recommendation: keep + trim `entityTrails`** (at minimum `experience_orb`) via config map if farms are common. Helps P0/P2. Low risk.
### 5. Inventory Particles — GUI-only particle decor (DOCUMENTED, cost INFERENCE)
- Client-side, data-driven particles attached to items in inventory screens (physics fully configurable via datapack). [CurseForge](https://www.curseforge.com/minecraft/mc-mods/inventory-particles) / [Modrinth](https://modrinth.com/project/XYnKrsxH)
- Cost only while a container/inventory screen is open; scales with how many items have particle definitions. INFERENCE: negligible for frame time; slight VRAM for particle textures.
- **Recommendation: keep.**
### 6. Sooty Chimneys — per-chimney smoke particles (DOCUMENTED)
- Adds chimneys that emit smoke particles; soot accumulates over time. By mortuusars. [Modrinth](https://modrinth.com/mod/sooty-chimneys)
- Cost: only where players place chimneys; smoke is the heaviest vanilla-style particle family but counts here are tiny. INFERENCE: negligible.
- **Recommendation: keep.**
### 7. WATUT 1.2.7 — real network + CPU cost; known breakage with Twilight Forest (VERIFIED config + issue tracker)
- Config keys verified from source (`ConfigClient.java`, file `watut-client`): `sendMouseInfo`, `sendTypingSpeed`, `sendActiveGui`, `sendIdleState`, `showPlayerAnimations`, `showPlayerAnimation_Typing/_Idle/_Gui`, `showPlayerActiveNonChatGui`, `showPlayerActiveChatGui`, `particleSizeScale`, **`tickReceiveAndRenderRateOfGUIUpdates` (default 10 = GUI image of other players refreshed 2×/s; you can only increase it)**, `dontSendDetailedGUIInfo`, `dontSendItemInfo`. [ConfigClient.java](https://github.com/Corosauce/WATUT/blob/1.21.0/src/main/java/com/corosus/watut/config/ConfigClient.java)
- v1.2.7 commit: *"Workaround flickering issue ... set default to not constantly update GUI"* — the default GUI-refresh behavior was already identified as costly. [commit 71342de](https://github.com/Corosauce/WATUT/commit/71342deaf617baa997fbfc6803bad1df423b4836)
- **Known bug, directly relevant:** issue #106 — WATUT dynamic GUIs *fail to render* in a 1.21.1 large modpack, with **Twilight Forest 4.8.3281** among the triggering mods (also Cold Sweat, Dungeons Delight, Vista). Our pack has TF 4.8.3345. [Issue #106](https://github.com/Corosauce/WATUT/issues/106)
- Cost: per-player NBT packets of screen state (client↔server) [network package](https://github.com/Corosauce/WATUT/tree/1.21.0/src/main/java/com/corosus/watut/network), then the client re-renders other players' GUIs via a custom particle/screen renderer ([ScreenParticleRenderer](https://github.com/Corosauce/WATUT/blob/1.21.0/src/main/java/com/corosus/watut/client/screen/ScreenParticleRenderer.java), [PlayerStatusManagerClient](https://github.com/Corosauce/WATUT/blob/1.21.0/src/main/java/com/corosus/watut/PlayerStatusManagerClient.java)). With ~10 friends, several AFK-in-inventory, this is continuous but small; the arm/head animations are model-side (cheap).
- **Recommendation: keep (it's a social mod for a friends' server) + tune.** If the TF GUI-rendering bug bites (visual, not perf), the fallback is `dontSendDetailedGUIInfo=true`. Helps P2 (CPU) and server bandwidth. Low risk.
### 8. Traveler's Titles — overlay text on biome/dimension entry (DOCUMENTED)
- Fully client-side; customizable text size/color/duration; biome & dimension blacklists; optional custom sounds per biome/dimension entry. [Modrinth](https://modrinth.com/mod/travelers-titles)
- Cost: transient overlay + a sound on biome change. INFERENCE: negligible.
- **Recommendation: keep.**
### 9. Legendary Tooltips 1.5.5 / Advancement Plaques / Held Item Tooltips / Items Displayed — tooltip & toast dressing (DOCUMENTED, cost INFERENCE)
- Legendary Tooltips: client-side, up to 16 custom borders selected by item/mod/tag/rarity/name-color/NBT; adds shadows, centered names, 3D item previews in tooltips; requires Iceberg (+Prism). [Modrinth](https://modrinth.com/mod/legendary-tooltips), [config wiki](https://github.com/AHilyard/LegendaryTooltips/wiki/Configuration-Instructions)
- Advancement Plaques: client-side (Forge/NeoForge variant needs server only for its custom sounds, which can be disabled in config); plaque position/type configurable. [Modrinth](https://modrinth.com/mod/advancement-plaques)
- Cost: rendering cost only while a tooltip/plaque is visible; the "3D item preview" tooltip option is the only notably heavier feature (renders an item model inside the tooltip). INFERENCE: negligible in normal play.
- **Recommendation: keep.** If tooltip-heavy screens (JEI!) show hitches on P2, disable 3D previews in Legendary Tooltips config first.
### 10. Emojiful 5.2.4 — font/atlas hooks, worst history of this group (DOCUMENTED issues)
- Hooks font rendering to inject emoji glyphs (incl. animated); supports datapack emoji; client+server. [Modrinth](https://modrinth.com/mod/emojiful)
- Known bugs: game **freeze when an emoji renders** (Cottage Witch pack, older version) [Issue #98](https://github.com/InnovativeOnlineIndustries/Emojiful/issues/98); **breaks chat text output** (e.g., `/spark tps` garbled) [FTB #3886](https://github.com/FTBTeam/FTB-Modpack-Issues/issues/3886); unreadable Patchouli text [FTB #5495](https://github.com/FTBTeam/FTB-Modpack-Issues/issues/5495); rendering breaks with "When Was That Again" [Issue #15](https://github.com/InnovativeOnlineIndustries/Emojiful/issues/15).
- Cost: animated GIF emojis add texture atlas memory/upload churn (VRAM) — INFERENCE; frame cost otherwise only when emoji render in chat/signs. INFERENCE.
- **Recommendation: candidate for removal** (flavour mod with freeze/chat-corruption history, near-zero gameplay value); at minimum pin the 1.21.1 line and disable animated emoji packs. Small startup + VRAM win for P1/P2. Low risk if the group agrees.
### 11. Exposure 1.9.18 — camera rendering is a real, but occasional, hitch (VERIFIED changelog)
- Pinned 1.9.18 still contains the "preload" that exists *"to reduce the lag spike when camera is first used after launch"*; 1.9.19 removed it. **Recommend updating to ≥1.9.19** to delete that startup/first-use spike. [CHANGELOG.md (1.21.1)](https://github.com/mortuusars/Exposure/blob/1.21.1/CHANGELOG.md)
- With Iris installed, photo capture uses the **direct capture** path ("due to technical limitation"), i.e. the world is re-rendered through the viewfinder; background capture (1.8.0+) is skipped. DH+Iris also forces direct capture (1.9.7). So taking a photo = one extra full render pass → visible hitch on P0/P1. [CHANGELOG.md](https://github.com/mortuusars/Exposure/blob/1.21.1/CHANGELOG.md)
- Veil interplay: 1.9.4 removed `effective` from the background-capture allowlist and **added `veil` to the mods that force direct capture** because *"it's the one that causes issues"* — our pack runs Veil (via Lodestone/irisveil stack). [CHANGELOG.md](https://github.com/mortuusars/Exposure/blob/1.21.1/CHANGELOG.md)
- Photos in frames = image textures (small, mipmaped since 1.8.0). Photograph-in-item-frame rendering is off by default.
- **Recommendation: keep, bump to 1.9.19+**; cost is opt-in (only while photographing). Low risk.
### 12. Immersive Paintings — LoD + streaming by design; config exists (VERIFIED config wiki)
- Officially: *"Using smart level of details, caching and lazy streaming of data the performance impact is not noticeable."* [Modrinth](https://modrinth.com/mod/immersive-paintings)
- Config (documented): `thumbnailSize=128`, `lodResolutionMinimum=32`, LoD thresholds `halfResolutionThreshold=2.0`, `quarterResolutionThreshold=4.0`, `eighthResolutionThreshold=8.0`, bandwidth `maxPacketsPerSecond=20`/`packetSize=64KB`, upload caps `maxUserImageWidth/Height=4096`, `maxUserImages=1000`, `testIfSpaceEmpty=false`, `showOtherPlayersPaintings=true`. [Config wiki](https://github.com/Luke100000/ImmersivePaintings/wiki/Config)
- Cost: VRAM scales with number of large custom paintings actually loaded in view (LoD halves resolution progressively); disk cache for uploads. For P1 (6GB VRAM) lower `maxUserImages`/`thumbnailSize` if friends upload big art. INFERENCE on exact VRAM numbers.
- **Recommendation: keep + cap uploads.** Low risk.
### 13. Controlify 3.0.1 — input mod; historical FPS bug fixed upstream (DOCUMENTED)
- 2.0.3 changelog: *"Drastically improved the performance of the on-screen keyboard — There is zero performance impact anymore. It used to decrease FPS by 8x (lol)"*; also "Fix extreme FPS drops when using the on-screen keyboard" (2.0.0-beta.14). [CurseForge 2.0.3](https://www.curseforge.com/minecraft/mc-mods/controlify/files/6347289) / [Modrinth](https://modrinth.com/mod/controlify/version/1HeJe83k)
- Actively supported on 1.21.1 NeoForge. [CurseForge](https://www.curseforge.com/minecraft/mc-mods/controlify)
- **Recommendation: keep** (Deck/controller users). No open perf issue found for 3.x (INFERENCE).
### 14. Ping Wheel — tiny HUD/network mod (DOCUMENTED)
- Client+server ping markers; config via `/pingwheel config`; optional item icons on markers. [Modrinth](https://modrinth.com/mod/ping-wheel)
- Cost: a few billboard quads + small packets. INFERENCE: negligible.
- **Recommendation: keep.**
### 15. Alex's Caves 2.0.10 — biome fog/lighting overrides vs shaders; known lag reports (COMMUNITY + issue tracker)
- Known heavy cases: *"immense lag when inside toxic caves"* (65–80 → ~40 FPS) [Issue #760](https://github.com/AlexModGuy/AlexsCaves/issues/760); FPS drops looking at raycats/irritated mobs [Issue #616](https://github.com/AlexModGuy/AlexsCaves/issues/616).
- The community-maintained **"Iris Caves"** patch mod exists specifically to fix Alex's Caves cave-fog vs shaderpack conflicts (lists Complementary-family patches; notes **MakeUp Ultra Fast "isn't supported at all: it has no single cave-fog color to hook"** — relevant since MUF 9.5f is in our pack; supports 1.21.1 NeoForge + Iris). [Iris Caves on CurseForge](https://www.curseforge.com/minecraft/mc-mods/iris-caves)
- Community-quoted `alexscaves-client.toml` keys: `biome_sky_overrides`, `biome_sky_fog_overrides` (both with in-file comment "May conflict with shaders") and `biome_ambient_light_coloring` (recommended to disable for DH/visual issues). Keys as quoted from the shipped config file — treat exact names as COMMUNITY-verified until opened in-game. [r/feedthebeast: AC conflicting with shaders](https://www.reddit.com/r/feedthebeast/comments/1m6hxwh/alexs_caves_conflicting_with_my_shaders/), [DH problems thread](https://www.reddit.com/r/feedthebeast/comments/1kg37wm/i_have_some_problems_with_distant_horizons/)
- **Recommendation: keep + tune** — with Complementary Reimagined, expect AC cave-biome fog/lighting glitches (documented by the existence of Iris Caves and the AC-shaders threads); consider disabling `biome_ambient_light_coloring`/sky overrides for shader users; investigate the toxic-caves lag with spark if players visit AC often. Helps P0/P1 (GPU/shader) most. Low risk.
### 16. Twilight Forest 4.8.3345 — sky/Aurora/weather effects have config toggles (VERIFIED via official wiki)
- `twilightforest-client.toml`: **`auroraBiomes`** (default `["twilightforest:glacier"]`; set `[]` to disable the Aurora shader entirely), `cloudBlockPrecipitationDistance` (client, default `-1` = follow common; `0` disables cloud precipitation rendering), `silentCicadas`. Common config `cloudBlockPrecipitationDistance` (default 32) — *"Lower if experiencing low tick rate"*. [TF Wiki: Configuration](http://benimatic.com/tfwiki/index.php/Configuration)
- Aurora shader history: added for Glacier with configurable biomes; a crash fix mentions "Aurora Shader ... not being registered properly" [TF changelog](http://benimatic.com/tfwiki/index.php/Change_Log)
- **Known shader conflict:** TF's custom skybox conflicts with major shaderpacks (e.g. Complementary Reimagined) causing *"glaring visual distortion"*; the community **"Disable Twilight Forest Skybox"** datapack (works 1.16.5→1.21.x) removes the skybox so shaders work properly in the dimension. [CurseForge datapack](https://www.curseforge.com/minecraft/data-packs/disable-twilight-forest-skybox); same class of issue tracked as [TF issue #854](https://github.com/TeamTwilight/twilightforest/issues/854) (older, OptiFine-era).
- Also relevant from §7: WATUT's dynamic GUIs break when TF is installed ([WATUT #106](https://github.com/Corosauce/WATUT/issues/106)).
- **Recommendation: keep (core content) + tune:** if the group plays TF with shaders, ship the skybox-disable datapack (or accept the artifact); set `cloudBlockPrecipitationDistance: 0` on weak clients; `auroraBiomes=[]` only if Glacier runs badly with shaders. Helps all machines in the TF dimension; P0/P1 GPU. Low risk.
### 17. Fusion 1.3.15b + Athena 4.0.6 — two CTM engines loaded at once (VERIFIED existence/claims; cost INFERENCE)
- Athena (CTM 4.0.6 line): *"cross-platform baked model loader that features built-in support for connected textures ... unique baked models for each type to ensure optimal performance"*; its CTM is designed to "minimize unnecessary calculations". [CurseForge](https://www.curseforge.com/minecraft/mc-mods/athena). Chipped's connected textures require Athena (community). [Reddit r/feedthebeast](https://www.reddit.com/r/feedthebeast/comments/1fa8mr3/connected_texture_resource_pack_compatable_with/)
- Fusion: resourcepack library providing connected textures + custom entity models. [Modpack Index page](https://www.modpackindex.com/mod/45224/fusion-connected-textures)
- **Verified Fusion perf bug pattern:** a 1.3.x changelog entry — *"Fixed performance issues when resolving custom texture tinting with Sodium installed"* — i.e., Fusion has had Sodium-interaction hot spots worth keeping current on. [Fusion changelog (Modrinth)](https://modrinth.com/mod/fusion-connected-textures/version/1.3.1-fabric-mc26.2)
- Cost of running both: each engine registers its own model-baking/CTM hooks; both are exercised only by resourcepacks that target their respective formats. Startup time + heap for double registration is the certain cost; runtime chunk-meshing cost depends on which packs are actually enabled (Better Leaves & MT-CT-style packs ship Fusion and/or Athena variants). MT-CT notes "CTM and Athena Compat did exist at the start but are Deprecated" — i.e., pack-side support for a single engine is the norm. [MT-CT on Modrinth](https://modrinth.com/project/TjOXlt9Y)
- **Recommendation: audit, then drop one if possible.** Determine which shipped resourcepacks actually need Fusion vs Athena; if everything the pack ships is Fusion-format (or Athena-format), remove the other engine → startup + heap win (matters for P2's 8GB free RAM), zero visual change. Medium confidence the pack needs both today (Chipped→Athena is the usual blocker).
### 18. Lodestone 1.8.2 / Veil — post-processing only when triggered (DOCUMENTED)
- Veil (FoundryMC) is the rendering library under Lodestone's 1.8.x stack: custom **post-processing pipeline**, shader injection, bone-animated models. [Veil README (branch 1.21)](https://github.com/FoundryMC/Veil/blob/1.21/README.md)
- Lodestone: library for Lodestar team mods — shaders, screenshake, utilities. [9Minecraft summary](https://www.9minecraft.net/lodestone-mod/) (secondary source; treat as description)
- Cost: post chains cost frame time only while an effect is active; presence of Veil also changes behavior of other mods (see Exposure §11: Veil forces Exposure's direct-capture path). Veil+Iris compat is what irisveil 0.3.0 provides in this pack.
- **Recommendation: keep** (dependency of the Create-adjacent stack); measure once with spark whether any Veil post chain runs continuously in normal play. Open question below.
### Fleet notes
| Mod | P0 Deck (iGPU, 800p) | P1 (VRAM-bound 1060) | P2 (CPU/heap-bound) |
|---|---|---|---|
| SPR raytrace | Med (CPU spikes) | Low | **High** |
| SPR level-clone cache | Low | Low | Med (heap) |
| WATUT GUI streams | Low-Med | Low | **Med (CPU+net)** |
| Subtle Effects / Perception trails | Med (fill-rate/particles) | Med | Low-Med |
| Perception chromatic aberration | Med (post pass) | Med | Low |
| AC biome fog/shader overrides | Med-High | Med-High | Low |
| TF Aurora + cloud precip + skybox×shaders | Med | Med | Low |
| Immersive Paintings textures | Low | **Med (VRAM)** | Low (heap) |
| Exposure capture hitch | **High (during use)** | High (during use) | Low |
| Emojiful animated emoji | Low | Low-Med (VRAM) | Low (startup) |
| Fusion+Athena double engine | Startup | Startup | **Startup/heap** |
| Tooltips/plaques/titles/pings/chimneys/inv-particles | Negligible | Negligible | Negligible |
## Sources
- Kept (primary): henkelmax/sound-physics-remastered `1.21.1` branch — `SoundPhysicsConfig.java`, `SoundRateConfig.java`, README (config keys, defaults, per-sound rates, level-clone cache).
- Kept (primary): Corosauce/WATUT branch 1.21.0 — `ConfigClient.java`, commit 71342de, issue #106 (TF conflict), client screen renderer sources.
- Kept (primary): Octo-Studios/perception branch 1.21.1 — `ChromaticAberrationConfig.java`, `TrailConfig.java`, module tree; Modrinth 0.1.0.2 notes (FPS leak fix).
- Kept (primary): mortuusars/Exposure branch 1.21.1 `CHANGELOG.md` (capture paths, Iris/DH/Veil interactions, preload removal in 1.9.19).
- Kept (primary): Luke100000/ImmersivePaintings wiki/Config + Modrinth description (LoD/caching/streaming).
- Kept (primary/official wiki): benimatic.com TF Wiki Configuration (`auroraBiomes`, `cloudBlockPrecipitationDistance`, client config list) + TF Change Log (Aurora shader).
- Kept (primary): MincraftEinstein/SubtleEffects wiki + Modrinth (per-feature toggles, particle culling/render distance, config sections).
- Kept (primary): CreativeMD/AmbientSounds repo + Modrinth (client-side, `/cmdclientconfig`); CreativeMD/AmbientSounds is the source repo.
- Kept (primary): FoundryMC/Veil README (post-processing pipeline); AHilyard LegendaryTooltips & AdvancementPlaques Modrinth pages; LukenSkyne Ping Wheel Modrinth; LopyTwich Inventory Particles CurseForge; Sooty Chimneys Modrinth; YUNG Travelers Titles Modrinth; isXander/CurseForge Controlify changelogs; Athena CurseForge description; Fusion Modrinth changelog; Iris Caves CurseForge page; "Disable TF Skybox" datapack page.
- Dropped: minecrafthub.io / feed-the-mods / 9minecraft / mcfuns / minecraftbible / tlauncher / craftymania — SEO mirrors with no unique verified facts.
- Dropped: Reddit threads except the two quoting actual `alexscaves-client.toml` contents (kept as COMMUNITY evidence of key names).
## Gaps
- **AmbientSounds concrete config keys** (density/feature toggles) not pulled from source — repo is CreativeMD/AmbientSounds (branch `1.21`), config is GUI-driven (`/cmdclientconfig`); verify in-game rather than trusting names from memory.
- **Subtle Effects 1.14.3 exact TOML keys**: config is Fzzy-Config GUI sections (`Entities/Dust Clouds`, `Items/Item Rarity → Particle Display Type` documented), but per-effect key names in the file were not read from source for the pinned 1.21.1 build.
- **alexscaves-client.toml key names** come from community quotes of the generated file, not from AC source; verify by opening the shipped config once.
- **Fusion 1.3.15b-specific** changelog wasn't diffed (research surfaced the newer-line Sodium-tinting fix); check the pinned file's own changelog on CurseForge before crediting it with the fix.
- **Heap impact of SPR's level-clone cache** (`level_clone_range=4` → radius-4 chunk clones retained 20 ticks) is unquantified — worth one spark/heap measurement on P2.
- Whether any **Veil post chain runs continuously** with this exact Lodestone/Aeronautics/SSRD stack is unmeasured.
## Top levers (ranked)
| # | Lever | Expected impact | Machines helped | Risk | Confidence |
|---|---|---|---|---|---|
| 1 | SPR: `environment_evaluation_ray_count` 32→16, `environment_evaluation_ray_bounces` 4→2–3, `strict_occlusion=true`; cap noisy modded sounds in the per-sound rate config (`0`/`>=1`) | **High** (CPU) on sound-dense scenes (Create) | P2, P0 | Low (audio quality slightly degrades) | High (config verified in source) |
| 2 | Alex's Caves: disable `biome_ambient_light_coloring` (+ sky/fog overrides) for shader users; test Iris Caves-style patches if AC fog glitches under Complementary Reimagined | Med-High (GPU + visual correctness) | P0, P1 | Low | Medium (community-verified keys) |
| 3 | Twilight Forest: `cloudBlockPrecipitationDistance` client → 0; ship "Disable TF Skybox" datapack for shader play; `auroraBiomes=[]` only if Glacier stutters | Med (in-dimension FPS/stability) | P0, P1 (all in TF) | Low | High (official wiki keys) |
| 4 | WATUT: raise `tickReceiveAndRenderRateOfGUIUpdates` (e.g. 20–40) or `dontSendDetailedGUIInfo=true` if GUI streaming costs show; watch known TF conflict (#106) | Med (CPU + network, 10 players) | P2 + server | Low (visual fidelity loss) | High (config verified) |
| 5 | Perception: clear `experience_orb` (and other high-traffic) entries from `entityTrails`; keep CA sound list short | Med (particle bursts in farms) | P0, P2 | Low | High (config verified) |
| 6 | Immersive Paintings: lower `maxUserImages`, `thumbnailSize` for P1 | Med (VRAM) | P1 | Low | Medium (config verified, effect unmeasured) |
| 7 | Remove one CTM engine (Fusion or Athena) after auditing shipped resourcepacks (Chipped pins Athena) | Low-Med (startup + heap) | P2 (startup/heap) | Medium (must re-verify every resourcepack) | Medium |
| 8 | Update Exposure to ≥1.9.19 (removes first-camera-use preload lag spike) | Low (hitch removal) | All, esp. P0 | Low | High (changelog verified) |
| 9 | Emojiful: candidate for removal (or drop animated emoji packs) | Low (startup, VRAM, avoids known freeze/chat bugs) | P1, P2 | Low (social acceptability) | Medium |
| 10 | Subtle Effects: turn off `Entities/Dust Clouds` + Item Rarity dots on P0/P1 if particle-bound | Low-Med (particles/fill-rate) | P0, P1 | Low | Medium |
| 11 | Keep as-is: Legendary Tooltips (disable 3D preview if JEI tooltips hitch), Advancement Plaques, Held Item Tooltips, Items Displayed, Ping Wheel, Travelers Titles, Sooty Chimneys, Inventory Particles, Controlify, AmbientSounds, Lodestone/Veil | — | — | — | Medium-High |
## Open questions to verify by benchmark
1. SPR CPU: measure frame/tick cost with a Create factory producing dozens of concurrent sounds, at default (32 rays/4 bounces) vs 16/2 vs strict occlusion; and heap delta of the level-clone cache on P2 (spark GC/alloc view).
2. SPR per-sound rate caps: which modded sounds (Create, Alex's Mobs, Twilight Forest ambients) actually exceed the cap in a session — read `performance_logging=true` output first.
3. WATUT: with 10 players and 4–5 GUIs open, cost of GUI streaming at `tickReceiveAndRenderRateOfGUIUpdates=10` vs 30 (client CPU + server→client bandwidth); confirm whether TF 4.8.3345 still triggers #106 dynamic-GUI failure.
4. Alex's Caves: FPS in Toxic Caves (issue #760 scenario) on P0/P1, with and without `biome_ambient_light_coloring=false`, under Complementary Reimagined r5.9.3 and MakeUp Ultra Fast 9.5f (MUF has no cave-fog hook per Iris Caves — expect visual, not perf, artifacts).
5. Twilight Forest: FPS in Glacier with Aurora shader on vs `auroraBiomes=[]` under shaders; skybox artifact severity with Complementary Reimagined with/without the disable-skybox datapack.
6. Perception: XP-orb trail particle count in a Create XP farm, `entityTrails.experience_orb` on vs removed (P0 800p fill-rate).
7. Exposure: hitch duration of first camera use on 1.9.18 vs 1.9.19 on P0; and photo-capture hitch with Iris (direct capture) at 1280×800.
8. Fusion vs Athena: startup time and heap with both loaded vs each removed alone (after confirming which resourcepacks need which engine).
9. AmbientSounds: resident RAM of its sound buffers on P2 (heap dump / AllTheLeaks) and whether `/ambient-debug` shows dense overlapping ambients in forest/swamp at night.
10. Veil/Lodestone: spark profile — does any Veil post chain run continuously in normal overworld play, or only during modded events?
@@ -0,0 +1,213 @@
# Research: Candidate client-side performance mods NOT yet in Onion MC
**Scope:** MC 1.21.1 / NeoForge 21.1.251, ~212 mods, client-side only. Existing stack assumed fixed
(Sodium 0.8.13, Iris 1.8.14-beta.1 + irisveil 0.3.0, Distant Horizons 3.3.2 mandatory, ImmediatelyFast 1.6.14,
EntityCulling 1.11.2, ModernFix 5.27.24, FerriteCore 7.0.3, Lithium 0.15.4, Dynamic FPS 3.11.4, AllTheLeaks 1.1.13,
EMF 3.3.9 + ETF 7.2.4 + Fresh Animations, Better Leaves 9.6, Create 6.0.10/Flywheel 1.0.6, Sable 2.0.5,
Xaero's Minimap/World Map, JEI 19.57, Controlify 3.0.1).
**Evidence tags used below:** `VERIFIED` = read from source code/repo/changelog/API metadata;
`DOCUMENTED` = official README/wiki/Modrinth body/changelog; `COMMUNITY` = forums/Reddit/Discord/answer sites;
`INFERENCE` = my reasoning from the above.
Primary source for availability was the **Modrinth v2 API** (`/project/<slug>/version?loaders=["neoforge"]&game_versions=["1.21.1"]`),
queried per mod. Any "version + date" below is a `VERIFIED` read of that API response unless tagged otherwise.
---
## Summary
1. **Most of the "standard" missing client perf mods simply do not exist for NeoForge 1.21.1** — Exordium (NeoForge builds only for 1.21.6+), Krypton (Fabric-only), Nvidium, VulkanMod, Enhanced Block Entities, FastChest, Memory Leak Fix (obsolete by its own README), ThreadTweak/Smooth Boot, More Culling Extra, YOSBR. This is a hard filter, not a judgement call.
2. **The real, available levers are: More Culling (or Cull Leaves), BadOptimizations, Particle Core, Gnetum, Ixeris, Flerovium, Better Block Entities, and (for the Steam Deck specifically) Super Resolution.** Of these, More Culling + Cloth Config, BadOptimizations and Particle Core are the lowest-risk/highest-confidence additions.
3. **Two landmines to avoid:** `Sodium Leaf Culling` (the mod people recommend for Better Leaves) **crashes on Sodium 0.8.11+** and is unmaintained since Apr 2025, so it is unusable on this pack's Sodium 0.8.13; and `ScalableLux` is reported to break Distant Horizons, which is mandatory here.
4. **Side finding worth escalating:** the pack's exact Iris 1.8.14-beta.1 + Sodium 0.8.13 combination on NeoForge 1.21.1 has a documented mixin incompatibility in the 1.21.1 NeoForge community, for which a third-party "Iris-Sodium Compat" patch exists on CurseForge. That is a stability question for the existing stack, not a new mod, but it should be checked before benchmarking anything else.
---
## Master candidate table
Availability column = NeoForge 1.21.1 build confirmed via Modrinth API (+ CurseForge where noted).
| Mod | NF 1.21.1? + version (date) | What it does | Expected impact | Conflicts with this pack | Risk | Recommendation |
|---|---|---|---|---|---|---|
| **More Culling** (`moreculling`) | ✅ 1.0.10 (2026‑09‑07) | Culls blockstates, leaves, item frames (3‑face/back/map), clouds, sign text, rain/snow, end gateway, beacon beam, paintings | **Med** — dense bases with signs/frames/leaves; helps all 3 machines | Needs **Cloth Config** (`cloth-config`, ✅ 1.21.1). Leaves culling overlaps a bushy-leaves pack (Better Leaves 9.6); More Culling issue #475 (unconfirmed Create/Flywheel report, maintainer says it "doesn't touch blockentity renderer") | Low‑Med | **Add** |
| **Cull Leaves** (`cull-leaves`) | ✅ 4.1.1+1.21.1-neoforge (2025‑12‑12) | Leaf-block face culling only ("Smart Leaves" replica) | **Low‑Med** — leaves only | Needs **MidnightLib** (`midnightlib`, ✅ 1.21.1). Designed to be used *with* Motschen's Better Leaves (same author) | Low | **Add** (or use More Culling's leaves option instead — pick one, not both) |
| **BadOptimizations** (`badoptimizations`) | ✅ 2.4.1 (2025‑12‑15) | Lightmap caching, sky-colour caching, skips idle debug renderers, entity/block-entity renderer caching, redundant FOV calcs | **Low‑Med** — author measured ~1926→2008 FPS (~+4%) in Fabulously Optimized; more relevant on tick-bound P2 | None known. Has a self-disabling incompatibility mechanism (`ignore_mod_incompatibilities`, `enable_entity_renderer_caching` etc.) | Low | **Add** |
| **Particle Core** (`particle-core`) | ✅ 0.3.3+1.21+neoforge (2026‑02‑05) | Particle frustum culling, custom vertex path, per-tick lightmap cache, async particle ticking, per-type spawn reduction/disable | **Med‑High** — author's spark profile: particle rendering went from ~25% of CPU time to "basically a non-item"; +50% relative over Sodium alone | Needs 2 libs (Modrinth deps). Do **not** pair with Async Particles (per community); pack has neither | Med (async ticking — can be disabled via `disableOptimizations`; auto-disables on instability) | **Add** |
| **Gnetum** (`gnetum`) | ✅ 3.3.6 (2026‑06‑24) | Distributes HUD rendering over N frames + HUD framebuffer caching; Sodium 0.8+ config integration | **Med** in HUD-heavy scenes (Xaero's, JEI, titles, tooltips) | Author states **ImmediatelyFast is "fully compatible and recommended"**; Xaero's flicker fixed 3.2.0; IF HUD-batching flicker fixed 3.3.4 | Low‑Med | **Add** (Trial if HUD flicker appears) |
| **Ixeris** (`ixeris`) | ✅ 4.6.8+1.21.1-neoforge (2026‑09‑21) | Threaded event polling off the render thread; buffered raw input (**Windows only**); GLFW state caching; FPS limiter rewrite | **High on P1** only if high-polling mouse (author: 8000 Hz 12→121 FPS; 500 Hz 134→151 FPS). **Low on Linux/P0/P2** (1.03–1.11×) | Open Iris conflict issue #151 (on MC 26.3 NeoForge, not 1.21.1); open crash reports on **older NVIDIA cards** (#134) and Intel iGPU alt-tab (#144); Exordium incompat (not in pack) | Med | **Trial, P1/P2 first** (P1 has a GTX 1060 = "old card" in issue #134) |
| **Super Resolution** (`superresolution`) | ✅ 0.9.2-alpha.2+opengl (2026‑10‑03) — **alpha only on 1.21.1** | FSR1/FSR2/FSR3, SGSR1/2, DLSS, XeSS upscaling (+ frame-gen frameworks); README lists Sodium/Iris/DH as supported | **High on P0** (RDNA2 8CU @1280×800); **Med on P1** (VRAM-bound); **Low on P2** (main-thread bound) | README: incompatible with OptiFine/Canvas/VulkanMod; marks Resolution Control/RenderScale/GPU Booster/GPU Tape incompatible. Needs OpenGL 4.3+. **Complementary Reimagined has no SR shader interface** (issue #317 is "On Hold") → only FSR1 compatibility mode; FSR3 has "severe entity ghosting" (author's own words) | Med‑High | **Trial, P0 first** |
| **Flerovium** (`flerovium`) | ✅ 1.1.3 (2026‑09‑12, beta) / 1.2.0 (2026‑09‑26, **alpha**) | Backface culling + fast-math + LOD for item, particle and entity rendering; author claims item 50%+, particles 50%, entities 30% faster | **Med** across all 3 | Needs **Sodium**. Author added "better compat with aeronautics mod" (pack has Create Aeronautics) and Accelerated Rendering. Backface culling on items/entities is a known source of visual glitches with layered/animated models | Med‑High | **Trial** (verify vs Better Combat, Emotecraft, 3D Skin Layers, EMF+Fresh Animations) |
| **Better Block Entities** (`better-block-entities`) | ✅ 1.3.4+mc1.21.1 (2026‑09‑15), explicitly built for "Sodium 0.8.12‑0.8.13" | Hybrid block-entity renderer: chests/shulkers/signs/pots/beds/bells/banners meshed into terrain when static, dynamic when animating | **High** in storage/BE-heavy bases | Needs **Sodium**. **EMF compat "only available for 1.21.11 versions and above"** (its own README) → **unverified with EMF 3.3.9 + Fresh Animations** which this pack uses. Touted as compatible with ImmediatelyFast, EntityCulling, Lithium, C2ME | Med | **Trial** |
| **Sodium Extra** (`sodium-extra`) | ✅ 0.9.4 (2026‑09‑16) | Animation/particle/detail/render toggles (OptiFine-style eye candy), fog controls, cloud height, static-entity rendering, FPS display | **Low direct**, but it is the cheapest way to expose per-machine particle/animation/entity levers (author's wiki) | Needs Sodium. Optional deps on RSO + another project (present as optional) | Low | **Add** |
| **Reese's Sodium Options** (`reeses-sodium-options`) | ✅ 2.2.4 (2026‑09‑16) | Alternative Sodium options screen, search, keyboard/controller nav | ~0 direct perf; big UX for tuning + **Controlify integration** (pack has Controlify 3.0.1) | Needs Sodium only | Low | **Add** (tuning ergonomics, especially on Deck) |
| **Default Options** (`default-options`) | ✅ (1.21.1 + neoforge listed) | Ships `options.txt`/keybinds/server-list defaults without overwriting user changes | 0 runtime; ensures the tuned baseline actually reaches every client | Needs **Balm** (`balm`, ✅ 1.21.1 neoforge). Achieves what YOSBR would (YOSBR is Fabric-only) | Low | **Add** |
| **Chloride** (`chloride`) | ✅ 1.8.1-NEO-1.21.1 (2026‑07‑19) | Entity distance culling + on-screen entity cap, leaves culling, solid chest/bed models, hide JEI/REI/EMI overlay until searching, fast language reload, fog controls, FPS overlay | **Med**, but largely **overlapping** with EntityCulling (present), More Culling, and JEI | Needs Sodium; updated to Sodium 0.8.12-beta.1 (1.7.9) and **adds Sable support for entity culling** (1.7.8) — Sable IS in the pack. Declares 1 mod as incompatible (changelog names "Smooth Skies"). Config file is `chloride-client.toml` | Med | **Trial** (only if you drop/disable overlapping culling) |
| **Krypton Reno** (`krypton-fnp`, CurseForge "Krypton FNP") | ✅ NeoForge 1.21.1 (CurseForge file 0.2.28.1‑1.21.1, 2026‑07‑06; Modrinth listing updated 2026‑07‑09) | Krypton-derived Netty/connection optimisations + optional server-side chunk/block/entity culling | **Low client-side** on a normal LAN link; the juicy packet-culling keys are server-side | README: incompatible with KryptonFoxified/Ceres/Pluto/Krypton Hybird/Chionanthus/Krypton-Fabric-with-Connector. Restricted 404Setup license (packwiz OK, full-game redistribution not) | Med | **Trial** (better evaluated as a *server* change) |
| **Raise Sound Limit Simplified** (`rsls`) | ✅ (1.21.1 + neoforge listed) | Sound-engine performance + raises sound source limit | Low‑Med (pack has Sound Physics Remastered, AmbientSounds, Subtle Effects, SRS) | Not verified against Sound Physics Remastered 1.5.1 | Low‑Med | **Trial** |
| **Async Logger** (`asynclogger`) | ✅ (1.21.1 + neoforge listed) | Asynchronous logging / log filtering | Low | Not verified vs ModernFix/AllTheLeaks log mixins | Low‑Med | **Trial (optional)** |
| **Sodium Options API** (`sodium-options-api`) | ✅ 1.21.1 listed (last update 2025‑04‑10) | Sodium options-menu API for addons | 0 direct | RSO's own docs: "Sodium Options API is no longer supported on versions where Sodium already provides the relevant options API directly" → Sodium 0.8.x provides it | Low | **Skip** |
| **Sodium Extras** (`sodium-extras`) | ✅ neoforge-1.21.1-1.0.8 (2025‑04‑07) | Entity culling (duplicate of EntityCulling), fog toggle, font-shadow toggle, borderless | Low | Requires Sodium **+ Sodium Options API**, which is obsolete on Sodium 0.8.x; no 0.8-era release | Med (stale) | **Skip** |
| **Sodium Dynamic Lights** (`sodium-dynamic-lights`) | listed for 1.21.1 (+neoforge), last update 2025‑04‑10 | LambDynamicLights port with Sodium options integration | 0 (already have LambDynamicLights 4.8.11) | Duplicate dynamic-lights implementation | Med | **Skip** |
| **Sodium Leaf Culling** (`sodiumleafculling`) | ✅ neoforge 1.0.1 (1.21.1, 2025‑04‑07) — **but** | Leaf culling injected into Sodium's chunk-mesh pipeline | would be Med‑High | **Broken:** GitHub issues #18 "Crashes with Sodium 0.8.11+ on 1.21.1" (2026‑05‑07) and #20 "Compatibility with modern Sodium 0.8.12 …" (2026‑05‑14) are **open**; no release since Apr 2025 | Very High (crash) | **Skip** (use Cull Leaves / More Culling) |
| **Exordium** (`exordium`) | ❌ No NeoForge build ≤1.21.5 (NeoForge builds only 1.21.6/1.21.8/1.21.10/1.21.11, both released 2026‑03/04) | Low-FPS GUI/screen rendering | would be Med | Author: "No backports planned!"; Modrinth status = **archived**, "not actively maintained" | — | **Skip** (use **Gnetum**, the maintained HUD equivalent) |
| **ScalableLux** (`scalablelux`) | ✅ 1.21.1 listed (fabric+neoforge) | Starlight-derived light engine, optional parallel light updates | Low client-side (mostly chunk-gen/server) | **Community reports DH breakage** with Starlight-derived engines ("if you are using Distant Horizons then do NOT use this as it will break") | High (DH mandatory) | **Skip** |
| **Krypton** (`krypton`) | ❌ Fabric only | Netty/connection optimisations | — | — | — | **Skip** (see Krypton Reno) |
| **Nvidium** (`nvidium`) | ❌ Fabric/quilt only; **requires NVIDIA Turing+ mesh shaders** | Mesh-shader terrain backend | would be High on P2's 1080 Ti… except Pascal ≠ Turing | — | — | **Skip** |
| **VulkanMod** (`vulkanmod`) | ❌ Fabric/quilt only; **listed incompatible with Distant Horizons** | Vulkan renderer | — | VulkanMod's own incompatible-mods wiki lists DH, EMF 2.2, ImmediatelyFast 1.2.20, Exordium, Embeddium | — | **Skip** |
| **Enhanced Block Entities** (`ebe`) | ❌ Fabric/quilt only, ≤1.21.4 | Baked models for chests/signs/bells/beds/shulkers/pots | — | — | — | **Skip** (see Better Block Entities) |
| **FastChest** (`fastchest`) | ❌ Fabric only (1.21.1 listed but loader = fabric) | Static chest models (loses lid animation) | — | — | — | **Skip** |
| **Memory Leak Fix** (`memoryleakfix`) | ❌ max 1.20.4 | Fixes MC memory leaks | 0 | Its own README: "Minecraft 1.20.5+: all the memory leaks previously fixed … have been fixed. Making this mod obsolete" | — | **Skip** |
| **Ksyxis** (`ksyxis`) | ✅ exists for 1.21.1 but **server_only** | Removes unneeded spawn chunks | **0 on client in multiplayer** (its own FAQ: "It has no effect on the client when playing multiplayer") | — | — | **Skip** (client) |
| **FastLoad** (`fastload`) | ❌ abandoned by author, max 1.20.1, no NeoForge | World-load speedups | — | — | — | **Skip** |
| **Noisium** (`noisium`) | ⚠️ neoforge builds exist but **server_only**, project now **unlisted** | Worldgen speedup | ~0 client in multiplayer | — | — | **Skip** (client); good server candidate |
| **C2ME** (`c2me-neoforge`) | ✅ 1.21.1 neoforge exists | Parallel chunk gen/IO | ~0 client in multiplayer (server_side = required, `server_only_client_optional`) | Fundamentally incompatible with Moonrise (per Moonrise README) | — | **Skip** (client); good server candidate |
| **Moonrise** (`moonrise-opt`) | ✅ NeoForge 0.1.0-beta.15 (2025‑10‑10) | Chunk-system/entity-tracking rewrite; README: "can run on either the client or server, but primarily benefits the server … on the client … similar to Lithium" | Low client-side; **and it auto-disables conflicting parts of Lithium + FerriteCore**, both in the pack | 3 declared incompatible projects in the version metadata; README names **C2ME** as fundamentally incompatible | Med | **Skip** (client); evaluate as server mod knowing it partially supersedes Lithium/FerriteCore |
| **Fast Item Frames** (`fast-item-frames`) | ✅ 1.21.1 listed | Item frames become blocks instead of entities; dyeable/invisible/waxable | Med in frame-heavy builds | Requires **Puzzles Lib**; **requires install on client AND server**; converts existing item-frame entities on chunk load; interaction with Immersive Paintings 0.7.9 unverified | High | **Skip** for this client-only pass |
| **Fast Paintings** (`fast-paintings`) | ✅ 1.21.1 listed | Fixes painting rendering, custom models | Low | `client_and_server` (needs server install too); interaction with Immersive Paintings unverified | Med | **Skip** for this client-only pass |
| **Model Gap Fix** (`modelfix`) | ✅ 1.21-1.10 (2024‑08‑03) | Fixes MC‑73186 model seams | ~0 (its own FAQ: does not slow the game down; it's a visual fix, not perf) | — | Low | **Skip** (not a perf lever; add only if seams annoy) |
| **YOSBR** (`yosbr`) | ❌ Fabric/quilt only | Default options shipping | — | — | — | **Skip** (use Default Options) |
| **ThreadTweak** (`threadtweak`) | ❌ Fabric/quilt only; Smooth Boot itself is dead | Thread priority tuning | — | — | — | **Skip** |
| **Smooth Boot** | ❌ legacy, main defect fixed in 1.19.4 | — | — | — | — | **Skip** |
| **More Culling Extra** (`morecullingextra`) | ❌ fabric/quilt, ≤1.20.4 | Extra glass/pane/beacon culling | — | — | — | **Skip** |
| **Idle Boost** (`idle-boost`) | ✅ 1.21.1 listed | Background-window optimisation | 0 | Duplicate of Dynamic FPS 3.11.4 (already in pack) | — | **Skip** |
| **Smart Particles** (`smart-particles`) | ✅ 1.21.1 listed (2026‑09‑18) | Particle rendering + limits optimiser | Med (alternative to Particle Core) | Overlaps Particle Core — pick **one** | Med | **Skip** unless Particle Core misbehaves |
| **Cull Particles MultiLoader** | ✅ 1.21.1 listed but last update 2025‑01‑30 | Particle culling | Low‑Med | Superseded by Particle Core; unmaintained | Med | **Skip** |
| **Connectivity** | ❌ no Modrinth project (404); 1.20.1-era Forge only | Forge networking | — | — | — | **Skip** |
| **Ecstatic** (`ecstatic`) | ✅ 1.21.1 neoforge, but LOD mod | Alternative LOD | — | DH 3.3.2 is mandatory in this pack | — | **Skip** |
---
## Findings
### A. Availability verdicts (the "everyone recommends it" list)
1. **Exordium is not available for NeoForge 1.21.1 at all** — the Modrinth API returns an **empty list** for `loaders=["neoforge"]&game_versions=["1.21.1"]`, and the NeoForge builds that do exist are 1.21.6/1.21.8/1.21.10/1.21.11. The author's own project page says "(Neo)Forge support? No… no backports planned!", and the project status is **archived** with "This mod is not actively maintained!" `VERIFIED`/`DOCUMENTED` ([Modrinth](https://modrinth.com/mod/exordium), [API](https://api.modrinth.com/v2/project/exordium/version?loaders=%5B%22neoforge%22%5D)).
**→ The correct 1.21.1 NeoForge substitute is Gnetum** (see Finding B4), which does the same job with Sodium's own config API and is actively maintained.
2. **Krypton is Fabric-only**; the NeoForge route is **Krypton Reno** (`krypton-fnp`), whose README states it is "ported from Krypton Fabric, with some unique optimizations added. Supports NeoForge/Forge" and "continuously provides compatibility for stable versions (1.20.1, 1.21.1)". Client-relevant keys in its documented config: `clientEncrypt`, `connectionMicroOpt`, `bestVarLong`, `netty.allocatorMaxOrder`, `netty.happyEyeballs`. The chunk/block-entity culling keys (`culling.chunk_block`, `culling.chunk_light`, `culling.entity`, `culling.block`) are explicitly server-side. `VERIFIED`/`DOCUMENTED` ([Modrinth body](https://modrinth.com/mod/krypton-fnp)).
3. **Nvidium and VulkanMod are Fabric/quilt-only, and both are additionally unusable here**: Nvidium needs NVIDIA **Turing+ mesh shaders** (P1 = GTX 1060 Pascal, P2 = GTX 1080 Ti Pascal, P0 = AMD RDNA2 → all fail) and "disables itself when iris is actively using shaders"; VulkanMod's own wiki lists **Distant Horizons** as incompatible, and shaders would need Beryl instead of Iris. `VERIFIED` ([Nvidium](https://modrinth.com/mod/nvidium), [VulkanMod incompatible list](https://github.com/xCollateral/VulkanMod/wiki/Incompatible-mods)).
4. **Enhanced Block Entities, FastChest, Memory Leak Fix, ThreadTweak, More Culling Extra, YOSBR are all unavailable or obsolete on this stack.** EBE is `fabric/quilt` and stops at 1.21.4; FastChest is `fabric`; Memory Leak Fix stops at 1.20.4 and its README declares itself obsolete from 1.20.5 on ("All the memory leaks in minecraft previously fixed by MemoryLeakFix have been fixed"); More Culling Extra stops at 1.20.4. `VERIFIED`.
5. **Ksyxis / Noisium / C2ME / Moonrise / FastLoad give ~0 client-side benefit in multiplayer.** Ksyxis literally says "It has no effect on the client when playing multiplayer"; Noisium is `server_only` and is now **unlisted**; C2ME-NeoForge is `server_only_client_optional`; Moonrise's README says it "primarily benefits the server" and that client-side gains would "behave similar to Lithium" (already in the pack). Note Moonrise **auto-disables conflicting parts of Lithium and FerriteCore** — both in this pack — so installing it client-side would partially neutralise two existing mods for a marginal client gain. `VERIFIED`/`DOCUMENTED`.
### B. Available candidates — details worth knowing before you test
1. **More Culling (1.0.10, 2026‑09‑07) is Sodium‑0.8‑ready and mature.** Its 1.0.8 changelog is literally "fix crash with sodium 0.8" and 1.0.9 fixed "dont cull option not working with sodium". The Cloth Config dependency is required (`9s6osm5g` = `cloth-config`, 1.21.1 NeoForge ✅, huge install base). The wiki enumerates exactly what is culled: aggressive BlockState culling, Item Frame (3-face/back/map), **Leaves Culling**, Powder Snow, Cloud, Sign Text, Rain/Snow, End Gateway, Beacon Beam, Painting. There is a documented "don't cull" escape hatch (added in 1.0.2) and the leaves technique is a separate toggleable culling technique. `VERIFIED`/`DOCUMENTED` ([versions API](https://api.modrinth.com/v2/project/moreculling/version?loaders=%5B%22neoforge%22%5D&game_versions=%5B%221.21.1%22%5D), [wiki](https://github.com/FxMorin/MoreCulling/wiki)).
2. **More Culling + Better Leaves 9.6: use one leaves system, not two.** Motschen authors both **Better Leaves** (the rp in this pack) and **Cull Leaves**, and the CurseForge page for Better Leaves says plainly: "In version 8.1 and lower, this resourcepack adds no textures… This comes at the cost of performance, though. **I strongly recommend installing the Cull Leaves mod alongside Sodium/Embeddium to get more FPS.**" Cull Leaves 4.1.1's changelog adds "**Add support for Sodium 0.8.0**". There is also a community resourcepack "Enhanced Bushy Leaves (More Culling compat)" whose existence implies More Culling's leaves culling needs pack-side adjustment on bushy leaf models. `DOCUMENTED`/`COMMUNITY` ([Cull Leaves 4.1.1 API](https://api.modrinth.com/v2/project/cull-leaves/version?loaders=%5B%22neoforge%22%5D&game_versions=%5B%221.21.1%22%5D), [Better Leaves CF page](https://www.curseforge.com/minecraft/texture-packs/motschens-better-leaves)).
**→ Practical recommendation: add More Culling for everything *except* leaves, and/or add Cull Leaves for leaves. Testing both leaves implementations simultaneously is a false economy.**
3. **Sodium Leaf Culling is the trap.** It is technically available for NeoForge 1.21.1 (1.0.1) and is exactly the mod people recommend for bushy-leaf packs ("injects directly into Sodium's chunk mesh render pipeline… 'Solid Aggressive' … sizable performance boost when using shaders in a dense forest"), and a Reddit thread even claims it "may be more effective than MoreCulling … because it works directly with Sodium's renderer". **But** its two newest reports are `#18 Crashes with Sodium 0.8.11+ on 1.21.1` (opened 2026‑05‑07) and `#20 Compatibility with modern Sodium 0.8.12 alpha backports to 1.21.1` (2026‑05‑14), both **still open**, with no release since 2025‑04‑07. This pack runs Sodium **0.8.13**. `VERIFIED` ([issue list](https://github.com/txnimc/SodiumLeafCulling/issues?q=is%3Aissue), [versions](https://api.modrinth.com/v2/project/sodiumleafculling/version)).
**→ Skip. This is the single most likely way to add a startup crash to the pack.**
4. **Gnetum (3.3.6, 2026‑06‑24) is the maintained Exordium replacement and explicitly pairs with ImmediatelyFast.** Its README: "✔️ ImmediatelyFast: fully compatible and recommended." Its changelogs track the exact risks this pack would hit: 3.2.0 "Fixed Xaero's Minimap flickering" (pack has Xaero's Minimap 26.5.0 + World Map 1.46.0), 3.3.4 "Fixed GUI flickering with ImmediatelyFast HUD batching enabled", 3.3.5 "Added basic integration with Sodium 0.8+ Video Settings screen", 3.2.0 also allows caching of "all modded HUDs" (with an off switch). Author's published comparison claims ~1.9× FPS in a HUD-heavy 1.20.1 test — treat as directional, not as this pack's number. `VERIFIED`/`DOCUMENTED` ([Modrinth body](https://modrinth.com/mod/gnetum), [versions](https://api.modrinth.com/v2/project/gnetum/version?loaders=%5B%22neoforge%22%5D&game_versions=%5B%221.21.1%22%5D)).
5. **Ixeris is the highest-variance candidate: potentially huge on P1, risky on P1.** Its own benchmark table is unusually specific: at **8000 Hz polling, 12 FPS → 121 FPS**; at 2000 Hz, 76 → 135; at 500 Hz, 134 → 151; in menus (1000 Hz) 133 → 165 on Windows, and only **355 vs 320 FPS on Linux/X11, 298 vs 289 on Wayland**. So it is a Windows + high-polling-rate-mouse win (P1), near-noise on P0 (Steam Deck/Linux) and P2 (Linux). Its README also states "As of version 3.1.0 the requirements of thread safety in the GLFW documentation are strictly obeyed", and there's a documented config key `allowBusyWaitInFramerateLimiter` (≤1.21.11). Counter-evidence: an open Iris-conflict issue (#151, 26.3 NeoForge, Oct 2026) and open crash reports on older NVIDIA cards (#134) and Intel Gen7/8 alt-tab (#144). `VERIFIED`/`DOCUMENTED`/`COMMUNITY` ([Modrinth body](https://modrinth.com/mod/ixeris), [issues](https://github.com/decce6/Ixeris/issues?q=is%3Aissue)).
**→ Because P1 is a GTX 1060 (Pascal) on Windows, treat P1 Ixeris as the highest-risk, highest-reward single test in this report.**
6. **Chloride is a plausible "one mod, several features" option that specifically supports two things in this pack.** Its changelogs show 1.7.8 "Added **Sable support for entity culling**" (pack has Sable 2.0.5) and 1.7.9/1.8.0 "Updated to Sodium 0.8.12(-beta.1)"; 1.8.1 "Fixed chloride mixins for Leaves Block collides with sodiums mixins (only warns, but breaks our culling)". Its config moved to `chloride-client.toml` in 1.8.0. Features that overlap the pack: entity distance culling (vs EntityCulling 1.11.2), leaves culling (vs More Culling/Cull Leaves), solid chest/bed models (vs no FastChest — actually a genuine gap-filler here), "Hide JEI/REI/EMI overlay until you type anything in their search bars" (pack has JEI 19.57), fast language reload. It also declares one dependency-flagged incompatibility (its own changelog names "Smooth Skies"). `VERIFIED`/`DOCUMENTED` ([versions API](https://api.modrinth.com/v2/project/chloride/version?loaders=%5B%22neoforge%22%5D&game_versions=%5B%221.21.1%22%5D), [Modrinth body](https://modrinth.com/mod/chloride)).
7. **Better Block Entities 1.3.4 is explicitly built against this Sodium version** ("Minecraft 1.21.1 (Sodium 0.8.12‑0.8.13)") and requires only Sodium — but its README caps EMF compatibility: "the compatibility with EMF is still being worked on and **will only be available for 1.21.11 versions and above**", and it targets "Minecraft versions from 1.21.6 and above" going forward. Given this pack runs EMF 3.3.9 + ETF 7.2.4 + Fresh Animations + FA All Extensions, BBE on 1.21.1 is a genuine unknown for chest/sign/bed models. `VERIFIED`/`DOCUMENTED` ([versions](https://api.modrinth.com/v2/project/better-block-entities/version?loaders=%5B%22neoforge%22%5D&game_versions=%5B%221.21.1%22%5D), [Modrinth body](https://modrinth.com/mod/better-block-entities)).
8. **Super Resolution is the only large GPU-side lever for P0, and it is alpha-only on 1.21.1.** Its README lists "✅ Supported: Sodium, Iris, DistantHorizons, Embeddium, Voxy" and requires OpenGL 4.3+; its 1.21.1 NeoForge builds are **all** `alpha` (latest 0.9.2-alpha.2, 2026‑10‑03, a ~33 MB jar). Two relevant changelog facts: 0.8.3-alpha.5 "**Added Sodium 0.8.x compatibility for Minecraft 1.21.1**" and "**AMD FSR now supports Linux**"; and 0.9.0-alpha.1 marks Resolution Control/RenderScale/GPU Booster/GPU Tape incompatible. The critical caveat for *this* pack: the shader-interface integration is **not implemented by Complementary Reimagined** (issue #317 is labelled "On Hold"), so only the fallback FSR1 compatibility path applies; the mod author states "for FSR3, entity ghosting was severe" with depth-reprojection motion vectors. `VERIFIED`/`DOCUMENTED` ([versions](https://api.modrinth.com/v2/project/superresolution/version?loaders=%5B%22neoforge%22%5D&game_versions=%5B%221.21.1%22%5D), [CR issue #317](https://github.com/ComplementaryDevelopment/ComplementaryReimagined/issues/317)).
**→ P0 (Steam Deck, 1280×800, RDNA2) is the right first target; P1 (VRAM-bound GTX 1060) second; P2 (main-thread bound) is *not* an upscaling problem and SR should not be expected to help there.**
9. **Particle Core's evidence is author-published spark profiles, not a pack benchmark.** From its Modrinth body: without it "world rendering is at 41% of CPU time, with renderParticles the lions share of that at 25%"; with it "rendering is now at only 16% of CPU time, particle rendering basically a non-item"; and overlaid with Sodium, "About 5% CPU time improvement, or 50% relative improvement". The 0.3.x line added **async particle ticking (default on)**, with an explicit escape hatch (`disableOptimizations` in `particle_core_config_v[x].json`), plus documented per-type controls (`turnOffPotionParticles`, `disableParticles`, `reduceParticlesByType`, `reduceParticlesAllChance`, `reduceParticlesDecreasedChance`). Community guidance says **do not** run it with Async Particles (a different mod; not in the pack). `DOCUMENTED`/`COMMUNITY`.
10. **BadOptimizations' own numbers are small but honest, and it has a real incompatibility system.** Author's README: 1926–1955 → 2008–2023 FPS (no toasts) and 1351–1384 → 1414–1458 FPS (with toasts) on an i7‑12700 + RTX 3060 in Fabulously Optimized. Documented config keys include `enable_entity_renderer_caching`, `enable_block_entity_renderer_caching`, `enable_entity_flag_caching`, `enable_remove_redundant_fov_calculations`, `lightmap_time_change_needed_for_update`, `ignore_mod_incompatibilities`, `ignore_mod_cache_hooks`, `log_config`; and third-party mods can mark themselves incompatible with individual options. It also says "Dependencies? None." `DOCUMENTED`.
11. **Sodium Extra + Reese's Sodium Options are fresh for 1.21.1 and are the tuning surface, not the gain.** Sodium Extra 0.9.4 (2026‑09‑16) requires Sodium, and optionally integrates with RSO plus one other project. RSO 2.2.4 (2026‑09‑16) requires Sodium and supports **Controlify** controller navigation — which this pack already ships (Controlify 3.0.1), making it a genuinely useful Deck addition. `VERIFIED`/`DOCUMENTED`.
12. **Default Options (TwelveIterations) is the NeoForge answer to "ship tuned defaults".** It is on 1.21.1 + NeoForge and requires **Balm** (also 1.21.1 + NeoForge). Its documented workflow: build the desired state, run `/defaultoptions saveAll`, ship `config/defaultoptions/`, and **do not** ship `options.txt`/`servers.dat`; fresh installs then start with your defaults and user changes persist across updates. YOSBR does the same job but is Fabric/quilt-only ("Requires Fabric Loader"). `DOCUMENTED`.
13. **`Modelfix` (Model Gap Fix) is not a performance mod.** Its own FAQ: "Will this slow down my game? Not at all! Removing texture zooming just removes some code and has no impact… it could very slightly worse that vanilla [in one edge case]". The 1.21.1 NeoForge build is `1.21-1.10` from 2024‑08‑03. `DOCUMENTED`. → Not a lever; add only for cosmetic reasons.
### C. Cross-cutting compatibility notes for this specific pack
14. **Existing-stack risk you should check before benchmarking: Iris 1.8.x + Sodium 0.8.x on NeoForge 1.21.1 has a documented mixin incompatibility.** Sodium's own Discord/issue trail ("Sodium 0.8.12 alpha backports to 1.21.1" was announced via [sable#878](https://github.com/ryanhcode/sable/issues/878)) plus a third-party CurseForge mod "Iris-Sodium Compat" whose description reads: "The latest releases of Iris and Sodium on 1.21.1 NeoForge don't work together. This fixes the issue. A simple compatibility mod between Iris 1.8.12 and Sodium 0.8.12 for NeoForge 1.21.1, fixing a missing mixin issue that's been plaguing the 1.21.1 NeoForge community for some time." `COMMUNITY`/`DOCUMENTED` ([CurseForge](https://www.curseforge.com/minecraft/mc-mods/iris-sodium-compat)).
**→ This is about the pack's *current* stack (Iris 1.8.14-beta.1 + Sodium 0.8.13), so verify the pack boots cleanly with shaders before attributing any new frame-time delta to a new mod.**
15. **More Culling × Create/Flywheel:** the only recent report is [MoreCulling#475 "Create Fly problem"](https://github.com/FxMorin/MoreCulling/issues/475) (2026‑10‑08), where the reporter says entity blocks disappear at some angles; the maintainer replied: "are you sure its caused by moreculling? because it doesn't touch blockentity renderer, also you seems to have blockstate culling disabled so it doesn't even touch blocks". Unresolved as of writing → `COMMUNITY`, low weight, but worth a Create-specific smoke test.
16. **Distinct pack-internal redundancies to avoid stacking:** EntityCulling 1.11.2 vs Chloride entity culling; More Culling leaves vs Cull Leaves vs Chloride leaves; Particle Core vs Smart Particles vs Cull Particles; Dynamic FPS 3.11.4 vs Idle Boost; LambDynamicLights 4.8.11 vs Sodium Dynamic Lights. Community consensus in the NeoForge 1.21.1 threads is that "MoreCulling and EntityCulling should play nice together" and that stacking more culling mods is not automatically better. `COMMUNITY`.
17. **No credible 2025‑2026 "best NeoForge 1.21.1 perf mods" list surfaced a major candidate I have not already covered.** The frequently-cited lists are Reddit threads (CAPTCHA-blocked for automated reading) and SEO guides; the mods they name on the client side are Sodium/Lithium/FerriteCore/ModernFix/ImmediatelyFast/EntityCulling/BadOptimizations/Cull Leaves/More Culling/Krypton/Ixeris/Gnetum — all covered above. The only additional NeoForge-1.21.1 client-optimisation projects Modrinth surfaced that are not in the list above were: Annus (networking), ORB (recipe book), Output Booster/inputbooster (input polling, AI-content flagged), AutoTune FPS (AI-generated, 0 followers), Fandai Engine (unsubstantiated "rewrites the entire rendering pipeline", 891 downloads) — none of which I would add on evidence grounds. `COMMUNITY`/`INFERENCE`.
---
## Top levers (ranked)
Ordered by (expected gain × confidence) / risk, for *this* fleet.
| # | Lever | Expected impact | Best fleet machine | Risk | Confidence |
|---|---|---|---|---|---|
| 1 | **More Culling 1.0.10 + Cloth Config** (leaves option off) | Med | all three; most on P1/P2 in dense bases | Low‑Med | High |
| 2 | **Particle Core 0.3.3** | Med‑High in particle-heavy scenes | P0, P1 (and P2 in Create/Alex's Mobs areas) | Med (async ticking off-switch) | Med‑High |
| 3 | **BadOptimizations 2.4.1** | Low‑Med (lightmap/tick) | all, incl. tick-bound P2 | Low | Med‑High |
| 4 | **Gnetum 3.3.6** (the Exordium replacement) | Med in HUD-heavy scenes | P0 (small screen, controller), P1 | Low‑Med | Med |
| 5 | **Ixeris 4.6.8** | High on P1 only if high-polling mouse; ~0 on Linux | P1 (and P2 if Windows-style mouse) | Med‑High | Med |
| 6 | **Super Resolution** (FSR1/SGSR, shaders in compatibility mode) | High on P0; Med on P1; ~0 on P2 | P0 first | Med‑High (alpha only on 1.21.1) | Low‑Med |
| 7 | **Better Block Entities 1.3.4** | High in chest/storage-heavy builds | all (base-build dependent) | Med (EMF compat not on 1.21.1) | Med |
| 8 | **Cull Leaves 4.1.1 + MidnightLib** (instead of, not in addition to, More Culling's leaves option) | Low‑Med, leaves only | all | Low | Med‑High |
| 9 | **Sodium Extra 0.9.4** (unlocks particle/animation/entity levers) + **Reese's Sodium Options 2.2.4** (Controlify-aware tuning UI) | Low direct / high enabling | P0, P1 | Low | Med‑High |
| 10 | **Flerovium 1.1.3** | Med on items/particles/entities | all | Med‑High (glitch-prone, alpha branch) | Low‑Med |
| 11 | **Default Options + Balm** | 0 runtime; guarantees tuned baseline ships | all | Low | High |
| 12 | **Chloride 1.8.1** (only if consolidating culling/JEI/chest models) | Med but overlapping | P2 (Sable-aware culling) | Med | Low‑Med |
| 13 | **Krypton Reno** — better judged as a *server* mod | Low client / Med server | P1/P2 chunk-packet stalls | Med (license, native libs) | Low‑Med |
| — | **Skip outright:** Exordium, Sodium Leaf Culling, ScalableLux, Nvidium, VulkanMod, EBE, FastChest, Memory Leak Fix, Ksyxis (client), FastLoad, Noisium (client), C2ME (client), Moonrise (client), Sodium Extras, Sodium Options API, Sodium Dynamic Lights, ThreadTweak/Smooth Boot, More Culling Extra, YOSBR, Idle Boost, Fast Item Frames, Fast Paintings, Model Gap Fix | — | — | — | High |
---
## Open questions to verify by benchmark
1. **What is each machine's actual bottleneck?** P0 = iGPU/GPU-bound at 1280×800; P1 = 6 GB VRAM; P2 = main-thread + 8 GB RAM. This determines whether Super Resolution (GPU), Particle Core (CPU/GPU), or nothing helps P2. Resolve with frame-time breakdown (not FPS) before adding anything.
2. **Does the pack's *current* Iris 1.8.14-beta.1 + Sodium 0.8.13 NeoForge 1.21.1 stack need the third-party "Iris-Sodium Compat" patch?** Boot with and without shaders and compare log mixin warnings before attributing any delta to a new mod.
3. **Ixeris on P1 (Windows + GTX 1060):** does it trigger the older-NVIDIA-card crash class (issue #134) or any Iris/DH interaction? Measure at the mouse's real polling rate.
4. **Leaves, three-way A/B:** (a) Better Leaves 9.6 alone, (b) + More Culling leaves option, (c) + Cull Leaves. Compare FPS *and* leaf appearance with Complementary Reimagined and with shaders off, in a dense forest.
5. **Better Block Entities vs EMF 3.3.9 + ETF 7.2.4 + Fresh Animations on 1.21.1:** do chest/sign/bed/shulker models break? BBE's EMF compat is documented as 1.21.11+ only.
6. **Particle Core async ticking stability** across Create 6.0.10 contraptions, Alex's Caves 2.0.10, Alex's Mobs and Twilight Forest 4.8.3345 particles; verify `disableOptimizations` is a sufficient fallback.
7. **Gnetum HUD caching vs Xaero's Minimap 26.5.0 / World Map 1.46.0 / JEI 19.57 / Travelers Titles / Legendary Tooltips / Inventory Particles** — flicker history exists (fixed in 3.2.0/3.3.4), re-verify on this HUD set.
8. **Flerovium backface culling vs Better Combat 2.4.0, Emotecraft 2.4.12, 3D Skin Layers 1.11.3, EMF+FA, Exposure 1.9.18 viewfinder** — look for missing faces / inverted normals, not just FPS.
9. **Super Resolution on P0 only:** FSR1-but-not-FSR3 with Complementary Reimagined r5.9.3, at 1.3–1.7× SR ratio, with Distant Horizons enabled; check DH LOD seam/quality and any RADV-specific artifacts.
10. **More Culling × Create 6.0.10/Flywheel 1.0.6 + Sable 2.0.5 + Create Aeronautics 1.3.2:** smoke-test moving contraptions/aeronautics physics frames for disappearing block entities (issue #475 class).
11. **Krypton Reno client-only vs client+server:** its client-side keys are only `clientEncrypt`/`connectionMicroOpt`/`bestVarLong`/netty sizing; the chunk-packet culling needs the server. Decide whether it is worth a server deployment at all.
12. **Chloride overlap audit:** if added, confirm EntityCulling 1.11.2 and Chloride's entity culling do not double-tax or disagree (whitelist interactions), and confirm its declared incompatible mod is not something the pack uses.
---
## Sources
**Kept (authoritative / primary):**
- Modrinth v2 API `/project/...` and `/project/.../version?loaders=["neoforge"]&game_versions=["1.21.1"]` — the availability backbone for every "y/n + version" claim (Sodium Extra, RSO, Sodium Options API, BadOptimizations, Flerovium, Ixeris, Sodium Leaf Culling, Cull Leaves, More Culling, Particle Core, Better Block Entities, Chloride, Super Resolution, Gnetum, Moonrise, Chloride, Default Options, Balm, EBE, FastChest, Nvidium, VulkanMod, Krypton, Ksyxis, Noisium, C2ME, Moonrise, Fast Item Frames, More Culling Extra, Memory Leak Fix, Lithium, Modelfix, Exordium, Sodium Extras, YOSBR, ThreadTweak, FastLoad, Krypton Reno, ScalableLux).
- https://modrinth.com/mod/exordium + https://github.com/tr7zw/Exordium/releases — "no backports planned", NeoForge builds 1.21.6+.
- https://github.com/txnimc/SodiumLeafCulling/issues?q=is%3Aissue — open Sodium‑0.8.11+ crash reports (the decisive "skip").
- https://github.com/FxMorin/MoreCulling/wiki (Home) — exact list of culling techniques.
- https://www.curseforge.com/minecraft/texture-packs/motschens-better-leaves + https://modrinth.com/mod/cull-leaves — same author recommends pairing Cull Leaves with Better Leaves.
- https://modrinth.com/mod/gnetum — ImmediatelyFast compatibility, Xaero's/IF flicker fixes, Sodium 0.8 config integration.
- https://modrinth.com/mod/ixeris — author benchmark table incl. per-OS numbers.
- https://modrinth.com/mod/krypton-fnp (Krypton Reno) — documented config keys, incompatibility list, server-vs-client split.
- https://github.com/ComplementaryDevelopment/ComplementaryReimagined/issues/317 — CR has no Super Resolution shader interface; FSR3 ghosting; motion-vector caveats.
- https://modrinth.com/mod/nvidium and https://github.com/xCollateral/VulkanMod/wiki/Incompatible-mods — Turing+ requirement; DH listed incompatible.
- https://modrinth.com/mod/moonrise-opt — "primarily benefits the server"; C2ME fundamentally incompatible; auto-disables conflicting Lithium/FerriteCore parts.
- https://github.com/FxMorin/MoreCulling/issues/475 — the only recent Create/Flywheel culling report (unconfirmed).
- https://www.curseforge.com/minecraft/mc-mods/iris-sodium-compat — third-party fix for the 1.21.1 NeoForge Iris/Sodium mixin gap.
**Dropped:**
- 9minecraft / minestrator / ouiheberg / topmoddedservers "best perf mods" listicles — SEO content, no version-date traceability, no primary confirmation.
- Reddit threads (r/feedthebeast, r/DistantHorizons, r/ModdedMinecraft) — bot-blocked on read, and only used as corroboration for the two claims I tagged `COMMUNITY` (More/EntityCulling coexistence, ScalableLux/DH breakage). Answer‑overflow/quorum mirrors used only for the DH+Starlight claim.
- CurseForge mod pages other than for file-level version confirmation — Modrinth API gave the same metadata with machine-readable versions.
- "Async Particles", "Optimized Block Entities", "Vanillin", "OptiLeaves", "Valkyrien", "OptiLeaves" — mentioned in community lists but not verified for NeoForge 1.21.1; out of budget.
---
## Gaps
- **No candidate has a published benchmark on a 212-mod pack with DH + Iris shaders.** Every gain figure quoted here is either the author's own micro-benchmark or a differently-configured pack (Fabulously Optimized, superflat worlds). Treat all impact ratings as directional.
- **Could not resolve the three project IDs declared incompatible by Moonrise 1.21.1 NeoForge builds** (only their IDs were in the API response; the README names C2ME explicitly and says Lithium/FerriteCore are auto-handled). Low priority since Moonrise is a server-side recommendation.
- **Could not find an official Distant Horizons "incompatible mods" page.** The ScalableLux/DH incompatibility and "More Culling is a 'smaller' DH-safe mod" claims rest on community answers (DH Discord mirrors), not on DH docs. If DH compat for any culling mod is a deciding factor, ask in the DH Discord or test directly.
- **Exordium alternatives beyond Gnetum were not searched exhaustively** (e.g. other HUD-caching mods for 1.21.1 NeoForge). Gnetum covers the use case and is the maintained option.
- **Chloride's declared incompatible project was inferred from its own changelog ("Smooth Skies"), not from the version dependency metadata**, which exposes only the project ID. Verify before installing.
- **Verification of `Sodium Extra`'s optional dependency projects** (Modrinth IDs `YL57xq9U`, `EE4vxUHj`) was not completed; both are optional, so this only matters if you try to add Sodium Extra without RSO.
@@ -0,0 +1,150 @@
# Research: JVM, launcher, OS & driver levers — Onion MC client (NeoForge 1.21.1, Java 21, ~212 mods, Distant Horizons mandatory)
## Summary
For a DH-mandatory 200+ mod NeoForge 1.21.1 client, the single biggest platform lever is getting off stock G1 GC (Distant Horizons itself warns about it) onto either Generational ZGC (`-XX:+UseZGC -XX:+ZGenerational` on JDK 21) or Shenandoah, with heap sized to real headroom (5–6 GB on the 16 GB Deck and the 8 GB-free Linux box, 6–8 GB on the 32 GB Windows box) — oversizing costs more than it buys. Most OS/driver levers are small but cheap: `mesa_glthread=true` + `gamemoderun` on the Steam Deck, explicit `__GL_THREADED_OPTIMIZATIONS=0` on Linux NVIDIA (Sodium already sets it in source), and NVCP "Prefer maximum performance" on Windows. GraalVM is a benchmark-first experiment only: GraalVM for JDK 21 does not support Generational ZGC and real-world NeoForge 1.21.1 miscompiles exist.
---
## Findings
### 1. The GC baseline: G1 + why DH complains about it
- **NeoForge 1.21.1 requires Java 21**, so GC options are: G1 (default), Parallel (default for server-class? no—G1 default since JDK 9), Generational ZGC, Shenandoah. [NeoForge docs](https://docs.neoforged.net/) (DOCUMENTED).
- Vanilla ships its own G1 tuning in the client JSON: `-XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M`. Widely quoted from Mojang's version JSON. [Minecraft Forum](https://www.minecraftforum.net/forums/support/java-edition-support/3082919-jvm-arguments-using-g1gc-for-minecraft) (COMMUNITY, corroborated across 2 threads).
- **Distant Horizons logs at startup**: `[Render thread/WARN]: Distant Horizons: G1 Garbage collector detected. This can cause FPS stuttering. It's recommended to use a concurrent garbage collector like ZGC (Java 21+) or Shenandoah (Java 8 through 17) for a smoother experience.` DH is closed-source; exact wording verified from two independent log excerpts. [Minecraft Forum log](https://www.minecraftforum.net/forums/support/java-edition-support/3228579-modpack-randomly-losing-fps-and-sometimes-crashing), [New Eden modpack page quoting the warning](https://modrinth.com/project/7jwudrLZ) (DOCUMENTED — it is DH's own runtime warning). Newer DH writes it to the log only instead of an on-screen alert [Reddit r/ModdedMinecraft](https://www.reddit.com/r/ModdedMinecraft/comments/1pnk5uc/getting_this_message_every_time_i_launch_my_game/) (COMMUNITY). Mechanism is consistent with DH's large LOD allocations → G1 old-gen/mixed pauses = visible stutters (INFERENCE from the warning text + DH's memory behavior).
- Practical note: on Java 21, `-XX:+UseZGC` **alone** selects the *legacy non-generational* ZGC. Generational ZGC (what you want, and what "Java 21+" implies) needs `-XX:+UseZGC -XX:+ZGenerational`. Generational mode is only the *default* on JDK 23+ (JEP 474); non-gen was removed in JDK 24 (JEP 490). [OpenJDK ZGC wiki](https://wiki.openjdk.org/display/zgc/Main), [JEP 474](https://openjdk.org/jeps/474) (VERIFIED).
### 2. G1 tuned (Aikar-style) vs client
- Aikar's flags were tuned for Paper *servers* with large heaps (`MaxGCPauseMillis=200`, `G1NewSizePercent=30`…). [aikar.co via brucethemoose Benchmark.py](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks/blob/main/Benchmark.py) (DOCUMENTED origin, COMMUNITY applicability).
- brucethemoose (benchmarked repo, most credible MC flags source): Aikar's high `G1NewSizePercent` effectively clamps `MaxGCPauseMillis`, producing long stutters on some *clients*; clients also fill old gen far slower than a busy server. He ships a client-flavored G1 set: `-XX:+UseG1GC -XX:MaxGCPauseMillis=37 -XX:G1HeapRegionSize=16M -XX:G1NewSizePercent=23 -XX:G1ReservePercent=20 -XX:G1MixedGCCountTarget=3 -XX:G1HeapWastePercent=20 -XX:InitiatingHeapOccupancyPercent=10 -XX:G1RSetUpdatingPauseTimePercent=0 -XX:MaxTenuringThreshold=1 -XX:GCTimeRatio=99 …` [README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks) (DOCUMENTED, benchmarked; **Java-17-era repo — revalidate on 21**).
- Expectation: tuned G1 remains the best default on **4C/8T CPUs with tight RAM** (P0, P2). It has no concurrent-cycle CPU tax like ZGC/Shenandoah. (INFERENCE from brucethemoose's guidance "G1GC on servers/clients with less RAM and fewer cores".)
### 3. Generational ZGC on JDK 21
- Flags for this pack on JDK 21: `-XX:+UseZGC -XX:+ZGenerational -Xmx<N>G` (+ optionally `-XX:SoftMaxHeapSize`, `-XX:ConcGCThreads`). [OpenJDK ZGC wiki](https://wiki.openjdk.org/display/zgc/Main) (VERIFIED).
- Sizing rule from the ZGC docs: heap must hold live-set **plus headroom for allocations while a cycle runs**; "in general, the more memory you give to ZGC the better", balanced against waste; `SoftMaxHeapSize` lets you cap heuristic target below Xmx. This makes ZGC a poor fit for P2 (only ~8 GB free RAM total) and marginal on the Deck's shared 16 GB. (VERIFIED docs + INFERENCE for fleet.)
- ZGC pauses are <1 ms regardless of heap, but it costs throughput: brucethemoose measured "a significant client FPS hit" from ZGC on an 8C/16T laptop, and notes ZGC wants *more* RAM and a raised `ConcGCThreads` cap (default = logical cores/4; he suggests 2 on 4-thread CPUs). [README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks) (DOCUMENTED/COMMUNITY benchmark).
- DH's warning explicitly blesses ZGC as the primary fix; the DH community answer is always `-XX:+UseZGC` on Java 21 [r/MinecraftHelp NeoForge 1.21.1 thread](https://www.reddit.com/r/MinecraftHelp/comments/1svzilf/java_neoforge_1211_distant_horizons_g1_garbage/) (COMMUNITY).
- **GraalVM for JDK 21 does not support Generational ZGC** ("The following JDK 21 features are not available: JEP 439 Generational ZGC"). So GenZGC ⇒ a plain OpenJDK distro (Temurin et al.), not GraalVM 21. [GraalVM JDK 21 release notes](https://www.graalvm.org/release-notes/JDK_21/) (VERIFIED).
### 4. Shenandoah
- Not in Oracle JDK; available in Temurin/OpenJDK-based builds "from version 11 onward". [Red Hat Temurin docs](https://docs.redhat.com/en/documentation/red_hat_build_of_openjdk/21/html-single/getting_started_with_eclipse_temurin/index); not every build ships it — verify with `java -XX:+UseShenandoahGC -version` [Stack Overflow](https://stackoverflow.com/questions/73344814/openjdk-17-cant-use-shenandoahgc) (DOCUMENTED + caveat).
- brucethemoose's benchmarked verdict: **"I recommend Shenandoah on clients"**; flags `-XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu -XX:ShenandoahGuaranteedGCInterval=1000000 -XX:AllocatePrefetchStyle=1`; it dislikes `AllocatePrefetchStyle=3`; mode/heuristic knobs changed little in his tests. [README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks) (DOCUMENTED).
- Like ZGC it is concurrent, so it eats background CPU on 4C/8T — cheap stutter fix, small FPS tax. (INFERENCE.)
### 5. Heap sizing for a 200+ mod pack, and the cost of oversizing
- Prism's own wiki: "MORE RAM ALLOCATED DOESN'T MEAN BETTER PERFORMANCE! … a huge heap makes each garbage collection pause longer, which shows up in game as a stutter." [Prism Java settings wiki](https://prismlauncher.org/wiki/help-pages/java-settings/) (DOCUMENTED).
- brucethemoose: "Allocating too much memory can break gc or just slow Minecraft down, even if you have plenty to spare… allocate only as much as it needs (usually less than 8G)"; set `-Xms` = `-Xmx` **except** on low-RAM systems where Xms should stay below Xmx. [README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks) (DOCUMENTED).
- For this pack: DH's LOD cache, Alex's Caves/Mowzie/Geckolib models and 212 mods plausibly put live-set near 3–5 GB with LODs loaded (INFERENCE — must be measured with Spark/F3). Recommended: **P0 5–6 GB, P1 6–8 GB, P2 5 GB max** (P2 has ~8 GB free for the whole OS+game). Oversizing harms: longer/less frequent G1 pauses, more RSS stolen from OS/page cache (fatal on 8 GB), ZGC cycles sweeping more memory. (INFERENCE, consistent with both sources above.)
### 6. `-XX:+AlwaysPreTouch` and Transparent Huge Pages (Linux)
- ZGC docs: if low latency is the goal, run Xms=Xmx and use `-XX:+AlwaysPreTouch` to page memory in **before** the app starts, avoiding commit/uncommit latency; uncommit can hurt latency. (VERIFIED: [ZGC wiki](https://wiki.openjdk.org/display/zgc/Main).)
- THP: `-XX:+UseLargePages -XX:+UseTransparentHugePages` issues `madvise(MADV_HUGEPAGE)`; requires kernel THP set to `madvise` in `/sys/kernel/mm/transparent_hugepage/enabled` (and, **for ZGC only**, `shmem_enabled=advise`). Some distros force `always`/`never` — check sysfs before benchmarking. (VERIFIED: [ZGC wiki](https://wiki.openjdk.org/display/zgc/Main).)
- brucethemoose: large pages "improve performance of Minecraft servers and clients"; on Windows they silently fail without admin/SeLockMemoryPrivilege — on Linux prefer `UseTransparentHugePages`. (DOCUMENTED: same README.)
- Cost: slower startup (pre-touch of full heap) and, with THP, potential memory bloat — risky on the 8 GB P2. Use on P1/P0, skip or test carefully on P2. (INFERENCE.)
### 7. GraalVM CE/EE (Oracle GraalVM) vs Temurin
- Since the "GraalVM for JDK 21" rebrand there is GraalVM Community Edition (free) and Oracle GraalVM; CE for JDK 21 exists as a full distribution. [GraalVM JDK 21 notes](https://www.graalvm.org/release-notes/JDK_21/) (VERIFIED). Note brucethemoose's README is older (recommends "EE 22.x", Java 17) — treat his EE claims as dated but directionally useful.
- Claims: client FPS gains are modest; chunk-gen/server workloads up to +20% on GraalVM EE. (DOCUMENTED-era 17: [README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks).)
- Constraints: **must use G1 with his Graal flags; GraalVM (of his era) doesn't work with ZGC/Shenandoah** — and GraalVM 21 verifiably lacks GenZGC (see §3). (DOCUMENTED both.)
- Compatibility risk is real on 1.21.1: a dedicated fix repo exists because "Integrated Scripting 1.0.22" crashes on GraalVM JDK 21 + NeoForge 1.21.1 [jan-guenter/integratedscripting-graalfix](https://github.com/jan-guenter/integratedscripting-graalfix); players report packs failing on GraalVM Java 21 [r/feedthebeast](https://www.reddit.com/r/feedthebeast/comments/18hta1r/how_i_about_doubled_my_minecraft_performance/) (COMMUNITY). With Flywheel 1.0.6 + Veil/Lodestone + Sable/Aeronautics JIT-heavy stacks in this pack, GraalVM is a **trial**, never the fleet baseline. (INFERENCE.)
- Obydux's "Minecraft-GraalVM-Flags" is **server startup** flags for GraalVM EE Java 17 — not applicable to a 1.21.1 client; dropped. [Obydux repo](https://github.com/Obydux/Minecraft-GraalVM-Flags).
### 8. Prism Launcher settings (applies to P0 flatpak and P2)
- **Memory**: per-instance Settings → Java → memory box (Xms/Xmx). Prism warns against over-allocation (see §5). [Java settings wiki](https://prismlauncher.org/wiki/help-pages/java-settings/) (DOCUMENTED).
- **Java path / JVM args**: same Java page — set the Temurin/GraalVM `bin/java` path and paste JVM arguments. (DOCUMENTED: same page.)
- **Wrapper command**: "Wrapper command allows launching using an extra wrapper program (like 'optirun' on Linux)" — this is where `gamemoderun` goes (Settings → Custom Commands). [Custom commands wiki](https://prismlauncher.org/wiki/help-pages/custom-commands/) (DOCUMENTED).
- **Environment variables**: Prism passes env vars to the java runtime (instance-level). [Env vars wiki](https://prismlauncher.org/wiki/help-pages/environment-variables/) (DOCUMENTED). Use for `mesa_glthread=true`, `__GL_THREADED_OPTIMIZATIONS=0`, `vblank_mode=0` etc.
- Flatpak Prism on the Deck: official install is via their own flatpak repo [Prism Steam Deck download](https://prismlauncher.org/download/steam-deck/); gamemode from inside a flatpak goes through the xdg-desktop-portal GameMode interface (proxies to Feral's daemon with PID mapping/permission checks) [portal docs](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.GameMode.html); some flatpaks need `flatpak override --talk-name=com.feralinteractive.GameMode` for direct D-Bus access [example](https://github.com/an-anime-team/flatpak-builds) (DOCUMENTED + COMMUNITY).
### 9. Linux driver/OS levers
- **mesa_glthread**: moves GL dispatch to a second thread inside Mesa. radeonsi (which is what Minecraft's OpenGL actually uses on the Deck's Van Gogh APU — RADV is Vulkan and irrelevant here) enables glthread **by default since Mesa 22.3**; Mesa has also shipped a driconf default for the *official Minecraft launcher* app since 22.0 — a Prism-launched `java` process should not be assumed to match those overrides, so set `mesa_glthread=true` explicitly. [Phoronix](https://www.phoronix.com/news/Mesa-22.3-RadeonSI-glthread-On), [PCGamingWiki](https://www.pcgamingwiki.com/wiki/Mesa), [MangoHud issue #676](https://github.com/flightlessmango/MangoHud/issues/676) (VERIFIED driver behavior; explicit-set recommendation INFERENCE). Glthread is "a big help to CPU-bound games" — i.e., exactly the Deck's 4-core Zen2 profile. (Phoronix, VERIFIED quote.)
- **NVIDIA proprietary**: Sodium 0.8.x/0.6.x **sets `__GL_THREADED_OPTIMIZATIONS=0` itself** on Linux right before GLFW window creation (`Libc.setEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", "0")` in `NvidiaWorkarounds`), because threaded optimization causes stalls with Sodium. [NvidiaWorkarounds.java (1.21.1/stable)](https://github.com/CaffeineMC/sodium/blob/1.21.1/stable/common/src/boot/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java) (VERIFIED). Setting it also in Prism env vars is harmless belt-and-braces.
- **gamemode**: `gamemoderun` as Prism wrapper; requests CPU governor + GPU perf level. [Feral GameMode](https://github.com/FeralInteractive/gamemode) / Prism wiki (DOCUMENTED, see §8).
- Optional: run java at raised priority (`renice` post-launch; negative nice needs root) — brucethemoose. (DOCUMENTED: README.)
### 10. Windows (P1) NVIDIA control panel
- **Threaded optimization is effectively not user-controllable for Minecraft**: Sodium's author (jellysquid3): the NVIDIA driver "forcefully enables Threaded Optimizations regardless of the control panel settings" because it hardcodes Minecraft detection for all `javaw.exe` processes. [sodium#2061](https://github.com/CaffeineMC/sodium/issues/2061) (VERIFIED, maintainer statement).
- What Sodium does on Windows instead: spoofs the process command line to `net.caffeinemc.sodium / net.minecraft.client.main.Main /` (keeps the driver's "good" Minecraft heuristics), then enables `GL_DEBUG_OUTPUT_SYNCHRONOUS` (KHR_debug) at context creation, which forces the driver to disable threaded command submission. It also detects the broken driver range x.y.15.2647–3622 (526.47 → before 536.23). [NvidiaWorkarounds.java](https://github.com/CaffeineMC/sodium/blob/1.21.1/stable/common/src/boot/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java), [sodium#1486 referenced in source](https://github.com/CaffeineMC/sodium/issues/1486) (VERIFIED).
- NVCP **Power management mode → Prefer maximum performance** remains a legitimate per-app setting for stabilizing clocks; community standard advice for MC. [Minecraft Forum thread on threaded optimization/NVCP](https://www.minecraftforum.net/forums/minecraft-java-edition/discussion/3144703-nvidia-threaded-optimization), [r/feedthebeast NVCP report](https://www.reddit.com/r/feedthebeast/comments/vzkoc0/great_performance_improvement_using_nvidia/) (COMMUNITY). Note P1 is VRAM-bound (1060 6GB): platform levers help pacing, not the VRAM wall (INFERENCE).
### 11. Steam Deck (P0) specifics
- Install Prism via its official flatpak repo; add Prism (or `flatpak run org.prismlauncher.PrismLauncher --launch <Instance>` desktop entry) as a non-Steam-game so it launches in Game Mode under gamescope (SteamOS's compositor — no extra gamescope config needed at 1280×800 native). [Prism Steam Deck page](https://prismlauncher.org/download/steam-deck/), [RetroDECK wiki example with `--launch`](https://retrodeck.readthedocs.io/en/latest/wiki_experiments/desktop-launch/desktop-launch-prism/), [GamingOnLinux guide](https://www.gamingonlinux.com/2022/10/minecraft-on-steam-deck-guide-with-prism-launcher-and-gamepad-support/) (DOCUMENTED + COMMUNITY).
- **UMA frame buffer (VRAM) is 1 GB reserved by default**; BIOS allows 4 GB. With DH + shaderpacks + 212 mods on an 8CU iGPU, raising it to 4 GB is a common stability/smoothness tweak (2560×1600 shared-memory reads dominate on Deck). [Windows Central how-to](https://www.windowscentral.com/gaming/pc-gaming/how-to-increase-vram-on-steam-deck), [PiMyLifeUp](https://pimylifeup.com/steam-deck-increase-vram/) (COMMUNITY).
- TDP cap (e.g., 8–10 W) stabilizes clocks → steadier frame pacing on battery; standard Deck practice. (COMMUNITY.)
- GC choice on 4C/8T Zen2 with 16 GB *shared* RAM: tuned G1 or Shenandoah; avoid ZGC (concurrent-cycle CPU tax + heap headroom taken from the iGPU's shared pool). (INFERENCE from §2–§5.)
### 12. Sodium's "NO_ERROR_CONTEXT" workaround — what it actually means
- Sodium's options include **"Use No-Error Context"** (`sodium.options.use_no_error_context`, tooltip: "Creates the OpenGL context without error checking") — i.e., Sodium requests a `KHR_no_error` GL context by default to shave per-call driver error-checking overhead. (VERIFIED from Sodium's own lang strings: [sodium#3407](https://github.com/CaffeineMC/sodium/issues/3407).)
- When the installed driver can't provide that, Sodium logs `Sodium has applied one or more workarounds …: [NVIDIA_THREADED_OPTIMIZATIONS_BROKEN, NO_ERROR_CONTEXT_UNSUPPORTED]` — `NO_ERROR_CONTEXT_UNSUPPORTED` simply means the no-error-context optimization was **disabled** and a normal error-checking context is used; "not necessarily an issue, but it may result in certain features or optimizations being disabled." [sodium#2961 log excerpt](https://github.com/CaffeineMC/sodium/issues/2961) (VERIFIED).
- User-facing takeaway: don't try to "fix" this warning; it's informational. Performance impact on supported drivers is small. (INFERENCE.)
---
## Lever table (recommended value per fleet machine)
| Lever | Recommended value | P0 Deck (Zen2/16GB shared) | P1 Win i7-7700K/1060 6GB | P2 Linux i7-6700K/1080 Ti, 8GB free | Expected impact | Risk | Confidence |
|---|---|---|---|---|---|---|---|
| GC engine | P0/P2: Shenandoah (`-XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu -XX:ShenandoahGuaranteedGCInterval=1000000`) or tuned G1; P1: Generational ZGC (`-XX:+UseZGC -XX:+ZGenerational`) | tuned G1 or Shenandoah | GenZGC (32 GB RAM makes headroom free) | tuned G1 or Shenandoah (not ZGC: RAM+CPU poor fit) | **High** (removes DH-flagged G1 stutters) | Low (config-only) | Med-High |
| G1 tuning (if G1) | brucethemoose client set: `MaxGCPauseMillis=37, G1NewSizePercent=23, G1HeapRegionSize=16M, G1MixedGCCountTarget=3, G1HeapWastePercent=20, IHOP=10, MaxTenuringThreshold=1` | yes | fallback if GenZGC regresses | yes | **Med** (1% lows) | Low | Med |
| Heap size | P0: 5–6 GB · P1: 6–8 GB · P2: 5 GB (Xmx=Xms except P2 low-RAM) | 5–6 GB | 6–8 GB | 5 GB, Xms<Xmx | **High** on P0/P2 (OOM/stutter), Med on P1 | Low | Med-High |
| `-XX:+AlwaysPreTouch` | on with Xms=Xmx | optional (slower boot from eMMC) | yes | skip (RAM-tight) | Low-Med (pacing consistency) | Low | Med |
| THP | `-XX:+UseLargePages -XX:+UseTransparentHugePages` with THP=`madvise` in sysfs (ZGC also needs `shmem_enabled=advise`) | test only | n/a (Windows: large pages need admin — skip) | test only (watch RSS bloat) | Low-Med | Low-Med | Low-Med |
| JVM distro | Temurin 21 baseline; GraalVM CE 21 as P1/P2 experiment (G1 only — no GenZGC on GraalVM 21) | Temurin | Temurin → GraalVM trial | Temurin → GraalVM trial (biggest CPU upside here) | Low-Med (Med upside on P2 CPU-bound scenes) | **Med** (mod miscompiles; e.g. Integrated Scripting fix repo) | Med |
| Prism wrapper | `gamemoderun` in Custom Commands → wrapper | yes | n/a | yes | Low-Med | Low | High (mechanism), Med (gain) |
| Prism env vars | `mesa_glthread=true` (P0); `__GL_THREADED_OPTIMIZATIONS=0` (P2) | yes | n/a | yes (Sodium also sets it; harmless) | Low-Med (P0 CPU-bound GL) | Low | Med-High |
| Mesa driver note | MC on Deck uses **radeonsi** (GL), not RADV; glthread default-on since Mesa 22.3 — still set env var for java | informational | n/a | n/a (NVIDIA proprietary has own path) | — | — | High |
| Windows NVCP | Power management: Prefer maximum performance; leave Threaded Optimization alone (driver ignores it for MC; Sodium's GL_DEBUG_OUTPUT_SYNCHRONOUS handles it) | n/a | yes | n/a | Low (P1 is VRAM-bound) | Low | Med |
| Steam Deck BIOS | UMA frame buffer 1 GB → 4 GB; cap TDP ~8–10 W | yes | n/a | n/a | Low-Med (stutter/stability) | Low-Med (BIOS fiddling) | Low-Med |
| Sodium no-error context | leave "Use No-Error Context" enabled; ignore `NO_ERROR_CONTEXT_UNSUPPORTED` log line | leave | leave | leave | ~0 (informational) | none | High |
---
## Sources
**Kept**
- [brucethemoose/Minecraft-Performance-Flags-Benchmarks README](https://github.com/brucethemoose/Minecraft-Performance-Flags-Benchmarks) — the benchmarked flags reference (G1 client vs ZGC vs Shenandoah, memory oversizing, large pages, GraalVM caveats).
- [OpenJDK ZGC wiki](https://wiki.openjdk.org/display/zgc/Main) — authoritative GenZGC flags, heap-headroom rule, SoftMaxHeapSize, AlwaysPreTouch, THP prerequisites.
- [JEP 474](https://openjdk.org/jeps/474) + ZGC wiki changelog — ZGenerational default only on JDK 23; non-gen removed JDK 24.
- [GraalVM for JDK 21 release notes](https://www.graalvm.org/release-notes/JDK_21/) — CE/Oracle split; Generational ZGC not available on GraalVM 21.
- Sodium source, branch [1.21.1/stable](https://github.com/CaffeineMC/sodium/tree/1.21.1/stable): [NvidiaWorkarounds.java](https://github.com/CaffeineMC/sodium/blob/1.21.1/stable/common/src/boot/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java), [AmdWorkarounds.java](https://github.com/CaffeineMC/sodium/blob/1.21.1/stable/common/src/boot/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/amd/AmdWorkarounds.java), [WindowMixin.java](https://github.com/CaffeineMC/sodium/blob/1.21.1/stable/common/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/context_creation/WindowMixin.java), [sodium#2061](https://github.com/CaffeineMC/sodium/issues/2061), [sodium#2961](https://github.com/CaffeineMC/sodium/issues/2961), [sodium#3407 (lang strings)](https://github.com/CaffeineMC/sodium/issues/3407) — exact meaning of NO_ERROR_CONTEXT / NVIDIA threaded-optimization workarounds, incl. `__GL_THREADED_OPTIMIZATIONS=0` on Linux.
- [Sodium Modrinth versions for 1.21.1 NeoForge](https://modrinth.com/mod/sodium/versions?g=1.21.1&l=neoforge) — confirms pack's Sodium 0.8.13 backport, Iris 1.8.13 / Sable / Aeronautics compat notes.
- [Prism wiki: Java settings](https://prismlauncher.org/wiki/help-pages/java-settings/), [Custom commands](https://prismlauncher.org/wiki/help-pages/custom-commands/), [Environment variables](https://prismlauncher.org/wiki/help-pages/environment-variables/), [Steam Deck download](https://prismlauncher.org/download/steam-deck/) — memory/java path/wrapper/env-var surfaces; flatpak install.
- [Phoronix: Mesa 22.3 RadeonSI glthread default](https://www.phoronix.com/news/Mesa-22.3-RadeonSI-glthread-On) + [PCGamingWiki Mesa](https://www.pcgamingwiki.com/wiki/Mesa) + [MangoHud#676](https://github.com/flightlessmango/MangoHud/issues/676) — glthread semantics/defaults and the Minecraft-launcher driconf nuance.
- DH warning text corroborated: [Minecraft Forum log](https://www.minecraftforum.net/forums/support/java-edition-support/3228579-modpack-randomly-losing-fps-and-sometimes-crashing), [New Eden on Modrinth](https://modrinth.com/project/7jwudrLZ).
- [Red Hat Temurin docs](https://docs.redhat.com/en/documentation/red_hat_build_of_openjdk/21/html-single/getting_started_with_eclipse_temurin/index) — Shenandoah bundled from 11 onward.
- [jan-guenter/integratedscripting-graalfix](https://github.com/jan-guenter/integratedscripting-graalfix) — concrete GraalVM JDK 21 + NeoForge 1.21.1 incompatibility.
- [Windows Central UMA frame buffer](https://www.windowscentral.com/gaming/pc-gaming/how-to-increase-vram-on-steam-deck) — Deck VRAM default/BIOS option.
- [xdg-desktop-portal GameMode](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.GameMode.html) — gamemode from inside flatpaks.
**Dropped**
- [Obydux/Minecraft-GraalVM-Flags](https://github.com/Obydux/Minecraft-GraalVM-Flags) — server startup flags, GraalVM EE Java 17 era; wrong target (client, Java 21).
- [fumora.net GraalVM vs OpenJDK "benchmarks"](https://www.fumora.net/lab/minecraft-graalvm-vs-openjdk) — third-party, server-plugin workload, methodology unclear.
- DriverEasy/SystWeak "fix stutter" pages — SEO content, low value.
- Most Reddit threads kept only as corroboration, not as primary claims (DH warning wording, GraalVM pack failures).
## Gaps
- **No credible client-side G1-vs-GenZGC-vs-Shenandoah benchmark for 200+ mod NeoForge 1.21.1 with DH** was found; brucethemoose's data is 1.20-era Java 17 and DH's warning is the only pack-specific signal. Must A/B locally (see below).
- Whether Shenandoah is present in *current Temurin 21 Windows x64* builds was not definitively confirmed (Red Hat doc implies yes; some historic Temurin builds lacked it) — verify with `java -XX:+UseShenandoahGC -version` per machine.
- SteamOS 3.x current THP sysfs defaults (`transparent_hugepage/enabled`, `shmem_enabled`) not verified remotely — check on device.
- Whether any mod in this pack (AllTheLeaks 1.1.13, DH 3.3.2) calls `System.gc()` such that `-XX:+DisableExplicitGC` would be counterproductive — not verified.
- Sodium 0.8.13-for-1.21.1 is a 2026 backport; exact workaround-list parity with mainline 0.8.x assumed (INFERENCE from 0.8.12 changelog "Improvements for hardware and mod compatibility").
## Top levers (ranked)
1. **Move off stock G1 per DH's warning** — P1: Generational ZGC; P0/P2: Shenandoah or client-tuned G1. Expected impact **High** (1% lows / hitching with DH LOD streams). All machines. Risk: low (launcher config). Confidence: Med-High.
2. **Heap sizing discipline** (P0 5–6 GB, P1 6–8 GB, P2 5 GB; Xms=Xmx except P2). Impact **High** on P0/P2, Med on P1. Risk low. Confidence Med-High.
3. **`mesa_glthread=true` + `gamemoderun` on the Deck** (explicit env var; glthread default-on only for driver/launcher overrides, not necessarily java). Impact **Med** (CPU-bound GL dispatch on 4 cores). Risk low. Confidence Med.
4. **GraalVM CE 21 trial on P2 (and P1)** — G1-only, keep Temurin fallback. Impact **Med** (CPU-bound chunk/scene prep). Risk **Med** (miscompiles; no GenZGC). Confidence Med.
5. **`__GL_THREADED_OPTIMIZATIONS=0` env var on P2** (Sodium already sets it — belt-and-braces). Impact **Low-Med**. Risk none. Confidence High (mechanism), Med (gain).
6. **AlwaysPreTouch (+THP `madvise`) with Xms=Xmx on P1; test on P0; skip on P2**. Impact Low-Med (pacing consistency, slower boot). Risk low-med. Confidence Med.
7. **Deck BIOS UMA 4 GB + TDP cap ~8–10 W**. Impact Low-Med (stability/frame pacing with DH+shaders on 8CU). Risk low-med. Confidence Low-Med.
8. **Windows NVCP "Prefer maximum performance" on P1; leave Threaded Optimization untouched** (Sodium overrides it in code). Impact Low (VRAM-bound). Risk none. Confidence Med.
## Open questions to verify by benchmark
1. On each machine: G1 client-tuned vs Shenandoah vs GenZGC — 1% lows, 0.1% lows and hitch count during DH LOD streaming + chunk gen (use Spark GC monitor + Sodium 0.8.x FPS percentiles).
2. P1: does GenZGC at 6–8 GB show longer average frame times (concurrent CPU tax) than tuned G1 on the 7700K?
3. P2: at 5 GB heap with server view-distance 8 + DH, does live-set actually fit (Spark `gcmonitor` / allocation-rate), or is Shenandoah/G1 forced to over-collect?
4. Does `-XX:+DisableExplicitGC` change behavior of DH 3.3.2 / AllTheLeaks 1.1.13 in this pack (explicit-GC dependence)?
5. GraalVM CE 21: does the full pack (Flywheel 1.0.6, Veil/Lodestone, Sable 2.0.5, Aeronautics 1.3.2, SSRD) survive a 30-min play session without miscompile crashes, and net FPS on P2?
6. Deck: `mesa_glthread=true` on/off — measure avg FPS and 1% lows at 1280×800 with Complementary Reimagined r5.9.3 vs MakeUp Ultra Fast 9.5f; also confirm current SteamOS Mesa version's glthread default for a Prism-launched java process.
7. Deck: UMA 1 GB → 4 GB — measurable reduction in texture-streaming hitches with DH + shaders?
8. THP `madvise` on P2 (and `shmem_enabled` if ZGC tested): THP on/off delta on frame pacing and RSS.
9. Windows P1: with Sodium active (GL_DEBUG_OUTPUT_SYNCHRONOUS path), any measurable difference from NVCP Threaded Optimization settings at all? (Expect none — confirm.)
10. Xms=Xmx + AlwaysPreTouch on the Deck: startup time penalty vs frame-pacing benefit.
@@ -0,0 +1,106 @@
# 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.
@@ -0,0 +1,85 @@
# Research: Client-side performance sweep — content/mob mods (Onion MC, 1.21.1 / NeoForge 21.1.251)
Scope: client-side only (frame time, client tick, RAM/VRAM, startup). All pinned versions are 1.21.1 NeoForge. Every claim is tagged **VERIFIED** (primary source directly states it), **DOCUMENTED** (official changelog/wiki/README), **COMMUNITY** (user reports, issue trackers, forums), or **INFERENCE** (my reasoning from the sources).
## Summary
The content/mob mods are individually cheap, but the *stack* has three real client-side risk patterns: (1) **entity-count inflation** — Alex's Mobs (unofficial port), Fowlplay and Critters and Companions all have open reports of over-spawning, which directly increases client render + tick work; (2) **animation cost multipliers** — Fresh Animations / EMF-ETF make every animated modded mob far more expensive to render, and EMF has a documented blow-up with many mobs on screen; (3) **a handful of specific offenders** (Ars Nouveau brand-new mirrorweave/SkyWeave rendering, Apotheosis loot beams, Citadel entity tracking) that are either already fixed in the pinned versions or have config levers. Most mods in this list have **no known client perf issues at all**.
---
## Per-mod table
Legend for **cost type**: frame = render-thread cost; c-tick = client tick; RAM/VRAM; startup; none-known.
| Mod (pinned) | What it does | Client cost type | Known perf issues (URL + fixed?) | Perf-relevant config levers (exact keys only if seen) | Judgement |
|---|---|---|---|---|---|
| **Alex's Mobs unofficial port 1.22.17** | 85+ animated new mobs | **frame**, c-tick, RAM (models/textures) | • Raguto port #62 "tons of monsters constantly spawn when mod is enabled" ramps up *vanilla* monster spawns → more entities to render — **OPEN** on 1.21.1 ([#62](https://github.com/Raguto/AlexsMobs-1.21.1/issues/62)) **COMMUNITY**<br>• Original mod reputation: "notoriously bad for performance… noticeable increase in lag caused by all the spawning" ([Reddit](https://www.reddit.com/r/feedthebeast/comments/1sjfen3/is_alexs_mobs_really_that_bad_performancewise/)) **COMMUNITY**<br>• Over-spawning lobsters/catfish/flyfish/terrapins breaking beds/boats ([SteamPunk #83](https://github.com/LunaPixelStudios/SteamPunk/issues/83)) **COMMUNITY**<br>• Fabric port: vertex explosions/tearing with Sodium+Iris shaders, all shaderpacks ([Alexs-Mobs-Fabric #121](https://github.com/astryxion/Alexs-Mobs-Fabric/issues/121), Sep 2026, **OPEN**, Fabric build not our port) **COMMUNITY**<br>• Leafcutter-ant tick lag was server-side TPS ([#382](https://github.com/Alex-the-666/AlexsMobs/issues/382)) | Per-mob spawn probability lives in the `alexsmobs` config folder (Fandom *Configuration* page, per-mob spawn probabilities) **DOCUMENTED** — exact keys not read (page returned 403). | **tune** — keep, but cap spawn rates |
| **Citadel port 2.7.6** (Alex's Mobs lib) | Shared models/AI/entity-data library | frame, RAM | • "Alex's Mobs X Citadel: Slow Chunk loading" — chunk-generation lag; user reports setting Citadel's *track entities* option to false helped slightly ([Citadel #156](https://github.com/AlexModGuy/Citadel/issues/156), closed "completed" 2025-06-25, still reported persisting Dec 2024) **COMMUNITY**<br>• Historic memory leak 609 MB (`registeredEntityData` / `WeakIdentityHashMap`), 1.16.3, ([Citadel #12](https://github.com/Alex-the-666/Citadel/issues/12)) — very old, assumed long fixed **COMMUNITY** | Issue cites `citadel-common.toml` entity-**tracking** toggle (exact key not verified — do not invent) | **keep** |
| **Mowzie's Mobs 1.8.2** | Boss-tier animated enemies (GeckoLib) | frame | • #30 "Performance issues, outdated file structures" on **1.21.1 / NeoForge 21.1.219 / MM 1.8.1** — spark showed mowziesmobs structure processing; owner: "I believe I have fixed the issue… next mod patch" ([#30](https://github.com/BobMowzie/MowziesMobs-Public/issues/30), closed 2026-03-13); our **1.8.2 presumably contains it** **INFERENCE**<br>• Elokosa leap checks tick cost ([#38](https://github.com/BobMowzie/MowziesMobs-Public/issues/38), [#59](https://github.com/BobMowzie/MowziesMobs-Public/issues/59)) — server/tick side **COMMUNITY**<br>• Old Frostmaw FPS drop ([Crackpack-3 #101](https://github.com/DarkPacks/Crackpack-3/issues/101), 1.12-era) **COMMUNITY** | none known | **keep** |
| **Adorable Hamster Pets 3.7.0** | Tiny animated pet hamsters (genetics/NBT heavy) | frame, c-tick, RAM/NBT | • 3.6.1 changelog: "Resolved… pathfinding and AI issues where tamed hamsters following the player would sometimes experience **server-tick lag spikes**… with a lot of hamsters [following] at once" — **fixed in 3.6.1**, therefore present in 3.7.0 **DOCUMENTED** ([Modrinth](https://modrinth.com/mod/adorable-hamster-pets/version/QitZ5fVO))<br>• 3.6.0: moved genome tracking to IntArray NBT "without lagging the player entity" **DOCUMENTED** | "Wander Mode" radius; a config fallback for auto-guidebook delivery ([changelogs](https://www.curseforge.com/minecraft/mc-mods/adorable-hamster-pets/files/7969762)) — exact keys not read | **keep** |
| **Doggy Talents Next 1.19.1** | Skill-tree/accessory overhaul of vanilla wolves | frame (custom dog models/skins) | No dedicated client-FPS issue found. Related: CarryOn #684 progressive instability/stall ([CarryOn #684](https://github.com/Tschipp/CarryOn/issues/684)) **COMMUNITY**. Wiki: creative dog beds "randomly generated to a certain limit… to avoid performance issues" ([FAQ](https://doggytalentsnext.wiki.gg/wiki/FAQ)) **DOCUMENTED** | Skin enable/disable per client (CurseForge file notes) **DOCUMENTED** | **keep** |
| **Better Dogs X DTN 1.2.2** | Replaces DTN dog models/skins | frame (slightly heavier models) | No perf issue found ([Modrinth](https://modrinth.com/mod/better_dogs_x_doggy_talents_next)) | none known | **keep** |
| **Icy's Better Horses 2.1.0.1** | Horse AI/progression/traversal tweaks | none-known | No perf issue. One **client crash** with another mod (#31, Fabric 1.20.1, fixed in next jar) — not perf ([#31](https://github.com/Icywhenhot/Icy-s-Better-Horses/issues/31)) **COMMUNITY** | none known | **keep** |
| **Friends&Foes 4.0.27** | Mob-vote mobs (Copper Golem, Crab, Glare, Moobloom, Iceologer, Rascal, Tuff Golem, Wildfire…) + structures | frame (few new mobs), worldgen | **No known client perf issues found.** Tracked issues are crashes/compat (e.g. startup `MixinExtrasBootstrap` crash [#418](https://github.com/Faboslav/friends-and-foes/issues/418)) **COMMUNITY** | YACL-based config exists (mod requires YetAnotherConfigLib — Modrinth dependency listing) **DOCUMENTED**; no perf keys read | **keep** |
| **Flowery Mooblooms** (F&F addon) | One moobloom variant per flower | frame (variant count) | No perf issue found ([repo](https://github.com/Faboslav/friends-and-foes-flowery-mooblooms)) | none known | **keep** |
| **Critters and Companions** | Vanilla-style animals (otters, dragonflies, ferrets…) | frame + entity count, c-tick | • #91: lag from otters/dragonflies; no config file; "dragonflies… fly out of range and become unloaded… chunks full to the gills with dragonflies". Dev: dragonfly spawn weight reduced + Fabric config / Forge datapack override added, **Jul 2025** ([#91](https://github.com/bonsaistudi0s/CrittersAndCompanions/issues/91), closed) **COMMUNITY**<br>• Community: "always made servers… laggy… loading new chunks cause a lot of stuttering and CPU usage" ([Reddit](https://www.reddit.com/r/feedthebeast/comments/1bn2xip/carryon_and_critters_and_companions_causing_a_lot/)) **COMMUNITY** | No TOML keys; spawns are **data-file driven** → override via datapack (dev statement in #91) | **tune** via datapack, else candidate-remove |
| **Fowlplay 1.2.3** | Birds with realistic flight, natural spawning | **c-tick**, frame (entity count), RAM | • #214 ducks/birds spawn non-stop near rivers/oceans; F3 spawn cap "right under 400"; "almost 200 birds sitting in a single area" even after minimising group spawns — **OPEN, 1.21.1 NeoForge** ([#214](https://github.com/aqariio/Fowl-Play/issues/214)) **COMMUNITY**<br>• #196 `BirdEntity`/`GullEntity` recalculate **paths every tick** (`PathFinder.findPath()` per tick) — server-side but scales badly ([#196](https://github.com/aqariio/Fowl-Play/issues/196), open, 1.20.1 Forge) **COMMUNITY**<br>• #213 hawk AI crash with c2me async chunkloading ([#213](https://github.com/aqariio/Fowl-Play/issues/213)) **COMMUNITY** | Custom mob category; group-spawn settings exist (referenced in #214); no TOML keys read | **tune** (spawns) or **candidate-remove** if bird spam appears |
| **Wings of Fire 1.0** | 6 phoenix breeds as summoned mounts | frame (only while summoned) | **No known client perf issues found** ([Modrinth](https://modrinth.com/mod/wings-of-fire!)) **DOCUMENTED** | none known | **keep** |
| **Tiny Dragons (`rpg_companions_tiny_dragons`)** | Tameable tiny dragon companions | frame | **No known client perf issues found.** MCreator-generated mod ([MCreator page](https://mcreator.net/modification/113331/rpg-companions-tiny-dragons)) — MCreator mods are typically less optimised **INFERENCE** | none known | **keep** (low priority) |
| **Mermod 3.3.2** | Necklace → mermaid transformation/tail rendering | frame (player model when transformed) | **No known client perf issues found** — GitHub issue search for `lag OR fps OR performance OR memory` returned 0 results ([issues](https://github.com/ThatPreston/Mermod/issues?q=is%3Aissue+lag+OR+fps+OR+performance+OR+memory)) **VERIFIED** | none known | **keep** |
| **Artifacts 13.2.5** | Curio-slot utility trinkets | none-known (light client-tick) | **No known client perf issues found.** Old spawn-rate complaint about Mimics ([#3](https://github.com/ochotonida/artifacts/issues/3)) **COMMUNITY** | none known | **keep** |
| **Ars Nouveau 5.13.1** | Magic/spell system; client-side spell entities, particles, own skybox-style shaders | **frame** (particles/projectiles/shader blocks), c-tick, RAM | • SkyWeave/mirrorweave FPS drops (77→19 fps) — fixed by commit `640db2d` / PR #1714, Mar 2025 ([#1221](https://github.com/baileyholl/Ars-Nouveau/issues/1221)) → **already fixed in 5.13.1** (fix predates 5.9.1) **VERIFIED**<br>• Agronomic Sourcelink + AE2 growth acceleration spawns excessive visual entities → client <20 fps ([#1904](https://github.com/baileyholl/Ars-Nouveau/issues/1904), 5.9.1, closed 2026-06-08) **COMMUNITY**<br>• Storage Lectern massive **client** lag sorting 500+ Apotheosis-affixed items ([#1274](https://github.com/baileyholl/Ars-Nouveau/issues/1274), 1.19.2/3.23.0) **COMMUNITY**<br>• Planarium + Mekanism pipes → 1 fps ([#2108](https://github.com/baileyholl/Ars-Nouveau/issues/2108)) **COMMUNITY**<br>• Sylph particle spawner FPS tank (Optifine-era, fixed) ([#379](https://github.com/baileyholl/Ars-Nouveau/issues/379)) **COMMUNITY**<br>• A widely-reported "Ars projectiles drop FPS" case was traced to **Xaero's Minimap** ([Reddit](https://www.reddit.com/r/feedthebeast/comments/1o0yn4q/ars_nouveau_projectiles_dropping_fps_wildly/)) **COMMUNITY**<br>• Maintainer notes block-entity lookalike blocks (mirrorweave) "will always be more laggy than a normal static block"; recommends **EntityCulling** ([#1221 comment](https://github.com/baileyholl/Ars-Nouveau/issues/1221)) **VERIFIED** | none verified for particle budget | **keep**; watch the storage-lectern/automation entity-spam cases |
| **Apotheosis 8.8.0** | Affix items, gems, bosses/elites, loot beams | frame (loot-beam effects, boss glow), RAM | • #1191 perf issue (ShieldBreaker repeated capability comparisons) — **fixed in 7.3.2** (`cf0e2e8`), so **not present in 8.8.0** ([#1191](https://github.com/Shadows-of-Fire/Apotheosis/issues/1191), [changelog 7.3.2](https://github.com/Shadows-of-Fire/Apotheosis/blob/1.21/changelog.md)) **DOCUMENTED**<br>• Boss glow is cheap (glow duration 2 min, 20 s boss cooldown) **DOCUMENTED**<br>• Affix **loot-beam** in-world effects were *added* in 8.3.0 and are render-thread cost **DOCUMENTED** | Changelog 8.3.0: "These loot effects **can be disabled in the config file**" (exact key not read) | **keep**; disable loot beams if chasing frame time |
| **Too Many Bows** | ~38 bows with unique projectile effects | frame (only when firing) | **No known client perf issues found.** v2.1.0 changelog: "Updates: Logic and performance of bows" ([CurseForge file](https://www.curseforge.com/minecraft/mc-mods/too-many-bows/files/5932404)) **DOCUMENTED** | `/tmb reload bows` for registered bow settings ([wiki](https://wiki.pixeldreamstudios.net/mods/too-many-bows)) **DOCUMENTED** | **keep** |
| **Dungeon's Delight 1.5.1** | Farmer's Delight addon — cook/eat monsters | none-known | **No known client perf issues found.** 1.5.1 changelog is a compatibility/one-bug fix for FD 1.3.4 ([Modrinth 1.5.1](https://modrinth.com/mod/dungeons_delight/version/1.5.1)) **DOCUMENTED**. The task's "29 vanilla mixins" claim could not be verified — no source read (**UNVERIFIED**) | none known | **keep** |
| **Fisherman's Haven** | Fishing overhaul (rods, traps, bait, custom mobs, deco) | none-known | **No known client perf issues found** ([Modrinth](https://modrinth.com/mod/fishermans-haven)) | none known | **keep** |
| **Aquaculture 2** | Fishing expansion (30+ fish, rods) | none-known | • Loot-table calc lag (#113) was **server-side**, **fixed in Aquaculture 2.1.0** for MC 1.16.3 — long since fixed, not applicable to your 1.21.1 build ([#113](https://github.com/TeamMetallurgy/Aquaculture/issues/113)) **DOCUMENTED**<br>• Optifine bobber-render crash ([Optifine #3538](https://github.com/sp614x/optifine/issues/3538)) — irrelevant on Sodium **COMMUNITY** | none known | **keep** |
---
## Cross-cutting (apply to the whole content/mob set)
- **Fresh Animations + EMF/ETF is the single biggest animation multiplier.** EMF alone is not the problem, but stacking Fresh Animations with many mobs on screen is: a benchmarked case went **165→40 fps** (30 mobs, shaders on) and 400+→30-40 fps with 50 cows ([EMF #443](https://github.com/Traben-0/Entity_Model_Features/issues/443)) **COMMUNITY**. Maintainer: "you aren't going to be easily pushing past 200 fps with Fresh Animations on ever". Mitigation is config, not removal: EMF added an **"Animation LOD distance"** setting (skips animation frames beyond a distance) and a **"Retain LOD at low fps"** setting ([EMF changelog 1.3](https://github.com/Traben-0/Entity_Model_Features/blob/master/CHANGELOG.MD)) **DOCUMENTED**. Every animated content mod below multiplies this cost, so the animation settings should be tuned **before** removing content mods.
- **Entity-count inflation is the recurring theme.** Alex's Mobs port (#62), Fowlplay (#214) and Critters and Companions (#91) all have **open/community** over-spawn reports on or near 1.21.1. More entities = more render-list entries, more client-tick AI interpolation, more packet traffic. This is arguably the highest-leverage fix for the fleet, and it is all server-side spawn tuning rather than mod removal.
- **EntityCulling is recommended by Ars Nouveau's author** for the mirrorweave/SkyWeave block-entity case specifically ([#1221](https://github.com/baileyholl/Ars-Nouveau/issues/1221)) — you already ship EntityCulling 1.11.2, so that's covered **VERIFIED**.
- **Sodium/Iris + animated modded mobs is a known fragile combination.** Aside from the Fabric Alex's Mobs vertex-explosion report ([#121](https://github.com/astryxion/Alexs-Mobs-Fabric/issues/121)), the EMF #443 reports are all on the Sodium/Iris/Embeddium/Oculus stack. Worth a visual + frame-time check with shaders on vs off once benchmarking starts **COMMUNITY**.
- **Most mods in this sweep are clean.** Mermod, Wings of Fire, Tiny Dragons, Icy's Better Horses, Friends&Foes (+Flowery Mooblooms), Artifacts, Doggy Talents Next, Better Dogs, Too Many Bows, Dungeon's Delight, Fisherman's Haven, Aquaculture 2 have **no known client perf issues found** relevant to the pinned versions.
---
## Notable (the 3–5 that matter most)
1. **Alex's Mobs unofficial port is the top entity-count risk.** Raguto's 1.21.1 port has an **open** issue that it "ramps up vanilla monster spawn rates like crazy" ([#62](https://github.com/Raguto/AlexsMobs-1.21.1/issues/62)), on top of the mod's long-standing over-spawning reputation and Citadel's chunk-loading lag ([Citadel #156](https://github.com/AlexModGuy/Citadel/issues/156)). This is a *tune-spawns* lever, and per-mob spawn probabilities are exposed in the `alexsmobs` config folder (**DOCUMENTED** via Fandom Configuration, not read directly).
2. **Fowlplay's bird spawning is un-bounded in practice.** #214 (open, **1.21.1 NeoForge**) reports up to ~400 birds / ~200 in one area even after reducing group spawns, and #196 shows flight entities recompute pathfinding **every tick**. Even though the tick cost is server-side, hundreds of visible birds is a direct client frame + RAM cost, and this is the mod most likely to need spawn tuning or removal.
3. **Fresh Animations + EMF with many mobs is the largest measured FPS multiplier.** EMF #443 shows 4–8× FPS loss with 30–50 mobs on screen on the Sodium/Iris stack. Fixing this (EMF "Animation LOD distance" / "Retain LOD at low fps") is cheaper than removing content mods, and it compounds with every animated mob mod above.
4. **Ars Nouveau is mostly fine at 5.13.1, but has two known client hitches.** The mirrorweave/SkyWeave rendering FPS bug is **already fixed** (PR #1714, Mar 2025, well before 5.13.1), but the **Storage Lectern sorting Apotheosis-affixed items** (#1274, large client lag) and **Agronomic Sourcelink entity spam** (#1904, <20 fps) remain behaviour that a busy server can hit. Note it also flags EntityCulling as the mitigation — which you already run.
5. **Critters and Companions has no config file** — spawns are data-file driven, so the only lever is a **datapack override** ([#91](https://github.com/bonsaistudi0s/CrittersAndCompanions/issues/91)). If chunk-loading stutter or dragonfly pile-ups show up in profiling, that's the fix (or removal), not a TOML tweak.
---
## Sources
**Kept:**
- Raguto/AlexsMobs-1.21.1 issue #62 (spawn inflation, 1.21.1 NeoForge) — https://github.com/Raguto/AlexsMobs-1.21.1/issues/62
- Citadel issue #156 (chunk loading, entity tracking toggle, closed-completed 2025) — https://github.com/AlexModGuy/Citadel/issues/156
- Citadel issue #12 (historic 609 MB memory leak) — https://github.com/Alex-the-666/Citadel/issues/12
- Alexs-Mobs-Fabric issue #121 (Sodium/Iris vertex explosion, Fabric build) — https://github.com/astryxion/Alexs-Mobs-Fabric/issues/121
- Mowzie's Mobs-Public issues #30 / #38 / #59 (structure + Elokosa tick perf; #30 fixed next patch) — https://github.com/BobMowzie/MowziesMobs-Public/issues/30
- Adorable Hamster Pets changelogs (3.6.1 AI/tick fix, 3.6.0 NBT fix) — https://modrinth.com/mod/adorable-hamster-pets/version/QitZ5fVO
- Doggy Talents Next FAQ (beds capped to avoid perf issues) — https://doggytalentsnext.wiki.gg/wiki/FAQ
- Icy's Better Horses issue #31 (client crash, not perf; fixed) — https://github.com/Icywhenhot/Icy-s-Better-Horses/issues/31
- Critters and Companions issue #91 (over-spawn, datapack-only config) — https://github.com/bonsaistudi0s/CrittersAndCompanions/issues/91
- Fowl-Play issues #196 / #214 / #233 (per-tick pathfinding, bird over-spawn, spawn-mod incompat) — https://github.com/aqariio/Fowl-Play/issues/214
- Ars Nouveau issues #379 / #1221 / #1274 / #1904 / #2108 (particles, mirrorweave fixed, lectern, sourcelink, planarium) — https://github.com/baileyholl/Ars-Nouveau/issues/1221
- Apotheosis issue #1191 (perf fix in 7.3.2) + changelogs 1.21 (loot beams, glow, shield breaker) — https://github.com/Shadows-of-Fire/Apotheosis/blob/1.21/changelog.md
- Aquaculture issue #113 (loot-calc lag, fixed in 2.1.0) — https://github.com/TeamMetallurgy/Aquaculture/issues/113
- EMF issue #443 + EMF changelog (Fresh Animations FPS blow-up; Animation LOD settings) — https://github.com/Traben-0/Entity_Model_Features/issues/443
- Mermod issues search (0 perf results = negative evidence) — https://github.com/ThatPreston/Mermod/issues?q=is%3Aissue+lag+OR+fps+OR+performance+OR+memory
- Modrinth/CurseForge pages for Friends&Foes 4.x, Flowery Mooblooms, Wings of Fire, Dungeon's Delight 1.5.1, Fisherman's Haven, Too Many Bows, Artifacts, Mermod 3.3.2 — used for version/feature/bugfix confirmation.
**Dropped:**
- SteamPunk #83, Reddit r/feedthebeast Alex's Mobs threads — used only as corroboration for the over-spawn theme; individual player reports not weighted as fact.
- AlexsCaves #168 / #616 (Ray Cat FPS drop) — different mod (Alex's Caves), not in this pack.
- Optifine #3538 (Aquaculture bobber) — Optifine-specific, not applicable to Sodium.
- Crackpack-3 #101 (Frostmaw FPS) — 1.12-era, not applicable to 1.21.1.
- Various "performance mods" listicles/SEO pages — no primary evidence.
- Alex's Mobs Fandom Configuration page — returned HTTP 403; could not read exact config keys.
@@ -0,0 +1,71 @@
# Research: R9 — Libraries / UI / Misc client hooks sweep (Onion MC, 1.21.1 NeoForge 21.1.251)
## Summary
This group is mostly low-cost UI/QoL/library mods: for the large majority **no known client perf issues found** (searched GitHub issue trackers for lag/fps/memory/stutter/sodium/iris). The real, actionable items are: **Puzzles Lib 21.1.62 predates a hot-path event-dispatch fix shipped in 21.1.64**; **Fancy World Animations** has a documented history of heavy chain/lantern animation cost under Iris/Sodium (mitigated in the pinned 1.2.31 via frustum culling + EntityCulling occlusion compat); and **Jade** is the most common *hidden* cost driver here, since its tooltip providers (incl. reading Sophisticated Backpack contents) run on the client while pointing at blocks.
## Findings table
| Mod | What it does (1 line) | Client cost type | Known perf issues (URL, fixed?) | Perf-relevant config levers (exact keys only if seen) | Value vs cost |
|---|---|---|---|---|---|
| Fancy World Animations (fwa) 1.2.31 | Animates doors/trapdoors/chests/chains/lanterns etc. (mixes into BlockRenderer, ShadowRenderer, RenderChunkRegion) | **Frame** (per-animated-block render work, worst w/ 3D-texture chain packs + shaders) | DOCUMENTED: 3D chains/lanterns caused ~2× FPS loss under Iris/Sodium pre-1.1.17 (https://github.com/maDU59/FancyWorldAnimations/issues/24 — fixed via frustum culling in 1.1.17, EntityCulling occlusion-culling compat + cached bounding boxes in **1.2.31**, per issue #24 and #74). CPU-temp complaint: https://github.com/maDU59/FancyWorldAnimations/issues/83 (closed). Sodium visual-only bugs #27/#34/#64/#78 (closed). Embeddium duplicate-render #91 (https://github.com/maDU59/FancyWorldAnimations/issues/91) — **not applicable**: dev states Embeddium unsupported, "use Sodium"; pack uses real Sodium 0.8.13 | Per-animation toggles in FWA config (chains / lanterns / doors…) — seen in issue #24 discussion, not read from the config file itself | **Keep** (pin ≥1.2.31; already pinned). **Tune on Steam Deck**: consider disabling chain/lantern animations in mineshaft-heavy exploration; they are the documented hot path |
| Moonlight Lib 3.7.1 | MehVahdJukaar library (Supplementaries-family APIs, dynamic asset caching) | Startup (conditional) | DOCUMENTED: dynamic-asset cache system massively slowed modpack startup (160→320s) when paired with asset-generating mods (EveryCompat) — https://github.com/MehVahdJukaar/Moonlight/issues/382 (open, but traced to EveryCompat generation-mode config + zip listing behavior). No Moonlight-modded mods of that family appear in this pack's list | `everycomp-*.toml` generation modes — only relevant if EveryCompat/Supplementaries present (not in this topic's list) | **Keep** if a listed mod needs it; else **candidate-remove** (verify dependents first) |
| Iceberg 1.3.2 | Grend_G modding library (events/helpers, animated texture utils) | none-known | No known client perf issues found (issue tracker shows crashes/compat, not perf) | — | Keep (required by dependents) |
| Puzzles Lib 21.1.62 | Fuzss multiloader framework (events, config screens, GUI helpers) used by several UI mods | **Frame** (event-dispatch overhead) + startup | VERIFIED: ~8% of render thread spent in `EntityRenderer.handler$…$puzzleslib$createRenderState()` via dynamic-proxy/MethodHandle dispatch (per-entity per-frame hot path) — https://github.com/Fuzss/puzzles-lib/issues/202 (fixed). **Fix backported to 1.21.1 in v21.1.64 (2026-10-11): "Cache method handles in FabricEventFactory to reduce event listener invocation overhead"** — changelog: https://modrinth.com/mod/puzzles-lib (versions 21.1.63/21.1.64 for 1.21.1 NeoForge). **Pack pins 21.1.62 (2026-09-29) → predates the fix.** Note the ~8% figure was measured on MC 26.2/Fabric; the 1.21.1 changelog entry confirms the same dispatch path exists in this line | — | **Tune → update 21.1.62 → 21.1.64+** (highest-value single change in this group) |
| Balm 21.0.66 | BlayTheNinth cross-version library (Waystones etc.) | none-known | No known client perf issues found | — | Keep (Waystones dep) |
| Chalk 2.0.2 | Draws chalk marks on blocks | none-known | No known client perf issues found | — | Keep |
| Charta 1.2.5 | Card-game mod (playable card tables) | Startup / VRAM (INFERENCE: registers ~31 core shaders at resource load); frame only at card tables | Server-side lag-spike on player join: https://github.com/lucaargolo/charta/issues/14 (closed). No client perf issues found | — | **Candidate-remove** if the group doesn't play cards (client+server mod — must be removed on both sides); shaders tax startup/VRAM regardless of use |
| Client Sort 3.89.1 | Sort/move items in any inventory screen (client-only) | Frame (only inside container screens) | No known client perf issues found | — | Keep |
| Sounds (sounds) 2.4.22 | UI/ambient sound polish mod | none-known | No known client perf issues found | — | Keep |
| Now Playing 1.5.16 | Shows currently playing music track (HUD/toast) | Frame (tiny, HUD element) | No known client perf issues found | — | Keep |
| Music Disc Maker 3.0.5 | Creates custom music discs | none-known | No known client perf issues found | — | Keep |
| cat_jam | Cats bob heads to music (cosmetic) | Frame (negligible) | No known client perf issues found | — | Keep |
| PlayerRevive 2.1.2 (+ CreativeCore 2.13.48) | Downed/revive multiplayer mechanic | Frame (downed-player overlays) | No known client perf issues found | — | Keep |
| Jade 15.10.6 | WAILA-style "what am I looking at" tooltip | **Client-tick + frame** while pointing at blocks/entities; tooltip providers can read container contents | VERIFIED: FPS→0 ~1s when looking at player heads — https://github.com/Snownee/Jade/issues/742 (closed not-planned on 1.21.10 branch, but **workaround applies to 1.21.1**: add `player_head` to `hide-blocks.json`). Freeze looking at containers documented but tied to ViaFabricPlus server-version bridging (https://github.com/Snownee/Jade/issues/783, dup https://github.com/Snownee/Jade/issues/790) — not applicable to a native 1.21.1 server. SB-content reading implicated as the real cost in https://github.com/P3pp3rF1y/SophisticatedBackpacks/issues/1352 (owner: "another mod that shows backpack contents (like Jade)"). Historical client-disconnect memory leak PR: https://github.com/Snownee/Jade/pull/405 (long since in 15.x line) | `hide-blocks.json` (config file, exact name seen in #742); provider/plugin toggles in Jade's in-game config (key names not verified — do not guess) | **Keep + tune**: hide player heads/decor blocks in `hide-blocks.json`; if profiling shows tooltip cost, disable container-contents display — biggest overlap is with Sophisticated Backpacks |
| Patchouli 1.21-88 line | Guide-book framework (botania-style books) | Client-tick / frame inside books; startup (parses book JSONs) | DOCUMENTED: excessive client lag spike on advancement toasts — https://github.com/VazkiiMods/Patchouli/issues/481 (1.18.1 era, closed; not confirmed still present in 1.21.1). Crash-after-days on 1.21.1 NeoForge: https://github.com/VazkiiMods/Patchouli/issues/795 (stability, not perf) | — | Keep (needed by guide books); only re-check #481-class advancement stutter if it reproduces |
| Modonomicon | kli_kli data-driven guide-book mod (Patchouli alternative) | Client-tick / frame inside books | No known client perf issues found | — | Keep |
| Sophisticated Backpacks/Storage/Core | Upgradeable backpacks + storage drawers | Client-tick when tooltip/Jade reads contents; frame on heavy-content tooltips | VERIFIED interplay: "Massive Lag when Looking at Backpack" traced by the SB owner to content-display mods (Jade), not SB itself — https://github.com/P3pp3rF1y/SophisticatedBackpacks/issues/1352 (closed). NBT-heavy-content tooltip stutter pattern documented for other backpack mods: https://github.com/AllTheMods/ATM-6/issues/490 | — | Keep; **tune**: if Jade+SB tooltips stutter on the Deck, hide backpack/stack contents in Jade or stop shift-hover previews |
| Zume 1.2.2 | Smooth zoom keybind | none-known | No known client perf issues found | — | Keep |
| Quick Skin 3.0.1 | Reload own skin without relog | none-known | No known client perf issues found | — | Keep |
| Room For Two 0.3.0 | Two players share one bed / sit together | none-known | No known client perf issues found | — | Keep |
| Keybind Atlas | Searchable keybind manager screen | none-known | No known client perf issues found | — | Keep |
| FindMe | Hover-item search/highlight across nearby inventories | Client-tick (search scope) | No known client perf issues found | — | Keep |
| OctoLib/ShatterLib 0.6.2 | Small library dependency | none-known | No known client perf issues found | — | Keep (if listed as dependency; verify consumer mod before removing) |
| Fragmentum 5.2.0 | Small library dependency | none-known | No known client perf issues found | — | Keep (same caveat) |
| Mino++ 1.4.0 | Small library/utility mod | none-known | No known client perf issues found | — | Keep (verify consumer mod) |
| Comforts | Sleeping bags/hammocks | none-known | No known client perf issues found | — | Keep |
| MRU 1.0.41 | Mrthomas20121 utility library | none-known | No known client perf issues found | — | Keep (verify consumer mod) |
| Blueprint 8.2.0 | TeamAbODE library (Chipped/variant mods family) | none-known | No known client perf issues found | — | Keep |
| YACL | YetAnotherConfigLib — config screens | none-known | No known client perf issues found | — | Keep |
| Extreme Sound Muffler | Muffle selected sounds | none-known | No known client perf issues found | — | Keep |
| Loot Journal | Journal of looted items | Client-tick (event log) | No known client perf issues found | — | Keep |
| Enchantment Descriptions | Enchant descriptions in tooltips | Frame (tooltip text only) | No known client perf issues found | — | Keep |
| Mouse Tweaks | Drag-scroll inventory manipulation | none-known | No known client perf issues found | — | Keep |
| Clumps | Merges XP orbs into single entities | **Negative cost** (reduces entity render/tick load client & server) | Old server-side orb flood w/ Apotheosis: https://github.com/jaredlll08/Clumps/issues/22 (2019-era, closed) | — | **Keep** — net perf positive |
| Gravestone (henkelmax) | Places grave with inventory on death | none-known | No known client perf issues found | — | Keep |
| Waystones | Fast-travel waystones | none-known (client) | Server-side worldgen/save hangs: https://github.com/TwelveIterations/Waystones/issues/428 + #448 — **fixed Nov 2021**, not client-applicable | — | Keep |
| Lootr | Per-player instanced loot chests | none-known (client) | Server-side SavedData disk-write lag spikes: https://github.com/LootrMinecraft/Lootr/issues/804 (closed Jun 2026; author: general SavedData/IO issue, improved by data-system rewrite — server concern, not client) | — | Keep (note for the *server* perf report) |
| Open Parties and Claims (client side) | Chunk claims/parties + claim overlay (uses Xaero maps) | Frame (claim outline overlay) | VERIFIED: client-side claim-coloring optimization was implemented in 2022 — https://github.com/thexaero/open-parties-and-claims/issues/67 (closed completed Sep 2022). #758 boat-collision and #816 1M-claim-crash items are server-side | — | Keep |
| Apothic Combat | Combat overhaul module (Apotheosis-family) | Frame (particle/affix rendering in fights) | DOCUMENTED (adjacent, Apotheosis 1.20.1): dual-wield affixed weapons + Better Combat tank FPS — https://github.com/Shadows-of-Fire/Apotheosis/issues/804. **Better Combat is not in this pack**, so not directly applicable — INFERENCE | — | Keep |
| Explorer's / Nature's Compass | Locate biomes/structures, HUD display | Client-tick (search runs server-side + synced result) | No known client perf issues found | — | Keep |
## Notable
1. **Bump Puzzles Lib 21.1.62 → 21.1.64.** The pinned version predates the "cache method handles in FabricEventFactory" fix (v21.1.64, 2026-10-11) that resolved a measured ~8% render-thread hot-path overhead in per-entity render-state creation ([issue #202](https://github.com/Fuzss/puzzles-lib/issues/202); 1.21.1 changelog on [Modrinth](https://modrinth.com/mod/puzzles-lib)). This is the only confirmed actionable perf bug in this entire group.
2. **FWA 1.2.31 is the right version to be on, but it is not free.** Chains/lanterns with 3D-texture packs + shaders were a documented ~2× FPS loss; frustum culling (1.1.17) and EntityCulling occlusion-culling compat + cached bounding boxes (1.2.31) address exactly this ([#24](https://github.com/maDU59/FancyWorldAnimations/issues/24)). On the Steam Deck (weakest GPU), toggling chain/lantern animations in FWA config for mineshaft-heavy play is the cheap lever. The Embeddium duplicate-render issue [#91](https://github.com/maDU59/FancyWorldAnimations/issues/91) does not apply — dev explicitly supports Sodium, which this pack uses.
3. **Jade is the hidden cost driver of this group, not the mods it points at.** The SB "looking at backpack = 20-30 FPS" report was attributed by the SB author to Jade's content display ([SB #1352](https://github.com/P3pp3rF1y/SophisticatedBackpacks/issues/1352)); player-head tooltips could drop FPS to 0, fixed for users via `hide-blocks.json` ([Jade #742](https://github.com/Snownee/Jade/issues/742)). Pre-tune Jade (hide player heads; trim container-contents display) before blaming Sophisticated Backpacks in benchmarks.
4. **Charta is a plausible small startup/VRAM tax for a mod most players rarely use** (~31 core shaders registered at resource load — INFERENCE from pack file listing; no client perf issue reported in its tracker). If the card tables are unused, remove it on client+server.
5. **Most of the scary issues in these trackers are server-side** (Lootr SavedData writes, Waystones worldgen, OPAC boat collisions/claim-crash, Charta join-lag) — they belong in the server perf report, not the client one. For the client, "no known client perf issues found" genuinely applies to ~30 of these 40 mods.
## Sources
- Kept: FWA issue tracker + #24/#74/#91/#83 (github.com/maDU59/FancyWorldAnimations) — authoritative on the pinned version's perf history
- Kept: Puzzles Lib #202 + Modrinth 1.21.1 version changelogs (api.modrinth.com/v2/project/puzzles-lib) — proves fix version vs pinned version
- Kept: Jade #742/#783/#790 (github.com/Snownee/Jade) — real client-tick/frame costs + the `hide-blocks.json` lever
- Kept: SophisticatedBackpacks #1352 (github.com/P3pp3rF1y/SophisticatedBackpacks) — attributes the cost to Jade-style content display
- Kept: Moonlight #382 (github.com/MehVahdJukaar/Moonlight) — startup cost mechanism, conditional on asset-gen mods
- Kept: Lootr #804, Waystones #428/#448, OPAC #67/#758/#816, Charta #14 — confirm server-side classification
- Dropped: Reddit threads (r/feedthebeast "which mods cause most lag", UsefulMods wiki) — generic, not version-pinned, uncorroborated for these exact versions
- Dropped: Iceberg/Clumps unrelated repos (apache/iceberg, moonlight-stream) — name collisions, not the MC mods
## Gaps
- Could not find per-mod client benchmarks; magnitudes are from individual user spark profiles, not controlled tests — validate Puzzles Lib gain and FWA chain cost with a spark profile on one Deck before/after.
- Exact config key names for Jade (hide-blocks list location beyond `hide-blocks.json`), FWA per-animation toggles, and any Sophisticated Backpacks tooltip toggle were not read from the mods' source/config files (only referenced in issues) — do not write keys into pack configs without opening the jars.
- Several tiny mods (Mino++, OctoLib/ShatterLib, Fragmentum, MRU, Keybind Atlas, Room For Two, Music Disc Maker) have little public issue activity at all; their "none-known" verdicts reflect absence of evidence. Before removal, verify which installed mod consumes each library (check each jar's `META-INF/neoforge.mods.toml` dependency list).