diff options
author | makamys <makamys@outlook.com> | 2021-05-07 16:30:57 +0200 |
---|---|---|
committer | makamys <makamys@outlook.com> | 2021-05-07 16:31:39 +0200 |
commit | 5b11d0fda343fcff44fd8bf8e9f7996f30568536 (patch) | |
tree | 48d1d00da8ca72b716729b77a39685e66b06d8b2 /src/main/java/makamys | |
parent | 5ee5b7deaccf951c168e202b91a1a2fc8438368f (diff) | |
download | Neodymium-5b11d0fda343fcff44fd8bf8e9f7996f30568536.tar.gz Neodymium-5b11d0fda343fcff44fd8bf8e9f7996f30568536.tar.bz2 Neodymium-5b11d0fda343fcff44fd8bf8e9f7996f30568536.zip |
Unload invisible meshes from VRAM
Diffstat (limited to 'src/main/java/makamys')
-rw-r--r-- | src/main/java/makamys/lodmod/renderer/LODChunk.java | 1 | ||||
-rw-r--r-- | src/main/java/makamys/lodmod/renderer/LODRenderer.java | 122 | ||||
-rw-r--r-- | src/main/java/makamys/lodmod/renderer/Mesh.java | 4 |
3 files changed, 100 insertions, 27 deletions
diff --git a/src/main/java/makamys/lodmod/renderer/LODChunk.java b/src/main/java/makamys/lodmod/renderer/LODChunk.java index 6a3012e..ab1a03d 100644 --- a/src/main/java/makamys/lodmod/renderer/LODChunk.java +++ b/src/main/java/makamys/lodmod/renderer/LODChunk.java @@ -43,7 +43,6 @@ public class LODChunk { for(int i = 0; i < newChunkMeshes.size(); i++) { chunkMeshes[cy * 2 + i] = newChunkMeshes.get(i); - renderer.sendMeshToGPU(newChunkMeshes.get(i)); } } diff --git a/src/main/java/makamys/lodmod/renderer/LODRenderer.java b/src/main/java/makamys/lodmod/renderer/LODRenderer.java index 6cea136..b28b654 100644 --- a/src/main/java/makamys/lodmod/renderer/LODRenderer.java +++ b/src/main/java/makamys/lodmod/renderer/LODRenderer.java @@ -16,9 +16,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Queue; +import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.commons.lang3.ArrayUtils; @@ -56,7 +59,8 @@ public class LODRenderer { List<LODChunk> pendingLODChunks = new ArrayList<>(); private boolean hasServerInited = false; - private HashMap<ChunkCoordIntPair, LODRegion> loadedRegionsMap = new HashMap<>(); + private Map<ChunkCoordIntPair, LODRegion> loadedRegionsMap = new HashMap<>(); + private List<Mesh> sentMeshes = new ArrayList<>(); // TODO make these packets to make this work on dedicated servers Queue<Chunk> farChunks = new ConcurrentLinkedQueue<>(); @@ -67,6 +71,9 @@ public class LODRenderer { private double lastSortY = Double.NaN; private double lastSortZ = Double.NaN; + private long lastGCTime = -1; + private long gcInterval = 60 * 1000; + public LODRenderer(){ hasInited = init(); } @@ -75,6 +82,12 @@ public class LODRenderer { if(hasInited) { mainLoop(); handleKeyboard(); + gcInterval = 10 * 1000; + if(lastGCTime == -1 || (System.currentTimeMillis() - lastGCTime) > gcInterval) { + runGC(); + lastGCTime = System.currentTimeMillis(); + } + if(renderLOD) { render(); } @@ -132,6 +145,52 @@ public class LODRenderer { wasDown[i] = Keyboard.isKeyDown(i); } } + + private void runGC() { + nextMeshOffset = 0; + nextTri = 0; + nextMesh = 0; + + piFirst.limit(0); + piCount.limit(0); + + glBindVertexArray(VAO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + + int deletedNum = 0; + int deletedRAM = 0; + for(Iterator<Mesh> it = sentMeshes.iterator(); it.hasNext(); ) { + Mesh mesh = it.next(); + if(!mesh.pendingGPUDelete) { + if(mesh.offset != nextMeshOffset) { + glBufferSubData(GL_ARRAY_BUFFER, nextMeshOffset, mesh.buffer); + } + mesh.iFirst = nextTri; + mesh.offset = nextMeshOffset; + + nextMeshOffset += mesh.buffer.limit(); + nextTri += mesh.quadCount * 6; + + piFirst.limit(piFirst.limit() + 1); + piFirst.put(nextMesh, mesh.iFirst); + piCount.limit(piCount.limit() + 1); + piCount.put(nextMesh, mesh.iCount); + nextMesh++; + } else { + mesh.iFirst = mesh.offset = -1; + mesh.visible = false; + mesh.pendingGPUDelete = false; + it.remove(); + deletedNum++; + deletedRAM += mesh.buffer.limit(); + } + } + + System.out.println("Deleted " + deletedNum + " meshes, freeing up " + (deletedRAM / 1024 / 1024) + "MB of VRAM"); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } private void render() { GL11.glPushAttrib(GL11.GL_ENABLE_BIT); @@ -368,12 +427,6 @@ public class LODRenderer { private void sendChunkToGPU(LODChunk lodChunk) { lodChunk.simpleMesh = new SimpleChunkMesh(lodChunk.chunk); - /*for(int cy = 0; cy < 16; cy++) { - lodChunk.chunkMeshes[cy] = ChunkMesh.getChunkMesh(lodChunk.x, cy, lodChunk.z); - sendMeshToGPU(lodChunk.chunkMeshes[cy]); - }*/ - - sendMeshToGPU(lodChunk.simpleMesh); Entity player = (Entity) Minecraft.getMinecraft().getIntegratedServer().getConfigurationManager().playerEntityList.get(0); @@ -427,29 +480,14 @@ public class LODRenderer { private int nextMeshOffset; private int nextMesh; - protected void sendMeshToGPU(Mesh mesh) { - if(mesh == null) { - return; - } - glBindVertexArray(VAO); - glBindBuffer(GL_ARRAY_BUFFER, VBO); - - glBufferSubData(GL_ARRAY_BUFFER, nextMeshOffset, mesh.buffer); - mesh.iFirst = nextTri; - mesh.iCount = mesh.quadCount * 6; - - nextTri += mesh.quadCount * 6; - nextMeshOffset += mesh.buffer.limit(); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - protected void setMeshVisible(Mesh mesh, boolean visible) { if(mesh == null) return; if(mesh.visible != visible) { if(!visible) { + if(mesh.iFirst == -1) { + System.out.println("uh"); + } piFirst.position(0); int[] piFirstArr = new int[piFirst.limit()]; piFirst.get(piFirstArr); @@ -461,6 +499,8 @@ public class LODRenderer { piFirst.limit(piFirst.limit() - 1); piCount.position(0); + + deleteMeshFromGPU(mesh); int[] piCountArr = new int[piCount.limit()]; piCount.get(piCountArr); piCountArr = ArrayUtils.remove(piCountArr, index); @@ -470,6 +510,7 @@ public class LODRenderer { piCount.limit(piCount.limit() - 1); nextMesh--; } else if(visible) { + sendMeshToGPU(mesh); piFirst.limit(piFirst.limit() + 1); piFirst.put(nextMesh, mesh.iFirst); piCount.limit(piCount.limit() + 1); @@ -480,6 +521,37 @@ public class LODRenderer { } } + private void sendMeshToGPU(Mesh mesh) { + if(mesh == null) { + return; + } + if(mesh.pendingGPUDelete) { + mesh.pendingGPUDelete = false; + return; + } + glBindVertexArray(VAO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + + glBufferSubData(GL_ARRAY_BUFFER, nextMeshOffset, mesh.buffer); + mesh.iFirst = nextTri; + mesh.iCount = mesh.quadCount * 6; + mesh.offset = nextMeshOffset; + + nextTri += mesh.quadCount * 6; + nextMeshOffset += mesh.buffer.limit(); + sentMeshes.add(mesh); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + + private void deleteMeshFromGPU(Mesh mesh) { + if(mesh == null) { + return; + } + mesh.pendingGPUDelete = true; + } + public Chunk getChunkFromChunkCoords(int x, int z) { for(Chunk chunk : myChunks) { if(chunk.xPosition == x && chunk.zPosition == z) { diff --git a/src/main/java/makamys/lodmod/renderer/Mesh.java b/src/main/java/makamys/lodmod/renderer/Mesh.java index be379f6..55f2d8b 100644 --- a/src/main/java/makamys/lodmod/renderer/Mesh.java +++ b/src/main/java/makamys/lodmod/renderer/Mesh.java @@ -8,7 +8,9 @@ public abstract class Mesh { public ByteBuffer buffer; public int quadCount; public boolean visible; - public int iFirst, iCount; + public boolean pendingGPUDelete; + public int iFirst = -1, iCount = -1; + public int offset = -1; public abstract int getStride(); |