summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@lindenlab.com>2025-03-11 00:40:36 -0400
committerGitHub <noreply@github.com>2025-03-11 06:40:36 +0200
commit5ce0c5858c387346b7b8923ec55b4cee3f1c4d12 (patch)
treec1895e6c06890e6fb3747e3c504b4fa2b481fb38
parent573ca63e0f837fd52cbfc8adc3546d8971d21b12 (diff)
#3409 Make maximum probe count adjustable. (#3709)
* #3409 Make probe count adjustable to better accomodate low VRAM scenarios
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl1
-rw-r--r--indra/newview/featuretable.txt10
-rw-r--r--indra/newview/featuretable_mac.txt10
-rw-r--r--indra/newview/llreflectionmapmanager.cpp112
-rw-r--r--indra/newview/llreflectionmapmanager.h49
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml17
7 files changed, 141 insertions, 69 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 594f40e5a1..0c83355a81 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -9076,6 +9076,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>RenderReflectionProbeCount</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of probes to render. Maximum of 256. Clamps to the nearest power of 2.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>256</integer>
+ </map>
<key>RenderReflectionProbeResolution</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
index 0283104a76..dba9c46332 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
@@ -87,6 +87,7 @@ vec3 clampHDRRange(vec3 color)
// This is a safety measure to prevent that.
// As to the specific number there - allegedly some HDR displays expect values to be in the 0-11.2 range. Citation needed.
// -Geenz 2025-03-05
+ color = mix(color, vec3(1), isinf(color));
color = mix(color, vec3(0.0), isnan(color));
return clamp(color, vec3(0.0), vec3(11.2));
}
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index cb79410d72..883963d558 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -86,6 +86,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 1
RenderDisableVintageMode 1 1
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 256
//
// Low Graphics Settings
@@ -128,6 +129,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 512
+RenderReflectionProbeCount 1 1
//
// Medium Low Graphics Settings
@@ -170,6 +172,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 1024
+RenderReflectionProbeCount 1 16
//
// Medium Graphics Settings (standard)
@@ -211,6 +214,7 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 32
//
// Medium High Graphics Settings
@@ -252,6 +256,7 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 64
//
// High Graphics Settings (SSAO + sun shadows)
@@ -293,6 +298,7 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 128
//
// High Ultra Graphics Settings (deferred + SSAO + all shadows)
@@ -334,6 +340,7 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 256
//
// Ultra graphics (REALLY PURTY!)
@@ -375,6 +382,7 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 256
//
// Class Unknown Hardware (unknown)
@@ -408,6 +416,7 @@ RenderReflectionProbeDetail 0 -1
RenderMirrors 0 0
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 0 0
list Intel
RenderAnisotropic 1 0
@@ -429,6 +438,7 @@ RenderMirrors 0 0
RenderGLMultiThreadedTextures 0 0
RenderGLMultiThreadedMedia 0 0
RenderDisableVintageMode 1 0
+RenderReflectionProbeCount 0 0
list TexUnit16orLess
RenderTerrainPBRDetail 1 -1
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index dc9473b042..103d24a26d 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -86,6 +86,7 @@ RenderTonemapMix 1 1
RenderDisableVintageMode 1 1
RenderDownScaleMethod 1 0
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 256
//
// Low Graphics Settings
@@ -128,6 +129,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 512
+RenderReflectionProbeCount 1 1
//
// Medium Low Graphics Settings
@@ -170,6 +172,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 1024
+RenderReflectionProbeCount 1 16
//
// Medium Graphics Settings (standard)
@@ -211,6 +214,7 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 32
//
// Medium High Graphics Settings
@@ -252,6 +256,7 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 64
//
// High Graphics Settings (SSAO + sun shadows)
@@ -293,6 +298,7 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 128
//
// High Ultra Graphics Settings (SSAO + all shadows)
@@ -334,6 +340,7 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 256
//
// Ultra graphics (REALLY PURTY!)
@@ -375,6 +382,7 @@ RenderExposure 1 1
RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 1 256
//
// Class Unknown Hardware (unknown)
@@ -407,6 +415,7 @@ RenderShadowDetail 0 0
RenderMirrors 0 0
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 2048
+RenderReflectionProbeCount 0 0
list TexUnit8orLess
RenderDeferredSSAO 0 0
@@ -447,6 +456,7 @@ RenderReflectionProbeDetail 0 0
RenderReflectionsEnabled 0 0
RenderMirrors 0 0
RenderDisableVintageMode 1 0
+RenderReflectionProbeCount 0 0
list VaryingVectors16orLess
RenderTerrainPBRPlanarSampleCount 1 1
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 9a20977652..48b73531ea 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -221,6 +221,14 @@ void LLReflectionMapManager::update()
resume();
}
+ static LLCachedControl<U32> probe_count(gSavedSettings, "RenderReflectionProbeCount", 256U);
+ bool countReset = mReflectionProbeCount != probe_count;
+
+ if (countReset)
+ {
+ mResetFade = -0.5f;
+ }
+
initReflectionMaps();
static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true);
@@ -335,6 +343,13 @@ void LLReflectionMapManager::update()
}
}
+ if (countReset)
+ {
+ mResetFade = -0.5f;
+ }
+
+ mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds), 1.f);
+
for (unsigned int i = 0; i < mProbes.size(); ++i)
{
LLReflectionMap* probe = mProbes[i];
@@ -1012,60 +1027,18 @@ void LLReflectionMapManager::updateUniforms()
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
- // structure for packing uniform buffer object
- // see class3/deferred/reflectionProbeF.glsl
- struct ReflectionProbeData
- {
- // for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of
- // the box probe
- LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT];
-
- LLMatrix4 heroBox;
-
- // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space
- LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT];
-
- // extra parameters
- // x - irradiance scale
- // y - radiance scale
- // z - fade in
- // w - znear
- LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT];
-
- LLVector4 heroSphere;
-
- // indices used by probe:
- // [i][0] - cubemap array index for this probe
- // [i][1] - index into "refNeighbor" for probes that intersect this probe
- // [i][2] - number of probes that intersect this probe, or -1 for no neighbors
- // [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes)
- GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4];
-
- // list of neighbor indices
- GLint refNeighbor[4096];
-
- GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth
- // numbrer of active refmaps
- GLint refmapCount;
-
- GLint heroShape;
- GLint heroMipCount;
- GLint heroProbeCount;
- };
mReflectionMaps.resize(mReflectionProbeCount);
getReflectionMaps(mReflectionMaps);
- ReflectionProbeData rpd;
-
F32 minDepth[256];
for (int i = 0; i < 256; ++i)
{
- rpd.refBucket[i][0] = mReflectionProbeCount;
- rpd.refBucket[i][1] = mReflectionProbeCount;
- rpd.refBucket[i][2] = mReflectionProbeCount;
- rpd.refBucket[i][3] = mReflectionProbeCount;
+ mProbeData.refBucket[i][0] = mReflectionProbeCount;
+ mProbeData.refBucket[i][1] = mReflectionProbeCount;
+ mProbeData.refBucket[i][2] = mReflectionProbeCount;
+ mProbeData.refBucket[i][3] = mReflectionProbeCount;
minDepth[i] = FLT_MAX;
}
@@ -1111,7 +1084,7 @@ void LLReflectionMapManager::updateUniforms()
if (refmap->mMinDepth < minDepth[i])
{
minDepth[i] = refmap->mMinDepth;
- rpd.refBucket[i][0] = refmap->mProbeIndex;
+ mProbeData.refBucket[i][0] = refmap->mProbeIndex;
}
}
}
@@ -1139,25 +1112,25 @@ void LLReflectionMapManager::updateUniforms()
}
}
modelview.affineTransform(refmap->mOrigin, oa);
- rpd.refSphere[count].set(oa.getF32ptr());
- rpd.refSphere[count].mV[3] = refmap->mRadius;
+ mProbeData.refSphere[count].set(oa.getF32ptr());
+ mProbeData.refSphere[count].mV[3] = refmap->mRadius;
}
- rpd.refIndex[count][0] = refmap->mCubeIndex;
+ mProbeData.refIndex[count][0] = refmap->mCubeIndex;
llassert(nc % 4 == 0);
- rpd.refIndex[count][1] = nc / 4;
- rpd.refIndex[count][3] = refmap->mPriority;
+ mProbeData.refIndex[count][1] = nc / 4;
+ mProbeData.refIndex[count][3] = refmap->mPriority;
// for objects that are reflection probes, use the volume as the influence volume of the probe
// only possibile influence volumes are boxes and spheres, so detect boxes and treat everything else as spheres
- if (refmap->getBox(rpd.refBox[count]))
+ if (refmap->getBox(mProbeData.refBox[count]))
{ // negate priority to indicate this probe has a box influence volume
- rpd.refIndex[count][3] = -rpd.refIndex[count][3];
+ mProbeData.refIndex[count][3] = -mProbeData.refIndex[count][3];
}
- rpd.refParams[count].set(
- llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale
- radscale, // radiance scale
+ mProbeData.refParams[count].set(
+ llmax(minimum_ambiance, refmap->getAmbiance())*ambscale * llmax(mResetFade, 0.f), // ambiance scale
+ radscale * llmax(mResetFade, 0.f), // radiance scale
refmap->mFadeIn, // fade in weight
oa.getF32ptr()[2] - refmap->mRadius); // z near
@@ -1182,7 +1155,7 @@ void LLReflectionMapManager::updateUniforms()
}
// this neighbor may be sampled
- rpd.refNeighbor[ni++] = idx;
+ mProbeData.refNeighbor[ni++] = idx;
neighbor_count++;
if (neighbor_count >= max_neighbors)
@@ -1195,11 +1168,11 @@ void LLReflectionMapManager::updateUniforms()
if (nc == ni)
{
//no neighbors, tag as empty
- rpd.refIndex[count][1] = -1;
+ mProbeData.refIndex[count][1] = -1;
}
else
{
- rpd.refIndex[count][2] = ni - nc;
+ mProbeData.refIndex[count][2] = ni - nc;
// move the cursor forward
nc = ni;
@@ -1237,19 +1210,19 @@ void LLReflectionMapManager::updateUniforms()
}
#endif
- rpd.refmapCount = count;
+ mProbeData.refmapCount = count;
gPipeline.mHeroProbeManager.updateUniforms();
// Get the hero data.
- rpd.heroBox = gPipeline.mHeroProbeManager.mHeroData.heroBox;
- rpd.heroSphere = gPipeline.mHeroProbeManager.mHeroData.heroSphere;
- rpd.heroShape = gPipeline.mHeroProbeManager.mHeroData.heroShape;
- rpd.heroMipCount = gPipeline.mHeroProbeManager.mHeroData.heroMipCount;
- rpd.heroProbeCount = gPipeline.mHeroProbeManager.mHeroData.heroProbeCount;
+ mProbeData.heroBox = gPipeline.mHeroProbeManager.mHeroData.heroBox;
+ mProbeData.heroSphere = gPipeline.mHeroProbeManager.mHeroData.heroSphere;
+ mProbeData.heroShape = gPipeline.mHeroProbeManager.mHeroData.heroShape;
+ mProbeData.heroMipCount = gPipeline.mHeroProbeManager.mHeroData.heroMipCount;
+ mProbeData.heroProbeCount = gPipeline.mHeroProbeManager.mHeroData.heroProbeCount;
- //copy rpd into uniform buffer object
+ //copy mProbeData into uniform buffer object
if (mUBO == 0)
{
glGenBuffers(1, &mUBO);
@@ -1258,7 +1231,7 @@ void LLReflectionMapManager::updateUniforms()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer");
glBindBuffer(GL_UNIFORM_BUFFER, mUBO);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &mProbeData, GL_STREAM_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
@@ -1392,7 +1365,8 @@ void LLReflectionMapManager::renderDebug()
void LLReflectionMapManager::initReflectionMaps()
{
- U32 count = LL_MAX_REFLECTION_PROBE_COUNT;
+ 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));
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
index f81fb30738..9f88776ac2 100644
--- a/indra/newview/llreflectionmapmanager.h
+++ b/indra/newview/llreflectionmapmanager.h
@@ -56,6 +56,51 @@ public:
REALTIME = 2
};
+ // General guidance for UBOs is to statically allocate all of these fields to make your life ever so slightly easier.
+ // Then set a "max" value for the number of probes you'll ever have, and use that to index into the arrays.
+ // We do this with refmapCount. The shaders will just pick up on it there.
+ // This data structure should _always_ match what's in class3/deferred/reflectionProbeF.glsl.
+ // The shader can and will break otherwise.
+ // -Geenz 2025-03-10
+ struct ReflectionProbeData
+ {
+ // for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of
+ // the box probe
+ LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT];
+
+ LLMatrix4 heroBox;
+
+ // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space
+ LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT];
+
+ // extra parameters
+ // x - irradiance scale
+ // y - radiance scale
+ // z - fade in
+ // w - znear
+ LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT];
+
+ LLVector4 heroSphere;
+
+ // indices used by probe:
+ // [i][0] - cubemap array index for this probe
+ // [i][1] - index into "refNeighbor" for probes that intersect this probe
+ // [i][2] - number of probes that intersect this probe, or -1 for no neighbors
+ // [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes)
+ GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4];
+
+ // list of neighbor indices
+ GLint refNeighbor[4096];
+
+ GLint refBucket[256][4]; // lookup table for which index to start with for the given Z depth
+ // numbrer of active refmaps
+ GLint refmapCount;
+
+ GLint heroShape;
+ GLint heroMipCount;
+ GLint heroProbeCount;
+ };
+
// allocate an environment map of the given resolution
LLReflectionMapManager();
@@ -207,8 +252,12 @@ private:
// if true, reset all probe render state on the next update (for teleports and sky changes)
bool mReset = false;
+ float mResetFade = 1.f;
+
// if true, only update the default probe
bool mPaused = false;
F32 mResumeTime = 0.f;
+
+ ReflectionProbeData mProbeData;
};
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index 96de9e61cb..f1c7ab78d0 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -859,6 +859,23 @@
</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"
follows="left|top"