From 0edf6e230e4580fc61917bc823f82d983d807ccf Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 23 Aug 2024 16:35:52 -0500 Subject: #2388 Texture downrezzing tune up. (#2414) - Hold onto unreferenced textures for 30 seconds. - Don't downres unless memory is low - Downres when viewer is backgrounded. --- indra/newview/llface.cpp | 7 ----- indra/newview/llviewertexture.cpp | 32 ++++++++++++++++++++- indra/newview/llviewertexture.h | 11 +++---- indra/newview/llviewertexturelist.cpp | 54 ++++++++++++++++++++++++++++------- 4 files changed, 78 insertions(+), 26 deletions(-) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4dec4d5641..c69d74ad1b 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2212,13 +2212,6 @@ bool LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) F32 dist = lookAt.getLength3().getF32(); dist = llmax(dist-size.getLength3().getF32(), 0.001f); - //ramp down distance for nearby objects - if (dist < 16.f) - { - dist /= 16.f; - dist *= dist; - dist *= 16.f; - } lookAt.normalize3fast() ; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index eab564a856..452d6f2c04 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -548,7 +548,37 @@ void LLViewerTexture::updateClass() was_low = is_low; - sDesiredDiscardBias = llclamp(sDesiredDiscardBias, 1.f, 3.f); + + // set to max discard bias if the window has been backgrounded for a while + static bool was_backgrounded = false; + static LLFrameTimer backgrounded_timer; + + bool in_background = (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) || !gFocusMgr.getAppHasFocus(); + + if (in_background) + { + if (backgrounded_timer.getElapsedTimeF32() > 10.f) + { + if (!was_backgrounded) + { + LL_INFOS() << "Viewer is backgrounded, freeing up video memory." << LL_ENDL; + } + was_backgrounded = true; + sDesiredDiscardBias = 4.f; + } + } + else + { + backgrounded_timer.reset(); + if (was_backgrounded) + { // if the viewer was backgrounded + LL_INFOS() << "Viewer is no longer backgrounded, resuming normal texture usage." << LL_ENDL; + was_backgrounded = false; + sDesiredDiscardBias = 1.f; + } + } + + sDesiredDiscardBias = llclamp(sDesiredDiscardBias, 1.f, 4.f); LLViewerTexture::sFreezeImageUpdates = false; } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 9046daeab2..3866c898a6 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -146,6 +146,8 @@ public: virtual F32 getMaxVirtualSize() ; + LLFrameTimer* getLastReferencedTimer() { return &mLastReferencedTimer; } + S32 getFullWidth() const { return mFullWidth; } S32 getFullHeight() const { return mFullHeight; } /*virtual*/ void setKnownDrawSize(S32 width, S32 height); @@ -195,6 +197,7 @@ protected: mutable F32 mMaxVirtualSize = 0.f; // The largest virtual size of the image, in pixels - how much data to we need? mutable S32 mMaxVirtualSizeResetCounter; mutable S32 mMaxVirtualSizeResetInterval; + LLFrameTimer mLastReferencedTimer; ll_face_list_t mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture U32 mNumFaces[LLRender::NUM_TEXTURE_CHANNELS]; @@ -571,10 +574,7 @@ public: /*virtual*/ void addFace(U32 ch, LLFace* facep) ; /*virtual*/ void removeFace(U32 ch, LLFace* facep) ; - /*virtual*/ F32 getMaxVirtualSize() ; - - // get the timer that tracks the last time reinit was called - LLFrameTimer* getLastReferencedTimer() { return &mLastReferencedTimer; } + /*virtual*/ F32 getMaxVirtualSize(); private: void switchTexture(U32 ch, LLFace* facep) ; @@ -596,9 +596,6 @@ private: bool mIsPlaying ; U32 mUpdateVirtualSizeTime ; - // tracks last time reinit was called - LLFrameTimer mLastReferencedTimer; - public: static void updateClass() ; static void cleanUpClass() ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 1ac97a20cf..a5700ab264 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -889,12 +889,9 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag static LLCachedControl texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.04f); static LLCachedControl texture_scale_max(gSavedSettings, "TextureScaleMaxAreaFactor", 25.f); - if (imagep->getType() == LLViewerTexture::LOD_TEXTURE && imagep->getBoostLevel() == LLViewerTexture::BOOST_NONE) - { // reset max virtual size for unboosted LOD_TEXTURES - // this is an alternative to decaying mMaxVirtualSize over time - // that keeps textures from continously downrezzing and uprezzing in the background - imagep->mMaxVirtualSize = 0.f; - } + + F32 max_vsize = 0.f; + bool on_screen = false; LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) @@ -911,6 +908,8 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag F32 vsize = face->getPixelArea(); bool in_frustum = face->calcPixelArea(cos_angle_to_view_dir, radius); + on_screen = in_frustum; + // Scale desired texture resolution higher or lower depending on texture scale // // Minimum usage examples: a 1024x1024 texture with aplhabet, runing string @@ -936,15 +935,40 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag if (apply_bias) { F32 bias = powf(4, LLViewerTexture::sDesiredDiscardBias - 1.f); - bias = (F32)llround(bias); + bias = (F32) llround(bias); vsize /= bias; } - imagep->addTextureStats(vsize); + max_vsize = llmax(max_vsize, vsize); } } } + if (imagep->getType() == LLViewerTexture::LOD_TEXTURE && imagep->getBoostLevel() == LLViewerTexture::BOOST_NONE) + { // conditionally reset max virtual size for unboosted LOD_TEXTURES + // this is an alternative to decaying mMaxVirtualSize over time + // that keeps textures from continously downrezzing and uprezzing in the background + + if (LLViewerTexture::sDesiredDiscardBias > 2.f || + (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) + { + imagep->mMaxVirtualSize = 0.f; + } + } + + + imagep->addTextureStats(max_vsize); + +#if 0 + imagep->setDebugText(llformat("%d/%d - %d/%d -- %d/%d", + (S32)sqrtf(max_vsize), + (S32)sqrtf(imagep->mMaxVirtualSize), + imagep->getDiscardLevel(), + imagep->getDesiredDiscardLevel(), + imagep->getWidth(), + imagep->getFullWidth())); +#endif + // make sure to addTextureStats for any spotlights that are using this texture for (S32 vi = 0; vi < imagep->getNumVolumes(LLRender::LIGHT_TEX); ++vi) { @@ -955,18 +979,26 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag F32 max_inactive_time = 20.f; // inactive time before deleting saved raw image S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, and 1 for "entries" in updateImagesFetchTextures + F32 lazy_flush_timeout = 30.f; // delete unused images after 30 seconds + // // Flush formatted images using a lazy flush // S32 num_refs = imagep->getNumRefs(); if (num_refs <= min_refs && flush_images) { - // Remove the unused image from the image list - deleteImage(imagep); - return; + if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout) + { + // Remove the unused image from the image list + deleteImage(imagep); + return; + } } else { + // still referenced outside of image list, reset timer + imagep->getLastReferencedTimer()->reset(); + if (imagep->hasSavedRawImage()) { if (imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time) -- cgit v1.2.3