Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 50 additions & 17 deletions indra/newview/app_settings/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8038,7 +8038,7 @@
<key>RenderTextureQuality</key>
<map>
<key>Comment</key>
<string>Texture quality preset: 0=Low, 1=Medium, 2=High, 3=Ultra. Drives RenderMaxTextureResolution, TexturePixelToTexelRatio, TexturePressureTightenRate, TexturePressureRelaxRate, and TextureChannelRatio* (Normal/BaseColor/Specular/Emissive). The pressure water marks (TexturePressureHighWater/LowWater) are constant across tiers.</string>
<string>Texture quality preset: 0=Low, 1=Medium, 2=High, 3=Ultra. Drives RenderMaxTextureResolution, TexturePixelToTexelRatio, TexturePressureTightenRate, TexturePressureRelaxRate, TextureChannelRatio* (Normal/BaseColor/Specular/Emissive), TextureOffscreenUnloadBias, TextureGCStepSeconds, TextureCooldownStepSeconds, and TextureUpRezMargin. The pressure water marks (TexturePressureHighWater/LowWater) are constant across tiers.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
Expand Down Expand Up @@ -11970,21 +11970,21 @@
<key>Value</key>
<real>5.0</real>
</map>
<key>TextureGCStepFrames</key>
<key>TextureGCStepSeconds</key>
<map>
<key>Comment</key>
<string>Foreground GC cooldown, in rendered frames. For every this many frames a texture goes without being drawn, its mip drops by TextureGCStepMips. Resets when the texture is drawn again.</string>
<string>Wall-clock seconds per unload step once TextureUnloadDwellSeconds has elapsed: every this many seconds of continued off-screen/occlusion staleness drops the mip by TextureGCStepMips. Driven by the RenderTextureQuality preset.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<string>F32</string>
<key>Value</key>
<integer>5</integer>
<real>2.0</real>
</map>
<key>TextureGCStepMips</key>
<map>
<key>Comment</key>
<string>Mip levels dropped each time a TextureGCStepFrames cooldown elapses. 1 is gentlest; higher sheds VRAM faster in coarser jumps.</string>
<string>Mip levels dropped each time a TextureGCStepSeconds cooldown elapses. 1 is gentlest; higher sheds VRAM faster in coarser jumps.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
Expand Down Expand Up @@ -12025,17 +12025,6 @@
<key>Value</key>
<integer>2</integer>
</map>
<key>TextureFrustumAllowance</key>
<map>
<key>Comment</key>
<string>Falloff width for out-of-frustum texture resolution, as a fraction of screen size. Content grazing the screen edge keeps full resolution; content this far past the edge reaches the deepest mip, lerped between. Keeps barely-out-of-view textures resident so panning back doesn't refetch them.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.5</real>
</map>
<key>TextureDecodeDisabled</key>
<map>
<key>Comment</key>
Expand Down Expand Up @@ -12179,6 +12168,50 @@
<key>Value</key>
<real>0.25</real>
</map>
<key>TextureOffscreenUnloadBias</key>
<map>
<key>Comment</key>
<string>How far out of frustum content must be before angle-driven unload reaches full depth, in behindness units (0 = frustum edge, 1 = directly behind). Unload fraction ramps linearly from the frustum edge to this point. Below 1 = full unload nearer the frustum edge (aggressive); above 1 = even directly-behind content never fully unloads (protective); 0 disables angle-driven unload.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>1.0</real>
</map>
<key>TextureStreamDebugText</key>
<map>
<key>Comment</key>
<string>Show per-texture streaming diagnostics as floating debug text on objects: current&gt;desired discard, held/full dims, measured coverage (px^2), behindness, off-screen flag, frames since last confirmed visible.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>TextureUnloadDwellSeconds</key>
<map>
<key>Comment</key>
<string>Seconds a texture must be continuously off-screen, occlusion-stale, or unmeasured before its first unload step; later steps follow TextureGCStepSeconds. Wall-clock, independent of frame rate. Damps evict/refetch cycling from glances away, occlusion flap, and geometry rebuilds.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>1.0</real>
</map>
<key>TextureVRAMReserve</key>
<map>
<key>Comment</key>
<string>Fraction of the texture VRAM budget held in reserve for other applications. Applied before the pressure watermarks. 0..0.9.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.2</real>
</map>
<key>ThreadPoolSizes</key>
<map>
<key>Comment</key>
Expand Down
22 changes: 14 additions & 8 deletions indra/newview/llface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2454,19 +2454,25 @@ bool LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ;
}

// On-screen test: does the face's projected disc overlap the screen disc?
// (Same construction as adjustPartialOverlapPixelArea.) Behind-camera faces
// get acos(cos) near pi and fall out; the generous screen radius errs toward
// "on screen" so fetch admission never starves edge content. mFrustumOverflow
// is how far past the boundary the disc sits, as a fraction of screen size -
// 0 on screen, 0.1 = 10% of a screen out - and feeds the frustum allowance
// falloff in computeDesiredDiscard.
// Screen-disc overlap -> mInFrustum; angular off-screen-ness ->
// mBehindness (0 = on screen, 1 = directly behind). Feeds fetch
// admission and the off-screen falloff in computeDesiredDiscard.
{
F32 center_px = acosf(llclamp(cos_angle_to_view_dir, -1.f, 1.f)) * LLDrawable::sCurPixelAngle;
F32 screen_radius = (F32)llmax(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
F32 past_edge = center_px - radius - screen_radius;
mInFrustum = past_edge <= 5.f;
mFrustumOverflow = llmax(past_edge - 5.f, 0.f) / screen_radius;

// Two boundaries on purpose: mInFrustum stays generous (fetch
// admission errs open); mBehindness starts at the circumscribed disc
// (~the real frustum edge) so everything outside the view belongs to
// the angular policy, never the GC.
F32 w = (F32)gViewerWindow->getWindowWidthRaw();
F32 h = (F32)gViewerWindow->getWindowHeightRaw();
F32 screen_half_diag = 0.5f * sqrtf(w * w + h * h);
F32 ang = acosf(llclamp(cos_angle_to_view_dir, -1.f, 1.f));
F32 edge_ang = (radius + screen_half_diag + 5.f) / LLDrawable::sCurPixelAngle;
mBehindness = llclamp((ang - edge_ang) / llmax(F_PI - edge_ang, 0.001f), 0.f, 1.f);
}

mLastCosAngleToViewDir = cos_angle_to_view_dir;
Expand Down
9 changes: 5 additions & 4 deletions indra/newview/llface.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,11 @@ class alignas(16) LLFace
// by calcPixelArea() (sticky between its throttled updates). Drives per-texture
// fetch admission (LLViewerTextureList::updateImageDecodePriority -> mOnScreen).
bool mInFrustum = false;
// How far past the screen boundary the projected disc sits, as a fraction of
// screen size (0 = on screen). Feeds the frustum-allowance falloff so barely
// out-of-view content keeps its resolution. Maintained with mInFrustum.
F32 mFrustumOverflow = 0.f;
// Angular off-screen-ness of the face: 0 = projected disc overlaps the screen
// (or ahead), 1 = directly behind the camera. Maintained with mInFrustum by
// calcPixelArea (sticky between throttled updates); drives the off-screen
// unload falloff.
F32 mBehindness = 0.f;
// value of gFrameCount the last time the face was touched by LLViewerTextureList::updateImageDecodePriority
U32 mLastTextureUpdate = 0;
// Cached per-channel streaming coverage (repeat-adjusted screen pixels),
Expand Down
22 changes: 17 additions & 5 deletions indra/newview/llviewercontrol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ namespace
F32 channel_ratio_basecolor; // TextureChannelRatioBaseColor
F32 channel_ratio_specular; // TextureChannelRatioSpecular
F32 channel_ratio_emissive; // TextureChannelRatioEmissive
F32 offscreen_unload_bias; // TextureOffscreenUnloadBias
F32 gc_step_seconds; // TextureGCStepSeconds (wall-clock)
F32 cooldown_step_seconds; // TextureCooldownStepSeconds
F32 uprez_margin; // TextureUpRezMargin
};

// Tier values: Low (2-4GB), Medium (4-8GB), High (8-16GB), Ultra (16+GB).
Expand All @@ -138,15 +142,19 @@ namespace
// floor (down to 0 = deepest mips), so there is no per-tier minimum.
// - the channel ratios coarsen specular/emissive/normal relative to base
// color (each is a multiplier on the global ratio).
// - offscreen_unload_bias (UB) is the behindness (0 = frustum edge,
// 1 = directly behind) at which out-of-frustum content reaches full
// unload: lower tiers slam sooner; High/Ultra (1.0) only reach full
// unload directly behind the camera.
// The pressure water marks (TexturePressureHighWater/LowWater) are NOT tiered - they're a
// physical "crossed the budget" threshold (0.90 / 0.70), constant across
// tiers. Lower tiers start blurrier (lower R_max) and tighten faster.
// max_res Rmax tight relax N BC S E
// max_res Rmax tight relax N BC S E UB GC CD UR
static constexpr TexturePreset TEXTURE_PRESETS[4] = {
/* 0 Low */ { "Low", 1024, 0.10f, 0.50f, 0.05f, 0.50f, 1.00f, 0.25f, 0.25f },
/* 1 Medium */ { "Medium", 2048, 0.40f, 0.35f, 0.08f, 1.00f, 1.00f, 0.50f, 0.50f },
/* 2 High */ { "High", 2048, 0.80f, 0.25f, 0.10f, 1.00f, 1.00f, 0.50f, 1.00f },
/* 3 Ultra */ { "Ultra", 2048, 1.00f, 0.15f, 0.12f, 1.00f, 1.00f, 1.00f, 1.00f },
/* 0 Low */ { "Low", 1024, 0.10f, 0.50f, 0.05f, 0.50f, 1.00f, 0.25f, 0.25f, 0.25f, 1.0f, 5.0f, 0.2f },
/* 1 Medium */ { "Medium", 2048, 0.40f, 0.35f, 0.08f, 1.00f, 1.00f, 0.50f, 0.50f, 0.50f, 1.0f, 5.0f, 0.2f },
/* 2 High */ { "High", 2048, 0.80f, 0.25f, 0.10f, 1.00f, 1.00f, 0.50f, 1.00f, 1.00f, 2.0f, 5.0f, 0.2f },
/* 3 Ultra */ { "Ultra", 2048, 1.00f, 0.15f, 0.12f, 1.00f, 1.00f, 1.00f, 1.00f, 1.00f, 2.0f, 5.0f, 0.2f },
};
}

Expand All @@ -164,6 +172,10 @@ static bool handleRenderTextureQualityChanged(const LLSD& newvalue)
gSavedSettings.setF32("TextureChannelRatioBaseColor", p.channel_ratio_basecolor);
gSavedSettings.setF32("TextureChannelRatioSpecular", p.channel_ratio_specular);
gSavedSettings.setF32("TextureChannelRatioEmissive", p.channel_ratio_emissive);
gSavedSettings.setF32("TextureOffscreenUnloadBias", p.offscreen_unload_bias);
gSavedSettings.setF32("TextureGCStepSeconds", p.gc_step_seconds);
gSavedSettings.setF32("TextureCooldownStepSeconds", p.cooldown_step_seconds);
gSavedSettings.setF32("TextureUpRezMargin", p.uprez_margin);

LL_INFOS("TextureStream") << "Applied texture quality preset: " << p.name << LL_ENDL;
return true;
Expand Down
Loading
Loading