Skip to content

Replace LWJGL 2/OpenGL with native Vulkan renderer (FML 4.0.0) - #5

Open
XMRhapsody0807 wants to merge 22 commits into
masterfrom
xmrhapsody/vulkan
Open

XMRhapsody0807 wants to merge 22 commits into
masterfrom
xmrhapsody/vulkan

Conversation

@XMRhapsody0807

@XMRhapsody0807 XMRhapsody0807 commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

中文摘要: 用 LWJGL 3.4.3 + 原生 Vulkan 渲染器替换 LWJGL 2/OpenGL(FML 4.0.0)。窗口/输入改用 GLFW,音频通过 FFM 调用 OpenAL,内置 Windows x64 与 macOS arm64/x64(含 MoltenVK)原生库;需要 Java 25。已在 macOS M5 Max 上完成真实运行测试,Windows 11 (RTX 5080) 经 PCL 用户测试,尚未完全验证。模组兼容性不在本次范围内。

Summary

Replaces the LWJGL 2 / OpenGL rendering stack with a native Vulkan renderer built on LWJGL 3.4.3. Version is plain 4.0.0.

What changed

  • LWJGL 3.4.3 + a native Vulkan renderer (pipeline library, GL state emulation layer, terrain section scheduling, translucent/water ordering fixes).
  • Bundled natives: Windows x64, macOS arm64 and x64 (including MoltenVK). Extracted to <gameDir>/.fml/natives.
  • GLFW window and input handling; OpenAL audio through the Java FFM API.
  • Java 25 runtime.
  • macOS: IOSurface-backed layer presentation path, swapchain info reporting.
  • Optimisations adapted from Minecraft 1.7 – 26.4 techniques plus Lunar/Badlion-style input handling; adaptive section commit budget and larger presenter surface pool.
  • F3 Vulkan debug overlay (can be disabled with debugOverlay=false in config/fml-vulkan.properties).
  • Removed the hidden 120 FPS cap; limit is now Client.fpsCap (0 = unlimited) and F3 shows the limit reason.
  • Mods and config are resolved from --gameDir.
  • MITEReleaseAccess falls back to the obfuscated Minecraft class (atv).
  • Bench harness: water/light scenes, optimisation switch logging, hitch attribution.

Testing

  • macOS (Apple M5 Max): real runs covering title screen, world load, traversal and all 4 dimensions.
  • NR-29 benchmark (OpenGL baseline vs native Vulkan v4). Setup: Apple M5 Max, macOS, 1920x1080 window, VSync off, all frame limiters off, presented-frame metrics, median of 3 runs; OpenGL baseline = master + LWJGL 2. Avg FPS / 1% low FPS:
Dimension Distance OpenGL baseline Native v4 Avg FPS x
Overworld normal (10) 422 / 259 4423 / 967 10.5x
Underworld normal (10) 491 / 288 4637 / 989 9.5x
Nether normal (10) 507 / 316 4571 / 991 9.0x
Twilight Forest normal (10) 132 / 79 1702 / 247 12.9x
Overworld far (15) 322 / 82 2941 / 899 9.1x
Underworld far (15) 316 / 96 2853 / 931 9.0x
Nether far (15) 355 / 110 2833 / 961 8.0x
Twilight Forest far (15) 94 / 37 871 / 210 9.2x

Note: frames above the display refresh rate are not all visible; these numbers measure render throughput. Windows was not benchmarked.

  • Issues found and fixed during real-hardware testing (Windows 11 RTX 5080 Laptop via PCL CE, and macOS M5 Max):
    • [Windows/PCL] PCL could not detect the Minecraft version (added clientVersion to the version JSON).
    • [Windows/PCL] Clear crash message when the game jar is missing.
    • [All] Terrain sections were never re-queued after a grid reload (placed blocks invisible, stale water).
    • [All] Terrain was drawn without the lightmap (caves too bright, entities/hand too dark), and the sky was darkened because the lightmap was left enabled.
    • [macOS] MoltenVK nextDrawable capped output at 120 FPS; replaced by the IOSurface layer presentation path.
    • [All] FML's hidden 120 FPS cap removed (Client.fpsCap, default unlimited) and VSync now defaults to off.
    • [All] F3 did not work when a devmod forced MITE dev mode.
    • [All] Mods and config are now resolved from --gameDir.

Known limitations

  • Mod compatibility is out of scope for this PR.
  • Twilight Forest + RustedIronCore has a mixin conflict.
  • Windows is not fully validated yet.
  • Normal-distance results of v4 are about 14-16% below v3 in the benchmark.

Breaking changes

  • Java 25 is required.
  • LWJGL 2 is removed (mods depending on it will not work).
  • Launcher version JSON changes (new libraries/natives, new FML library entry net.xiaoyu233.fishmodloader:fishmodloader:4.0.0).
  • Config key Client.fpsLimit (default 120) is replaced by Client.fpsCap (default 0); the old key is ignored.

Only dev environments have the named jar on the class path, so
/net/minecraft/Minecraft.class was not found in a real install and the
static initializer failed with a NullPointerException. Read /atv.class
(the obfuscated Minecraft) when the named class is missing, close the
stream, and fail with a clear message when neither class is on the class
path.
The game keeps calling the LWJGL 2 API unchanged; underneath it now runs
on LWJGL 3.4.3 and Vulkan.

Rendering and API compatibility
- org.lwjgl.opengl/input/openal and Sys are now FML classes: LWJGL 2 API
  facades with the original descriptors, generated by
  tools/GenLwjgl2Compat.java and tools/GenLwjgl2OpenAL.java.
- The GL facades sit on a GL 1.5 fixed-function emulation on Vulkan
  (net.xiaoyu233.fml.vulkan: state machine, draw system with client
  arrays/VBOs/queries/display lists, texture manager, pipelines, render
  core, swapchain).
- GLFW window and input (WindowManager, InputManager); clipboard and link
  mixins replace the AWT/Desktop paths. OpenAL goes through Java FFM over
  the bundled OpenAL Soft.

Build
- LWJGL 3.4.3 core/glfw/vulkan/vma with natives for windows x64 and macOS
  arm64/x64 (incl. MoltenVK) bundled in the FML jar; the real LWJGL 2
  core/platform are excluded, lwjgl_util 2.x stays.
- GLSL -> SPIR-V at build time (shaders.gradle, src/shadertool, shaders in
  src/main/shaders, output under /assets/fml_vulkan/shaders).
- Java 25 release, Multi-Release and Enable-Native-Access manifest,
  updateInstallerJar task, run options (-Pvk.*, -PrunDir, -Pxmx/-Pxms).
- Test harness: AutoScript and the vulkan.mixin.test mixins (only active
  through -Dfml.vulkan.* properties) and a dev-only test bot source set
  (src/devtest, runClient -Ptestbot) that is never packed into the jar.

Launch
- NativeExtractor unpacks the natives to <gameDir>/.fml/natives and sets
  the LWJGL/Vulkan library paths.
- MacFirstThread restarts the JVM with -XstartOnFirstThread on macOS.
- VulkanConfigLoader maps config/fml-vulkan.properties to fml.vulkan.*.
- LaunchDelegate keeps the real LWJGL 2 core jar out of Knot and fails
  early when an older ASM shadows the one in the FML jar. The installer
  version json drops the LWJGL 2/guava/ASM 9.3 libraries and adds the JVM
  arguments (-XstartOnFirstThread on macOS, --enable-native-access).

Runtime fixes
- FixNetHandler: the multi-block-change guard is a HEAD injection instead
  of an @overwrite that fails under Mixin 0.8.7 and dropped the extended
  block ids; PacketMultiBlockChangeMixin injector signature fixed.
- Display lists: texture image/sub-image uploads compiled into a list are
  recorded with a copy of the pixels and replayed.
- ConfigEditor.isSupported(): no Swing editor on macOS/headless, the
  /configs edit command points to the json files and /configs reload.
- FML 3.x getters (deprecated) on LanguageResourceReloadEvent and
  PlayerLoggedInEvent keep mods compiled against 3.x working.
Add native (non-GL-emulation) render path: mixins for GUI, entities,
mobs, objects, TESRs and models; GPU command stream and pipeline
library; terrain section scheduler, particle fast path, native
tessellator. Rework GLState/GLStateImpl, CommandRecorder, texture
management and input handling. Add VulkanConfig, shader tooling,
devtest/benchtest bots and GlSiteScan tool.
Introduce LayerPresenter and SwapchainInfo, and rework device/swapchain setup
and config so frames can be presented through a CAMetalLayer/IOSurface path.
Requeue sections correctly in the scheduler, update snapshots and mesh workers,
fix translucent sort order and expose terrain stats for diagnostics.
Show renderer, terrain and frame stats in the F3 screen via VulkanDebugOverlay.
New WaterScene and LightScene, extra bench metrics, PERF_JVM and
bench_width/bench_height overrides for runBench; ignore local Claude settings.
Add fpsCap config (default 0 = uncapped), FpsLimit helper, FramePacer limit reason and a Present/VSync/limit line in F3.
Use the fml.gameDir property instead of the process working directory.
Log OptFlags at startup, show Opt line in overlay, add hitch attribution columns and AutoScript test commands.
VK_NV_low_latency2 (Reflex) or VK_AMD_anti_lag when the driver offers it;
fml.vulkan.reflex=off|on|boost (default on), F3+L cycles while playing.
With Reflex active the driver sleep replaces the software FPS limiter.
F3 shows the Reflex state, measured latency and 'FML 4.0.0 build <sha date>'
(FML-Build manifest attribute written by shadowJar).
Falls back to icons bundled in the jar when the assets dir has none and adds
the 48..256 px sizes the Windows taskbar uses.
MITE sets GL_LINEAR + GL_CLAMP on the lightmap every enableLightmap call; the
dynamic texture upload resets it to NEAREST, so smooth light banded in steps.
…e installer

LWJGL 3.4.3 natives for linux and linux-arm64 (lwjgl, glfw, vma, openal) are
shaded like the Windows and macOS ones; Linux uses the system Vulkan loader
(libvulkan.so.1) as Windows does. The installer refuses a client install on a
platform without bundled natives instead of failing at the first launch.

Native extraction hardening: refuse a symlinked natives directory, replace a
symlink planted in place of a library, serialise concurrent launches on a
lock file in the directory, and keep a library that is in use only when its
SHA-1 still matches (size alone was accepted before).
The preset restart rebuilds 'java <jvm args> -cp <cp> client.Main <args>'.
Skip it (and print the flags to add to the launcher instead) when another
main class or a jar started the JVM (launcher wrappers, agent bootstraps),
when a debugger is attached, or with -Dfml.jvm.relaunch=false.
The default output was an absolute path on one developer machine; it is now
build/reports/gl-site-scan (override with -PglScanOut).
…er meshing

TerrainDraw records straight into the command stream but did not flush the
draw the GL emulation still held back for merging. A mod sky drawn from
display lists (Twilight Forest's lower sky disc) could therefore land on top
of the terrain, covering ground and water with flat sky colour. beginPass now
calls LegacyInterop.beforeRawCommands first.

RenderTypeAllowList only let net.minecraft blocks mesh on workers, so every
section with a mod block was meshed on the render thread; in a dimension made
of mod blocks turning the camera dropped to ~60 fps. Packages listed in
fml.vulkan.meshAllowPackages now mesh on workers with any render type.
The phase-1 (GL emulation) pipelines bake depth test/write/compare and cull;
recording vkCmdSetDepth*/CullMode while one is bound is invalid. NVIDIA's
driver then drew with the dynamic values: a mod sky drawn through the
emulation with glDepthMask(false) (Twilight Forest's sky discs) wrote depth
and covered water and terrain with flat sky colour, triggered once the
inventory GUI had left a native depth-write state behind. The dynamic state
now stays dirty until a native pipeline is bound again.

Also adds an opt-in render state log (-Dfml.vulkan.stateDump=true: native and
emulated state at the world pass start, every 5 s and on GUI screen changes)
and a dev-only bench scene (-Dfml.vulkan.tfSkyScene=<dir>) with TF sky/water
captures before and after opening the inventory.
Spawns every Twilight Forest boss on a stone floor, kills it with fire damage
alone and logs the reward chests and dropped items around it. Dev only.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant