aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authormakamys <makamys@outlook.com>2022-06-06 23:56:24 +0200
committermakamys <makamys@outlook.com>2022-06-07 01:24:27 +0200
commit8ec6aebebefe045d65aa13e2b59aaf4df0895f7f (patch)
tree54e4bf9074ff058c83930f0bc5d3f68402e2f515 /src/main
parent3c5f6da8509cdc6a83526003b043177c5e1cd24f (diff)
downloadNeodymium-8ec6aebebefe045d65aa13e2b59aaf4df0895f7f.tar.gz
Neodymium-8ec6aebebefe045d65aa13e2b59aaf4df0895f7f.tar.bz2
Neodymium-8ec6aebebefe045d65aa13e2b59aaf4df0895f7f.zip
Factor out GPU memory management into separate class
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/makamys/lodmod/renderer/GPUMemoryManager.java122
-rw-r--r--src/main/java/makamys/lodmod/renderer/LODRenderer.java111
2 files changed, 138 insertions, 95 deletions
diff --git a/src/main/java/makamys/lodmod/renderer/GPUMemoryManager.java b/src/main/java/makamys/lodmod/renderer/GPUMemoryManager.java
new file mode 100644
index 0000000..72f22a2
--- /dev/null
+++ b/src/main/java/makamys/lodmod/renderer/GPUMemoryManager.java
@@ -0,0 +1,122 @@
+package makamys.lodmod.renderer;
+
+import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
+import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
+import static org.lwjgl.opengl.GL15.glBindBuffer;
+import static org.lwjgl.opengl.GL15.glBufferData;
+import static org.lwjgl.opengl.GL15.glBufferSubData;
+import static org.lwjgl.opengl.GL15.glDeleteBuffers;
+import static org.lwjgl.opengl.GL15.glGenBuffers;
+import static org.lwjgl.opengl.GL30.glBindVertexArray;
+import static org.lwjgl.opengl.GL30.glGenVertexArrays;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import makamys.lodmod.renderer.Mesh.GPUStatus;
+
+public class GPUMemoryManager {
+
+ private static int BUFFER_SIZE = 1024 * 1024 * 1024;
+
+ public int VBO;
+
+ private int nextTri;
+ private int nextMeshOffset;
+ private int nextMesh;
+
+ private List<Mesh> sentMeshes = new ArrayList<>();
+
+ public GPUMemoryManager() {
+ VBO = glGenBuffers();
+
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+
+ glBufferData(GL_ARRAY_BUFFER, BUFFER_SIZE, GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+
+ public void runGC() {
+ nextMeshOffset = 0;
+ nextTri = 0;
+
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+
+ int deletedNum = 0;
+ int deletedRAM = 0;
+
+ long t0 = System.nanoTime();
+
+ for(Iterator<Mesh> it = sentMeshes.iterator(); it.hasNext(); ) {
+ Mesh mesh = it.next();
+ if(mesh.gpuStatus == GPUStatus.SENT) {
+ if(mesh.offset != nextMeshOffset) {
+ glBufferSubData(GL_ARRAY_BUFFER, nextMeshOffset, mesh.buffer);
+ }
+ mesh.iFirst = nextTri;
+ mesh.offset = nextMeshOffset;
+
+ nextMeshOffset += mesh.bufferSize();
+ nextTri += mesh.quadCount * 6;
+ } else if(mesh.gpuStatus == GPUStatus.PENDING_DELETE) {
+ mesh.iFirst = mesh.offset = -1;
+ mesh.visible = false;
+ mesh.gpuStatus = GPUStatus.UNSENT;
+ mesh.destroyBuffer();
+
+ it.remove();
+ deletedNum++;
+ deletedRAM += mesh.bufferSize();
+ }
+ }
+
+ long t1 = System.nanoTime();
+
+ System.out.println("Deleted " + deletedNum + " meshes in " + ((t1 - t0) / 1_000_000.0) + " ms, freeing up " + (deletedRAM / 1024 / 1024) + "MB of VRAM");
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+
+ public void sendMeshToGPU(Mesh mesh) {
+ if(mesh == null) {
+ return;
+ }
+ if(mesh.gpuStatus == GPUStatus.UNSENT) {
+ mesh.prepareBuffer();
+
+ 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);
+ }
+
+ mesh.gpuStatus = GPUStatus.SENT;
+ }
+
+ public void deleteMeshFromGPU(Mesh mesh) {
+ if(mesh == null || mesh.gpuStatus == GPUStatus.UNSENT) {
+ return;
+ }
+ mesh.gpuStatus = GPUStatus.PENDING_DELETE;
+ }
+
+ public void destroy() {
+ glDeleteBuffers(VBO);
+ }
+
+ public List<String> getDebugText() {
+ return Arrays.asList("VRAM: " + (nextMeshOffset / 1024 / 1024) + "MB / " + (BUFFER_SIZE / 1024 / 1024) + "MB");
+ }
+
+}
diff --git a/src/main/java/makamys/lodmod/renderer/LODRenderer.java b/src/main/java/makamys/lodmod/renderer/LODRenderer.java
index 3ec1a08..5ed9377 100644
--- a/src/main/java/makamys/lodmod/renderer/LODRenderer.java
+++ b/src/main/java/makamys/lodmod/renderer/LODRenderer.java
@@ -61,13 +61,13 @@ public class LODRenderer {
public boolean renderWorld;
public boolean rendererActive;
- private static int BUFFER_SIZE = 1024 * 1024 * 1024;
private static int MAX_MESHES = 100000;
- private int VAO, VBO, shaderProgram;
+ private int VAO, shaderProgram;
private IntBuffer[] piFirst = new IntBuffer[2];
private IntBuffer[] piCount = new IntBuffer[2];
private List<Mesh>[] sentMeshes = (List<Mesh>[])new ArrayList[] {new ArrayList<Mesh>(), new ArrayList<Mesh>()};
+ GPUMemoryManager mem;
List<Chunk> myChunks = new ArrayList<Chunk>();
List<LODChunk> pendingLODChunks = new ArrayList<>();
@@ -123,7 +123,7 @@ public class LODRenderer {
handleKeyboard();
}
if(lastGCTime == -1 || (System.currentTimeMillis() - lastGCTime) > gcInterval) {
- runGC();
+ mem.runGC();
lastGCTime = System.currentTimeMillis();
}
if(lastSaveTime == -1 || (System.currentTimeMillis() - lastSaveTime) > saveInterval && LODMod.saveMeshes) {
@@ -263,51 +263,6 @@ public class LODRenderer {
}
}
- private void runGC() {
- nextMeshOffset = 0;
- nextTri = 0;
-
- glBindVertexArray(VAO);
- glBindBuffer(GL_ARRAY_BUFFER, VBO);
-
- int[] deletedNum = new int[2];
- int deletedRAM = 0;
-
- long t0 = System.nanoTime();
-
- for(int i = 0; i < 2; i++) {
- for(Iterator<Mesh> it = sentMeshes[i].iterator(); it.hasNext(); ) {
- Mesh mesh = it.next();
- if(mesh.gpuStatus == GPUStatus.SENT) {
- if(mesh.offset != nextMeshOffset) {
- glBufferSubData(GL_ARRAY_BUFFER, nextMeshOffset, mesh.buffer);
- }
- mesh.iFirst = nextTri;
- mesh.offset = nextMeshOffset;
-
- nextMeshOffset += mesh.bufferSize();
- nextTri += mesh.quadCount * 6;
- } else if(mesh.gpuStatus == GPUStatus.PENDING_DELETE) {
- mesh.iFirst = mesh.offset = -1;
- mesh.visible = false;
- mesh.gpuStatus = GPUStatus.UNSENT;
- mesh.destroyBuffer();
-
- it.remove();
- deletedNum[i]++;
- deletedRAM += mesh.bufferSize();
- }
- }
- }
-
- long t1 = System.nanoTime();
-
- System.out.println("Deleted " + deletedNum[0] + "+" + deletedNum[1] + " meshes in " + ((t1 - t0) / 1_000_000.0) + " ms, freeing up " + (deletedRAM / 1024 / 1024) + "MB of VRAM");
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(0);
- }
-
FloatBuffer modelView = BufferUtils.createFloatBuffer(16);
FloatBuffer projBuf = BufferUtils.createFloatBuffer(16);
IntBuffer viewportBuf = BufferUtils.createIntBuffer(16);
@@ -406,10 +361,9 @@ public class LODRenderer {
VAO = glGenVertexArrays();
glBindVertexArray(VAO);
- VBO = glGenBuffers();
- glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ mem = new GPUMemoryManager();
- glBufferData(GL_ARRAY_BUFFER, BUFFER_SIZE, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, mem.VBO);
int stride = 7 * 4;
@@ -475,7 +429,7 @@ public class LODRenderer {
glDeleteProgram(shaderProgram);
glDeleteVertexArrays(VAO);
- glDeleteBuffers(VBO);
+ mem.destroy();
SimpleChunkMesh.instances = 0;
SimpleChunkMesh.usedRAM = 0;
@@ -595,10 +549,6 @@ public class LODRenderer {
}
}
- private int nextTri;
- private int nextMeshOffset;
- private int nextMesh;
-
protected void setMeshVisible(Mesh mesh, boolean visible) {
setMeshVisible(mesh, visible, false);
}
@@ -610,48 +560,17 @@ public class LODRenderer {
mesh.visible = visible;
if(mesh.gpuStatus == GPUStatus.UNSENT) {
- sendMeshToGPU(mesh);
+ mem.sendMeshToGPU(mesh);
+ sentMeshes[mesh.pass].add(mesh);
}
}
}
public void removeMesh(Mesh mesh) {
- deleteMeshFromGPU(mesh);
+ mem.deleteMeshFromGPU(mesh);
+ sentMeshes[mesh.pass].remove(mesh);
setMeshVisible(mesh, false);
- }
-
- private void sendMeshToGPU(Mesh mesh) {
- if(mesh == null) {
- return;
- }
- if(mesh.gpuStatus == GPUStatus.UNSENT) {
- mesh.prepareBuffer();
-
- 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[mesh.pass].add(mesh);
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(0);
- }
-
- mesh.gpuStatus = GPUStatus.SENT;
- }
-
- private void deleteMeshFromGPU(Mesh mesh) {
- if(mesh == null || mesh.gpuStatus == GPUStatus.UNSENT) {
- return;
- }
- mesh.gpuStatus = GPUStatus.PENDING_DELETE;
- }
+ }
public Chunk getChunkFromChunkCoords(int x, int z) {
for(Chunk chunk : myChunks) {
@@ -672,13 +591,15 @@ public class LODRenderer {
}
public List<String> getDebugText() {
- return Arrays.asList(
- "VRAM: " + (nextMeshOffset / 1024 / 1024) + "MB / " + (BUFFER_SIZE / 1024 / 1024) + "MB",
+ List<String> text = new ArrayList<>();
+ text.addAll(mem.getDebugText());
+ text.addAll(Arrays.asList(
"Simple meshes: " + SimpleChunkMesh.instances + " (" + SimpleChunkMesh.usedRAM / 1024 / 1024 + "MB)",
"Full meshes: " + ChunkMesh.instances + " (" + ChunkMesh.usedRAM / 1024 / 1024 + "MB)",
"Total RAM used: " + ((SimpleChunkMesh.usedRAM + ChunkMesh.usedRAM) / 1024 / 1024) + " MB",
"Rendered: " + renderedMeshes
- );
+ ));
+ return text;
}
public void onSave() {