From 8804c019a817812828aa8b4602fd7af11c276478 Mon Sep 17 00:00:00 2001
From: Ansariel <ansariel.hiller@phoenixviewer.com>
Date: Wed, 26 Jun 2024 20:38:51 +0200
Subject: Increase texture discard bias if system memory gets low

---
 indra/newview/app_settings/settings.xml | 22 +++++++++++++++
 indra/newview/lltextureview.cpp         |  2 --
 indra/newview/llviewertexture.cpp       | 48 +++++++++++++++++++++++++++------
 indra/newview/llviewertexture.h         |  1 +
 4 files changed, 63 insertions(+), 10 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 50632a7b07..e7e9fc5b88 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7716,6 +7716,28 @@
     <key>Value</key>
     <integer>0</integer>
   </map>
+  <key>RenderMinFreeMainMemoryThreshold</key>
+  <map>
+    <key>Comment</key>
+    <string>Minimum of available physical memory in MB before textures get scaled down</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>512</integer>
+  </map>
+  <key>RenderLowMemMinDiscardIncrement</key>
+  <map>
+    <key>Comment</key>
+    <string>Minimum increment of discard level if system memory gets low</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>F32</string>
+    <key>Value</key>
+    <real>0.1</real>
+  </map>
   <key>RenderMaxTextureIndex</key>
   <map>
     <key>Comment</key>
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index f521293b96..b51bcc5601 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -59,8 +59,6 @@
 #include "llvoavatarself.h"
 #include "lltexlayer.h"
 
-extern F32 texmem_lower_bound_scale;
-
 LLTextureView *gTextureView = NULL;
 
 #define HIGH_PRIORITY 100000000.f
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index c1062b9a01..c716eb4e86 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -101,6 +101,7 @@ U32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA;
 bool LLViewerTexture::sFreezeImageUpdates = false;
 F32 LLViewerTexture::sCurrentTime = 0.0f;
 
+constexpr F32 MEMORY_CHECK_WAIT_TIME = 1.0f;
 constexpr F32 MIN_VRAM_BUDGET = 768.f;
 F32 LLViewerTexture::sFreeVRAMMegabytes = MIN_VRAM_BUDGET;
 
@@ -484,10 +485,6 @@ void LLViewerTexture::initClass()
     LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture();
 }
 
-// non-const (used externally
-F32 texmem_lower_bound_scale = 0.85f;
-F32 texmem_middle_bound_scale = 0.925f;
-
 //static
 void LLViewerTexture::updateClass()
 {
@@ -519,14 +516,49 @@ void LLViewerTexture::updateClass()
     sFreeVRAMMegabytes = target - used;
 
     F32 over_pct = llmax((used-target) / target, 0.f);
-    sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.f + over_pct);
 
-    if (sDesiredDiscardBias > 1.f)
+    if (isSystemMemoryLow())
+    {
+        // System RAM is low -> ramp up discard bias over time to free memory
+        if (sEvaluationTimer.getElapsedTimeF32() > MEMORY_CHECK_WAIT_TIME)
+        {
+            static LLCachedControl<F32> low_mem_min_discard_increment(gSavedSettings, "RenderLowMemMinDiscardIncrement", .1f);
+            sDesiredDiscardBias += llmax(low_mem_min_discard_increment, over_pct);
+            sEvaluationTimer.reset();
+        }
+    }
+    else
     {
-        sDesiredDiscardBias -= gFrameIntervalSeconds * 0.01;
+        sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.f + over_pct);
+
+        if (sDesiredDiscardBias > 1.f)
+        {
+            sDesiredDiscardBias -= gFrameIntervalSeconds * 0.01;
+        }
     }
 
-    LLViewerTexture::sFreezeImageUpdates = false; // sDesiredDiscardBias > (desired_discard_bias_max - 1.0f);
+    LLViewerTexture::sFreezeImageUpdates = false;
+}
+
+//static
+bool LLViewerTexture::isSystemMemoryLow()
+{
+    static LLFrameTimer timer;
+    static U32Megabytes physical_res = U32Megabytes(U32_MAX);
+
+    static LLCachedControl<U32> min_free_main_memory(gSavedSettings, "RenderMinFreeMainMemoryThreshold", 512);
+    const U32Megabytes MIN_FREE_MAIN_MEMORY(min_free_main_memory);
+
+    if (timer.getElapsedTimeF32() < MEMORY_CHECK_WAIT_TIME) //call this once per second.
+    {
+        return physical_res < MIN_FREE_MAIN_MEMORY;
+    }
+
+    timer.reset();
+
+    LLMemory::updateMemoryInfo();
+    physical_res = LLMemory::getAvailableMemKB();
+    return physical_res < MIN_FREE_MAIN_MEMORY;
 }
 
 //end of static functions
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index dc9182bf1b..9963626ada 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -117,6 +117,7 @@ protected:
 public:
     static void initClass();
     static void updateClass();
+    static bool isSystemMemoryLow();
 
     LLViewerTexture(bool usemipmaps = true);
     LLViewerTexture(const LLUUID& id, bool usemipmaps) ;
-- 
cgit v1.2.3