-
Bug
-
Resolution: Unresolved
-
None
-
Minecraft 1.13.2, Minecraft 19w05a, Minecraft 19w06a, Minecraft 19w07a, Minecraft 19w08b, Minecraft 1.14 Pre-Release 2, Minecraft 1.14 Pre-Release 3, Minecraft 1.14 Pre-Release 4, Minecraft 1.14 Pre-Release 5, Minecraft 1.14, 1.15.2, 20w06a
-
None
-
Community Consensus
-
(Unassigned)
Switching worlds can cause NO LAG! Just remove System.gc() from the code and don't delete all VBOs when changing dimensions. For example, on Hypixel dimension switch is sent 2 times which causes the screen to darken 2 times (especially with render distance 32). This lag can take up to 5 seconds on Windows and 30+ seconds on linux leading to disconnection with the server.
How to reproduce:
Set render distance to 32 and go through the nether portal in singleplayer
or switch subserver in multiplayer.
Solution:
Remove System.gc() Reuse buffers. Sample code below
public class GlBuffer { public static GlBuffersStack glBuffers = new GlBuffersStack(1024*64); private static int glBuffersIndex = 0; public static int vmem = 0; private int index; public static GlBuffer genBuffer(){ GlBuffer result = null; if(glBuffersIndex < glBuffers.size()){ result = glBuffers.get(glBuffersIndex); }else{ result = new GlBuffer(); glBuffers.push(result); } result.index = glBuffersIndex; glBuffersIndex++; return result; } public static void trimUnused(){ while(glBuffers.size() > 0){ GlBuffer gb = glBuffers.get(glBuffers.size()-1); if(gb.released()){ gb.deleteGlBuffers(); glBuffers.popSilently(); }else{ break; } } } private int glBufferId; private int size; private static int globalCount = 0; public GlBuffer() { this.glBufferId = OpenGlHelper.glGenBuffers(); globalCount++; } public void bindBuffer() { OpenGlHelper.glBindBuffer(OpenGlHelper.GL_ARRAY_BUFFER, this.glBufferId); } public void setBufferData(ByteBuffer data) { vmem -= this.size; this.bindBuffer(); OpenGlHelper.glBufferData(OpenGlHelper.GL_ARRAY_BUFFER, data, 35044); this.unbindBuffer(); this.size = data.limit(); vmem += this.size; } public void drawArrays(int mode, int count) { GL11.glDrawArrays(mode, 0, count); } public void unbindBuffer() { OpenGlHelper.glBindBuffer(OpenGlHelper.GL_ARRAY_BUFFER, 0); } public void deleteGlBuffers() { if (this.glBufferId >= 0) { OpenGlHelper.glDeleteBuffers(this.glBufferId); this.glBufferId = -1; globalCount--; } } public void releaseGenBuffer(){ if(this.index == -1){ return; } GlBuffer self = glBuffers.get(this.index); if(this != self){ throw new RuntimeException("wrong order in releaseGenBuffer"); } glBuffersIndex--; GlBuffer last = glBuffers.get(glBuffersIndex); glBuffers.set(this.index, last); glBuffers.set(glBuffersIndex, self); last.index = this.index; this.index = -1; } public boolean released(){ return this.index == -1; } public static int getGlobalCount(){ return globalCount; } public int getSize(){ return this.size; } } public final class GlBuffersStack { public GlBuffer[] stack; public int size; public GlBuffersStack(int initialCapacity) { stack = new GlBuffer[initialCapacity]; } public GlBuffer push(GlBuffer value) { if (size + 1 >= stack.length) { resizeStack(stack.length * 2); } stack[size++] = value; return value; } public void popSilently() { stack[--size] = null; } public GlBuffer pop() { final GlBuffer result = stack[--size]; stack[size] = null; return result; } public GlBuffer peek() { return size == 0 ? null : stack[size - 1]; } public int size() { return size; } public boolean hasStuff() { return size > 0; } public GlBuffer get(int i) { return stack[i]; } private void resizeStack(int newCapacity) { GlBuffer[] newStack = new GlBuffer[newCapacity]; System.arraycopy(stack, 0, newStack, 0, Math.min(size, newCapacity)); stack = newStack; } public String toString() { StringBuffer result = new StringBuffer("["); for (int i = 0; i < size; i++) { if (i > 0) { result.append(", "); } result.append(stack[i]); } result.append(']'); return result.toString(); } public void set(int i, GlBuffer value) { stack[i] = value; } }