From b121735e3cc7dbadf6fe3aca469457269c6e3dce Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Sun, 8 Sep 2024 16:10:35 -0400
Subject: [PATCH] Backport probe/mirror fixes

---
 indra/newview/llheroprobemanager.cpp     |  77 +++++++-----
 indra/newview/llheroprobemanager.h       |  21 ++--
 indra/newview/llpanelvolume.cpp          |   2 +-
 indra/newview/llreflectionmap.cpp        |   4 +-
 indra/newview/llreflectionmap.h          |  12 +-
 indra/newview/llreflectionmapmanager.cpp | 150 ++++++++++++-----------
 indra/newview/llreflectionmapmanager.h   |   4 +-
 indra/newview/llviewerobject.h           |   7 +-
 indra/newview/llvovolume.cpp             |   6 +-
 indra/newview/llvovolume.h               |  14 +--
 10 files changed, 159 insertions(+), 138 deletions(-)

diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp
index 852116958b3..6e1f833dcd1 100644
--- a/indra/newview/llheroprobemanager.cpp
+++ b/indra/newview/llheroprobemanager.cpp
@@ -91,19 +91,19 @@ void LLHeroProbeManager::update()
 
     if (!mRenderTarget.isComplete())
     {
-        U32 color_fmt = GL_RGB16F;
+        U32 color_fmt = GL_RGBA16F;
         mRenderTarget.allocate(mProbeResolution, mProbeResolution, color_fmt, true);
     }
 
     if (mMipChain.empty())
     {
         U32 res = mProbeResolution;
-        U32 count = log2((F32)res) + 0.5f;
+        U32 count = (U32)(log2((F32)res) + 0.5f);
 
         mMipChain.resize(count);
-        for (int i = 0; i < count; ++i)
+        for (U32 i = 0; i < count; ++i)
         {
-            mMipChain[i].allocate(res, res, GL_RGB16F);
+            mMipChain[i].allocate(res, res, GL_RGBA16F);
             res /= 2;
         }
     }
@@ -122,6 +122,7 @@ void LLHeroProbeManager::update()
         // Find our nearest hero candidate.
         float last_distance = 99999.f;
         float camera_center_distance = 99999.f;
+        mNearestHero = nullptr;
         for (auto vo : mHeroVOList)
         {
             if (vo && !vo->isDead() && vo->mDrawable.notNull() && vo->isReflectionProbe() && vo->getReflectionProbeIsBox())
@@ -189,26 +190,22 @@ void LLHeroProbeManager::update()
                 LLVector3(0, 0, -1)
             };
 
-            // Iterate through each face of the cube
-            for (int i = 0; i < 6; i++)
-            {
-                float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i]));
-
-                cube_facing = 1 - cube_facing;
-
-                mFaceUpdateList[i] = ceilf(cube_facing * gPipeline.RenderHeroProbeConservativeUpdateMultiplier);
-            }
-
-            
             mProbes[0]->mOrigin = probe_pos;
+            mProbes[0]->mRadius = mNearestHero->getScale().magVec() * 0.5f;
         }
         else
         {
             mNearestHero = nullptr;
+            mDefaultProbe->mViewerObject = nullptr;
         }
 
         mHeroProbeStrength = 1;
     }
+    else
+    {
+        mNearestHero = nullptr;
+        mDefaultProbe->mViewerObject = nullptr;
+    }
 }
 
 void LLHeroProbeManager::renderProbes()
@@ -221,9 +218,10 @@ void LLHeroProbeManager::renderProbes()
 
     static LLCachedControl<S32> sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1);
     static LLCachedControl<S32> sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3);
+    static LLCachedControl<S32> sUpdateRate(gSavedSettings, "RenderHeroProbeUpdateRate", 0);
 
     F32 near_clip = 0.01f;
-    if (mNearestHero != nullptr && (gPipeline.RenderHeroProbeUpdateRate == 0 || (gFrameCount % gPipeline.RenderHeroProbeUpdateRate) == 0) &&
+    if (mNearestHero != nullptr &&
         !gTeleportDisplay && !gDisconnected && !LLAppViewer::instance()->logoutRequestSent())
     {
         LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime");
@@ -231,22 +229,36 @@ void LLHeroProbeManager::renderProbes()
         bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass();
 
         gPipeline.mReflectionMapManager.mRadiancePass = true;
-        mRenderingMirror                              = true;
+        mRenderingMirror = true;
 
-        doOcclusion();
+        S32 rate = sUpdateRate;
 
-        for (U32 j = 0; j < mProbes.size(); j++)
+        // rate must be divisor of 6 (1, 2, 3, or 6)
+        if (rate < 1)
+        {
+            rate = 1;
+        }
+        else if (rate > 3)
         {
+            rate = 6;
+        }
+
+        if (!mProbes.empty() && !mProbes[0].isNull() && !mProbes[0]->mOccluded)
+        {
+            LL_PROFILE_ZONE_NUM(gFrameCount % rate);
+            LL_PROFILE_ZONE_NUM(rate);
+
             for (U32 i = 0; i < 6; ++i)
             {
-                if (mFaceUpdateList[i] > 0 && mCurrentProbeUpdateFrame % mFaceUpdateList[i] == 0)
-                {
-                    updateProbeFace(mProbes[j], i, mNearestHero->getReflectionProbeIsDynamic() && sDetail > 0, near_clip);
-                    mCurrentProbeUpdateFrame = 0;
+                if ((gFrameCount % rate) == (i % rate))
+                { // update 6/rate faces per frame
+                    LL_PROFILE_ZONE_NUM(i);
+                    updateProbeFace(mProbes[0], i, mNearestHero->getReflectionProbeIsDynamic() && sDetail > 0, near_clip);
                 }
             }
-            generateRadiance(mProbes[j]);
+            generateRadiance(mProbes[0]);
         }
+
         mRenderingMirror = false;
 
         gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass;
@@ -254,8 +266,6 @@ void LLHeroProbeManager::renderProbes()
         mProbes[0]->mViewerObject = mNearestHero;
         mProbes[0]->autoAdjustOrigin();
     }
-
-    mCurrentProbeUpdateFrame++;
 }
 
 // Do the reflection map update render passes.
@@ -330,7 +340,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool
             gGaussianProgram.unbind();
         }
 
-        S32 mips = log2((F32)mProbeResolution) + 0.5f;
+        S32 mips = (S32)(log2((F32)mProbeResolution) + 0.5f);
 
         gReflectionMipProgram.bind();
         S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
@@ -360,7 +370,8 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool
 
             res /= 2;
 
-            S32 mip = i - (mMipChain.size() - mips);
+            llassert(mMipChain.size() <= size_t(S32_MAX));
+            GLint mip = i - (S32(mMipChain.size()) - mips);
 
             if (mip >= 0)
             {
@@ -388,6 +399,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool
 // Useful when we may not always be rendering a full set of faces of the probe.
 void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe)
 {
+    LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
     S32 sourceIdx = mReflectionProbeCount;
 
     // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes.
@@ -418,7 +430,7 @@ void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe)
                 static LLStaticHashedString sStrength("probe_strength");
 
                 gHeroRadianceGenProgram.uniform1f(sRoughness, (F32) i / (F32) (mMipChain.size() - 1));
-                gHeroRadianceGenProgram.uniform1f(sMipLevel, i);
+                gHeroRadianceGenProgram.uniform1f(sMipLevel, (GLfloat)i);
                 gHeroRadianceGenProgram.uniform1i(sWidth, mProbeResolution);
                 gHeroRadianceGenProgram.uniform1f(sStrength, 1);
 
@@ -487,7 +499,8 @@ void LLHeroProbeManager::updateUniforms()
         mHeroData.heroSphere.mV[3] = mProbes[0]->mRadius;
     }
 
-    mHeroData.heroMipCount = mMipChain.size();
+    llassert(mMipChain.size() <= size_t(S32_MAX));
+    mHeroData.heroMipCount = S32(mMipChain.size());
 }
 
 void LLHeroProbeManager::renderDebug()
@@ -518,7 +531,7 @@ void LLHeroProbeManager::initReflectionMaps()
         mReset = false;
         mReflectionProbeCount = count;
         mProbeResolution      = gSavedSettings.getS32("RenderHeroProbeResolution");
-        mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1
+        mMaxProbeLOD = log2f((F32)mProbeResolution) - 1.f; // number of mips - 1
 
         mTexture = new LLCubeMapArray();
 
@@ -588,7 +601,7 @@ void LLHeroProbeManager::doOcclusion()
 
     for (auto& probe : mProbes)
     {
-        if (probe != nullptr && probe != mDefaultProbe)
+        if (probe != nullptr)
         {
             probe->doOcclusion(eye);
         }
diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h
index 123cadf8082..58a94a3de82 100644
--- a/indra/newview/llheroprobemanager.h
+++ b/indra/newview/llheroprobemanager.h
@@ -51,18 +51,18 @@ class alignas(16) LLHeroProbeManager
 {
     LL_ALIGN_NEW
 public:
-    enum class DetailLevel 
+    enum class DetailLevel
     {
         STATIC_ONLY = 0,
         STATIC_AND_DYNAMIC,
         REALTIME = 2
     };
 
-    // allocate an environment map of the given resolution 
+    // allocate an environment map of the given resolution
     LLHeroProbeManager();
     ~LLHeroProbeManager();
 
-    // release any GL state 
+    // release any GL state
     void cleanup();
 
     // maintain reflection probes
@@ -90,11 +90,11 @@ class alignas(16) LLHeroProbeManager
     LLVector3 mMirrorPosition;
     LLVector3     mMirrorNormal;
     HeroProbeData mHeroData;
-    
+
 private:
     friend class LLPipeline;
     friend class LLReflectionMapManager;
-    
+
     // update UBO used for rendering (call only once per render pipe flush)
     void updateUniforms();
 
@@ -118,7 +118,7 @@ class alignas(16) LLHeroProbeManager
     // update the specified face of the specified probe
     void updateProbeFace(LLReflectionMap* probe, U32 face, bool is_dynamic, F32 near_clip);
     void generateRadiance(LLReflectionMap *probe);
-    
+
     // list of active reflection maps
     std::vector<LLPointer<LLReflectionMap>> mProbes;
 
@@ -129,10 +129,10 @@ class alignas(16) LLHeroProbeManager
 
     // resolution of reflection probes
     U32 mProbeResolution = 1024;
-    
+
     // maximum LoD of reflection probes (mip levels - 1)
     F32 mMaxProbeLOD = 6.f;
-    
+
     F32 mHeroProbeStrength = 1.f;
     bool mIsInTransition = false;
 
@@ -140,10 +140,7 @@ class alignas(16) LLHeroProbeManager
     bool mReset = false;
 
     bool mRenderingMirror = false;
-    std::map<int, int> mFaceUpdateList;
-    
-    U32 mCurrentProbeUpdateFrame = 0;
-    
+
     std::vector<LLPointer<LLVOVolume>>                       mHeroVOList;
     LLPointer<LLVOVolume>                                 mNearestHero;
 
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 0807fafee08..a6ffb3c619a 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -1270,7 +1270,7 @@ void LLPanelVolume::onPasteLight()
 
         if (clipboard.has("reflection_probe"))
         {
-            volobjp->setIsReflectionProbe(TRUE);
+            volobjp->setIsReflectionProbe(true);
             volobjp->setReflectionProbeIsBox(clipboard["reflection_probe"]["is_box"].asBoolean());
             volobjp->setReflectionProbeAmbiance((F32)clipboard["reflection_probe"]["ambiance"].asReal());
             volobjp->setReflectionProbeNearClip((F32)clipboard["reflection_probe"]["near_clip"].asReal());
diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp
index 99993f26b45..dbddef8460c 100644
--- a/indra/newview/llreflectionmap.cpp
+++ b/indra/newview/llreflectionmap.cpp
@@ -220,7 +220,7 @@ F32 LLReflectionMap::getNearClip()
 
     if (mViewerObject && mViewerObject->getVolume())
     {
-        ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeNearClip();
+        ret = mViewerObject->getReflectionProbeNearClip();
     }
     else if (mGroup)
     {
@@ -241,7 +241,7 @@ bool LLReflectionMap::getIsDynamic()
         mViewerObject &&
         mViewerObject->getVolume())
     {
-        return ((LLVOVolume*)mViewerObject)->getReflectionProbeIsDynamic();
+        return mViewerObject->getReflectionProbeIsDynamic();
     }
 
     return false;
diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h
index 9e888f20d0d..117ea4cfa66 100644
--- a/indra/newview/llreflectionmap.h
+++ b/indra/newview/llreflectionmap.h
@@ -36,7 +36,7 @@ class alignas(16) LLReflectionMap : public LLRefCount
 {
     LL_ALIGN_NEW
 public:
-    
+
     enum class ProbeType
     {
         ALL = 0,
@@ -44,8 +44,8 @@ class alignas(16) LLReflectionMap : public LLRefCount
         IRRADIANCE,
         REFLECTION
     };
-    
-    // allocate an environment map of the given resolution 
+
+    // allocate an environment map of the given resolution
     LLReflectionMap();
 
     ~LLReflectionMap();
@@ -86,7 +86,7 @@ class alignas(16) LLReflectionMap : public LLRefCount
 
     // point at which environment map was last generated from (in agent space)
     LLVector4a mOrigin;
-    
+
     // distance from main viewer camera
     F32 mDistance = -1.f;
 
@@ -106,7 +106,7 @@ class alignas(16) LLReflectionMap : public LLRefCount
     // cube map used to sample this environment map
     LLPointer<LLCubeMapArray> mCubeArray;
     S32 mCubeIndex = -1; // index into cube map array or -1 if not currently stored in cube map array
-    
+
     // probe has had at least one full update and is ready to render
     bool mComplete = false;
 
@@ -136,7 +136,7 @@ class alignas(16) LLReflectionMap : public LLRefCount
     GLuint mOcclusionQuery = 0;
     bool mOccluded = false;
     U32 mOcclusionPendingFrames = 0;
-    
+
     ProbeType mType;
 };
 
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 9a650412ad4..69da7b965e9 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -67,7 +67,7 @@ void load_exr(const std::string& filename)
     const char* err = NULL; // or nullptr in C++11
 
     int ret =  LoadEXRWithLayer(&out, &width, &height, filename.c_str(), /* layername */ nullptr, &err);
-    if (ret == TINYEXR_SUCCESS) 
+    if (ret == TINYEXR_SUCCESS)
     {
         U32 texName = 0;
         LLImageGL::generateTextures(1, &texName);
@@ -80,6 +80,8 @@ void load_exr(const std::string& filename)
         gGL.getTexUnit(0)->bind(gEXRImage);
 
         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_FLOAT, out);
+
+
         free(out); // release memory of image data
 
         glGenerateMipmap(GL_TEXTURE_2D);
@@ -87,12 +89,12 @@ void load_exr(const std::string& filename)
         gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 
     }
-    else 
+    else
     {
         LLSD notif_args;
         notif_args["WHAT"] = filename;
         notif_args["REASON"] = "Unknown";
-        if (err) 
+        if (err)
         {
             notif_args["REASON"] = std::string(err);
             FreeEXRErrorMessage(err); // release memory of error message.
@@ -220,8 +222,28 @@ void LLReflectionMapManager::update()
 
     initReflectionMaps();
 
+    if (!mRenderTarget.isComplete())
+    {
+        U32 color_fmt = GL_RGB16F;
+        U32 targetRes = mProbeResolution * 4; // super sample
+        mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
+    }
+
+    if (mMipChain.empty())
+    {
+        U32 res = mProbeResolution;
+        U32 count = (U32)(log2((F32)res) + 0.5f);
+
+        mMipChain.resize(count);
+        for (U32 i = 0; i < count; ++i)
+        {
+            mMipChain[i].allocate(res, res, GL_RGB16F);
+            res /= 2;
+        }
+    }
+
     llassert(mProbes[0] == mDefaultProbe);
-    
+
     LLVector4a camera_pos;
     camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
 
@@ -231,12 +253,12 @@ void LLReflectionMapManager::update()
         auto const & iter = std::find(mProbes.begin(), mProbes.end(), probe);
         if (iter != mProbes.end())
         {
-            deleteProbe(iter - mProbes.begin());
+            deleteProbe((U32)(iter - mProbes.begin()));
         }
     }
 
     mKillList.clear();
-    
+
     // process create list
     for (auto& probe : mCreateList)
     {
@@ -252,12 +274,12 @@ void LLReflectionMapManager::update()
 
 
     bool did_update = false;
-    
+
     static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1);
     static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3);
 
     bool realtime = sDetail >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
-    
+
     LLReflectionMap* closestDynamic = nullptr;
 
     LLReflectionMap* oldestProbe = nullptr;
@@ -296,7 +318,7 @@ void LLReflectionMapManager::update()
     // next distribute the free indices
     U32 count = llmin(mReflectionProbeCount, (U32)mProbes.size());
 
-    for (S32 i = 1; i < count && !mCubeFree.empty(); ++i)
+    for (U32 i = 1; i < count && !mCubeFree.empty(); ++i)
     {
         // find the closest probe that needs a cube index
         LLReflectionMap* probe = mProbes[i];
@@ -310,7 +332,7 @@ void LLReflectionMapManager::update()
         }
     }
 
-    for (int i = 0; i < mProbes.size(); ++i)
+    for (unsigned int i = 0; i < mProbes.size(); ++i)
     {
         LLReflectionMap* probe = mProbes[i];
         if (probe->getNumRefs() == 1)
@@ -319,8 +341,8 @@ void LLReflectionMapManager::update()
             --i;
             continue;
         }
-        
-        if (probe != mDefaultProbe.get() && 
+
+        if (probe != mDefaultProbe.get() &&
             (!probe->isRelevant() || mPaused))
         { // skip irrelevant probes (or all non-default probes if paused)
             continue;
@@ -422,7 +444,7 @@ void LLReflectionMapManager::update()
     {
         LLReflectionMap* probe = oldestProbe;
         llassert(probe->mCubeIndex != -1);
-        
+
         probe->autoAdjustOrigin();
 
         sUpdateCount++;
@@ -530,17 +552,22 @@ void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& ma
 
 LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* group)
 {
-    if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME)
+    if (!group)
     {
-        OctreeNode* node = group->getOctreeNode();
-        F32 size = node->getSize().getF32ptr()[0];
-        if (size >= 15.f && size <= 17.f)
-        {
-            return addProbe(group);
-        }
+        return nullptr;
     }
-
-    return nullptr;
+    LLSpatialPartition* part = group->getSpatialPartition();
+    if (!part || part->mPartitionType != LLViewerRegion::PARTITION_VOLUME)
+    {
+        return nullptr;
+    }
+    OctreeNode* node = group->getOctreeNode();
+    F32 size = node->getSize().getF32ptr()[0];
+    if (size < 15.f || size > 17.f)
+    {
+        return nullptr;
+    }
+    return addProbe(group);
 }
 
 LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vobj)
@@ -610,7 +637,7 @@ void LLReflectionMapManager::doProbeUpdate()
     llassert(mUpdatingProbe != nullptr);
 
     updateProbeFace(mUpdatingProbe, mUpdatingFace);
-    
+
     bool debug_updates = gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PROBE_UPDATES) && mUpdatingProbe->mViewerObject;
 
     if (++mUpdatingFace == 6)
@@ -663,11 +690,11 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
         touch_default_probe(probe);
 
         gPipeline.pushRenderTypeMask();
-        
+
         //only render sky, water, terrain, and clouds
         gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY,
             LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES);
-        
+
         probe->update(mRenderTarget.getWidth(), face);
 
         gPipeline.popRenderTypeMask();
@@ -676,7 +703,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
     {
         probe->update(mRenderTarget.getWidth(), face);
     }
-    
+
     gPipeline.mRT = &gPipeline.mMainRT;
 
     S32 sourceIdx = mReflectionProbeCount;
@@ -735,7 +762,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
         }
 
 
-        S32 mips = log2((F32)mProbeResolution) + 0.5f;
+        S32 mips = (S32)(log2((F32)mProbeResolution) + 0.5f);
 
         gReflectionMipProgram.bind();
         S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
@@ -753,15 +780,15 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
                 gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1]));
             }
 
-            
+
             gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2));
-            
+
             gPipeline.mScreenTriangleVB->setBuffer();
             gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-            
+
             res /= 2;
 
-            S32 mip = i - (mMipChain.size() - mips);
+            GLint mip = i - (static_cast<GLint>(mMipChain.size()) - mips);
 
             if (mip >= 0)
             {
@@ -813,7 +840,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
                 static LLStaticHashedString sWidth("u_width");
 
                 gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
-                gRadianceGenProgram.uniform1f(sMipLevel, i);
+                gRadianceGenProgram.uniform1f(sMipLevel, (GLfloat)i);
                 gRadianceGenProgram.uniform1i(sWidth, mProbeResolution);
 
                 for (int cf = 0; cf < 6; ++cf)
@@ -848,7 +875,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
 
             gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
             gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
-            
+
             mVertexBuffer->setBuffer();
             int start_mip = 0;
             // find the mip target to start with based on irradiance map resolution
@@ -925,7 +952,7 @@ void LLReflectionMapManager::updateNeighbors(LLReflectionMap* probe)
     //remove from existing neighbors
     {
         LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - clear");
-    
+
         for (auto& other : probe->mNeighbors)
         {
             auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe);
@@ -1036,7 +1063,7 @@ void LLReflectionMapManager::updateUniforms()
     bool is_ambiance_pass = gCubeSnapshot && !isRadiancePass();
     F32 ambscale = is_ambiance_pass ? 0.f : 1.f;
     F32 radscale = is_ambiance_pass ? 0.5f : 1.f;
-    
+
     for (auto* refmap : mReflectionMaps)
     {
         if (refmap == nullptr)
@@ -1054,8 +1081,8 @@ void LLReflectionMapManager::updateUniforms()
             //      4. For each bucket, store the index of the nearest probe that might influence pixels in that bucket
             //      5. In the shader, lookup the bucket for the pixel depth to get the index of the first probe that could possibly influence
             //          the current pixel.
-            int depth_min = llclamp(llfloor(refmap->mMinDepth), 0, 255);
-            int depth_max = llclamp(llfloor(refmap->mMaxDepth), 0, 255);
+            unsigned int depth_min = llclamp(llfloor(refmap->mMinDepth), 0, 255);
+            unsigned int depth_max = llclamp(llfloor(refmap->mMaxDepth), 0, 255);
             for (U32 i = depth_min; i <= depth_max; ++i)
             {
                 if (refmap->mMinDepth < minDepth[i])
@@ -1167,7 +1194,7 @@ void LLReflectionMapManager::updateUniforms()
     {
         // fill in gaps in refBucket
         S32 probe_idx = mReflectionProbeCount;
-        
+
         for (int i = 0; i < 256; ++i)
         {
             if (i < count)
@@ -1344,18 +1371,22 @@ void LLReflectionMapManager::initReflectionMaps()
 {
     U32 count = LL_MAX_REFLECTION_PROBE_COUNT;
 
-    static LLCachedControl<U32> probe_res_cc(gSavedSettings, "RenderReflectionProbeResolution", 128);
-    U32 probe_resolution = nhpo2(llclamp(probe_res_cc(), (U32)64, (U32)512));
-    bool probe_resolution_changed = mProbeResolution != probe_resolution;
-
-    if (mTexture.isNull() || mReflectionProbeCount != count || probe_resolution_changed || mReset)
+    static LLCachedControl<U32> ref_probe_res(gSavedSettings, "RenderReflectionProbeResolution", 128U);
+    U32 probe_resolution = nhpo2(llclamp(ref_probe_res(), (U32)64, (U32)512));
+    if (mTexture.isNull() || mReflectionProbeCount != count || mProbeResolution != probe_resolution || mReset)
     {
+        if(mProbeResolution != probe_resolution)
+        {
+            mRenderTarget.release();
+            mMipChain.clear();
+        }
+
         gEXRImage = nullptr;
 
         mReset = false;
         mReflectionProbeCount = count;
         mProbeResolution = probe_resolution;
-        mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1
+        mMaxProbeLOD = log2f((F32)mProbeResolution) - 1.f; // number of mips - 1
 
         if (mTexture.isNull() ||
             mTexture->getWidth() != mProbeResolution ||
@@ -1410,31 +1441,6 @@ void LLReflectionMapManager::initReflectionMaps()
 
         touch_default_probe(mDefaultProbe);
     }
-    if (probe_resolution_changed)
-    {
-        mRenderTarget.release();
-        mMipChain.clear();
-    }
-
-    if (!mRenderTarget.isComplete())
-    {
-        U32 color_fmt = GL_RGB16F;
-        U32 targetRes = mProbeResolution * 4; // super sample
-        mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
-    }
-
-    if (mMipChain.empty())
-    {
-        U32 res = mProbeResolution;
-        U32 count = log2((F32)res) + 0.5f;
-
-        mMipChain.resize(count);
-        for (int i = 0; i < count; ++i)
-        {
-            mMipChain[i].allocate(res, res, GL_RGB16F);
-            res /= 2;
-        }
-    }
 
     if (mVertexBuffer.isNull())
     {
@@ -1443,9 +1449,9 @@ void LLReflectionMapManager::initReflectionMaps()
         buff->allocateBuffer(4, 0);
 
         LLStrider<LLVector3> v;
-        
+
         buff->getVertexStrider(v);
-        
+
         v[0] = LLVector3(-1, -1, -1);
         v[1] = LLVector3(1, -1, -1);
         v[2] = LLVector3(-1, 1, -1);
@@ -1473,7 +1479,7 @@ void LLReflectionMapManager::cleanup()
 
     mReflectionMaps.clear();
     mUpdatingFace = 0;
-    
+
     mDefaultProbe = nullptr;
     mUpdatingProbe = nullptr;
 
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
index 5c0651bc248..f81fb307386 100644
--- a/indra/newview/llreflectionmapmanager.h
+++ b/indra/newview/llreflectionmapmanager.h
@@ -67,7 +67,7 @@ class alignas(16) LLReflectionMapManager
 
     // add a probe for the given spatial group
     LLReflectionMap* addProbe(LLSpatialGroup* group = nullptr);
-    
+
     // Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size()
     // If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr.
     //  maps -- presized array of Reflection Map pointers
@@ -160,7 +160,7 @@ class alignas(16) LLReflectionMapManager
 
     // update the specified face of the specified probe
     void updateProbeFace(LLReflectionMap* probe, U32 face);
-    
+
     // list of active reflection maps
     std::vector<LLPointer<LLReflectionMap> > mProbes;
 
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 4e002560a28..ab415717bb6 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -276,7 +276,12 @@ class LLViewerObject
     virtual BOOL isMesh() const                     { return FALSE; }
     virtual BOOL isRiggedMesh() const               { return FALSE; }
     virtual BOOL hasLightTexture() const            { return FALSE; }
-    virtual BOOL isReflectionProbe() const          { return FALSE; }
+    virtual bool isReflectionProbe() const          { return false; }
+    virtual F32 getReflectionProbeAmbiance() const  { return 0.f; }
+    virtual F32 getReflectionProbeNearClip() const  { return 0.f; }
+    virtual bool getReflectionProbeIsBox() const    { return false; }
+    virtual bool getReflectionProbeIsDynamic() const { return false; };
+    virtual bool getReflectionProbeIsMirror() const { return false; };
 
     // This method returns true if the object is over land owned by
     // the agent, one of its groups, or it encroaches and
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index b674e897e36..2294ca1c588 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3343,14 +3343,14 @@ F32 LLVOVolume::getLightCutoff() const
     }
 }
 
-BOOL LLVOVolume::isReflectionProbe() const
+bool LLVOVolume::isReflectionProbe() const
 {
     return getReflectionProbeParams() != nullptr;
 }
 
-bool LLVOVolume::setIsReflectionProbe(BOOL is_probe)
+bool LLVOVolume::setIsReflectionProbe(bool is_probe)
 {
-    BOOL was_probe = isReflectionProbe();
+    bool was_probe = isReflectionProbe();
     if (is_probe != was_probe)
     {
         if (is_probe)
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index b93baf211a1..055a0120a1a 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -300,19 +300,19 @@ class LLVOVolume final : public LLViewerObject
     F32 getLightCutoff() const;
 
     // Reflection Probes
-    bool setIsReflectionProbe(BOOL is_probe);
+    bool setIsReflectionProbe(bool is_probe);
     bool setReflectionProbeAmbiance(F32 ambiance);
     bool setReflectionProbeNearClip(F32 near_clip);
     bool setReflectionProbeIsBox(bool is_box);
     bool setReflectionProbeIsDynamic(bool is_dynamic);
     bool setReflectionProbeIsMirror(bool is_mirror);
 
-    BOOL isReflectionProbe() const override;
-    F32 getReflectionProbeAmbiance() const;
-    F32 getReflectionProbeNearClip() const;
-    bool getReflectionProbeIsBox() const;
-    bool getReflectionProbeIsDynamic() const;
-    bool getReflectionProbeIsMirror() const;
+    bool isReflectionProbe() const override;
+    F32 getReflectionProbeAmbiance() const override;
+    F32 getReflectionProbeNearClip() const override;
+    bool getReflectionProbeIsBox() const override;
+    bool getReflectionProbeIsDynamic() const override;
+    bool getReflectionProbeIsMirror() const override;
 
     // Flexible Objects
     U32 getVolumeInterfaceID() const;
-- 
GitLab