summaryrefslogtreecommitdiff
path: root/indra/newview/llviewertexture.cpp
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@geenzo.com>2026-07-22 00:38:20 -0400
committerJonathan "Geenz" Goodman <geenz@geenzo.com>2026-07-22 00:38:20 -0400
commit91c11c8d87c963f2b17e45b525396bf8c8386c26 (patch)
tree3c5027410c843e8cc31ed2b253df720096529b3d /indra/newview/llviewertexture.cpp
parente9fd0450e92c569640a462baecabb89dfd537571 (diff)
Revert "Geenz/texture loading speed (#5985)"
This reverts commit a937b237de3651e79cdb517f14381a5bdd4c844b.
Diffstat (limited to 'indra/newview/llviewertexture.cpp')
-rw-r--r--indra/newview/llviewertexture.cpp112
1 files changed, 28 insertions, 84 deletions
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 90facfa333..80daffdbf3 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -571,20 +571,6 @@ void LLViewerTexture::updateClass()
sPixelToTexelRatio += llmax((F32)relax_rate, 0.f) * dt;
}
// else: hold in the hysteresis band.
-
- // Allocation failures outrank the byte estimate: if setManualImage hit
- // GL_OUT_OF_MEMORY since last frame, the CPU-side vram_used estimate has
- // diverged from reality, so step the ratio down now regardless of the band.
- static U32 last_oom_count = 0;
- U32 oom_count = LLImageGL::sOOMErrorCount.load();
- if (oom_count > last_oom_count)
- {
- U32 new_events = llmin(oom_count - last_oom_count, (U32)5);
- sPixelToTexelRatio -= llmax((F32)tighten_rate, 0.f) * 1.0f * (F32)new_events;
- last_oom_count = oom_count;
- LL_WARNS_ONCE("Texture") << "GL out-of-memory during texture upload triggered a pixel:texel ratio backoff." << LL_ENDL;
- }
-
sPixelToTexelRatio = llclamp(sPixelToTexelRatio, 0.f, r_max);
// Keep the GC-suspend frame current while backgrounded. This suppresses
@@ -1497,16 +1483,6 @@ void LLViewerFetchedTexture::postCreateTexture()
setActive();
- // Start the visibility-GC clock at creation. A texture fetched but never
- // drawn (occluded, or the camera moved on) would otherwise keep
- // mLastBindFrame == 0 forever, and the GC skips never-bound textures - it
- // would hold residency indefinitely. Anchoring here means it ages out on
- // the normal GC cooldown unless a real draw stamps it first.
- if (mGLTexturep.notNull() && mGLTexturep->mLastBindFrame == 0)
- {
- mGLTexturep->mLastBindFrame = LLFrameTimer::getFrameCount();
- }
-
// rebuild any volumes that are using this texture for sculpts in case their LoD has changed
for (U32 i = 0; i < mNumVolumes[LLRender::SCULPT_TEX]; ++i)
{
@@ -1966,14 +1942,7 @@ bool LLViewerFetchedTexture::updateFetch()
S32 current_discard = getCurrentDiscardLevelForFetching();
S32 desired_discard = getDesiredDiscardLevel();
-
- // Two-tier fetch priority, constantly drained by the fetch worker (it
- // sorts HTTP dispatch by this value): any on-screen texture outranks every
- // off-screen one. Within the visible tier, coverage orders by size on
- // screen; within the off-screen tier the same geometric coverage
- // (area/dist^2) orders by proximity. addTextureStats clamps
- // mMaxVirtualSize to sMaxVirtualSize, so the band offset is strict.
- F32 decode_priority = mMaxVirtualSize + (mOnScreen ? sMaxVirtualSize : 0.f);
+ F32 decode_priority = mMaxVirtualSize;
if (mIsFetching)
{
@@ -2034,29 +2003,6 @@ bool LLViewerFetchedTexture::updateFetch()
// discards are served from the GL mip pyramid via scaleDown.
desired_discard = llmin(desired_discard, (S32)mCodecMaxDiscardLevel);
- // Progressive refinement: when resident data is much coarser than desired,
- // fetch in steps of TextureFetchStepMips instead of jumping straight to the
- // final discard. Each step is small, decodes fast, and shows on screen
- // while the next chains behind it (the per-frame fast pump makes chaining
- // nearly free). Without this, seen-before textures (dims known, so the
- // coarse first-fetch fallback never applies) sat blurry for the whole
- // full-file read+decode, then popped. Boosted/pinned content still jumps.
- static LLCachedControl<U32> fetch_step(gSavedSettings, "TextureFetchStepMips", 2);
- const S32 step = (S32)fetch_step;
- if (step > 0
- && current_discard >= 0
- && desired_discard < current_discard - step
- && mBoostLevel < LLGLTexture::BOOST_HIGH
- && mUseMipMaps
- && !mDontDiscard
- && !isAgentAvatarBoost(mBoostLevel))
- {
- // Re-clamp: current can sit past codec max after scaleDown (GL
- // pyramid goes deeper than the codestream) - a stepped request
- // above codec max reaches the decoder with an invalid discard.
- desired_discard = llmin(current_discard - step, (S32)mCodecMaxDiscardLevel);
- }
-
bool make_request = true;
if (decode_priority <= 0)
{
@@ -2082,9 +2028,30 @@ bool LLViewerFetchedTexture::updateFetch()
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current < min");
make_request = false;
}
- // No visibility gate here: off-screen content still fetches, just in the
- // low-priority band (decode_priority above), so the worker services it only
- // after visible work. Residency stays with the GC (computeDesiredDiscard).
+ else
+ {
+ // Only fetch streamed world textures the renderer is actually drawing
+ // (mLastBindFrame is stamped per drawn frame). Out-of-view content gets
+ // no residency. Exempt: boosted/UI, avatar bakes, textures with loaded
+ // callbacks, and bake uploads.
+ static LLCachedControl<U32> vis_frames(gSavedSettings, "TextureFetchVisibilityFrames", 5);
+ const bool visibility_gated = mBoostLevel < LLGLTexture::BOOST_HIGH
+ && mUseMipMaps
+ && !mDontDiscard
+ && !isAgentAvatarBoost(mBoostLevel)
+ && !mForceToSaveRawImage
+ && mLoadedCallbackList.empty();
+ if (visibility_gated && mGLTexturep.notNull())
+ {
+ const U32 last = mGLTexturep->mLastBindFrame;
+ const U32 now = LLFrameTimer::getFrameCount();
+ if (last == 0 || now - last > llmax((U32)vis_frames, 1u))
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - not visible");
+ make_request = false;
+ }
+ }
+ }
if (make_request)
{
@@ -3068,23 +3035,6 @@ S32 LLViewerLODTexture::computeDesiredDiscard(S32 dim_max_i, bool avatar_bake) c
// (a 2048 map can't hit its own resolution on a 1080p screen), which reads
// as everything being blurry. Pressure still evicts by lowering R_global.
ideal = llmax(ideal, 0.f);
-
- // Frustum allowance: a falloff on how unloaded out-of-view content gets,
- // by how far out it is. Grazing the edge keeps full resolution; at
- // TextureFrustumAllowance (fraction of a screen) past the edge it reaches
- // the deepest mip, lerped between. Keeps barely-out-of-view textures
- // resident so a camera swing back doesn't refetch them. Applied to the
- // continuous ideal so it shares the hysteresis dead-band below - applied
- // after it, camera motion made desired flap a mip at a time and churned
- // the fetch/scaleDown queues.
- static LLCachedControl<F32> frustum_allowance(gSavedSettings, "TextureFrustumAllowance", 0.2f);
- if (!avatar_bake && mFrustumOverflow > 0.f)
- {
- const F32 f = llclamp(mFrustumOverflow / llmax((F32)frustum_allowance, 0.01f), 0.f, 1.f);
- ideal += f * ((F32)dim_max_i - ideal);
- mLastOffScreenFrame = LLFrameTimer::getFrameCount();
- }
-
const S32 target = (S32)floor(ideal);
// Hysteresis: a texture at discard C is "happy" while floor(ideal) == C,
@@ -3119,12 +3069,7 @@ S32 LLViewerLODTexture::computeDesiredDiscard(S32 dim_max_i, bool avatar_bake) c
// mip by gc_step, walking gradually toward the deepest mip instead of slamming.
// Content drawn within the last cooldown stays full-res, so a fast camera pan
// finds it only a step or two coarse on the way back. Resets when drawn again.
- //
- // Out-of-frustum content is governed by the frustum allowance above instead
- // (spatial falloff, not bind staleness) - without this exclusion the GC would
- // walk barely-out-of-view content to the deepest mip within a second and the
- // allowance would protect nothing.
- if (!avatar_bake && mFrustumOverflow <= 0.f)
+ if (!avatar_bake)
{
if (LLImageGL* gli = getGLTexture())
{
@@ -3132,9 +3077,8 @@ S32 LLViewerLODTexture::computeDesiredDiscard(S32 dim_max_i, bool avatar_bake) c
static LLCachedControl<U32> gc_step_mips(gSavedSettings, "TextureGCStepMips", 1);
constexpr U32 GC_RESUME_GRACE_FRAMES = 10;
const U32 now = LLFrameTimer::getFrameCount();
- if (gli->mLastBindFrame > 0 // drawn, or anchored at creation (postCreateTexture)
- && now - sGCSuspendedFrame > GC_RESUME_GRACE_FRAMES // not just back from background
- && now - mLastOffScreenFrame > GC_RESUME_GRACE_FRAMES) // re-entering content gets one grace window to be drawn and re-stamp before staleness is judged
+ if (gli->mLastBindFrame > 0 // drawn at least once
+ && now - sGCSuspendedFrame > GC_RESUME_GRACE_FRAMES) // not just back from background
{
const U32 cooldown = llmax((U32)gc_cooldown_frames, 1u);
const S32 periods = (S32)((now - gli->mLastBindFrame) / cooldown);