Files
logan 611a1a5952 docs: client-perf analysis, bench harness and work journal
Everything the next agent needs to run the Phase 2 optimisation loop on a
machine that can launch the client:

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

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

43 KiB
Raw Permalink Blame History

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 — 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 — VERIFIED.

Defaults are hard-coded in PerformanceSettings / QualitySettings / AdvancedSettings in SodiumOptions.java @ mc1.21.1-0.8.13 — 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). 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 vs 0.8.13 lang — 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 — 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 — 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 — 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 — 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). 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 — 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 — 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 — 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 — 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 — 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:

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 — 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 — 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 — VERIFIED.

What that costs, confirmed in Create's own code: Create 6's kinetic/contraption renderers are guarded by Flywheel visualization availability —

protected void renderSafe(T be, …) {
    if (VisualizationManager.supportsVisualization(be.getLevel())) return;
    …
}

Create KineticBlockEntityRenderer @ mc1.21.1/dev — 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 — 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 — 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 — 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 — 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

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 — 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 — 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 — 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 — 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 — 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 — DOCUMENTED. Shipped defaults (config/entityculling.json, configVersion 9) — 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 — 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 — 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 — VERIFIED. Options and defaults — FerriteConfig.java @ 1.21.1 — 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 FastMaps 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 — 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 — 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 — 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 — 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 — 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 — 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 — DOCUMENTED. EntityCulling's solidLeaves option exists for exactly this scenario. Cull Leaves is not in the pack. Community reports 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 — DOCUMENTED. Reported cost ~5–10 FPS in mob-dense areas mcmodhub — 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 — DOCUMENTED (bug report). EMF exposes throttles (VERIFIED from 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 — 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

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.