summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerdisplay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewerdisplay.cpp')
-rw-r--r--indra/newview/llviewerdisplay.cpp36
1 files changed, 32 insertions, 4 deletions
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 1276ec5263..affd57a8d1 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -140,6 +140,27 @@ void render_disconnected_background();
void getProfileStatsContext(boost::json::object& stats);
std::string getProfileStatsFilename();
+// Adaptive texture-pipeline budget: spend the frame-time headroom between the
+// frame we're rendering and TextureLoadTargetFPS, clamped [2ms, max]. Headroom
+// is measured (smoothed frame interval minus the pipeline's own last spend),
+// so fast machines get big budgets and machines already at target hold the
+// floor. Only consumed while queues have work - drain loops exit when empty.
+static F32 sTexturePipelineSpent = 0.f;
+static F32 texture_pipeline_budget()
+{
+ static LLCachedControl<F32> target_fps(gSavedSettings, "TextureLoadTargetFPS", 60.f);
+ static LLCachedControl<F32> max_ms(gSavedSettings, "TextureLoadBudgetMaxMS", 10.f);
+ static F32 smoothed_other = 0.008f;
+ F32 other = llmax(gFrameIntervalSeconds.value() - sTexturePipelineSpent, 0.f);
+ // A single multi-second hitch must not crater the budget for the following
+ // frames, so cap the sample before it enters the EMA.
+ other = llmin(other, 0.1f);
+ smoothed_other = smoothed_other * 0.9f + other * 0.1f;
+ F32 target_interval = 1.f / llclamp((F32)target_fps, 15.f, 240.f);
+ F32 headroom = target_interval - smoothed_other;
+ return llclamp(headroom, 0.002f, llclamp((F32)max_ms, 2.f, 50.f) * 0.001f);
+}
+
void display_startup()
{
if ( !gViewerWindow
@@ -217,6 +238,11 @@ void display_update_camera()
{
final_far *= 0.5f;
}
+ // When system memory is critically low or recovering, shrink draw distance.
+ else if (const F32 mem_factor = LLMemory::getSystemMemoryBudgetFactor(); mem_factor > 1.f)
+ {
+ final_far = llmax(32.f, final_far / mem_factor);
+ }
LLViewerCamera::getInstance()->setFar(final_far);
LLVOAvatar::sRenderDistance = llclamp(final_far, 16.f, 256.f);
gViewerWindow->setup3DRender();
@@ -519,9 +545,10 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("List");
- F32 max_image_decode_time = 0.050f * gFrameIntervalSeconds.value(); // 50 ms/second decode time
- max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f); // min 2ms/frame, max 5ms/frame)
+ F32 max_image_decode_time = texture_pipeline_budget();
+ LLTimer tex_timer;
gTextureList.updateImages(max_image_decode_time);
+ sTexturePipelineSpent = tex_timer.getElapsedTimeF32();
}
{
@@ -897,9 +924,10 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("List");
- F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds.value(); // 50 ms/second decode time
- max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
+ F32 max_image_decode_time = texture_pipeline_budget();
+ LLTimer tex_timer;
gTextureList.updateImages(max_image_decode_time);
+ sTexturePipelineSpent = tex_timer.getElapsedTimeF32();
}
{