Stage 3 'Дополнительные GL-оптимизации' item 1. GlStateManager bytecode in
26.2 (com.mojang.blaze3d.opengl.GlStateManager) shows every other GL bind
(texture, blend, depth, cull, scissor, framebuffer) is already absorbed by
vanilla's BLEND/DEPTH/CULL/SCISSOR/TEXTURES/COLOR_MASK/readFbo/writeFbo state
arrays, but _glUseProgram and _glBindVertexArray reach GL33C every time. Cache
those two slots and skip the redundant driver call.
GlStateCache holds (program, vao) with UNKNOWN=-1 as the safe state (never
short-circuits a real id). GlStateManagerCacheMixin @Inject HEAD cancellable
on both _glUseProgram and _glBindVertexArray; @Inject HEAD on glDeleteProgram
resets because the driver may recycle ids. Gated by micro_opts, so switching
micro-opts off also drops the cache (the mixin resets when the gate is off).
Optimize.onDisable also calls GlStateCache.reset().
Mixins/optimize/gl/ hits the 4-file folder limit, so the mixin lives under
mixins/optimize/gl/state/. Render/engine/optimize/gl/ hits the same limit,
holder is in render/engine/optimize/gl/state/.
6 new tests cover UNKNOWN start, mark/already-bound round trip per slot, slot
independence, id-reuse and '0 is a valid id'. Doc: mark the item ✅ partial
(only these two sites are safe to add; the other three would duplicate
vanilla's caches and hurt).
Stage 1 item 4 from optimize-layer-design.md, simplified to what the
reference does (auto|true|false) instead of the original 'measure first'
plan. Workers now holds the resolved flag:
- Workers.PARALLEL_MIN_CORES = 4 gate for AUTO mode
- Workers.configureParallelParticles(Boolean forced, boolean moduleEnabled)
- Workers.shouldParallelParticles() read by the future particle-extraction
mixin (26.2 QuadParticleGroup/SpriteBillboardParticle wiring is separate)
- Workers.resetParallelParticles() called by Optimize.onDisable
Optimize gains a parallel_particles BooleanValue (default true = AUTO).
OptimizePropertyBridge parses -Dlovisual.opt.parallel_particles as tri-state:
null (unset or 'auto' -> defer to module + cores gate), TRUE, FALSE;
the key is now part of OVERRIDE_KEYS so hasOverrides() sees it and toString()
includes it.
Docs: 'Что делаем лучше' item 4 marked done — no measurement gate, matching
the new plan direction.
Tests: 5 new WorkersTest cases for resolveParallelParticles + configure/reset
round trip; 4 new OptimizePropertyBridgeTest cases for the tri-state parser
(unset / explicit 'auto' / forced true|false / hasOverrides pickup). gradle
compileJava compileTestJava test checkFolderLimit green.
Adds five visible-cut switches to the misc/Optimize module (no_particles,
no_menu_background, no_bloom, entity_cull + entity_cull_distance) with
call-site helpers. Retargets EntityRenderDispatcherMixin, MenuBackgroundRenderer
and every bloomDisabled() call site (TrailsParticles, HitParticleHelper,
WorldParticlesFunnel, TargetEspCrystalRenderer, PredictionsWorldRenderer) to
Optimize. Blur2D drops its FpsOptimizer glass gate — the existing
OptimizeState.isNoGlass() already covers it. Deletes the standalone
visuals/optimization/FpsOptimizer module and misc/optimize/world/OutlineTracker
with its LevelRendererOutlineMixin (and its test).
Lang: consolidate module.optimize.description (fixes duplicate key), move the
five fpsoptimizer.* setting labels under optimize.*, drop fpsoptimizer.name/
description. lovisual.mixins.json: unregister the deleted mixin.
Docs: refresh optimize-layer-design.md status header; drop the 'we measure on
Windows before enabling' gate — universal-wins GL/Vulkan items go behind
default-off switches, benchmarks are optional and not blocking; note the
stage-3 p.9 (no_item_sort / item_single_copy) block is API-driven, not
measurement-driven; mark stage 4 in progress.
Per mod/docs/optimize-layer-design.md.
Status header: was 'черновик на согласование (2026-10-09)', now
'Этап 1 готов, Этап 2 + начало Этапа 3 готовы (2026-10-10)'.
New 'История изменений' section: three dated entries (Stage 1, Stage 2,
Stage 3 partial) listing files / tests / patch references.
Stages section: each line now carries a status icon (✅/🔄/❌), a completion
date, and a one-line summary of what shipped. Stage 3 partial lists what's
done (RenderBackendOps + GlRenderBackendOps + 3 GL mixins) and what's still
left (FrameFence, SharedDepthFbos, SkinAtlas, AnimFreeze, ItemLod,
LivingEntityLodMixin, ParticleMixin, SpawnerRendererMixin, etc.).
New 'Оценки для Этапов 3-4' section: rough effort estimates for the
remaining Stage 3 work (~25 mixins + ~8 helpers, 3-4 work sessions) and
Stage 4 (6 Vulkan items, profiling-driven, 1+ session for vkCmdCopyImage
which is needed for SkinAtlas to work on Vulkan).
Per mod/docs/optimize-layer-design.md Stage 1: pure helpers and mixin-contract
interfaces for the Optimize module, plus the OptimizeToggles engine-side state
holder and nine new toggles in Optimize. GL/Vulkan hooks are Stages 3-4.