From d6b0f3f9978799b26a3ebca1a91ebc110a6b894a Mon Sep 17 00:00:00 2001 From: makamys Date: Tue, 21 Jun 2022 04:46:43 +0200 Subject: Recycle MeshQuad objects Reduces client thread's RAM allocation rate from ~80 MB/s to ~20 MB/s. --- .../java/makamys/neodymium/renderer/ChunkMesh.java | 10 ++++-- .../java/makamys/neodymium/renderer/MeshQuad.java | 34 +++++++++++++++++++- .../java/makamys/neodymium/util/RecyclingList.java | 37 ++++++++++++++++++++++ 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/main/java/makamys/neodymium/util/RecyclingList.java diff --git a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java index abe9a2d..ff6e6ba 100644 --- a/src/main/java/makamys/neodymium/renderer/ChunkMesh.java +++ b/src/main/java/makamys/neodymium/renderer/ChunkMesh.java @@ -19,6 +19,7 @@ import makamys.neodymium.MixinConfigPlugin; import makamys.neodymium.Neodymium; import makamys.neodymium.ducks.IWorldRenderer; import makamys.neodymium.util.BufferWriter; +import makamys.neodymium.util.RecyclingList; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; @@ -40,6 +41,8 @@ public class ChunkMesh extends Mesh { public static int usedRAM = 0; public static int instances = 0; + private static RecyclingList quadBuf = new RecyclingList<>(() -> new MeshQuad()); + public ChunkMesh(int x, int y, int z, Flags flags, int quadCount, ByteBuffer buffer, int pass) { this.x = x; this.y = y; @@ -86,13 +89,14 @@ public class ChunkMesh extends Mesh { ChunkMesh.Flags flags = new ChunkMesh.Flags(t.hasTexture, t.hasBrightness, t.hasColor, t.hasNormals); - List quads = new ArrayList<>(); + quadBuf.reset(); for(int quadI = 0; quadI < t.vertexCount / 4; quadI++) { - MeshQuad quad = new MeshQuad(t.rawBuffer, quadI * 32, flags, tessellatorXOffset, tessellatorYOffset, tessellatorZOffset); - quads.add(quad); + quadBuf.next().setState(t.rawBuffer, quadI * 32, flags, tessellatorXOffset, tessellatorYOffset, tessellatorZOffset); } + List quads = quadBuf.getAsList(); + if(Config.simplifyChunkMeshes) { ArrayList> quadsByPlaneDir = new ArrayList<>(); // XY, XZ, YZ for(int i = 0; i < 3; i++) { diff --git a/src/main/java/makamys/neodymium/renderer/MeshQuad.java b/src/main/java/makamys/neodymium/renderer/MeshQuad.java index 2024efd..1ff4173 100644 --- a/src/main/java/makamys/neodymium/renderer/MeshQuad.java +++ b/src/main/java/makamys/neodymium/renderer/MeshQuad.java @@ -96,7 +96,9 @@ public class MeshQuad { } } - public MeshQuad(int[] rawBuffer, int offset, ChunkMesh.Flags flags, int offsetX, int offsetY, int offsetZ) { + public void setState(int[] rawBuffer, int offset, ChunkMesh.Flags flags, int offsetX, int offsetY, int offsetZ) { + resetState(); + read(rawBuffer, offset, offsetX, offsetY, offsetZ); uDirectionIs01 = us[0] != us[1]; @@ -110,6 +112,36 @@ public class MeshQuad { normal = QuadNormal.fromVector(vectorC); } + private void resetState() { + Arrays.fill(xs, 0); + Arrays.fill(ys, 0); + Arrays.fill(zs, 0); + Arrays.fill(us, 0); + Arrays.fill(vs, 0); + Arrays.fill(bs, 0); + Arrays.fill(cs, 0); + + minX = Float.POSITIVE_INFINITY; + minY = Float.POSITIVE_INFINITY; + minZ = Float.POSITIVE_INFINITY; + maxX = Float.NEGATIVE_INFINITY; + maxY = Float.NEGATIVE_INFINITY; + maxZ = Float.NEGATIVE_INFINITY; + + deleted = noMerge = false; + normal = null; + offset = 0; + flags = null; + uDirectionIs01 = false; + Arrays.fill(quadCountByDirection, 1); + Arrays.fill(totalMergeCountByPlane, 0); + mergeReference = null; + } + + public MeshQuad() { + + } + public void writeToBuffer(BufferWriter out) throws IOException { for(int vertexI = 0; vertexI < 4; vertexI++) { int vi = vertexI; diff --git a/src/main/java/makamys/neodymium/util/RecyclingList.java b/src/main/java/makamys/neodymium/util/RecyclingList.java new file mode 100644 index 0000000..ea240bb --- /dev/null +++ b/src/main/java/makamys/neodymium/util/RecyclingList.java @@ -0,0 +1,37 @@ +package makamys.neodymium.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +public class RecyclingList { + + private Supplier constructor; + + int nextIndex; + private List list; + + public RecyclingList(Supplier constructor) { + this.constructor = constructor; + this.list = new ArrayList(); + } + + public T get(int i) { + while(list.size() <= i) { + list.add(constructor.get()); + } + return list.get(i); + } + + public T next() { + return get(nextIndex++); + } + + public void reset() { + nextIndex = 0; + } + + public List getAsList() { + return list.subList(0, nextIndex); + } +} -- cgit