Dynamic Probe Allocation (#3787)

* #3788 Support dynamic probe allocation.
* #3738 Mitigate probe flashing
* #3735 Mitigate realtime probes flashing
master
Jonathan "Geenz" Goodman 2025-03-21 09:33:23 -04:00 committed by GitHub
parent 3c96bd2c69
commit 32c7d3064f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 87 additions and 66 deletions

View File

@ -154,6 +154,7 @@ void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, ou
if (classic_mode < 1)
{
amblit = srgb_to_linear(amblit);
amblit = vec3(dot(amblit, vec3(0.2126, 0.7152, 0.0722)));
sunlit = srgb_to_linear(sunlit);
}

View File

@ -86,7 +86,6 @@ RenderTonemapType 1 1
RenderTonemapMix 1 1
RenderDisableVintageMode 1 1
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
//
// Low Graphics Settings
@ -129,7 +128,6 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 512
RenderReflectionProbeCount 1 1
//
// Medium Low Graphics Settings
@ -172,7 +170,6 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 1024
RenderReflectionProbeCount 1 16
//
// Medium Graphics Settings (standard)
@ -214,7 +211,6 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 32
//
// Medium High Graphics Settings
@ -245,7 +241,7 @@ RenderFSAASamples 1 1
RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 1
RenderScreenSpaceReflections 1 0
RenderReflectionProbeLevel 1 2
RenderReflectionProbeLevel 1 1
RenderMirrors 1 0
RenderHeroProbeResolution 1 512
RenderHeroProbeDistance 1 6
@ -256,7 +252,6 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 64
//
// High Graphics Settings (SSAO + sun shadows)
@ -287,7 +282,7 @@ RenderFSAASamples 1 2
RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 1
RenderScreenSpaceReflections 1 0
RenderReflectionProbeLevel 1 3
RenderReflectionProbeLevel 1 2
RenderMirrors 1 0
RenderHeroProbeResolution 1 512
RenderHeroProbeDistance 1 8
@ -298,7 +293,6 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 128
//
// High Ultra Graphics Settings (deferred + SSAO + all shadows)
@ -340,7 +334,6 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
//
// Ultra graphics (REALLY PURTY!)
@ -382,7 +375,6 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
//
// Class Unknown Hardware (unknown)
@ -416,7 +408,6 @@ RenderReflectionProbeDetail 0 -1
RenderMirrors 0 0
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 0 0
list Intel
RenderAnisotropic 1 0
@ -438,7 +429,6 @@ RenderMirrors 0 0
RenderGLMultiThreadedTextures 0 0
RenderGLMultiThreadedMedia 0 0
RenderDisableVintageMode 1 0
RenderReflectionProbeCount 0 0
list TexUnit16orLess
RenderTerrainPBRDetail 1 -1

View File

@ -86,7 +86,6 @@ RenderTonemapMix 1 1
RenderDisableVintageMode 1 1
RenderDownScaleMethod 1 0
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
//
// Low Graphics Settings
@ -129,7 +128,6 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 512
RenderReflectionProbeCount 1 1
//
// Medium Low Graphics Settings
@ -172,7 +170,6 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 1024
RenderReflectionProbeCount 1 16
//
// Medium Graphics Settings (standard)
@ -214,7 +211,6 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 32
//
// Medium High Graphics Settings
@ -256,7 +252,6 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 64
//
// High Graphics Settings (SSAO + sun shadows)
@ -298,7 +293,6 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 128
//
// High Ultra Graphics Settings (SSAO + all shadows)
@ -340,7 +334,6 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
//
// Ultra graphics (REALLY PURTY!)
@ -382,7 +375,6 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
//
// Class Unknown Hardware (unknown)
@ -415,7 +407,6 @@ RenderShadowDetail 0 0
RenderMirrors 0 0
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 0 0
list TexUnit8orLess
RenderDeferredSSAO 0 0
@ -456,7 +447,6 @@ RenderReflectionProbeDetail 0 0
RenderReflectionsEnabled 0 0
RenderMirrors 0 0
RenderDisableVintageMode 1 0
RenderReflectionProbeCount 0 0
list VaryingVectors16orLess
RenderTerrainPBRPlanarSampleCount 1 1

View File

@ -52,6 +52,9 @@ LLReflectionMap::~LLReflectionMap()
void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip, bool useClipPlane, LLPlane clipPlane)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
if (!mCubeArray.notNull())
return;
mLastUpdateTime = gFrameTimeSeconds;
llassert(mCubeArray.notNull());
llassert(mCubeIndex != -1);

View File

@ -144,13 +144,14 @@ static void touch_default_probe(LLReflectionMap* probe)
LLReflectionMapManager::LLReflectionMapManager()
{
mDynamicProbeCount = LL_MAX_REFLECTION_PROBE_COUNT;
initCubeFree();
}
void LLReflectionMapManager::initCubeFree()
{
// start at 1 because index 0 is reserved for mDefaultProbe
for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i)
for (U32 i = 1; i < mDynamicProbeCount; ++i)
{
mCubeFree.push_back(i);
}
@ -221,15 +222,50 @@ void LLReflectionMapManager::update()
resume();
}
static LLCachedControl<U32> probe_count(gSavedSettings, "RenderReflectionProbeCount", 256U);
bool countReset = mReflectionProbeCount != probe_count;
static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1);
static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3);
if (countReset)
// Once every 20 frames, update the dynamic probe count.
if (gFrameCount % 20)
{
mResetFade = -0.5f;
U32 probe_count_temp = mDynamicProbeCount;
if (sLevel == 0)
{
mDynamicProbeCount = 1;
}
else if (sLevel == 1)
{
mDynamicProbeCount = (U32)mProbes.size();
}
else if (sLevel == 2)
{
mDynamicProbeCount = llmax((U32)mProbes.size(), 128);
}
else
{
mDynamicProbeCount = 256;
}
// Round mDynamicProbeCount to the nearest increment of 32
mDynamicProbeCount = ((mDynamicProbeCount + 16) / 32) * 32;
mDynamicProbeCount = llclamp(mDynamicProbeCount, 1, LL_MAX_REFLECTION_PROBE_COUNT);
if (mDynamicProbeCount < probe_count_temp * 1.1 && mDynamicProbeCount > probe_count_temp * 0.9)
mDynamicProbeCount = probe_count_temp;
else
mGlobalFadeTarget = 0.f;
}
initReflectionMaps();
if (mGlobalFadeTarget < mResetFade)
mResetFade = llmax(mGlobalFadeTarget, mResetFade - (F32)gFrameIntervalSeconds * 2);
else
mResetFade = llmin(mGlobalFadeTarget, mResetFade + (F32)gFrameIntervalSeconds * 2);
if (mResetFade == mGlobalFadeTarget)
{
initReflectionMaps();
}
static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true);
@ -286,9 +322,6 @@ void LLReflectionMapManager::update()
bool did_update = false;
static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1);
static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3);
bool realtime = sDetail >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
LLReflectionMap* closestDynamic = nullptr;
@ -343,12 +376,7 @@ void LLReflectionMapManager::update()
}
}
if (countReset)
{
mResetFade = -0.5f;
}
mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds), 1.f);
mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f);
for (unsigned int i = 0; i < mProbes.size(); ++i)
{
@ -520,6 +548,16 @@ LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
return probe;
}
U32 LLReflectionMapManager::probeCount()
{
return mDynamicProbeCount;
}
U32 LLReflectionMapManager::probeMemory()
{
return (mDynamicProbeCount * 6 * (mProbeResolution * mProbeResolution) * 4) / 1024 / 1024 + (mDynamicProbeCount * 6 * (LL_IRRADIANCE_MAP_RESOLUTION * LL_IRRADIANCE_MAP_RESOLUTION) * 4) / 1024 / 1024;
}
struct CompareProbeDepth
{
bool operator()(const LLReflectionMap* lhs, const LLReflectionMap* rhs)
@ -1058,7 +1096,11 @@ void LLReflectionMapManager::updateUniforms()
bool is_ambiance_pass = gCubeSnapshot && !isRadiancePass();
F32 ambscale = is_ambiance_pass ? 0.f : 1.f;
ambscale *= mResetFade;
ambscale = llmax(0, ambscale);
F32 radscale = is_ambiance_pass ? 0.5f : 1.f;
radscale *= mResetFade;
radscale = llmax(0, radscale);
for (auto* refmap : mReflectionMaps)
{
@ -1129,8 +1171,8 @@ void LLReflectionMapManager::updateUniforms()
}
mProbeData.refParams[count].set(
llmax(minimum_ambiance, refmap->getAmbiance())*ambscale * llmax(mResetFade, 0.f), // ambiance scale
radscale * llmax(mResetFade, 0.f), // radiance scale
llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale
radscale, // radiance scale
refmap->mFadeIn, // fade in weight
oa.getF32ptr()[2] - refmap->mRadius); // z near
@ -1365,12 +1407,9 @@ void LLReflectionMapManager::renderDebug()
void LLReflectionMapManager::initReflectionMaps()
{
static LLCachedControl<U32> probe_count(gSavedSettings, "RenderReflectionProbeCount", 256U);
U32 count = probe_count();
static LLCachedControl<U32> ref_probe_res(gSavedSettings, "RenderReflectionProbeResolution", 128U);
U32 probe_resolution = nhpo2(llclamp(ref_probe_res(), (U32)64, (U32)512));
if (mTexture.isNull() || mReflectionProbeCount != count || mProbeResolution != probe_resolution || mReset)
if (mTexture.isNull() || mReflectionProbeCount != mDynamicProbeCount || mProbeResolution != probe_resolution || mReset)
{
if(mProbeResolution != probe_resolution)
{
@ -1379,9 +1418,10 @@ void LLReflectionMapManager::initReflectionMaps()
}
gEXRImage = nullptr;
mGlobalFadeTarget = 1.f;
mResetFade = -0.125f;
mReset = false;
mReflectionProbeCount = count;
mReflectionProbeCount = mDynamicProbeCount;
mProbeResolution = probe_resolution;
mMaxProbeLOD = log2f((F32)mProbeResolution) - 1.f; // number of mips - 1

View File

@ -38,7 +38,7 @@ class LLViewerObject;
#define LL_MAX_REFLECTION_PROBE_COUNT 256
// reflection probe resolution
#define LL_IRRADIANCE_MAP_RESOLUTION 64
#define LL_IRRADIANCE_MAP_RESOLUTION 16
// reflection probe mininum scale
#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f;
@ -159,6 +159,9 @@ public:
// with false when done.
void forceDefaultProbeAndUpdateUniforms(bool force = true);
U32 probeCount();
U32 probeMemory();
private:
friend class LLPipeline;
friend class LLHeroProbeManager;
@ -166,6 +169,9 @@ private:
// initialize mCubeFree array to default values
void initCubeFree();
// Just does a bulk clear of all of the cubemaps.
void clearCubeMaps();
// delete the probe with the given index in mProbes
void deleteProbe(U32 i);
@ -240,6 +246,8 @@ private:
// number of reflection probes to use for rendering
U32 mReflectionProbeCount;
U32 mDynamicProbeCount;
// resolution of reflection probes
U32 mProbeResolution = 128;
@ -253,6 +261,7 @@ private:
bool mReset = false;
float mResetFade = 1.f;
float mGlobalFadeTarget = 1.f;
// if true, only update the default probe
bool mPaused = false;

View File

@ -559,10 +559,12 @@ void LLGLTexMemBar::draw()
gGL.color4f(0.f, 0.f, 0.f, 0.25f);
gl_rect_2d(-10, getRect().getHeight() + line_height*2 + 1, getRect().getWidth()+2, getRect().getHeight()+2);
text = llformat("Est. Free: %d MB Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
text = llformat("Est. Free: %d MB Sys Free: %d MB FBO: %d MB Probe#: %d Probe Mem: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
(S32)LLViewerTexture::sFreeVRAMMegabytes,
LLMemory::getAvailableMemKB()/1024,
LLRenderTarget::sBytesAllocated/(1024*1024),
gPipeline.mReflectionMapManager.probeCount(),
gPipeline.mReflectionMapManager.probeMemory(),
discard_bias,
cache_usage,
cache_max_usage);

View File

@ -504,8 +504,11 @@ void LLViewerTexture::updateClass()
// 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 budget = max_vram_budget == 0 ? (F32)gGLManager.mVRAM : (F32)max_vram_budget;
budget /= tex_vram_divisor;
// 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;
// Try to leave at least half a GB for everyone else and for bias,
// but keep at least 768MB for ourselves

View File

@ -858,23 +858,6 @@
value="3"/>
</combo_box>
<slider
control_name="RenderReflectionProbeCount"
decimal_digits="0"
follows="left|top"
height="16"
increment="1"
initial_value="256"
label="Max. Reflection Probes:"
label_width="145"
layout="topleft"
left="420"
min_val="1"
max_val="256"
name="MaxProbes"
top_delta="24"
width="260" />
<slider
control_name="RenderExposure"
decimal_digits="1"