diff options
| author | Jonathan "Geenz" Goodman <geenz@geenzo.com> | 2026-06-30 17:15:12 -0400 |
|---|---|---|
| committer | Jonathan "Geenz" Goodman <geenz@geenzo.com> | 2026-06-30 17:15:12 -0400 |
| commit | cd62a49879374c84b66e1ee963e161c3e6109977 (patch) | |
| tree | 8b023e916f13cd76daa6479ad62e4aac6734a9ff | |
| parent | c299c8038e73e541cafe3c8df135752cb48b903c (diff) | |
| parent | c99cd251383ed17b4dd1210ee0701d2a3b4dd0e5 (diff) | |
Merge branch 'release/26.3' into geenz/texture-streaming-tweaks
22 files changed, 173 insertions, 93 deletions
diff --git a/autobuild.xml b/autobuild.xml index 3a2cfa0b46..1456dca104 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3390,7 +3390,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>license_file</key> <string>docs/LICENSE-source.txt</string> <key>copyright</key> - <string>Copyright (c) 2020, Linden Research, Inc.</string> + <string>Copyright (c) 2026, Linden Research, Inc.</string> <key>version_file</key> <string>newview/viewer_version.txt</string> <key>name</key> diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index 6f7510fef2..4957cf3c02 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -653,39 +653,14 @@ void LLSettingsSky::blend(LLSettingsBase::ptr_t &end, F64 blendf) } } + mHasLegacyHaze |= lerp_legacy_float(mHazeHorizon, mLegacyHazeHorizon, other->mHazeHorizon, other->mLegacyHazeHorizon, 0.19f, (F32)blendf); mHasLegacyHaze |= lerp_legacy_float(mHazeDensity, mLegacyHazeDensity, other->mHazeDensity, other->mLegacyHazeDensity, 0.7f, (F32)blendf); mHasLegacyHaze |= lerp_legacy_float(mDistanceMultiplier, mLegacyDistanceMultiplier, other->mDistanceMultiplier, other->mLegacyDistanceMultiplier, 0.8f, (F32)blendf); + mHasLegacyHaze |= lerp_legacy_float(mDensityMultiplier, mLegacyDensityMultiplier, other->mDensityMultiplier, other->mLegacyDensityMultiplier, 0.0001f, (F32)blendf); mHasLegacyHaze |= lerp_legacy_color(mAmbientColor, mLegacyAmbientColor, other->mAmbientColor, other->mLegacyAmbientColor, LLColor3(0.25f, 0.25f, 0.25f), (F32)blendf); + mHasLegacyHaze |= lerp_legacy_color(mBlueHorizon, mLegacyBlueHorizon, other->mBlueHorizon, other->mLegacyBlueHorizon, LLColor3(0.4954f, 0.4954f, 0.6399f), (F32)blendf); mHasLegacyHaze |= lerp_legacy_color(mBlueDensity, mLegacyBlueDensity, other->mBlueDensity, other->mLegacyBlueDensity, LLColor3(0.2447f, 0.4487f, 0.7599f), (F32)blendf); - if (mLegacyHazeHorizon == mLegacyDensityMultiplier == mLegacyBlueHorizon) - { - // mHazeHorizon coupled with mDensityMultiplier, mDistanceMultiplier and - // drastic blue horizon changes can result in a very bright sky during - // the transition. Purpose of this code is to calculate a 'fake level' - // and use it to even out brightness change. - // - // Example values that make lerp-based individual transition painfully bright: - // Start: 3 Haze Horiz, 0.1 Density, 6.54 Distance, white ambient, white blue horizon - // End: 0.03 Haze Horiz, 0.775 Density, 90.95 Distance, black ambient, black blue horizon - F32 strt_level = mHazeHorizon * mDensityMultiplier * mBlueHorizon.length(); - F32 end_level = other->mHazeHorizon * other->mDensityMultiplier * other->mBlueHorizon.length(); - mHasLegacyHaze |= lerp_legacy_float(mHazeHorizon, mLegacyHazeHorizon, other->mHazeHorizon, other->mLegacyHazeHorizon, 0.19f, (F32)blendf); - mHasLegacyHaze |= lerp_legacy_float(mDensityMultiplier, mLegacyDensityMultiplier, other->mDensityMultiplier, other->mLegacyDensityMultiplier, 0.0001f, (F32)blendf); - mHasLegacyHaze |= lerp_legacy_color(mBlueHorizon, mLegacyBlueHorizon, other->mBlueHorizon, other->mLegacyBlueHorizon, LLColor3(0.4954f, 0.4954f, 0.6399f), (F32)blendf); - - // lerp the fake level instead of density multiplier to avoid brightening the sky too much. - // This makes density multiplier non linear. - F32 new_level = lerp(strt_level, end_level, (F32)blendf); - mDensityMultiplier = new_level / (mHazeHorizon * mBlueHorizon.length()); - } - else - { - // default values are used, so we should lerp settings independently - mHasLegacyHaze |= lerp_legacy_float(mHazeHorizon, mLegacyHazeHorizon, other->mHazeHorizon, other->mLegacyHazeHorizon, 0.19f, (F32)blendf); - mHasLegacyHaze |= lerp_legacy_float(mDensityMultiplier, mLegacyDensityMultiplier, other->mDensityMultiplier, other->mLegacyDensityMultiplier, 0.0001f, (F32)blendf); - mHasLegacyHaze |= lerp_legacy_color(mBlueHorizon, mLegacyBlueHorizon, other->mBlueHorizon, other->mLegacyBlueHorizon, LLColor3(0.4954f, 0.4954f, 0.6399f), (F32)blendf); - } parammapping_t defaults = other->getParameterMap(); stringset_t skip = getSkipInterpolateKeys(); stringset_t slerps = getSlerpKeys(); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index c185fc6c4a..6230cc3026 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -4704,6 +4704,16 @@ void LLWindowWin32::requestHighPerformanceGPU() const << ", Vendor: 0x" << std::hex << desc.VendorId << std::dec << ", Flags: " << desc.Flags << LL_ENDL; } + // Skip Microsoft Basic Render Driver, it's a placeholder for missing drivers + else if (description.find("Microsoft Basic Render Driver") != std::string::npos) + { + // User is likely missing drivers, so log a warning. + // Don't consider this adapter as a valid selection. + LL_WARNS("Window") << "Adapter " << adapterIndex << ": " << description + << ", Dedicated VRAM: " << (desc.DedicatedVideoMemory / 1024 / 1024) << " MB" + << ", Vendor: 0x" << std::hex << desc.VendorId << std::dec + << ", Flags: " << desc.Flags << LL_ENDL; + } else { LL_INFOS("Window") << "Adapter " << adapterIndex << ": " << description diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 88367540e9..b85bf003fc 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2184,7 +2184,7 @@ if (DARWIN) set(MACOSX_BUNDLE_BUNDLE_NAME "SecondLife") set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}") set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}") - set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2020") + set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2026") set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "SecondLife.nib") set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "LLApplication") diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6e25d2e835..519041bbeb 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5903,7 +5903,7 @@ <key>Type</key> <string>S32</string> <key>Value</key> - <integer>110</integer> + <integer>127</integer> </map> <key>NotificationChannelRightMargin</key> <map> diff --git a/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl b/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl index 8e12d09443..df58f68556 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/CASF.glsl @@ -1171,12 +1171,12 @@ vec3 linear_to_srgb(vec3 cl); // - Float zero is mapped to center of integers (so clear to integer zero is a nice default for atomic max usage). // Burns 3 ops for conversion {shift,or,xor}. //============================================================================================================================== - AU1 AFisToU1(AU1 x){return x^(( AShrSU1(x,AU1_(31)))|AU1_(0x80000000));} - AU1 AFisFromU1(AU1 x){return x^((~AShrSU1(x,AU1_(31)))|AU1_(0x80000000));} + AU1 AFisToU1(AU1 x){return x^(( AShrSU1(x,AU1_(31)))|AU1_(0x80000000u));} + AU1 AFisFromU1(AU1 x){return x^((~AShrSU1(x,AU1_(31)))|AU1_(0x80000000u));} //------------------------------------------------------------------------------------------------------------------------------ // Just adjust high 16-bit value (useful when upper part of 32-bit word is a 16-bit float value). - AU1 AFisToHiU1(AU1 x){return x^(( AShrSU1(x,AU1_(15)))|AU1_(0x80000000));} - AU1 AFisFromHiU1(AU1 x){return x^((~AShrSU1(x,AU1_(15)))|AU1_(0x80000000));} + AU1 AFisToHiU1(AU1 x){return x^(( AShrSU1(x,AU1_(15)))|AU1_(0x80000000u));} + AU1 AFisFromHiU1(AU1 x){return x^((~AShrSU1(x,AU1_(15)))|AU1_(0x80000000u));} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //_____________________________________________________________/\_______________________________________________________________ diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp index 3941b82e75..246a9d28e4 100644 --- a/indra/newview/lldebugview.cpp +++ b/indra/newview/lldebugview.cpp @@ -101,7 +101,7 @@ void LLDebugView::init() addChild(gSceneMonitorView); gSceneMonitorView->setRect(rect); - r.set(150, rect.getHeight() - 60, 820, 110); + r.set(150, rect.getHeight() - 60, 835, 110); LLTextureView::Params tvp; tvp.name("gTextureView"); tvp.rect(r); diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 0358233637..02f013ad3c 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -134,6 +134,7 @@ void LLLoginInstance::reconnect() { // Sort of like connect, only using the pre-existing // request params. + mAttemptComplete = false; std::vector<std::string> uris; LLGridManager::getInstance()->getLoginURIs(uris); mLoginModule->connect(uris.front(), mRequestData); diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index b48417bd71..623db82939 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -402,8 +402,6 @@ void LLSidepanelInventory::onOpen(const LLSD& key) gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", (U32)time_corrected()); } #endif - - gAgent.showLatestFeatureNotification("inventory"); } void LLSidepanelInventory::performActionOnSelection(const std::string &action) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 55f23eb021..60c6a5c194 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1353,6 +1353,10 @@ bool idle_startup() { set_startup_status(0.30f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD); do_startup_frame(); + + // close login UI before world UI is initialized, if it is still visible + LLPanelLogin::closePanel(); + // We should have an agent id by this point. llassert(!(gAgentID == LLUUID::null)); diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 1cc26896b1..1c341a06cd 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -250,7 +250,7 @@ void LLTextureBar::draw() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); // Draw the progress bar. - S32 bar_width = 100; + S32 bar_width = 110; S32 bar_left = 260; left = bar_left; right = left + bar_width; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 3de61dffc7..e905a879cb 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -301,7 +301,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) mIsScriptDialog = (notif_name == "ScriptDialog" || notif_name == "ScriptDialogGroup"); static LLCachedControl<S32> btn_width(gSavedSettings, "ToastButtonWidth", 90); - static LLCachedControl<S32> script_button_width(gSavedSettings, "ScriptToastButtonWidth", 110); + static LLCachedControl<S32> script_button_width(gSavedSettings, "ScriptToastButtonWidth", 127); mButtonWidth = mIsScriptDialog ? script_button_width : btn_width; bool is_content_trusted = (notif_name != "LoadWebPage"); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 9dfa9a0efd..4773a8a555 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -217,9 +217,10 @@ void display_update_camera() { final_far *= 0.5f; } - else if (LLViewerTexture::sDesiredDiscardBias > 2.f) + // When system memory is critically low or recovering, shrink draw distance. + else if (LLViewerTexture::getSystemMemoryBudgetFactor() > 1.f) { - final_far = llmax(32.f, final_far / (LLViewerTexture::sDesiredDiscardBias - 1.f)); + final_far = llmax(32.f, final_far / LLViewerTexture::getSystemMemoryBudgetFactor()); } LLViewerCamera::getInstance()->setFar(final_far); LLVOAvatar::sRenderDistance = llclamp(final_far, 16.f, 256.f); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 812ba76551..612af029b9 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3372,9 +3372,10 @@ void send_agent_update(bool force_send, bool send_reliable) static F32 last_draw_disatance_step = 1024; F32 memory_limited_draw_distance = gAgentCamera.mDrawDistance; - if (LLViewerTexture::isSystemMemoryCritical()) + if (LLViewerTexture::getSystemMemoryBudgetFactor() > 1.f) { - // If we are low on memory, reduce requested draw distance + // We are critcally low on memory or recovering, + // limit requested draw distance memory_limited_draw_distance = llmax(gAgentCamera.mDrawDistance / LLViewerTexture::getSystemMemoryBudgetFactor(), gAgentCamera.mDrawDistance / 2.f); } diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index b1673d2232..3b79666f7c 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -1143,6 +1143,8 @@ void LLOcclusionCullingGroup::checkOcclusion() GLuint query_result; // Will be # samples drawn, or a boolean depending on mHasOcclusionQuery2 (both are type GLuint) { LL_PROFILE_ZONE_NAMED_CATEGORY_OCTREE("co - query result"); + // Ping watchdog before a blocking GL_QUERY_RESULT GPU call + LLAppViewer::instance()->pingMainloopTimeout("Display:CullQueryResult"); glGetQueryObjectuiv(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT, &query_result); } #if LL_TRACK_PENDING_OCCLUSION_QUERIES diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index c2cdd54910..545264b980 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -128,6 +128,7 @@ constexpr F32 MEMORY_CHECK_WAIT_TIME = 1.0f; constexpr F32 MIN_VRAM_BUDGET = 768.f; F32 LLViewerTexture::sFreeVRAMMegabytes = MIN_VRAM_BUDGET; F32 LLViewerTexture::sWindowPixelArea = 1.f; +F32 LLViewerTexture::sSysMemoryFactor = 1.f; LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; @@ -504,6 +505,13 @@ void LLViewerTexture::initClass() LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture(); } +S32Megabytes get_render_free_main_memory_treshold() +{ + static LLCachedControl<U32> min_free_main_memory(gSavedSettings, "RenderMinFreeMainMemoryThreshold", 512); + const U32Megabytes MIN_FREE_MAIN_MEMORY(min_free_main_memory); + return MIN_FREE_MAIN_MEMORY; +} + //static void LLViewerTexture::updateClass() { @@ -537,23 +545,24 @@ void LLViewerTexture::updateClass() // get an estimate of how much video memory we're using // NOTE: our metrics miss about half the vram we use, so this biases high but turns out to typically be within 5% of the real number - F32 used = (F32)ll_round(texture_bytes_alloc + vertex_bytes_alloc); + F32 vram_used = (F32)ll_round(texture_bytes_alloc + vertex_bytes_alloc); // For debugging purposes, it's useful to be able to set the VRAM budget manually. // But when manual control is not enabled, use the VRAM divisor. // While we're at it, assume we have 1024 to play with at minimum when the divisor is in use. Works more elegantly with the logic below this. // -Geenz 2025-03-21 - F32 budget = max_vram_budget == 0 ? llmax(1024, (F32)gGLManager.mVRAM / tex_vram_divisor) : (F32)max_vram_budget; + F32 vram_budget = max_vram_budget == 0 ? llmax(1024, (F32)gGLManager.mVRAM / tex_vram_divisor) : (F32)max_vram_budget; // 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 = target - used; + F32 vram_target = llmax(llmin(vram_budget - 512.f, vram_budget * 0.8f), MIN_VRAM_BUDGET); + sFreeVRAMMegabytes = vram_target - vram_used; + const S32Megabytes free_sys_mem = getFreeSystemMemory(); - F32 over_pct = (used - target) / target; + F32 over_pct = (vram_used - vram_target) / vram_target; // Watermark-driven discard-bias controller. One clean signal: the bias // climbs while used VRAM is above the high watermark, relaxes below the @@ -573,18 +582,41 @@ void LLViewerTexture::updateClass() static LLCachedControl<F32> bias_ramp(gSavedSettings, "TextureDiscardBiasRampRate", 2.0f); static LLCachedControl<F32> bias_decay(gSavedSettings, "TextureDiscardBiasDecayRate", 1.0f); - F32 high_frac = llclamp((F32)wm_high, 0.1f, 1.f); - F32 low_frac = llclamp((F32)wm_low, 0.05f, high_frac); - F32 high = budget * high_frac; - F32 low = budget * low_frac; - F32 cap = llmax((F32)bias_max, 0.f); - F32 dt = (F32)gFrameIntervalSeconds; + F32 backoff_target = vram_target * llclamp((F32)backoff_start, 0.05f, 1.f); + F32 cap = llmax((F32)max_mult, 1.0001f); + F32 dt = (F32)gFrameIntervalSeconds; + + // Skip the full-list iteration when there is no pressure to react to: + // mult already at baseline, last-ditch at zero, and used well clear of + // the backoff target. Worst case the controller picks up the spike one + // frame later, from `used` alone. + bool need_predict = sMemoryPressureMultiplier > 1.001f + || sLastDitchMinDiscard > 0.f + || vram_used > backoff_target * 0.5f; - if (used > high) + S64 pending_bytes_increase = 0; + S64 pending_bytes_decrease = 0; + if (need_predict) { sDiscardBias += llmax((F32)bias_ramp, 0.f) * dt; } - else if (used < low) + + // 1024 * 512 = 524288: matches the unit reduction at line 513. + constexpr F32 BYTES_TO_USED_UNITS = 1.f / 524288.f; + F32 predicted_used = vram_used + + (F32)pending_bytes_increase * BYTES_TO_USED_UNITS + - (F32)pending_bytes_decrease * BYTES_TO_USED_UNITS; + F32 predicted_over = predicted_used / llmax(backoff_target, 1.f); + + // High water mark: when used crosses budget * high_water, skip the + // smoothed convergence and slam the controller into hard-cap state. + // Recovers the historical 90% behavior - immediate aggressive + // response instead of waiting for the lerp to chase the target. + static LLCachedControl<F32> high_water(gSavedSettings, "TextureMemoryHighWaterMark", 0.8f); + bool above_high_water = vram_used >= vram_budget * llclamp((F32)high_water, 0.5f, 1.f); + + F32 target_mult = llclamp(powf(llmax(predicted_over, 1.f), llmax((F32)prediction_gain, 0.0001f)), 1.f, cap); + if (above_high_water) { sDiscardBias -= llmax((F32)bias_decay, 0.f) * dt; } @@ -596,25 +628,86 @@ void LLViewerTexture::updateClass() if (s_pressure_log_timer.getElapsedTimeF32() > 1.f) { s_pressure_log_timer.reset(); + F32 over = vram_used / llmax(backoff_target, 1.f); LL_INFOS("TextureStream") << "pressure" - << " discard_bias=" << sDiscardBias - << " progress=" << getMemoryPressureProgress() - << " used=" << used - << " budget=" << budget - << " high=" << high - << " low=" << low - << " over_pct=" << over_pct - << " legacy_bias=" << sDesiredDiscardBias + << " mult=" << sMemoryPressureMultiplier + << " target_mult=" << target_mult + << " progress=" << progress + << " used=" << vram_used + << " predicted=" << predicted_used + << " target=" << vram_target + << " over=" << over + << " pred_over=" << predicted_over + << " in+=" << (S32)(pending_bytes_increase / 1024 / 1024) + << "MB in-=" << (S32)(pending_bytes_decrease / 1024 / 1024) + << "MB bias=" << sDesiredDiscardBias + << " ldmin=" << sLastDitchMinDiscard << " dsq=" << (S32)gTextureList.mDownScaleQueue.size() << LL_ENDL; } } bool is_sys_low = isSystemMemoryLow(); + bool is_sys_critically_low = isSystemMemoryCritical(); bool is_low = is_sys_low || over_pct > 0.f; static bool was_low = false; + static bool sys_was_low = false; + + // System memory factor + // sSysMemoryFactor affects draw distance + // + // We only decrement when more than 406MB is free, but increment + // when below 256MB free. This should provide a stable value + // in the 256-406MB range to avoid draw range fluctuations. + // + // Draw range reduction is a last resort, texture bias is supposed + // to free at least some memory before we get here. + // Note: textures were mostly moved to vram, we might want to + // detach texture bias from system memory. + if (is_sys_critically_low) + { + const S32Megabytes MIN_FREE_MAIN_MEMORY(get_render_free_main_memory_treshold() / 2); + // debt is a negative value since MIN_FREE_MAIN_MEMORY > free memory. + S32 sys_budget_debt = free_sys_mem - MIN_FREE_MAIN_MEMORY; + + // Leave some padding, otherwise we will crash out of memory before hitting factor 2. + const S32Megabytes PAD_BUFFER(32); + S32Megabytes budget_target = MIN_FREE_MAIN_MEMORY - PAD_BUFFER; + if (!sys_was_low) + { + // Result should range from 1 at 0 debt to 2 at -224 debt, 2.14 at -256MB + F32 new_factor = 1.f - (F32)sys_budget_debt / (F32)budget_target; + sSysMemoryFactor = llmax(sSysMemoryFactor, new_factor); + } + else + { + // Slowly ramp up factor to free memory (increasing factor decreases draw range) + constexpr F32 MAX_INCREMENT = 0.05f; + F32 increment = MAX_INCREMENT * llmax(-(F32)sys_budget_debt / (F32)budget_target, 0.f); + sSysMemoryFactor += increment * gFrameIntervalSeconds; + } + sSysMemoryFactor = llclamp(sSysMemoryFactor, 1.f, 2.f); + } + else + { + const S32Megabytes MIN_FREE_MAIN_MEMORY(get_render_free_main_memory_treshold() / 2); + // Only start ramping down when we have breathing room. + // This should be under the value of isSystemMemoryLow to not throw texture + // bias into 1.5+ territory each time we fluctuate around isSystemMemoryLow's + // treshold. + const S32Megabytes MEM_THRESHOLD = MIN_FREE_MAIN_MEMORY + S32Megabytes(150); + if (free_sys_mem > MEM_THRESHOLD && sSysMemoryFactor > 1.f) + { + // Ramp down factor over time. + constexpr F32 DECREMENT = 0.02f; + sSysMemoryFactor -= DECREMENT * gFrameIntervalSeconds; + sSysMemoryFactor = llclamp(sSysMemoryFactor, 1.f, 2.f); + } + } + sys_was_low = is_sys_critically_low; + // VRAM memory bias if (is_low && !was_low) { if (is_sys_low) @@ -662,12 +755,11 @@ void LLViewerTexture::updateClass() // lower discard bias over time when at least 10% of budget is free constexpr F32 FREE_PERCENTAGE_TRESHOLD = -0.1f; - constexpr U32 FREE_SYS_MEM_TRESHOLD = 100; - static LLCachedControl<U32> min_free_main_memory(gSavedSettings, "RenderMinFreeMainMemoryThreshold", 512); - const S32Megabytes MIN_FREE_MAIN_MEMORY(min_free_main_memory() + FREE_SYS_MEM_TRESHOLD); + constexpr U32 FREE_SYS_MEM_THRESHOLD = 100; // 100MB more than isSystemMemoryLow to avoid fluctuations. + const S32Megabytes MIN_FREE_MAIN_MEMORY(get_render_free_main_memory_treshold() + S32Megabytes(FREE_SYS_MEM_THRESHOLD)); if (sDesiredDiscardBias > 1.f && over_pct < FREE_PERCENTAGE_TRESHOLD - && getFreeSystemMemory() > MIN_FREE_MAIN_MEMORY + && free_sys_mem > MIN_FREE_MAIN_MEMORY && !eviction_in_flight) { static LLCachedControl<F32> high_mem_discard_decrement(gSavedSettings, "RenderHighMemMinDiscardDecrement", .1f); @@ -797,13 +889,6 @@ U32Megabytes LLViewerTexture::getFreeSystemMemory() return physical_res; } -S32Megabytes get_render_free_main_memory_treshold() -{ - static LLCachedControl<U32> min_free_main_memory(gSavedSettings, "RenderMinFreeMainMemoryThreshold", 512); - const U32Megabytes MIN_FREE_MAIN_MEMORY(min_free_main_memory); - return MIN_FREE_MAIN_MEMORY; -} - //static bool LLViewerTexture::isSystemMemoryLow() { @@ -816,18 +901,10 @@ bool LLViewerTexture::isSystemMemoryCritical() return getFreeSystemMemory() < get_render_free_main_memory_treshold() / 2; } +// static F32 LLViewerTexture::getSystemMemoryBudgetFactor() { - const S32Megabytes MIN_FREE_MAIN_MEMORY(get_render_free_main_memory_treshold() / 2); - S32 free_budget = (S32Megabytes)getFreeSystemMemory() - MIN_FREE_MAIN_MEMORY; - if (free_budget < 0) - { - // Leave some padding, otherwise we will crash out of memory before hitting factor 2. - const S32Megabytes PAD_BUFFER(32); - // Result should range from 1 at 0 free budget to 2 at -224 free budget, 2.14 at -256MB - return 1.f - free_budget / (MIN_FREE_MAIN_MEMORY - PAD_BUFFER); - } - return 1.f; + return sSysMemoryFactor; } //end of static functions diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 390a6caa58..51ef9f8206 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -116,6 +116,8 @@ public: static void updateClass(); static bool isSystemMemoryLow(); static bool isSystemMemoryCritical(); + + // Ranges from 1 (no RAM deficit) to 2 (RAM deficit) static F32 getSystemMemoryBudgetFactor(); LLViewerTexture(bool usemipmaps = true); @@ -272,6 +274,7 @@ public: // estimated free memory for textures, by bias calculation static F32 sFreeVRAMMegabytes; + static F32 sSysMemoryFactor; // Viewport pixel area, refreshed once per frame. Hoisted to keep the // per-texture hot path out of gViewerWindow. static F32 sWindowPixelArea; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 2f39a76156..460570d0e5 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -8575,6 +8575,10 @@ bool LLVOAvatar::processFullyLoadedChange(bool loading) if (changed && isSelf()) { + // Agent's own avatar doesn't track bakes the same way as other avatars. + // So just update here, on cloud removal. + markBodyPartsComplexityDirty(); + // to know about outfit switching LLAvatarRenderNotifier::getInstance()->updateNotificationState(); } @@ -10170,6 +10174,10 @@ void LLVOAvatar::onInitialBakedTextureLoaded( bool success, LLViewerFetchedTextu } if (final || !success ) { + if (selfp) + { + selfp->markBodyPartsComplexityDirty(); + } delete avatar_idp; } } @@ -11458,7 +11466,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() // Store results mVisualComplexity = total_cost; - // Call the existing reporting function with the aggregated lists + // Call the reporting function with the aggregated lists processComplexityCostChange(hud_complexity_list, object_complexity_list); // Stop processing until something changes diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 5d456b1a19..7618739b3c 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -488,7 +488,7 @@ void LLVOCacheEntry::updateDebugSettings() static const F32 MIN_RADIUS = 1.0f; F32 draw_radius = gAgentCamera.mDrawDistance; - if (LLViewerTexture::isSystemMemoryCritical()) + if (LLViewerTexture::getSystemMemoryBudgetFactor() > 1.f) { // Factor is intended to go from 1.0 to 2.0 // For safety cap reduction at 50%, we don't want to go below half of draw distance diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index dc2ba5f171..c9ca758555 100755 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -157,7 +157,7 @@ BEGIN VALUE "FileDescription", "Second Life" VALUE "FileVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" VALUE "InternalName", "Second Life" - VALUE "LegalCopyright", "Copyright (c) 2020, Linden Research, Inc." + VALUE "LegalCopyright", "Copyright (c) 2026, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" VALUE "ProductVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" diff --git a/indra/newview/skins/default/xui/en/floater_script.xml b/indra/newview/skins/default/xui/en/floater_script.xml index ae6e68de17..20feec615c 100644 --- a/indra/newview/skins/default/xui/en/floater_script.xml +++ b/indra/newview/skins/default/xui/en/floater_script.xml @@ -8,8 +8,8 @@ can_dock="true" can_minimize="true" visible="false" - width="350" + width="402" can_resize="false" - min_width="350" + min_width="402" min_height="200"> </floater> diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index 4d924a6c24..fcfd2357b5 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -196,8 +196,8 @@ text_color="LtGray" tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!" top="13" - valign="bottom" - width="290"> + valign="bottom" + width="310"> Places you save to your favorites bar will appear here. </label> <!-- More button actually is a text box. --> |
