From 87ecafd7b4b2d6f33c54547e561b0594ae742f8a Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 20 Mar 2023 20:08:40 +0200
Subject: [PATCH] SL-19426 AutoFPS - when enabled always render at least 5
 avatars

---
 indra/newview/llvoavatar.cpp | 91 ++++++++++++++++++++++++++++++++++--
 indra/newview/llvoavatar.h   |  5 ++
 2 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index dbfd47d2fa7..772abfc6a17 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -207,6 +207,8 @@ const F64 HUD_OVERSIZED_TEXTURE_DATA_SIZE = 1024 * 1024;
 
 const F32 MAX_TEXTURE_WAIT_TIME_SEC = 60;
 
+const S32 MIN_NONTUNED_AVS = 5;
+
 enum ERenderName
 {
 	RENDER_NAME_NEVER,
@@ -618,6 +620,8 @@ F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
 F32 LLVOAvatar::sGreyTime = 0.f;
 F32 LLVOAvatar::sGreyUpdateTime = 0.f;
 LLPointer<LLViewerTexture> LLVOAvatar::sCloudTexture = NULL;
+std::vector<LLUUID> LLVOAvatar::sAVsIgnoringARTLimit;
+S32 LLVOAvatar::sAvatarsNearby = 0;
 
 //-----------------------------------------------------------------------------
 // Helper functions
@@ -821,6 +825,8 @@ LLVOAvatar::~LLVOAvatar()
         LLPerfStats::tunedAvatars--;
         mTuned = false;
     }
+    sAVsIgnoringARTLimit.erase(std::remove(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID), sAVsIgnoringARTLimit.end());
+
 
 	logPendingPhases();
 	
@@ -8359,8 +8365,24 @@ void LLVOAvatar::updateTooSlow()
         render_time_raw = mRenderTime;
         render_geom_time_raw = mGeomTime;		
     }
-    if( (LLPerfStats::renderAvatarMaxART_ns > 0) && 
-        (LLPerfStats::raw_to_ns(render_time_raw) >= LLPerfStats::renderAvatarMaxART_ns) ) 
+
+	bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf();
+
+	bool ignore_tune = false;
+    if (autotune && sAVsIgnoringARTLimit.size() > 0)
+    {
+        auto it = std::find(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID);
+        if (it != sAVsIgnoringARTLimit.end())
+        {
+            S32 index = it - sAVsIgnoringARTLimit.begin();
+            ignore_tune = (index < (MIN_NONTUNED_AVS - sAvatarsNearby + 1 + LLPerfStats::tunedAvatars));
+        }
+    }
+
+	bool exceeds_max_ART =
+        ((LLPerfStats::renderAvatarMaxART_ns > 0) && (LLPerfStats::raw_to_ns(render_time_raw) >= LLPerfStats::renderAvatarMaxART_ns));
+
+    if (exceeds_max_ART && !ignore_tune)
     {
         if( !mTooSlow ) // if we were previously not slow (with or without shadows.)
         {			
@@ -8386,7 +8408,12 @@ void LLVOAvatar::updateTooSlow()
     {
         // LL_INFOS() << this->getFullname() << " ("<< (combined?"combined":"geometry") << ") good render time = " << LLPerfStats::raw_to_ns(render_time_raw) << " vs ("<< LLVOAvatar::sRenderTimeCap_ns << " set @ " << mLastARTUpdateFrame << LL_ENDL;
         mTooSlow = false;
-        mTooSlowWithoutShadows = false;	
+        mTooSlowWithoutShadows = false;
+
+		if (ignore_tune)
+		{
+            return;
+		}
     }
     if(mTooSlow && !mTuned)
     {
@@ -10661,6 +10688,64 @@ void LLVOAvatar::idleUpdateRenderComplexity()
 
     // Render Complexity
     calculateUpdateRenderComplexity(); // Update mVisualComplexity if needed	
+
+	bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf();
+    if (autotune && !isDead())
+    {
+        static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
+        F32 radius = render_far_clip * render_far_clip;
+
+        bool is_nearby = true;
+        if ((dist_vec_squared(getPositionGlobal(), gAgent.getPositionGlobal()) > radius) &&
+            (dist_vec_squared(getPositionGlobal(), gAgentCamera.getCameraPositionGlobal()) > radius))
+        {
+            is_nearby = false;
+        }
+
+        if (is_nearby && (sAVsIgnoringARTLimit.size() < MIN_NONTUNED_AVS))
+        {
+            if (std::count(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID) == 0)
+            {
+                sAVsIgnoringARTLimit.push_back(mID);
+            }
+        }
+        else if (!is_nearby)
+        {
+            sAVsIgnoringARTLimit.erase(std::remove(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID),
+                                       sAVsIgnoringARTLimit.end());
+        }
+        updateNearbyAvatarCount();
+    }
+}
+
+void LLVOAvatar::updateNearbyAvatarCount()
+{
+    static LLFrameTimer agent_update_timer;
+
+	if (agent_update_timer.getElapsedTimeF32() > 1.0f)
+    {
+        S32 avs_nearby = 0;
+        static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
+        F32 radius = render_far_clip * render_far_clip;
+        std::vector<LLCharacter *>::iterator char_iter = LLCharacter::sInstances.begin();
+        while (char_iter != LLCharacter::sInstances.end())
+        {
+            LLVOAvatar *avatar = dynamic_cast<LLVOAvatar *>(*char_iter);
+            if (avatar && !avatar->isDead() && !avatar->isControlAvatar())
+            {
+                if ((dist_vec_squared(avatar->getPositionGlobal(), gAgent.getPositionGlobal()) > radius) &&
+                    (dist_vec_squared(avatar->getPositionGlobal(), gAgentCamera.getCameraPositionGlobal()) > radius))
+                {
+                    char_iter++;
+                    continue;
+                }
+                avs_nearby++;
+            }
+            char_iter++;
+        }
+        sAvatarsNearby = avs_nearby;
+        agent_update_timer.reset();
+    }
 }
 
 void LLVOAvatar::idleUpdateDebugInfo()
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index e07ead9d46d..970ca523a52 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -315,6 +315,8 @@ class LLVOAvatar :
 
 	void 			idleUpdateBelowWater();
 
+	static void updateNearbyAvatarCount();
+
 	//--------------------------------------------------------------------
 	// Static preferences (controlled by user settings/menus)
 	//--------------------------------------------------------------------
@@ -339,6 +341,9 @@ class LLVOAvatar :
 
     static LLPointer<LLViewerTexture>  sCloudTexture;
 
+	static std::vector<LLUUID> sAVsIgnoringARTLimit;
+    static S32 sAvatarsNearby;
+
 	//--------------------------------------------------------------------
 	// Region state
 	//--------------------------------------------------------------------
-- 
GitLab