-
Bug
-
Resolution: Fixed
-
19w39a, 19w40a, 19w42a, 19w44a, 19w45b
-
Java version:
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (IcedTea 3.13.0) (Gentoo icedtea-3.13.0)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)
GPU, GPU driver and opengl version (from glxinfo output):
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) Haswell Mobile
OpenGL core profile version string: 4.5 (Core Profile) Mesa 19.3.0-devel (git-f3e978db4d)
OpenGL core profile shading language version string: 4.50
Attached forced crash reports from MC 19w40a and 19w37aJava version: openjdk version "1.8.0_222" OpenJDK Runtime Environment (IcedTea 3.13.0) (Gentoo icedtea-3.13.0) OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode) GPU, GPU driver and opengl version (from glxinfo output): OpenGL vendor string: Intel Open Source Technology Center OpenGL renderer string: Mesa DRI Intel(R) Haswell Mobile OpenGL core profile version string: 4.5 (Core Profile) Mesa 19.3.0-devel (git-f3e978db4d) OpenGL core profile shading language version string: 4.50 Attached forced crash reports from MC 19w40a and 19w37a
-
Community Consensus
-
Performance, Rendering
-
Very Important
The bug
This already happened in earlier versions, but ONLY when VBOs are disabled (that only happened on some GPU drivers, for example linux intel GPU drivers). That option has been removed in one of recent versions so this shouldn't be an issue anymore.
I can reproduce it reliably every time now immediately after entering the world, but in the initial few tests, it appeared to happen only after a while of flying around the world (I don't know what actually triggered it).
This was not an issue in 19w37a, it appears to be introduced in 19w38a
It seems to coincide with MC not displaying GPU vendor and opengl version properly (screenshots showing this attached, it does show up correctly in crash report output).
Running visualvm sampler shows that all of the time is spent in RenderSystem.glGenBuffers and subsequently GL15C.nglGenBuffers (sampler snapshot attached). As far as my understanding goes, this is very likely caused by requesting gl buffers separately for each render section, instead of all at once.
Update: opengl version and vendor not being shown is a completely separate thing that doesn't affect anything. Appearing in the same snapshot was a coincidence.
The reason
After a bit of testing in mod development environment with latest snapshot, I was able to find a fix/workaround in code in GlStateManager. It's not exactly the best solution, but works really well in practice and requires very little code changes:
private static final int GENBUFFERS_BATCH = 2048; private static IntBuffer BUFFERS; public static int genBuffers() { RenderSystem.assertThread(RenderSystem::isOnRenderThreadOrInit); if (BUFFERS == null || !BUFFERS.hasRemaining()) { if (BUFFERS == null) { BUFFERS = BufferUtils.createIntBuffer(GENBUFFERS_BATCH); } BUFFERS.rewind(); GL15.glGenBuffers(BUFFERS); BUFFERS.rewind(); } return BUFFERS.get(); }
This confirms that the issue is the huge amount of glGenBuffers calls, but it's still unclear to me why it's a performance issue to begin with, especially with glDeleteBuffers not being an issue at all.
A good solution would be to allocate and delete all the chunk buffers in one glGenBuffers call but that doesn't work nicely with the way this code is written.
--
I also verified that this code didn't change in any significant way even since 1.12.2 so I really have no idea what has changed here that suddenntly makes this code path so much slower.
After more debugging, this is the real reason (full explanation of how I found it in comments):
Minecraft is binding already deleted VertexBuffers, which it internally assigns an ID of -1 to. This ends up changing mesa driver internal state in a way that always triggers a very slow code path for glGenBuffers.