From 1452c5b82e0b391f37af536bccd51aa1dd4ef665 Mon Sep 17 00:00:00 2001 From: minerjr Date: Wed, 15 Jan 2025 01:25:21 -0400 Subject: [PATCH 1/5] FIRE-35011 - Initial work on fixing the main issue (deleting textures) Created a shadow mUUIDMap called mUUIDDeleteMap which contains a key/image pair of any object that is deleted. When a texture is deleted, it not moves over to this list, and is removed from the normal mUUIDMap and mImageList. Currently the callbacks are still there, but not being called by not being in the main lists. Added the reduction of calls as bias falls, adding flag to turn on/off the new feature. Fixed issue of not disconnecting the textures on shutdown. --- indra/newview/app_settings/settings.xml | 11 +++ indra/newview/llviewertexture.cpp | 39 ++++++++ indra/newview/llviewertexture.h | 5 + indra/newview/llviewertexturelist.cpp | 97 +++++++++++++++++-- indra/newview/llviewertexturelist.h | 1 + .../xui/en/panel_preferences_graphics1.xml | 10 ++ 6 files changed, 157 insertions(+), 6 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f23ae785a29..d639c877871 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2,6 +2,17 @@ + FSTextureNewBiasAdjustments + + Comment + Enable New Texture Bias Adjustments + Persist + 1 + Type + Boolean + Value + 1 + FSLandmarkCreatedNotification Comment diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 363f62b5f22..75b41114f37 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -91,6 +91,11 @@ S32 LLViewerTexture::sAuxCount = 0; LLFrameTimer LLViewerTexture::sEvaluationTimer; F32 LLViewerTexture::sDesiredDiscardBias = 0.f; +// +F32 LLViewerTexture::sPreviousDesiredDiscardBias = 0.f; // Init the static value of the previous discard bias, used to know what direction the bias is going, up, down or staying the same +F32 LLViewerTexture::sOverMemoryBudgetStartTime = 0.0f; // Init the static time when system first went over VRAM budget +F32 LLViewerTexture::sOverMemoryBudgetEndTime = 0.0f; // Init the static time when the system finally reached a normal memory amount +// S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size constexpr S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64; const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez; @@ -539,10 +544,35 @@ void LLViewerTexture::updateClass() static bool was_low = false; static bool was_sys_low = false; + // FIRE-35011 + //if (is_low && !was_low) + //{ + // // slam to 1.5 bias the moment we hit low memory (discards off screen textures immediately) + // sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.5f); + // + // if (is_sys_low || over_pct > 2.f) + // { // if we're low on system memory, emergency purge off screen textures to avoid a death spiral + // LL_WARNS() << "Low system memory detected, emergency downrezzing off screen textures" << LL_ENDL; + // for (auto& image : gTextureList) + // { + // gTextureList.updateImageDecodePriority(image, false /*will modify gTextureList otherwise!*/); + // } + // } + //} + // Update the previous desired discard bias with the current value before it is modified below. (By comparing the two, you can see if + // the bias is increasing, decreasing or staying the same. This is useful for determining how the system handles being over budget of + // RAM. + sPreviousDesiredDiscardBias = sDesiredDiscardBias; if (is_low && !was_low) { // slam to 1.5 bias the moment we hit low memory (discards off screen textures immediately) sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.5f); + // We want to store the time from when the system went over budget to when it finished, this can be used to help delay when textures are + // updated again after back to normal memory usage is achieved. This can help smooth out the suddent spikes in high resolution fetch + // requests. Set the over memory budget start time to the current time + sOverMemoryBudgetStartTime = sCurrentTime; + // Reset the over memory budget end time to 0.0 as the old value is longer valid + sOverMemoryBudgetEndTime = 0.0f; if (is_sys_low || over_pct > 2.f) { // if we're low on system memory, emergency purge off screen textures to avoid a death spiral @@ -553,6 +583,7 @@ void LLViewerTexture::updateClass() } } } + // was_low = is_low; was_sys_low = is_sys_low; @@ -623,6 +654,14 @@ void LLViewerTexture::updateClass() } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, 1.f, 4.f); + // + // If the desired discard bias is 1.0 but was previously a larger number, that means we are back to normal memory usage again + if (sDesiredDiscardBias == 1.0f && sPreviousDesiredDiscardBias > sDesiredDiscardBias) + { + // So we need to set the memory buget end time to the current time + sOverMemoryBudgetEndTime = sCurrentTime; + } + // LLViewerTexture::sFreezeImageUpdates = false; } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index bf890dbde79..24dc8bfad7f 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -226,6 +226,11 @@ class LLViewerTexture : public LLGLTexture static S32 sAuxCount; static LLFrameTimer sEvaluationTimer; static F32 sDesiredDiscardBias; + // + static F32 sPreviousDesiredDiscardBias; // Static value of the previous Desired Discard Bias (Used to determine if the desired discard bias is increasing, decreasing, or staying the same + static F32 sOverMemoryBudgetStartTime; // Static value stores the mCurrentTime when the viewer first went over budget of RAM (sDesiredDiscardBias > 1.0) + static F32 sOverMemoryBudgetEndTime; // Static value stores the mCurrentTime when the viewer first exists over budget of RAM (sDesiredDiscardBias == 1.0) + // static S32 sMaxSculptRez ; static U32 sMinLargeImageSize ; static U32 sMaxSmallImageSize ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index c15ef711d51..ea4ab8106be 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -117,6 +117,10 @@ void LLViewerTextureList::doPreloadImages() llassert_always(mInitialized) ; llassert_always(mImageList.empty()) ; llassert_always(mUUIDMap.empty()) ; + // FIRE-35011 + // Clear out the mUUIDDeleteMap as well + llassert_always(mUUIDDeleteMap.empty()); + // FIRE-35011 // Set the "missing asset" image LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); @@ -351,7 +355,6 @@ void LLViewerTextureList::shutdown() LL_DEBUGS() << "saving " << imagelist.size() << " image list entries" << LL_ENDL; LLSDSerialize::toPrettyXML(imagelist, file); } - // // Clean up "loaded" callbacks. // @@ -366,7 +369,9 @@ void LLViewerTextureList::shutdown() mFastCacheList.clear(); mUUIDMap.clear(); - + // FIRE-35011 + mUUIDDeleteMap.clear(); // Clear the UUIDMap for delete textures + // mImageList.clear(); mInitialized = false ; //prevent loading textures again. @@ -689,14 +694,38 @@ void LLViewerTextureList::findTexturesByID(const LLUUID &image_id, std::vectorsecond); iter++; } + // FIRE-35011 + // Possibly add the deleted images on to this list, depending on the use case. + // FIRE-35011 } LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLTextureKey &search_key) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; uuid_map_t::iterator iter = mUUIDMap.find(search_key); + // FIRE-35011 + // If the iterator reached the end, instead of returning null, try to see if the image exists on the deleted list if (iter == mUUIDMap.end()) + { + // + // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + // + // If the search_key exists on the delete map + if (mUUIDDeleteMap.count(search_key) == 1 && use_new_bias_adjustments) + { + // Set the normal map to have the same image as the delete map + mUUIDMap[search_key] = mUUIDDeleteMap[search_key]; + // Add the deleted image to the Image List + mImageList.insert(mUUIDMap[search_key]); + // Set the flag that the image is on the list to try + mUUIDMap[search_key]->setInImageList(true); + // And return the found image + return mUUIDMap[search_key]; + } + // Otherwise, return false as the image does not exist on either the normal or deleted lists return NULL; + } return iter->second; } @@ -790,14 +819,21 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListTy { LL_INFOS() << "Image with ID " << image_id << " already in list" << LL_ENDL; } + // + if (mUUIDDeleteMap.count(key) == 1) + { + // The key also exists on the delete list + // Remove the reference + } sNumImages++; addImageToList(new_image); mUUIDMap[key] = new_image; new_image->setTextureListType(tex_type); } - - + +// +/* void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -813,7 +849,35 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image) removeImageFromList(image); } } - +*/ +// Added new mapping for storing deleted textures (The deleting and creating new textures is what is killing the system. +void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + if( image) + { + //if (image->hasCallbacks()) + //{ + // mCallbackList.erase(image); + //} + LLTextureKey key(image->getID(), (ETexListType)image->getTextureListType()); + // Check to see if the key exists on the delete list first, if not, then + if (mUUIDDeleteMap.count(key) == 0) + { + // Add the image to the delete UUIDMap + mUUIDDeleteMap[key] = image; + } + else + { + // We should clean up the one that is about to be replaced. (SHould not happed) + mUUIDDeleteMap[key] = image; + } + llverify(mUUIDMap.erase(key) == 1); + sNumImages--; + removeImageFromList(image); + } +} +// /////////////////////////////////////////////////////////////////////////////// @@ -894,6 +958,17 @@ void LLViewerTextureList::clearFetchingRequests() LLViewerFetchedTexture* imagep = *iter; imagep->forceToDeleteRequest() ; } + // FIRE-35011 + // Need to purge any requests on the delete list + for (uuid_map_t::iterator iter = mUUIDDeleteMap.begin(); iter != mUUIDDeleteMap.end(); ++iter) + { + LLViewerFetchedTexture* imagep = iter->second; + if (imagep) + { + imagep->forceToDeleteRequest(); + } + } + // FIRE-35011 } extern bool gCubeSnapshot; @@ -1214,11 +1289,21 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) //update MIN_UPDATE_COUNT or 5% of other textures, whichever is greater update_count = llmax((U32) MIN_UPDATE_COUNT, (U32) mUUIDMap.size()/20); - if (LLViewerTexture::sDesiredDiscardBias > 1.f) + // + //if (LLViewerTexture::sDesiredDiscardBias > 1.f) + //{ + // // we are over memory target, update more agresively + // update_count = (S32)(update_count * LLViewerTexture::sDesiredDiscardBias); + //} + // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + // If the desired discard bias is greater then 1 and is increasing or stable, if descreasing, use the normal about of texture updates + if (LLViewerTexture::sDesiredDiscardBias > 1.f && LLViewerTexture::sDesiredDiscardBias >= LLViewerTexture::sPreviousDesiredDiscardBias) { // we are over memory target, update more agresively update_count = (S32)(update_count * LLViewerTexture::sDesiredDiscardBias); } + // update_count = llmin(update_count, (U32) mUUIDMap.size()); { // copy entries out of UUID map to avoid iterator invalidation from deletion inside updateImageDecodeProiroty or updateFetch below diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 3816c325006..a942cbc6874 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -238,6 +238,7 @@ class LLViewerTextureList private: typedef std::map< LLTextureKey, LLPointer > uuid_map_t; uuid_map_t mUUIDMap; + uuid_map_t mUUIDDeleteMap; LLTextureKey mLastUpdateKey; image_list_t mImageList; diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 9d4cd92403b..26e31070715 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -1230,6 +1230,16 @@ If you do not understand the distinction then leave this control alone." width="100"> Second(s) + From 2262f1544305c0c486189fe729cc46a439030f09 Mon Sep 17 00:00:00 2001 From: minerjr Date: Wed, 15 Jan 2025 12:22:53 -0400 Subject: [PATCH 2/5] FIRE-35011 - Possible final fix Added new handler for when memory runs low. Stopped deleting textures and instead put delete detects on a separate map which then can be later referenced and restored when the same texture request comes back again. Added sFreeVRAMMegabytes = llmax(target - used, 0.001f); fix that LL implemented. Added state object for the LLVIewerTexture memory (Fetched and LOD) --- indra/newview/llviewertexture.cpp | 179 +++++++++++++++++++++++++- indra/newview/llviewertexture.h | 27 +++- indra/newview/llviewertexturelist.cpp | 61 ++++++--- 3 files changed, 244 insertions(+), 23 deletions(-) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 75b41114f37..83b86a34a83 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -534,7 +534,7 @@ void LLViewerTexture::updateClass() // can negatively impact performance, so leave 20% of a breathing room for // 'bias' calculation to kick in. F32 target = llmax(llmin(budget - 512.f, budget * 0.8f), MIN_VRAM_BUDGET); - sFreeVRAMMegabytes = llmax(target - used, 0.f); + sFreeVRAMMegabytes = llmax(target - used, 0.001f); F32 over_pct = (used - target) / target; @@ -1768,6 +1768,157 @@ void LLViewerFetchedTexture::setDebugText(const std::string& text) extern bool gCubeSnapshot; +// +// This method will will handle the memory overage for the process texture stats methods for both Fetched and LOD textures +bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() +{ + // Static saved settings allowing to enable/disable the new bias adjustment feature + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + if (use_new_bias_adjustments) + { + // Check the current texture state is in delay, and if so, + if (mTextureState & LLViewerTexture::ETextureStates::RECOVERY_DELAY) + { + // Check to see if the current time is past the delay to normal use + if (mDelayToNormalUseAfterOverBudget <= sCurrentTime) + { + // If we are still in memory overage, then + if (sDesiredDiscardBias > 1.0f) + { + // Create an additional 1 second delay for this texture + mDelayToNormalUseAfterOverBudget = sCurrentTime + 1.0f; + // If the texture was deleted, we want to have a larger delay + if (mTextureState & ETextureStates::VRAM_OVERAGE_DELETED) + { + // We want to reset the delay as we should still wait + mDelayToNormalUseAfterOverBudget += 2.0f * sDesiredDiscardBias; + } + // Else if the texture was just scaled down, delay it a smaller amount + else if (mTextureState & ETextureStates::VRAM_SCALED_DOWN) + { + // Add to the delay 1/2 the current discard bias + mDelayToNormalUseAfterOverBudget += 0.5f * sDesiredDiscardBias; + } + + // Clear the Recovery delay as we should go back to see about lowering the quality of this texture again + // Save the current state back to to the next state + mPreviousTextureState = mTextureState; + + return true; + } + else + { + // Reset the delay to noral use back to 0.0f + mDelayToNormalUseAfterOverBudget = 0.0f; + // Store the current texture state in the previous state + mPreviousTextureState = mTextureState; + // Reset the texture back to normal + mTextureState = ETextureStates::NORMAL; + } + } + else + { + // Still waiting, so just return + return true; + } + } + // Else, we want to check to see if we are in a memory overage state + else if (sDesiredDiscardBias > 1.0f) + { + // If the texture currently is Normal + if (mTextureState == ETextureStates::NORMAL) + { + // Check to see if the texture should be scaled down + if (mDesiredDiscardLevel < (MAX_DISCARD_LEVEL - 1) && mBoostLevel < LLGLTexture::BOOST_SCULPTED) + { + // If the current desired discard bias is great then 2 and the discard level is incresing + if (sDesiredDiscardBias > 2.0f && sPreviousDesiredDiscardBias < sDesiredDiscardBias) + { + // Textures use a scale of 0 = max resolution, 5 = MAX_DISCARD_LEVEL (smallest level) + // Try to increase the current desired discard level by 1 level to see that helps + mDesiredDiscardLevel += 1; + // Store the current texture state before modifing it + mPreviousTextureState = mTextureState; + // Flag the texture as haven scaled down + mTextureState |= ETextureStates::VRAM_SCALED_DOWN; + // Update the virtual size + updateVirtualSize(); + } + + return true; + } + } + // Else, the texture has already been affected by the delay, check its status + else + { + // If the texture has already been deleted by the overage at least already + if (mTextureState & ETextureStates::VRAM_OVERAGE_DELETED) + { + // If the desired discard level is below the max discard level and the boost on the texture is less then BOOST_SCULPTED + if (mDesiredDiscardLevel < (MAX_DISCARD_LEVEL - 1) && mBoostLevel < LLGLTexture::BOOST_SCULPTED) + { + // Set the desired discard level to the max low quality + mDesiredDiscardLevel = MAX_DISCARD_LEVEL - 1; + // Update the virtual size + updateVirtualSize(); + } + } + // Else if the texture was scaled down before + else if (mTextureState & ETextureStates::VRAM_SCALED_DOWN) + { + // If more then 30 seconds has elapsed since going into texture over budget, then try to down size it to free + // up more memory + if (sCurrentTime - sOverMemoryBudgetStartTime > 30.0f) + { + // If the desired discard level is below the max discard level and the boost on the texture is less then + // BOOST_SCULPTED + if (mDesiredDiscardLevel < (MAX_DISCARD_LEVEL - 1) && mBoostLevel < LLGLTexture::BOOST_SCULPTED) + { + // Set the desired discard level to the next lower quality (by increaseing the value by 1) + mDesiredDiscardLevel += 1; + // Update the virtual size + updateVirtualSize(); + } + } + } + + return true; + } + } + // Else if we hve returned to normal memory usage after the memory acted up and it affected this texture + else if (sDesiredDiscardBias == 1.0f && mTextureState != ETextureStates::NORMAL && sOverMemoryBudgetEndTime != 0.0f) + { + // Create an additional 1 second delay for this texture + mDelayToNormalUseAfterOverBudget = sCurrentTime + 1.0f; + + // If the texture was deleted, we want to have a larger delay + if (mTextureState & ETextureStates::VRAM_OVERAGE_DELETED) + { + // We want to hold off on updating the time based upon how much time was spent during over budget, within 1 to 45 seconds + mDelayToNormalUseAfterOverBudget += llclamp((sOverMemoryBudgetEndTime - sOverMemoryBudgetStartTime), 1.0f, 45.0f); + } + // Else if the texture was just scaled down, delay it a smaller amount + else if (mTextureState & ETextureStates::VRAM_SCALED_DOWN) + { + // We want to hold off on updating the time based upon how much time was spent during over budget, within 1 to 5 seconds + mDelayToNormalUseAfterOverBudget += llclamp((sOverMemoryBudgetEndTime - sOverMemoryBudgetStartTime), 1.0f, 5.0f); + } + + // Store the current texture state before modifing it + mPreviousTextureState = mTextureState; + // Set the current texture state RECOVERY_DELAY flag + mTextureState |= ETextureStates::RECOVERY_DELAY; + + // Return as we don't want to process the bolow code + return true; + } + } + + // Default to return false, and that we don't want the parent method to return early. + return false; +} +// +// //virtual void LLViewerFetchedTexture::processTextureStats() { @@ -1775,6 +1926,19 @@ void LLViewerFetchedTexture::processTextureStats() llassert(!gCubeSnapshot); // should only be called when the main camera is active llassert(!LLPipeline::sShadowRender); + // + // Static saved settings allowing to enable/disable the new bias adjustment feature + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + if (use_new_bias_adjustments) + { + // If the handle memory overage returns true, then this method needs to exit early as it wants to delay loading more + // textures + if (handleMemoryOverageForProcessTextureStats()) + { + return; + } + } + // if(mFullyLoaded) { if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more @@ -3054,6 +3218,19 @@ bool LLViewerLODTexture::isUpdateFrozen() void LLViewerLODTexture::processTextureStats() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + // + // Static saved settings allowing to enable/disable the new bias adjustment feature + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + if (use_new_bias_adjustments) + { + // If the handle memory overage returns true, then this method needs to exit early as it wants to delay loading more + // textures + if (handleMemoryOverageForProcessTextureStats()) + { + return; + } + } + // updateVirtualSize(); bool did_downscale = false; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 24dc8bfad7f..5da3f518b54 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -185,6 +185,23 @@ class LLViewerTexture : public LLGLTexture typedef std::vector material_list_t; material_list_t mMaterialList; // reverse pointer pointing to LL::GLTF::Materials using this image as texture + // FIRE-35011 + // Create an enum bitfield for storing the various memory states + enum ETextureStates + { + NORMAL = 0, // Normal state + DELETED = 1, // Normal Delete + VRAM_OVERAGE_DELETED = 2, // Deleted during VRAM overage + VRAM_SCALED_DOWN = 4, // Scaled down during VRAM overage + RECOVERY_DELAY = 8 // Recovery delay after VRAM_OVERAGE_DELETED or VRAM_SCALED_DOWN is true + }; + + mutable U8 mTextureState; // Bitfield which represents the texture's current state + mutable U8 mPreviousTextureState; // Bitfield which represents the texture's current state + F32 mDelayToNormalUseAfterOverBudget; // Time to wait for returning to normal texture adjustments for larger resolution requests after + // being over VRAM budget + // + protected: void cleanup() ; void init(bool firstinit) ; @@ -226,11 +243,11 @@ class LLViewerTexture : public LLGLTexture static S32 sAuxCount; static LLFrameTimer sEvaluationTimer; static F32 sDesiredDiscardBias; - // + // FIRE-35011 static F32 sPreviousDesiredDiscardBias; // Static value of the previous Desired Discard Bias (Used to determine if the desired discard bias is increasing, decreasing, or staying the same static F32 sOverMemoryBudgetStartTime; // Static value stores the mCurrentTime when the viewer first went over budget of RAM (sDesiredDiscardBias > 1.0) static F32 sOverMemoryBudgetEndTime; // Static value stores the mCurrentTime when the viewer first exists over budget of RAM (sDesiredDiscardBias == 1.0) - // + // FIRE-35011 static S32 sMaxSculptRez ; static U32 sMinLargeImageSize ; static U32 sMaxSmallImageSize ; @@ -358,7 +375,11 @@ class LLViewerFetchedTexture : public LLViewerTexture void destroyTexture() ; - virtual void processTextureStats() ; + // FIRE-35011 + // New behavior for handling low memory for the ProcessTextureStats method for both Fetch and LOD textures + // Returns true if the the + bool handleMemoryOverageForProcessTextureStats(); + virtual void processTextureStats() ; bool needsAux() const { return mNeedsAux; } diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index ea4ab8106be..1a5fa35cac4 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -702,15 +702,14 @@ void LLViewerTextureList::findTexturesByID(const LLUUID &image_id, std::vector FIRE-35011 - // If the iterator reached the end, instead of returning null, try to see if the image exists on the deleted list + uuid_map_t::iterator iter = mUUIDMap.find(search_key); if (iter == mUUIDMap.end()) { - // + // FIRE-35011 + // If the iterator reached the end, instead of returning null, try to see if the image exists on the deleted list // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); - // + // If the search_key exists on the delete map if (mUUIDDeleteMap.count(search_key) == 1 && use_new_bias_adjustments) { @@ -724,6 +723,7 @@ LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLTextureKey &searc return mUUIDMap[search_key]; } // Otherwise, return false as the image does not exist on either the normal or deleted lists + // FIRE-35011 return NULL; } return iter->second; @@ -856,22 +856,45 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image) LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if( image) { - //if (image->hasCallbacks()) - //{ - // mCallbackList.erase(image); - //} - LLTextureKey key(image->getID(), (ETexListType)image->getTextureListType()); - // Check to see if the key exists on the delete list first, if not, then - if (mUUIDDeleteMap.count(key) == 0) - { - // Add the image to the delete UUIDMap - mUUIDDeleteMap[key] = image; - } - else + // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + // Do the old method of deleteing the call backs if using the old method, but we want to skip that in the + // new process + if (image->hasCallbacks() && !use_new_bias_adjustments) { - // We should clean up the one that is about to be replaced. (SHould not happed) - mUUIDDeleteMap[key] = image; + mCallbackList.erase(image); } + LLTextureKey key(image->getID(), (ETexListType)image->getTextureListType()); + // Instead of deleting the object, what we want to do it move it over to the UUID Delete Map + if (use_new_bias_adjustments) + { + // Check to see if the key exists on the delete list first, if not, then + if (mUUIDDeleteMap.count(key) == 0) + { + // Add the image to the delete UUIDMap + mUUIDDeleteMap[key] = image; + } + else + { + // We should clean up the one that is about to be replaced. (Should not happed) + mUUIDDeleteMap[key] = image; + } + // Store the current texture state in the previous texture state + image->mPreviousTextureState = image->mTextureState; + // Set the texture state based upon if the system is running out of memory + // If we are running out of memory + if (LLViewerTexture::sDesiredDiscardBias > 1.0f) + { + // Set the texture state to VRAM_OVERAGE_DELETED + image->mTextureState = LLViewerTexture::ETextureStates::VRAM_OVERAGE_DELETED; + } + // Else, this is normal delete, + else + { + // So just set the texture state to the normal delete state + image->mTextureState = LLViewerTexture::ETextureStates::DELETED; + } + } llverify(mUUIDMap.erase(key) == 1); sNumImages--; removeImageFromList(image); From 5a3663b268ad92d77371fed03c775b271f86ad45 Mon Sep 17 00:00:00 2001 From: minerjr Date: Wed, 15 Jan 2025 13:59:57 -0400 Subject: [PATCH 3/5] FIRE-35011 - Comment fixes and formatting updates Fixed up the comments to include the full JIRA issue. Added some comments on possible further investigations and tests if needed. --- indra/newview/app_settings/settings.xml | 6 +- indra/newview/llviewertexture.cpp | 37 +++++----- indra/newview/llviewertexture.h | 10 +-- indra/newview/llviewertexturelist.cpp | 69 ++++++++++++++----- indra/newview/llviewertexturelist.h | 4 +- .../xui/en/panel_preferences_graphics1.xml | 3 + 6 files changed, 90 insertions(+), 39 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index d639c877871..119877a36b6 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2,6 +2,9 @@ + + + FSTextureNewBiasAdjustments Comment @@ -11,8 +14,9 @@ Type Boolean Value - 1 + 0 + FSLandmarkCreatedNotification Comment diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 83b86a34a83..e2cc570e1cb 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -91,11 +91,11 @@ S32 LLViewerTexture::sAuxCount = 0; LLFrameTimer LLViewerTexture::sEvaluationTimer; F32 LLViewerTexture::sDesiredDiscardBias = 0.f; -// +// [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card F32 LLViewerTexture::sPreviousDesiredDiscardBias = 0.f; // Init the static value of the previous discard bias, used to know what direction the bias is going, up, down or staying the same F32 LLViewerTexture::sOverMemoryBudgetStartTime = 0.0f; // Init the static time when system first went over VRAM budget F32 LLViewerTexture::sOverMemoryBudgetEndTime = 0.0f; // Init the static time when the system finally reached a normal memory amount -// +// [FIRE-35011] S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size constexpr S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64; const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez; @@ -544,7 +544,7 @@ void LLViewerTexture::updateClass() static bool was_low = false; static bool was_sys_low = false; - // FIRE-35011 + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card //if (is_low && !was_low) //{ // // slam to 1.5 bias the moment we hit low memory (discards off screen textures immediately) @@ -583,7 +583,7 @@ void LLViewerTexture::updateClass() } } } - // + // [FIRE-35011] was_low = is_low; was_sys_low = is_sys_low; @@ -654,14 +654,14 @@ void LLViewerTexture::updateClass() } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, 1.f, 4.f); - // + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // If the desired discard bias is 1.0 but was previously a larger number, that means we are back to normal memory usage again if (sDesiredDiscardBias == 1.0f && sPreviousDesiredDiscardBias > sDesiredDiscardBias) { // So we need to set the memory buget end time to the current time sOverMemoryBudgetEndTime = sCurrentTime; } - // + // [FIRE-35011] LLViewerTexture::sFreezeImageUpdates = false; } @@ -1768,7 +1768,7 @@ void LLViewerFetchedTexture::setDebugText(const std::string& text) extern bool gCubeSnapshot; -// +// [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // This method will will handle the memory overage for the process texture stats methods for both Fetched and LOD textures bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() { @@ -1800,9 +1800,10 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() mDelayToNormalUseAfterOverBudget += 0.5f * sDesiredDiscardBias; } - // Clear the Recovery delay as we should go back to see about lowering the quality of this texture again // Save the current state back to to the next state mPreviousTextureState = mTextureState; + // Clear the RECOVERY_DELAY flag so the regular memory overage code can take over + mTextureState &= ~LLViewerTexture::ETextureStates::RECOVERY_DELAY; return true; } @@ -1885,8 +1886,9 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() return true; } } - // Else if we hve returned to normal memory usage after the memory acted up and it affected this texture - else if (sDesiredDiscardBias == 1.0f && mTextureState != ETextureStates::NORMAL && sOverMemoryBudgetEndTime != 0.0f) + // Else if we have returned to normal memory usage after the memory acted up and it affected this texture + else if (sDesiredDiscardBias == 1.0f && mTextureState != ETextureStates::NORMAL && mTextureState != ETextureStates::DELETED && + sOverMemoryBudgetEndTime != 0.0f) { // Create an additional 1 second delay for this texture mDelayToNormalUseAfterOverBudget = sCurrentTime + 1.0f; @@ -1917,7 +1919,7 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() // Default to return false, and that we don't want the parent method to return early. return false; } -// +// [FIRE-35011] // //virtual void LLViewerFetchedTexture::processTextureStats() @@ -1926,7 +1928,7 @@ void LLViewerFetchedTexture::processTextureStats() llassert(!gCubeSnapshot); // should only be called when the main camera is active llassert(!LLPipeline::sShadowRender); - // + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // Static saved settings allowing to enable/disable the new bias adjustment feature static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); if (use_new_bias_adjustments) @@ -1938,7 +1940,7 @@ void LLViewerFetchedTexture::processTextureStats() return; } } - // + // [FIRE-35011] if(mFullyLoaded) { if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more @@ -2591,7 +2593,10 @@ void LLViewerFetchedTexture::clearCallbackEntryList() return; } - +// [FIRE-35011] +// These following three methods may need to modified for use by the mUUIDDeleteMap, but right now they are +// not causing any issue. Just a future note. When on the Delete list, they are not active. +// [FIRE-35011] void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::source_callback_list_t* callback_list) { if(mLoadedCallbackList.empty() || !callback_list) @@ -3218,7 +3223,7 @@ bool LLViewerLODTexture::isUpdateFrozen() void LLViewerLODTexture::processTextureStats() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - // + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // Static saved settings allowing to enable/disable the new bias adjustment feature static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); if (use_new_bias_adjustments) @@ -3230,7 +3235,7 @@ void LLViewerLODTexture::processTextureStats() return; } } - // + // [FIRE-35011] updateVirtualSize(); bool did_downscale = false; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 5da3f518b54..0320d60043c 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -185,7 +185,7 @@ class LLViewerTexture : public LLGLTexture typedef std::vector material_list_t; material_list_t mMaterialList; // reverse pointer pointing to LL::GLTF::Materials using this image as texture - // FIRE-35011 + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // Create an enum bitfield for storing the various memory states enum ETextureStates { @@ -200,7 +200,7 @@ class LLViewerTexture : public LLGLTexture mutable U8 mPreviousTextureState; // Bitfield which represents the texture's current state F32 mDelayToNormalUseAfterOverBudget; // Time to wait for returning to normal texture adjustments for larger resolution requests after // being over VRAM budget - // + // [FIRE-35011] protected: void cleanup() ; @@ -243,11 +243,11 @@ class LLViewerTexture : public LLGLTexture static S32 sAuxCount; static LLFrameTimer sEvaluationTimer; static F32 sDesiredDiscardBias; - // FIRE-35011 + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card static F32 sPreviousDesiredDiscardBias; // Static value of the previous Desired Discard Bias (Used to determine if the desired discard bias is increasing, decreasing, or staying the same static F32 sOverMemoryBudgetStartTime; // Static value stores the mCurrentTime when the viewer first went over budget of RAM (sDesiredDiscardBias > 1.0) static F32 sOverMemoryBudgetEndTime; // Static value stores the mCurrentTime when the viewer first exists over budget of RAM (sDesiredDiscardBias == 1.0) - // FIRE-35011 + // [FIRE-35011] static S32 sMaxSculptRez ; static U32 sMinLargeImageSize ; static U32 sMaxSmallImageSize ; @@ -375,7 +375,7 @@ class LLViewerFetchedTexture : public LLViewerTexture void destroyTexture() ; - // FIRE-35011 + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // New behavior for handling low memory for the ProcessTextureStats method for both Fetch and LOD textures // Returns true if the the bool handleMemoryOverageForProcessTextureStats(); diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 1a5fa35cac4..5765ab26be2 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -117,10 +117,10 @@ void LLViewerTextureList::doPreloadImages() llassert_always(mInitialized) ; llassert_always(mImageList.empty()) ; llassert_always(mUUIDMap.empty()) ; - // FIRE-35011 + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // Clear out the mUUIDDeleteMap as well llassert_always(mUUIDDeleteMap.empty()); - // FIRE-35011 + // [FIRE-35011] // Set the "missing asset" image LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); @@ -355,6 +355,7 @@ void LLViewerTextureList::shutdown() LL_DEBUGS() << "saving " << imagelist.size() << " image list entries" << LL_ENDL; LLSDSerialize::toPrettyXML(imagelist, file); } + // // Clean up "loaded" callbacks. // @@ -369,9 +370,9 @@ void LLViewerTextureList::shutdown() mFastCacheList.clear(); mUUIDMap.clear(); - // FIRE-35011 + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card mUUIDDeleteMap.clear(); // Clear the UUIDMap for delete textures - // + // [FIRE-35011] mImageList.clear(); mInitialized = false ; //prevent loading textures again. @@ -694,9 +695,9 @@ void LLViewerTextureList::findTexturesByID(const LLUUID &image_id, std::vectorsecond); iter++; } - // FIRE-35011 + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // Possibly add the deleted images on to this list, depending on the use case. - // FIRE-35011 + // [FIRE-35011] } LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLTextureKey &search_key) @@ -705,7 +706,7 @@ LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLTextureKey &searc uuid_map_t::iterator iter = mUUIDMap.find(search_key); if (iter == mUUIDMap.end()) { - // FIRE-35011 + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // If the iterator reached the end, instead of returning null, try to see if the image exists on the deleted list // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); @@ -723,7 +724,7 @@ LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLTextureKey &searc return mUUIDMap[search_key]; } // Otherwise, return false as the image does not exist on either the normal or deleted lists - // FIRE-35011 + // [FIRE-35011] return NULL; } return iter->second; @@ -832,7 +833,7 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListTy new_image->setTextureListType(tex_type); } -// +// [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card /* void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image) { @@ -900,7 +901,7 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image) removeImageFromList(image); } } -// +// [FIRE-35011] /////////////////////////////////////////////////////////////////////////////// @@ -962,6 +963,30 @@ void LLViewerTextureList::updateImages(F32 max_time) } } + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card + /* + // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + + // Currently we are no longer deleting the Texture Memory at all, just forcing all images to scale down. + // We can possibly have an emergency clear for the map of deleted textures if we spend over 2 minutes at high memory. + // But this may just re-introduce the issue with the deleting textures as it is. + if (use_new_bias_adjustments && LLViewerTexture::sDesiredDiscardBias >= 4.0f && (LLViewerTexture::sCurrentTime - LLViewerTexture::sOverMemoryBudgetStartTime) > 120.0f) + { + // Need to purge any requests on the delete list + for (uuid_map_t::iterator iter = mUUIDDeleteMap.begin(); iter != mUUIDDeleteMap.end(); ++iter) + { + LLViewerFetchedTexture* imagep = iter->second; + if (imagep) + { + imagep->forceToDeleteRequest(); + } + } + mUUIDDeleteMap.clear(); // Clear the UUIDMap for delete textures + } + */ + // [FIRE-35011] + updateImagesUpdateStats(); } @@ -981,7 +1006,7 @@ void LLViewerTextureList::clearFetchingRequests() LLViewerFetchedTexture* imagep = *iter; imagep->forceToDeleteRequest() ; } - // FIRE-35011 + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // Need to purge any requests on the delete list for (uuid_map_t::iterator iter = mUUIDDeleteMap.begin(); iter != mUUIDDeleteMap.end(); ++iter) { @@ -1312,7 +1337,7 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) //update MIN_UPDATE_COUNT or 5% of other textures, whichever is greater update_count = llmax((U32) MIN_UPDATE_COUNT, (U32) mUUIDMap.size()/20); - // + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card //if (LLViewerTexture::sDesiredDiscardBias > 1.f) //{ // // we are over memory target, update more agresively @@ -1321,12 +1346,24 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); // If the desired discard bias is greater then 1 and is increasing or stable, if descreasing, use the normal about of texture updates - if (LLViewerTexture::sDesiredDiscardBias > 1.f && LLViewerTexture::sDesiredDiscardBias >= LLViewerTexture::sPreviousDesiredDiscardBias) + if (use_new_bias_adjustments) + { + if (LLViewerTexture::sDesiredDiscardBias > 1.f && + LLViewerTexture::sDesiredDiscardBias >= LLViewerTexture::sPreviousDesiredDiscardBias) + { + // we are over memory target, update more agresively + update_count = (S32)(update_count * LLViewerTexture::sDesiredDiscardBias); + } + } + else { - // we are over memory target, update more agresively - update_count = (S32)(update_count * LLViewerTexture::sDesiredDiscardBias); + if (LLViewerTexture::sDesiredDiscardBias > 1.f) + { + // we are over memory target, update more agresively + update_count = (S32)(update_count * LLViewerTexture::sDesiredDiscardBias); + } } - // + // [FIRE-35011] update_count = llmin(update_count, (U32) mUUIDMap.size()); { // copy entries out of UUID map to avoid iterator invalidation from deletion inside updateImageDecodeProiroty or updateFetch below diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index a942cbc6874..7b37f1ba90c 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -238,7 +238,9 @@ class LLViewerTextureList private: typedef std::map< LLTextureKey, LLPointer > uuid_map_t; uuid_map_t mUUIDMap; - uuid_map_t mUUIDDeleteMap; + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card + uuid_map_t mUUIDDeleteMap; // New storage for Delete Textures (they now don't go away fully), fixing manuy performace issues + // [FIRE-35011] LLTextureKey mLastUpdateKey; image_list_t mImageList; diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 26e31070715..3a038e0e6da 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -1230,6 +1230,8 @@ If you do not understand the distinction then leave this control alone." width="100"> Second(s) + + + From fded1f0ab75faf2a30791b73c61b7d62376e8c7d Mon Sep 17 00:00:00 2001 From: minerjr Date: Wed, 15 Jan 2025 21:11:19 -0400 Subject: [PATCH 4/5] FIRE-35011 - More updates with more polished code and tests Update to have more checks around new code for enable/disable the feature. Re-added checks on updatefetch to limit the deleted and scaled texture desired. Added comment out code to automatically delete data in the delete UUIDMap, but want to test out the current system as is. --- indra/newview/llviewertexture.cpp | 116 ++++++++++++++++++++++---- indra/newview/llviewertexture.h | 4 +- indra/newview/llviewertexturelist.cpp | 63 +++++++++++--- 3 files changed, 155 insertions(+), 28 deletions(-) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index e2cc570e1cb..58730b18b22 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -527,14 +527,14 @@ void LLViewerTexture::updateClass() // Expose max texture VRAM setting //F32 budget = max_vram_budget == 0 ? (F32)gGLManager.mVRAM : (F32)max_vram_budget; F32 budget = !max_vram_budget_enabled ? (F32)gGLManager.mVRAM : (F32)max_vram_budget; - + //budget *= 2.0f; // Try to leave at least half a GB for everyone else and for bias, // but keep at least 768MB for ourselves // Viewer can 'overshoot' target when scene changes, if viewer goes over budget it // can negatively impact performance, so leave 20% of a breathing room for // 'bias' calculation to kick in. F32 target = llmax(llmin(budget - 512.f, budget * 0.8f), MIN_VRAM_BUDGET); - sFreeVRAMMegabytes = llmax(target - used, 0.001f); + sFreeVRAMMegabytes = llmax(target - used, 0.0f); F32 over_pct = (used - target) / target; @@ -607,12 +607,13 @@ void LLViewerTexture::updateClass() // don't execute above until the slam to 1.5 has a chance to take effect sEvaluationTimer.reset(); - // lower discard bias over time when free memory is available - if (sDesiredDiscardBias > 1.f && over_pct < 0.f) + // lower discard bias over time when at least 10% of budget is free + const F32 FREE_PERCENTAGE_TRESHOLD = -0.1f; + if (sDesiredDiscardBias > 1.f && over_pct < FREE_PERCENTAGE_TRESHOLD) { static LLCachedControl high_mem_discard_decrement(gSavedSettings, "RenderHighMemMinDiscardDecrement", .1f); - F32 decrement = high_mem_discard_decrement - llmin(over_pct, 0.f); + F32 decrement = high_mem_discard_decrement - llmin(over_pct - FREE_PERCENTAGE_TRESHOLD, 0.f); sDesiredDiscardBias -= decrement * gFrameIntervalSeconds; } } @@ -666,6 +667,17 @@ void LLViewerTexture::updateClass() LLViewerTexture::sFreezeImageUpdates = false; } +// [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card +// Accessor method to store the current texture state and update the current texture state +void LLViewerTexture::setTextureState(ETextureStates newState) +{ + // Store the current texture state + mPreviousTextureState = mTextureState; + // Update the current texture state with the flag passed in + mTextureState |= mPreviousTextureState; +} +// [FIRE-35011] + //static bool LLViewerTexture::isSystemMemoryLow() { @@ -741,7 +753,12 @@ void LLViewerTexture::init(bool firstinit) mMaxVirtualSizeResetInterval = 1; mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval; mParcelMedia = NULL; - + + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card + mTextureState = ETextureStates::NORMAL; // Init the Texture state to NORMAL + mPreviousTextureState = ETextureStates::NORMAL; // Init the prevous texture state to NORMAL + mDelayToNormalUseAfterOverBudget = 0.0f; // Set the delay to normal use after over budget to 0.0f + // [FIRE-35011] memset(&mNumVolumes, 0, sizeof(U32)* LLRender::NUM_VOLUME_TEXTURE_CHANNELS); mVolumeList[LLRender::LIGHT_TEX].clear(); mVolumeList[LLRender::SCULPT_TEX].clear(); @@ -1786,7 +1803,7 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() if (sDesiredDiscardBias > 1.0f) { // Create an additional 1 second delay for this texture - mDelayToNormalUseAfterOverBudget = sCurrentTime + 1.0f; + mDelayToNormalUseAfterOverBudget = sCurrentTime + 1.0f + ll_rand() * 10.0f; // If the texture was deleted, we want to have a larger delay if (mTextureState & ETextureStates::VRAM_OVERAGE_DELETED) { @@ -1800,11 +1817,6 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() mDelayToNormalUseAfterOverBudget += 0.5f * sDesiredDiscardBias; } - // Save the current state back to to the next state - mPreviousTextureState = mTextureState; - // Clear the RECOVERY_DELAY flag so the regular memory overage code can take over - mTextureState &= ~LLViewerTexture::ETextureStates::RECOVERY_DELAY; - return true; } else @@ -1829,6 +1841,7 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() // If the texture currently is Normal if (mTextureState == ETextureStates::NORMAL) { + /* // Check to see if the texture should be scaled down if (mDesiredDiscardLevel < (MAX_DISCARD_LEVEL - 1) && mBoostLevel < LLGLTexture::BOOST_SCULPTED) { @@ -1844,14 +1857,25 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() mTextureState |= ETextureStates::VRAM_SCALED_DOWN; // Update the virtual size updateVirtualSize(); + //Reset + + + // If we are not forced to save the raw iamge, then + if (!mForceToSaveRawImage) + { + // should scale down + //scaleDown(); + } } - return true; + //return true; } + */ } // Else, the texture has already been affected by the delay, check its status else { + /* // If the texture has already been deleted by the overage at least already if (mTextureState & ETextureStates::VRAM_OVERAGE_DELETED) { @@ -1862,6 +1886,12 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() mDesiredDiscardLevel = MAX_DISCARD_LEVEL - 1; // Update the virtual size updateVirtualSize(); + // If we are not forced to save the raw iamge, then + if (!mForceToSaveRawImage) + { + // should scale down + //scaleDown(); + } } } // Else if the texture was scaled down before @@ -1879,11 +1909,18 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() mDesiredDiscardLevel += 1; // Update the virtual size updateVirtualSize(); + // If we are not forced to save the raw iamge, then + if (!mForceToSaveRawImage) + { + // should scale down + //scaleDown(); + } } } } - - return true; + */ + + return false; } } // Else if we have returned to normal memory usage after the memory acted up and it affected this texture @@ -2208,7 +2245,10 @@ bool LLViewerFetchedTexture::updateFetch() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static LLCachedControl textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false); - + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card + // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + // [FIRE-35011] if(textures_decode_disabled) // don't fetch the surface textures in wireframe mode { return false; @@ -2341,8 +2381,38 @@ bool LLViewerFetchedTexture::updateFetch() } else { + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // already at a higher resolution mip, don't discard - if (current_discard >= 0 && current_discard <= desired_discard) + //if (current_discard >= 0 && current_discard <= desired_discard) + // If we are in a high memory situation which is increasing and our texture is not normal + if (use_new_bias_adjustments && sDesiredDiscardBias > 1.0f && sDesiredDiscardBias > sPreviousDesiredDiscardBias && mTextureState != LLViewerTexture::ETextureStates::NORMAL) + { + // If the texture has already been deleted by the overage at least already + if (mTextureState & ETextureStates::VRAM_OVERAGE_DELETED) + { + // If the desired discard level is below the max discard level and the boost on the texture is less then BOOST_SCULPTED + if (mDesiredDiscardLevel < (MAX_DISCARD_LEVEL - 1) && mBoostLevel < LLGLTexture::BOOST_SCULPTED) + { + // Set the desired discard level to the max low quality + mDesiredDiscardLevel = MAX_DISCARD_LEVEL - 1; + } + } + // Else if the texture was scaled down before + else if (mTextureState & ETextureStates::VRAM_SCALED_DOWN) + { + // If the desired discard level is below the max discard level and the boost on the texture is less then + // BOOST_SCULPTED + if (mDesiredDiscardLevel < (MAX_DISCARD_LEVEL - 1) && mBoostLevel < LLGLTexture::BOOST_SCULPTED) + { + // Set the desired discard level to the next lower quality (by increaseing the value by 1) + mDesiredDiscardLevel += 1; + } + } + } + // already at a higher resolution mip, don't discard + //if (current_discard >= 0 && current_discard <= desired_discard) + else if (current_discard >= 0 && current_discard <= desired_discard) + // [FIRE-35011] { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current <= desired"); make_request = false; @@ -2593,6 +2663,7 @@ void LLViewerFetchedTexture::clearCallbackEntryList() return; } + // [FIRE-35011] // These following three methods may need to modified for use by the mUUIDDeleteMap, but right now they are // not causing any issue. Just a future note. When on the Delete list, they are not active. @@ -3367,6 +3438,17 @@ bool LLViewerLODTexture::scaleDown() if (!mDownScalePending) { + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card + // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + if (sDesiredDiscardBias > 1.0f && use_new_bias_adjustments) + { + // Store the previous texture state + mPreviousTextureState = mTextureState; + // Flag that the texture was downscaled during low memory + mTextureState |= ETextureStates::VRAM_SCALED_DOWN; + } + // [FIRE-35011] mDownScalePending = true; gTextureList.mDownScaleQueue.push(this); } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 0320d60043c..a376c8404fd 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -196,6 +196,7 @@ class LLViewerTexture : public LLGLTexture RECOVERY_DELAY = 8 // Recovery delay after VRAM_OVERAGE_DELETED or VRAM_SCALED_DOWN is true }; + void setTextureState(ETextureStates newState); mutable U8 mTextureState; // Bitfield which represents the texture's current state mutable U8 mPreviousTextureState; // Bitfield which represents the texture's current state F32 mDelayToNormalUseAfterOverBudget; // Time to wait for returning to normal texture adjustments for larger resolution requests after @@ -375,11 +376,12 @@ class LLViewerFetchedTexture : public LLViewerTexture void destroyTexture() ; + virtual void processTextureStats() ; // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // New behavior for handling low memory for the ProcessTextureStats method for both Fetch and LOD textures // Returns true if the the bool handleMemoryOverageForProcessTextureStats(); - virtual void processTextureStats() ; + bool needsAux() const { return mNeedsAux; } diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 5765ab26be2..664dc90ae7a 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -696,7 +696,27 @@ void LLViewerTextureList::findTexturesByID(const LLUUID &image_id, std::vector [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card - // Possibly add the deleted images on to this list, depending on the use case. + // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + // If we are using the new bias adjustments, then + if (use_new_bias_adjustments) + { + // Add the deleted images on to this list, + uuid_map_t::iterator del_iter = mUUIDDeleteMap.lower_bound(search_key); + while (del_iter != mUUIDDeleteMap.end() && del_iter->first.textureId == image_id) + { + // Set the normal map to have the same image as the delete map + mUUIDMap[del_iter->first] = del_iter->second; + // Add the deleted image to the Image List + mImageList.insert(del_iter->second); + // Set the flag that the image is on the list to try + mUUIDMap[del_iter->first]->setInImageList(true); + output.push_back(del_iter->second); + // Remove the deleted texture from the delete UUID Map + mUUIDDeleteMap.erase(del_iter->first); + del_iter++; + } + } // [FIRE-35011] } @@ -720,6 +740,8 @@ LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLTextureKey &searc mImageList.insert(mUUIDMap[search_key]); // Set the flag that the image is on the list to try mUUIDMap[search_key]->setInImageList(true); + // Remove the deleted texture from the delete UUID Map + mUUIDDeleteMap.erase(search_key); // And return the found image return mUUIDMap[search_key]; } @@ -824,7 +846,8 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListTy if (mUUIDDeleteMap.count(key) == 1) { // The key also exists on the delete list - // Remove the reference + // Remove the reference + mUUIDDeleteMap.erase(key); } sNumImages++; @@ -1008,15 +1031,22 @@ void LLViewerTextureList::clearFetchingRequests() } // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // Need to purge any requests on the delete list - for (uuid_map_t::iterator iter = mUUIDDeleteMap.begin(); iter != mUUIDDeleteMap.end(); ++iter) + // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) + static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); + // If we are using the new bias system + if (use_new_bias_adjustments) { - LLViewerFetchedTexture* imagep = iter->second; - if (imagep) + // Iterator over all of the objects in the UUID Delete Map + for (uuid_map_t::iterator iter = mUUIDDeleteMap.begin(); iter != mUUIDDeleteMap.end(); ++iter) { - imagep->forceToDeleteRequest(); + LLViewerFetchedTexture* imagep = iter->second; + if (imagep) + { + imagep->forceToDeleteRequest(); + } } } - // FIRE-35011 + // [FIRE-35011] } extern bool gCubeSnapshot; @@ -1110,11 +1140,21 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag // this is an alternative to decaying mMaxVirtualSize over time // that keeps textures from continously downrezzing and uprezzing in the background - if (LLViewerTexture::sDesiredDiscardBias > 1.5f || - (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card + //if (LLViewerTexture::sDesiredDiscardBias > 1.5f || + // (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) + //{ + // imagep->mMaxVirtualSize = 0.f; + //} + // Only keep downsizeing if the bias is increasing + if ((LLViewerTexture::sDesiredDiscardBias > 1.5f || (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) && + LLViewerTexture::sDesiredDiscardBias > LLViewerTexture::sPreviousDesiredDiscardBias) { imagep->mMaxVirtualSize = 0.f; + // Flag the image that it was downsized + imagep->setTextureState(LLViewerTexture::ETextureStates::VRAM_SCALED_DOWN); } + // [FIRE-35011] } imagep->addTextureStats(max_vsize); @@ -1345,9 +1385,11 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) //} // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); - // If the desired discard bias is greater then 1 and is increasing or stable, if descreasing, use the normal about of texture updates + // If using the new bias adjustments, then perform the new actions if (use_new_bias_adjustments) { + // If the desired discard bias is greater then 1 and is increasing or stable, if descreasing, use the normal about of texture + // updates if (LLViewerTexture::sDesiredDiscardBias > 1.f && LLViewerTexture::sDesiredDiscardBias >= LLViewerTexture::sPreviousDesiredDiscardBias) { @@ -1357,6 +1399,7 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) } else { + // Else, use the standard method if (LLViewerTexture::sDesiredDiscardBias > 1.f) { // we are over memory target, update more agresively From 62369b087ab6cec15962fd511a11f87510ab4d27 Mon Sep 17 00:00:00 2001 From: minerjr Date: Thu, 16 Jan 2025 14:18:29 -0400 Subject: [PATCH 5/5] FIRE - 35011 Some change, but not working well currently. --- indra/newview/llviewertexture.cpp | 94 +++++++++++++++++++++------ indra/newview/llviewertexture.h | 29 ++++++++- indra/newview/llviewertexturelist.cpp | 83 +++++++++++++++-------- 3 files changed, 156 insertions(+), 50 deletions(-) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 58730b18b22..364e3cfe134 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -95,6 +95,7 @@ F32 LLViewerTexture::sDesiredDiscardBias = 0.f; F32 LLViewerTexture::sPreviousDesiredDiscardBias = 0.f; // Init the static value of the previous discard bias, used to know what direction the bias is going, up, down or staying the same F32 LLViewerTexture::sOverMemoryBudgetStartTime = 0.0f; // Init the static time when system first went over VRAM budget F32 LLViewerTexture::sOverMemoryBudgetEndTime = 0.0f; // Init the static time when the system finally reached a normal memory amount +LLViewerTexture::OverMemoryBudetStates_u LLViewerTexture::sOverMemoryBudgetState; // Init the static flag to determine if the over budget is staying still // [FIRE-35011] S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size constexpr S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64; @@ -563,8 +564,15 @@ void LLViewerTexture::updateClass() // the bias is increasing, decreasing or staying the same. This is useful for determining how the system handles being over budget of // RAM. sPreviousDesiredDiscardBias = sDesiredDiscardBias; + // Update the state of the over memory budget state to the values stored here + sOverMemoryBudgetState.ClearState = 0; + sOverMemoryBudgetState.States.LowSystemRAM = is_sys_low; + sOverMemoryBudgetState.States.PreviousLowSystemRam = was_sys_low; + sOverMemoryBudgetState.States.LowVRAM = was_low; + if (is_low && !was_low) { + sOverMemoryBudgetState.States.UseBias = 1; // slam to 1.5 bias the moment we hit low memory (discards off screen textures immediately) sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.5f); // We want to store the time from when the system went over budget to when it finished, this can be used to help delay when textures are @@ -577,6 +585,7 @@ void LLViewerTexture::updateClass() if (is_sys_low || over_pct > 2.f) { // if we're low on system memory, emergency purge off screen textures to avoid a death spiral LL_WARNS() << "Low system memory detected, emergency downrezzing off screen textures" << LL_ENDL; + sOverMemoryBudgetState.States.Overage_High = 1; for (auto& image : gTextureList) { gTextureList.updateImageDecodePriority(image, false /*will modify gTextureList otherwise!*/); @@ -590,6 +599,8 @@ void LLViewerTexture::updateClass() if (is_low) { + // Flag that we are using the bias + sOverMemoryBudgetState.States.UseBias = 1; // ramp up discard bias over time to free memory LL_DEBUGS("TextureMemory") << "System memory is low, use more aggressive discard bias." << LL_ENDL; if (sEvaluationTimer.getElapsedTimeF32() > MEMORY_CHECK_WAIT_TIME) @@ -598,6 +609,7 @@ void LLViewerTexture::updateClass() F32 increment = low_mem_min_discard_increment + llmax(over_pct, 0.f); sDesiredDiscardBias += increment * gFrameIntervalSeconds; + sOverMemoryBudgetState.States.IncreaseBias; } } else @@ -612,9 +624,16 @@ void LLViewerTexture::updateClass() if (sDesiredDiscardBias > 1.f && over_pct < FREE_PERCENTAGE_TRESHOLD) { static LLCachedControl high_mem_discard_decrement(gSavedSettings, "RenderHighMemMinDiscardDecrement", .1f); - + //F32 decrement = high_mem_discard_decrement - llmin(over_pct, 0.f); F32 decrement = high_mem_discard_decrement - llmin(over_pct - FREE_PERCENTAGE_TRESHOLD, 0.f); - sDesiredDiscardBias -= decrement * gFrameIntervalSeconds; + sDesiredDiscardBias -= decrement * gFrameIntervalSeconds; + sOverMemoryBudgetState.States.DecreaseBias; + } + // Else if we are good on memory, but at the 10% range + else if (sDesiredDiscardBias > 1.f) + { + // Flag the over memory budget state that we are holding the bias. + sOverMemoryBudgetState.States.NormalHoldBias = 1; } } @@ -662,6 +681,12 @@ void LLViewerTexture::updateClass() // So we need to set the memory buget end time to the current time sOverMemoryBudgetEndTime = sCurrentTime; } + // If none of the flags were set + if (sOverMemoryBudgetState.ClearState == 0) + { + // Set the normal flag as true + sOverMemoryBudgetState.States.Normal = 1; + } // [FIRE-35011] LLViewerTexture::sFreezeImageUpdates = false; @@ -1800,7 +1825,7 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() if (mDelayToNormalUseAfterOverBudget <= sCurrentTime) { // If we are still in memory overage, then - if (sDesiredDiscardBias > 1.0f) + if (sOverMemoryBudgetState.States.UseBias) { // Create an additional 1 second delay for this texture mDelayToNormalUseAfterOverBudget = sCurrentTime + 1.0f + ll_rand() * 10.0f; @@ -1836,7 +1861,7 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() } } // Else, we want to check to see if we are in a memory overage state - else if (sDesiredDiscardBias > 1.0f) + else if (sOverMemoryBudgetState.States.UseBias) { // If the texture currently is Normal if (mTextureState == ETextureStates::NORMAL) @@ -1923,9 +1948,20 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() return false; } } + else if ((sOverMemoryBudgetState.States.Normal || sOverMemoryBudgetState.States.NormalHoldBias) && + mTextureState == ETextureStates::SCALED_DOWN) + { + // Create an additional 1 second delay for this texture + mDelayToNormalUseAfterOverBudget = sCurrentTime + 1.0f + (F32)ll_rand(5); + + // Store the current texture state before modifing it + mPreviousTextureState = mTextureState; + // Set the current texture state RECOVERY_DELAY flag + mTextureState |= ETextureStates::RECOVERY_DELAY; + } // Else if we have returned to normal memory usage after the memory acted up and it affected this texture - else if (sDesiredDiscardBias == 1.0f && mTextureState != ETextureStates::NORMAL && mTextureState != ETextureStates::DELETED && - sOverMemoryBudgetEndTime != 0.0f) + else if ((sOverMemoryBudgetState.States.Normal || sOverMemoryBudgetState.States.NormalHoldBias) && mTextureState != ETextureStates::NORMAL && + mTextureState != ETextureStates::DELETED) { // Create an additional 1 second delay for this texture mDelayToNormalUseAfterOverBudget = sCurrentTime + 1.0f; @@ -1934,13 +1970,19 @@ bool LLViewerFetchedTexture::handleMemoryOverageForProcessTextureStats() if (mTextureState & ETextureStates::VRAM_OVERAGE_DELETED) { // We want to hold off on updating the time based upon how much time was spent during over budget, within 1 to 45 seconds - mDelayToNormalUseAfterOverBudget += llclamp((sOverMemoryBudgetEndTime - sOverMemoryBudgetStartTime), 1.0f, 45.0f); + + mDelayToNormalUseAfterOverBudget += 1.0f + (F32)ll_rand(45); } // Else if the texture was just scaled down, delay it a smaller amount else if (mTextureState & ETextureStates::VRAM_SCALED_DOWN) { // We want to hold off on updating the time based upon how much time was spent during over budget, within 1 to 5 seconds - mDelayToNormalUseAfterOverBudget += llclamp((sOverMemoryBudgetEndTime - sOverMemoryBudgetStartTime), 1.0f, 5.0f); + mDelayToNormalUseAfterOverBudget += 1.0f + (F32)ll_rand(5); + } + else if (mTextureState & ETextureStates::SCALED_DOWN) + { + // We want to hold off on updating the time based upon how much time was spent during over budget, within 1 to 5 seconds + mDelayToNormalUseAfterOverBudget += 1.0f + (F32)ll_rand(5); } // Store the current texture state before modifing it @@ -2381,6 +2423,15 @@ bool LLViewerFetchedTexture::updateFetch() } else { + // already at a higher resolution mip, don't discard + // if (current_discard >= 0 && current_discard <= desired_discard) + if (current_discard >= 0 && current_discard <= desired_discard) + // [FIRE-35011] + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current <= desired"); + make_request = false; + } + /* // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // already at a higher resolution mip, don't discard //if (current_discard >= 0 && current_discard <= desired_discard) @@ -2391,10 +2442,10 @@ bool LLViewerFetchedTexture::updateFetch() if (mTextureState & ETextureStates::VRAM_OVERAGE_DELETED) { // If the desired discard level is below the max discard level and the boost on the texture is less then BOOST_SCULPTED - if (mDesiredDiscardLevel < (MAX_DISCARD_LEVEL - 1) && mBoostLevel < LLGLTexture::BOOST_SCULPTED) + if (desired_discard < (MAX_DISCARD_LEVEL - 1) && mBoostLevel < LLGLTexture::BOOST_SCULPTED) { // Set the desired discard level to the max low quality - mDesiredDiscardLevel = MAX_DISCARD_LEVEL - 1; + desired_discard = mDesiredDiscardLevel = MAX_DISCARD_LEVEL - 1; } } // Else if the texture was scaled down before @@ -2402,21 +2453,15 @@ bool LLViewerFetchedTexture::updateFetch() { // If the desired discard level is below the max discard level and the boost on the texture is less then // BOOST_SCULPTED - if (mDesiredDiscardLevel < (MAX_DISCARD_LEVEL - 1) && mBoostLevel < LLGLTexture::BOOST_SCULPTED) + if (desired_discard < (MAX_DISCARD_LEVEL - 1) && mBoostLevel < LLGLTexture::BOOST_SCULPTED) { // Set the desired discard level to the next lower quality (by increaseing the value by 1) - mDesiredDiscardLevel += 1; + desired_discard = mDesiredDiscardLevel += 1; } } - } - // already at a higher resolution mip, don't discard - //if (current_discard >= 0 && current_discard <= desired_discard) - else if (current_discard >= 0 && current_discard <= desired_discard) - // [FIRE-35011] - { - LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current <= desired"); - make_request = false; } + // [FIRE-35011] + */ } } @@ -3441,13 +3486,20 @@ bool LLViewerLODTexture::scaleDown() // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card // Saved Settings bool flag used to enable the newer system (Can be removed but good for testing and comparing) static LLCachedControl use_new_bias_adjustments(gSavedSettings, "FSTextureNewBiasAdjustments", false); - if (sDesiredDiscardBias > 1.0f && use_new_bias_adjustments) + if (sOverMemoryBudgetState.States.UseBias && use_new_bias_adjustments) { // Store the previous texture state mPreviousTextureState = mTextureState; // Flag that the texture was downscaled during low memory mTextureState |= ETextureStates::VRAM_SCALED_DOWN; } + else if (use_new_bias_adjustments) + { + // Store the previous texture state + mPreviousTextureState = mTextureState; + // Flag that the texture was downscaled during low memory + mTextureState |= ETextureStates::SCALED_DOWN; + } // [FIRE-35011] mDownScalePending = true; gTextureList.mDownScaleQueue.push(this); diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index a376c8404fd..5ead1fe880f 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -191,9 +191,10 @@ class LLViewerTexture : public LLGLTexture { NORMAL = 0, // Normal state DELETED = 1, // Normal Delete - VRAM_OVERAGE_DELETED = 2, // Deleted during VRAM overage - VRAM_SCALED_DOWN = 4, // Scaled down during VRAM overage - RECOVERY_DELAY = 8 // Recovery delay after VRAM_OVERAGE_DELETED or VRAM_SCALED_DOWN is true + SCALED_DOWN = 2, // Normal Scaled Down + VRAM_OVERAGE_DELETED = 4, // Deleted during VRAM overage + VRAM_SCALED_DOWN = 8, // Scaled down during VRAM overage + RECOVERY_DELAY = 16 // Recovery delay after VRAM_OVERAGE_DELETED or VRAM_SCALED_DOWN is true }; void setTextureState(ETextureStates newState); @@ -248,6 +249,28 @@ class LLViewerTexture : public LLGLTexture static F32 sPreviousDesiredDiscardBias; // Static value of the previous Desired Discard Bias (Used to determine if the desired discard bias is increasing, decreasing, or staying the same static F32 sOverMemoryBudgetStartTime; // Static value stores the mCurrentTime when the viewer first went over budget of RAM (sDesiredDiscardBias > 1.0) static F32 sOverMemoryBudgetEndTime; // Static value stores the mCurrentTime when the viewer first exists over budget of RAM (sDesiredDiscardBias == 1.0) + typedef union + { + U32 ClearState; + struct + { + U32 Normal : 1; + U32 LowSystemRAM : 1; + U32 LowVRAM : 1; + U32 PreviousLowSystemRam : 1; + U32 PrevouusLowVRAM : 1; + U32 Overage_High : 1; + U32 Overage_Low : 1; + U32 No_Overage : 1; + U32 NormalHoldBias : 1; + U32 UseBias : 1; + U32 IncreaseBias : 1; + U32 DecreaseBias : 1; + } States; + + } OverMemoryBudetStates_u; + + static OverMemoryBudetStates_u sOverMemoryBudgetState; // State of the over memory budget // [FIRE-35011] static S32 sMaxSculptRez ; static U32 sMinLargeImageSize ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 664dc90ae7a..e7d1685f1fb 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -907,7 +907,7 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image) image->mPreviousTextureState = image->mTextureState; // Set the texture state based upon if the system is running out of memory // If we are running out of memory - if (LLViewerTexture::sDesiredDiscardBias > 1.0f) + if (LLViewerTexture::sOverMemoryBudgetState.States.UseBias) { // Set the texture state to VRAM_OVERAGE_DELETED image->mTextureState = LLViewerTexture::ETextureStates::VRAM_OVERAGE_DELETED; @@ -1055,13 +1055,14 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag { llassert(!gCubeSnapshot); - if (imagep->getBoostLevel() < LLViewerFetchedTexture::BOOST_HIGH) // don't bother checking face list for boosted textures + if (imagep->getBoostLevel() < LLViewerFetchedTexture::BOOST_HIGH) // don't bother checking face list for boosted textures { static LLCachedControl texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.04f); static LLCachedControl texture_scale_max(gSavedSettings, "TextureScaleMaxAreaFactor", 25.f); - F32 max_vsize = 0.f; - bool on_screen = false; + F32 max_vsize = 0.f; + bool on_screen = false; + F32 original_max_size = imagep->getMaxVirtualSize(); U32 face_count = 0; @@ -1070,7 +1071,12 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag F32 bias = llclamp(max_discard - 2.f, 1.f, LLViewerTexture::sDesiredDiscardBias); // convert bias into a vsize scaler - bias = (F32) llroundf(powf(4, bias - 1.f)); + bias = (F32)llroundf(powf(4, bias - 1.f)); + + if (LLViewerTexture::sOverMemoryBudgetState.States.UseBias == 0) + { + bias = 1.0f; + } LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) @@ -1089,7 +1095,7 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag { // only call calcPixelArea at most once every 10 frames for a given face // this helps eliminate redundant calls to calcPixelArea for faces that have multiple textures // assigned to them, such as is the case with GLTF materials or Blinn-Phong materials - face->mInFrustum = face->calcPixelArea(cos_angle_to_view_dir, radius); + face->mInFrustum = face->calcPixelArea(cos_angle_to_view_dir, radius); face->mLastTextureUpdate = gFrameCount; } @@ -1104,11 +1110,11 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag // // Maximum usage examples: huge chunk of terrain repeats texture // TODO: make this work with the GLTF texture transforms - S32 te_offset = face->getTEOffset(); // offset is -1 if not inited - LLViewerObject* objp = face->getViewerObject(); - const LLTextureEntry* te = (te_offset < 0 || te_offset >= objp->getNumTEs()) ? nullptr : objp->getTE(te_offset); - F32 min_scale = te ? llmin(fabsf(te->getScaleS()), fabsf(te->getScaleT())) : 1.f; - min_scale = llclamp(min_scale * min_scale, texture_scale_min(), texture_scale_max()); + S32 te_offset = face->getTEOffset(); // offset is -1 if not inited + LLViewerObject* objp = face->getViewerObject(); + const LLTextureEntry* te = (te_offset < 0 || te_offset >= objp->getNumTEs()) ? nullptr : objp->getTE(te_offset); + F32 min_scale = te ? llmin(fabsf(te->getScaleS()), fabsf(te->getScaleT())) : 1.f; + min_scale = llclamp(min_scale * min_scale, texture_scale_min(), texture_scale_max()); vsize /= min_scale; // apply bias to offscreen faces all the time, but only to onscreen faces when bias is large @@ -1121,7 +1127,7 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag if (face->mInFrustum) { static LLCachedControl texture_camera_boost(gSavedSettings, "TextureCameraBoost", 8.f); - vsize *= llmax(face->mImportanceToCamera*texture_camera_boost, 1.f); + vsize *= llmax(face->mImportanceToCamera * texture_camera_boost, 1.f); } max_vsize = llmax(max_vsize, vsize); @@ -1140,24 +1146,41 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag // this is an alternative to decaying mMaxVirtualSize over time // that keeps textures from continously downrezzing and uprezzing in the background - // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card - //if (LLViewerTexture::sDesiredDiscardBias > 1.5f || - // (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) - //{ - // imagep->mMaxVirtualSize = 0.f; - //} - // Only keep downsizeing if the bias is increasing - if ((LLViewerTexture::sDesiredDiscardBias > 1.5f || (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) && - LLViewerTexture::sDesiredDiscardBias > LLViewerTexture::sPreviousDesiredDiscardBias) + if (LLViewerTexture::sDesiredDiscardBias > 1.5f || (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f) && LLViewerTexture::sOverMemoryBudgetState.States.UseBias) { imagep->mMaxVirtualSize = 0.f; - // Flag the image that it was downsized - imagep->setTextureState(LLViewerTexture::ETextureStates::VRAM_SCALED_DOWN); } - // [FIRE-35011] } imagep->addTextureStats(max_vsize); + // [FIRE-35011] Weird patterned extreme CPU usage when using more than 6gb vram on 10g card + if (imagep->getMaxVirtualSize() < original_max_size) + { + //imagep->addTextureStats(original_max_size); + if (LLViewerTexture::sOverMemoryBudgetState.States.UseBias) + { + // Flag the image that it was downsized + // imagep->setTextureState(LLViewerTexture::ETextureStates::VRAM_SCALED_DOWN); + } + else + { + //imagep->setTextureState(LLViewerTexture::ETextureStates::SCALED_DOWN); + } + } + else + { + // If we are in a low state, just reset the max virtual size back to the original value + if (LLViewerTexture::sOverMemoryBudgetState.States.UseBias) + { + //imagep->mMaxVirtualSize = original_max_size; + } + else if (imagep->mTextureState & LLViewerTexture::ETextureStates::SCALED_DOWN && + LLViewerTexture::sOverMemoryBudgetState.States.NormalHoldBias) + { + //imagep->mMaxVirtualSize = original_max_size; + } + } + // [FIRE-35011] } #if 0 @@ -1195,7 +1218,14 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag return; } } - else + // + else if (imagep->mTextureState & LLViewerTexture::ETextureStates::VRAM_SCALED_DOWN && imagep->getMaxVirtualSize() == 0.0f && + imagep->getType() == LLViewerTexture::LOD_TEXTURE && imagep->getBoostLevel() == LLViewerTexture::BOOST_NONE) + { + // We are going to delete the image after scaling it down, so do it now. + //deleteImage(imagep); + } + // { // still referenced outside of image list, reset timer imagep->getLastReferencedTimer()->reset(); @@ -1391,7 +1421,8 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) // If the desired discard bias is greater then 1 and is increasing or stable, if descreasing, use the normal about of texture // updates if (LLViewerTexture::sDesiredDiscardBias > 1.f && - LLViewerTexture::sDesiredDiscardBias >= LLViewerTexture::sPreviousDesiredDiscardBias) + LLViewerTexture::sDesiredDiscardBias >= LLViewerTexture::sPreviousDesiredDiscardBias && + LLViewerTexture::sOverMemoryBudgetState.States.UseBias && !LLViewerTexture::sOverMemoryBudgetState.States.NormalHoldBias) { // we are over memory target, update more agresively update_count = (S32)(update_count * LLViewerTexture::sDesiredDiscardBias);