From e91864da9812b04c0d39c1d0bea3bdfd093ea1ab Mon Sep 17 00:00:00 2001
From: makamys <makamys@outlook.com>
Date: Wed, 8 Jun 2022 00:05:48 +0200
Subject: Recover from full VRAM

---
 src/main/java/makamys/lodmod/LODMod.java           |  2 +-
 .../makamys/lodmod/renderer/GPUMemoryManager.java  | 29 ++++++++++++++++------
 .../java/makamys/lodmod/renderer/LODRenderer.java  |  7 +++++-
 3 files changed, 28 insertions(+), 10 deletions(-)

(limited to 'src')

diff --git a/src/main/java/makamys/lodmod/LODMod.java b/src/main/java/makamys/lodmod/LODMod.java
index 27aac70..4812b65 100644
--- a/src/main/java/makamys/lodmod/LODMod.java
+++ b/src/main/java/makamys/lodmod/LODMod.java
@@ -156,7 +156,7 @@ public class LODMod
     }
     
     public static boolean isActive() {
-        return renderer != null && renderer.hasInited;
+        return renderer != null && renderer.hasInited && !renderer.destroyPending;
     }
     
     private World getRendererWorld() {
diff --git a/src/main/java/makamys/lodmod/renderer/GPUMemoryManager.java b/src/main/java/makamys/lodmod/renderer/GPUMemoryManager.java
index 77460e6..2d27630 100644
--- a/src/main/java/makamys/lodmod/renderer/GPUMemoryManager.java
+++ b/src/main/java/makamys/lodmod/renderer/GPUMemoryManager.java
@@ -6,6 +6,7 @@ import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 
+import makamys.lodmod.LODMod;
 import makamys.lodmod.renderer.Mesh.GPUStatus;
 import makamys.lodmod.util.GuiHelper;
 
@@ -29,16 +30,18 @@ public class GPUMemoryManager {
         glBindBuffer(GL_ARRAY_BUFFER, 0);
     }
     
-    public void runGC() {
+    public void runGC(boolean full) {
         glBindBuffer(GL_ARRAY_BUFFER, VBO);
         
         int moved = 0;
+        int timesReachedEnd = 0;
         int checksLeft = sentMeshes.size();
         
-        while(moved < 4 && checksLeft-- > 0 && !sentMeshes.isEmpty()) {
+        while((!full && (moved < 4 && checksLeft-- > 0)) || (full && timesReachedEnd < 2) && !sentMeshes.isEmpty()) {
             nextMesh++;
             if(nextMesh >= sentMeshes.size()) {
                 nextMesh = 0;
+                timesReachedEnd++;
             }
             Mesh mesh = sentMeshes.get(nextMesh);
             
@@ -89,11 +92,26 @@ public class GPUMemoryManager {
         }
     }
     
+    private int end() {
+        return (sentMeshes.isEmpty() ? 0 : sentMeshes.get(sentMeshes.size() - 1).getEnd());
+    }
+    
     public void sendMeshToGPU(Mesh mesh) {
         if(mesh == null) {
             return;
         }
         
+        if(end() + mesh.bufferSize() >= BUFFER_SIZE) {
+            runGC(true);
+        }
+        
+        if(end() + mesh.bufferSize() >= BUFFER_SIZE) {
+            System.out.println("VRAM is full! Try increasing the allocated VRAM in the config, if possible. Reverting to vanilla renderer.");
+            LODMod.renderer.destroyPending = true;
+            // TODO restart renderer with more VRAM allocated when this happens.
+            return;
+        }
+        
         int size = mesh.bufferSize();
         int insertIndex = -1;
         
@@ -121,11 +139,6 @@ public class GPUMemoryManager {
         }
         if(nextBase == -1) nextBase = 0;
         
-        if(nextBase + size >= BUFFER_SIZE) {
-            return;
-        }
-        
-        
         
         if(mesh.gpuStatus == GPUStatus.UNSENT) {
             mesh.prepareBuffer();
@@ -162,7 +175,7 @@ public class GPUMemoryManager {
     }
 
     public List<String> getDebugText() {
-        return Arrays.asList("VRAM: " + ((sentMeshes.isEmpty() ? 0 : sentMeshes.get(sentMeshes.size() - 1).getEnd()) / 1024 / 1024) + "MB / " + (BUFFER_SIZE / 1024 / 1024) + "MB");
+        return Arrays.asList("VRAM: " + (end() / 1024 / 1024) + "MB / " + (BUFFER_SIZE / 1024 / 1024) + "MB");
     }
 
     public void drawInfo() {
diff --git a/src/main/java/makamys/lodmod/renderer/LODRenderer.java b/src/main/java/makamys/lodmod/renderer/LODRenderer.java
index 5b8e467..d194fe5 100644
--- a/src/main/java/makamys/lodmod/renderer/LODRenderer.java
+++ b/src/main/java/makamys/lodmod/renderer/LODRenderer.java
@@ -55,6 +55,7 @@ import static org.lwjgl.opengl.GL30.*;
 public class LODRenderer {
     
     public boolean hasInited = false;
+    public boolean destroyPending;
     
     private boolean[] wasDown = new boolean[256];
     private int renderQuads = 0;
@@ -125,7 +126,7 @@ public class LODRenderer {
                 handleKeyboard();
             }
             if(frameCount % 2 == 0) {
-                mem.runGC();
+                mem.runGC(false);
             }
             lastGCTime = System.currentTimeMillis();
             if(lastSaveTime == -1 || (System.currentTimeMillis() - lastSaveTime) > saveInterval && LODMod.saveMeshes) {
@@ -150,6 +151,10 @@ public class LODRenderer {
     }
     
     public void onRenderTickEnd() {
+        if(destroyPending) {
+            LODMod.renderer = null;
+            return;
+        }
         if(showMemoryDebugger && mem != null) {
             GuiHelper.begin();
             mem.drawInfo();
-- 
cgit