diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/newview/lldebugview.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/lltextureview.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llviewermessage.cpp | 5 | ||||
| -rw-r--r-- | indra/newview/llviewertexture.cpp | 115 | ||||
| -rw-r--r-- | indra/newview/llviewertexture.h | 3 | ||||
| -rw-r--r-- | indra/newview/llvocache.cpp | 2 |
6 files changed, 91 insertions, 38 deletions
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/lltextureview.cpp b/indra/newview/lltextureview.cpp index 4534db958f..470a133fa7 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/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index cf1ce421b3..d63e0dc836 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3392,9 +3392,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/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 0dfc40b85f..c351d4da95 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -114,6 +114,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; @@ -490,6 +491,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() { @@ -523,23 +531,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; // Predicted-VRAM pressure controller. Eviction is fast, refetch is slow, // so feedback on instantaneous `used` sawtooths; feeding `used + @@ -550,7 +559,7 @@ void LLViewerTexture::updateClass() static LLCachedControl<F32> prediction_gain(gSavedSettings, "TextureMemoryPressurePredictionGain", 10.f); static LLCachedControl<F32> smoothing_rate(gSavedSettings, "TextureMemoryPressureSmoothingRate", 4.f); - F32 backoff_target = target * llclamp((F32)backoff_start, 0.05f, 1.f); + 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; @@ -560,7 +569,7 @@ void LLViewerTexture::updateClass() // frame later, from `used` alone. bool need_predict = sMemoryPressureMultiplier > 1.001f || sLastDitchMinDiscard > 0.f - || used > backoff_target * 0.5f; + || vram_used > backoff_target * 0.5f; S64 pending_bytes_increase = 0; S64 pending_bytes_decrease = 0; @@ -597,7 +606,7 @@ void LLViewerTexture::updateClass() // 1024 * 512 = 524288: matches the unit reduction at line 513. constexpr F32 BYTES_TO_USED_UNITS = 1.f / 524288.f; - F32 predicted_used = used + 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); @@ -607,7 +616,7 @@ void LLViewerTexture::updateClass() // 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 = used >= budget * llclamp((F32)high_water, 0.5f, 1.f); + 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) @@ -649,14 +658,14 @@ void LLViewerTexture::updateClass() if (s_pressure_log_timer.getElapsedTimeF32() > 1.f) { s_pressure_log_timer.reset(); - F32 over = used / llmax(backoff_target, 1.f); + F32 over = vram_used / llmax(backoff_target, 1.f); LL_INFOS("TextureStream") << "pressure" << " mult=" << sMemoryPressureMultiplier << " target_mult=" << target_mult << " progress=" << progress - << " used=" << used + << " used=" << vram_used << " predicted=" << predicted_used - << " target=" << target + << " target=" << vram_target << " over=" << over << " pred_over=" << predicted_over << " in+=" << (S32)(pending_bytes_increase / 1024 / 1024) @@ -669,10 +678,66 @@ void LLViewerTexture::updateClass() } 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.05; + 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.02; + 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) @@ -720,12 +785,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); @@ -835,13 +899,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() { @@ -854,18 +911,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 991bb638a1..8c5c48bafd 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); @@ -268,6 +270,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/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 |
