summaryrefslogtreecommitdiff
path: root/indra/newview/llreflectionmapmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llreflectionmapmanager.cpp')
-rw-r--r--indra/newview/llreflectionmapmanager.cpp521
1 files changed, 350 insertions, 171 deletions
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 2708d5edf0..aa48035aa8 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -54,6 +54,7 @@
#endif
LLPointer<LLImageGL> gEXRImage;
+//LLTrace::BlockTimerStatHandle FTM_RENDER_RADIANCE("Render Radiance");
void load_exr(const std::string& filename)
{
@@ -144,13 +145,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);
}
@@ -210,6 +212,7 @@ void LLReflectionMapManager::update()
}
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ LL_PROFILE_GPU_ZONE("reflection manager update");
llassert(!gCubeSnapshot); // assert a snapshot is not in progress
if (LLAppViewer::instance()->logoutRequestSent())
{
@@ -221,13 +224,83 @@ void LLReflectionMapManager::update()
resume();
}
+ static LLCachedControl<F32> sProbeUpdateSlowDown(gSavedSettings, "MPRenderProbeSlowDown", 0.05);
+
+ bool realtime = mRenderReflectionProbeDetail >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
+
+ if(sProbeUpdateSlowDown > 0.0)
+ {
+ if ( mLastUpdate > 0.f )
+ {
+ F32 elapsed = gFrameTimeSeconds - mLastUpdate;
+ if (elapsed > 0.0 && elapsed < sProbeUpdateSlowDown)
+ {
+ return;
+ }
+ }
+ }
+
+ mLastUpdate = gFrameTimeSeconds;
+
+ mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f);
+
+ {
+ U32 probe_count_temp = mDynamicProbeCount;
+ if (mRenderReflectionProbeDynamicAllocation > -1)
+ {
+ if (mRenderReflectionProbeLevel == 0)
+ {
+ mDynamicProbeCount = 1;
+ }
+ else if (mRenderReflectionProbeLevel == 1)
+ {
+ mDynamicProbeCount = (U32)mProbes.size();
+ }
+ else if (mRenderReflectionProbeLevel == 2)
+ {
+ mDynamicProbeCount = llmax((U32)mProbes.size(), 128);
+ }
+ else
+ {
+ mDynamicProbeCount = 256;
+ }
+
+ if (mRenderReflectionProbeDynamicAllocation > 1)
+ {
+ // Round mDynamicProbeCount to the nearest increment of 16
+ mDynamicProbeCount = ((mDynamicProbeCount + mRenderReflectionProbeDynamicAllocation / 2) / mRenderReflectionProbeDynamicAllocation) * 16;
+ mDynamicProbeCount = llclamp(mDynamicProbeCount, 1, mRenderReflectionProbeCount);
+ }
+ else
+ {
+ mDynamicProbeCount = llclamp(mDynamicProbeCount + mRenderReflectionProbeDynamicAllocation, 1, mRenderReflectionProbeCount);
+ }
+ }
+ else
+ {
+ mDynamicProbeCount = mRenderReflectionProbeCount;
+ }
+
+ mDynamicProbeCount = llmin(mDynamicProbeCount, LL_MAX_REFLECTION_PROBE_COUNT);
+
+ if (mDynamicProbeCount != probe_count_temp)
+ mResetFade = 1.f;
+ }
+
initReflectionMaps();
static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true);
+ static LLCachedControl<U32> MPColorPrecision(gSavedSettings, "MPColorPrecision", 0);
+
+ U32 color_fmt = render_hdr ? GL_R11F_G11F_B10F : GL_RGB8;
+
+ if(MPColorPrecision == 1)
+ {
+ color_fmt = GL_RGB8;
+ }
if (!mRenderTarget.isComplete())
{
- U32 color_fmt = render_hdr ? GL_R11F_G11F_B10F : GL_RGB8;
U32 targetRes = mProbeResolution * 4; // super sample
mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
}
@@ -240,7 +313,7 @@ void LLReflectionMapManager::update()
mMipChain.resize(count);
for (U32 i = 0; i < count; ++i)
{
- mMipChain[i].allocate(res, res, render_hdr ? GL_R11F_G11F_B10F : GL_RGB8);
+ mMipChain[i].allocate(res, res, color_fmt);
res /= 2;
}
}
@@ -278,11 +351,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;
LLReflectionMap* oldestProbe = nullptr;
@@ -315,6 +383,10 @@ void LLReflectionMapManager::update()
probe->mCubeArray = nullptr;
probe->mCubeIndex = -1;
probe->mComplete = false;
+ probe->mCompletedCount = 0;
+ probe->mLastUpdateTime = 0.0;
+ probe->mNextUpdateTime = 0.0;
+ probe->mFadeIn = 0;
}
}
@@ -335,6 +407,10 @@ void LLReflectionMapManager::update()
}
}
+ mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f);
+
+ static LLCachedControl<F32> sDefaultUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.0);
+
for (unsigned int i = 0; i < mProbes.size(); ++i)
{
LLReflectionMap* probe = mProbes[i];
@@ -351,6 +427,8 @@ void LLReflectionMapManager::update()
continue;
}
+ // Calculating distance
+
LLVector4a d;
if (probe != mDefaultProbe)
@@ -362,13 +440,14 @@ void LLReflectionMapManager::update()
d.setSub(camera_pos, probe->mOrigin);
probe->mDistance = d.getLength3().getF32() - probe->mRadius;
}
- else if (probe->mComplete)
+ else if (mDefaultProbe->mComplete)
{
// make default probe have a distance of 64m for the purposes of prioritization (if it's already been generated once)
probe->mDistance = 64.f;
}
else
{
+ probe->mNextUpdateTime = 0.f;
probe->mDistance = -4096.f; //boost priority of default probe when it's not complete
}
@@ -377,8 +456,13 @@ void LLReflectionMapManager::update()
probe->autoAdjustOrigin();
probe->mFadeIn = llmin((F32) (probe->mFadeIn + gFrameIntervalSeconds), 1.f);
}
+
+ // Guess oldest probe
+
if (probe->mOccluded && probe->mComplete)
{
+ // occluded probe
+
if (oldestOccluded == nullptr)
{
oldestOccluded = probe;
@@ -407,7 +491,7 @@ void LLReflectionMapManager::update()
closestDynamic = probe;
}
- if (sLevel == 0)
+ if (mRenderReflectionProbeLevel == 0)
{
// only update default probe when coverage is set to none
llassert(probe == mDefaultProbe);
@@ -415,6 +499,8 @@ void LLReflectionMapManager::update()
}
}
+ // realtime
+
if (realtime && closestDynamic != nullptr)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime");
@@ -430,21 +516,23 @@ void LLReflectionMapManager::update()
{
updateProbeFace(closestDynamic, i);
}
+ if(mRealtimeRadiancePass) updateProbeRadiance(closestDynamic);
+ else updateProbeIrradiance(closestDynamic);
mRealtimeRadiancePass = !mRealtimeRadiancePass;
// restore "isRadiancePass"
mRadiancePass = radiance_pass;
}
- static LLCachedControl<F32> sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f);
- if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod)
+ if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sDefaultUpdatePeriod)
{
- if (sLevel == 0)
+// if (sLevel == 0 && mDefaultProbe->mComplete)
+ if (mRenderReflectionProbeLevel == 0)
{ // when probes are disabled don't update the default probe more often than the prescribed update period
oldestProbe = nullptr;
}
}
- else if (sLevel > 0)
+ else if (mRenderReflectionProbeLevel > 0)
{ // when probes are enabled don't update the default probe less often than the prescribed update period
oldestProbe = mDefaultProbe;
}
@@ -455,11 +543,21 @@ void LLReflectionMapManager::update()
LLReflectionMap* probe = oldestProbe;
llassert(probe->mCubeIndex != -1);
+ bool shouldUpdate = true;
+
+ if( probe->mNextUpdateTime > 0.f && gFrameTimeSeconds < probe->mNextUpdateTime)
+ {
+ shouldUpdate = false;
+ }
+
+ if(shouldUpdate)
+ {
probe->autoAdjustOrigin();
sUpdateCount++;
mUpdatingProbe = probe;
doProbeUpdate();
+ }
}
if (oldestOccluded)
@@ -470,6 +568,14 @@ void LLReflectionMapManager::update()
}
}
+void LLReflectionMapManager::refreshSettings()
+{
+ mRenderReflectionProbeDetail = gSavedSettings.getS32("RenderReflectionProbeDetail");
+ mRenderReflectionProbeLevel = gSavedSettings.getS32("RenderReflectionProbeLevel");
+ mRenderReflectionProbeCount = gSavedSettings.getU32("RenderReflectionProbeCount");
+ mRenderReflectionProbeDynamicAllocation = gSavedSettings.getS32("RenderReflectionProbeDynamicAllocation");
+}
+
LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
{
if (gGLManager.mGLVersion < 4.05f || !LLPipeline::sReflectionProbesEnabled)
@@ -505,6 +611,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)
@@ -657,11 +773,19 @@ void LLReflectionMapManager::doProbeUpdate()
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
llassert(mUpdatingProbe != nullptr);
- updateProbeFace(mUpdatingProbe, mUpdatingFace);
+ if(mUpdatingFace < 6)
+ {
+ updateProbeFace(mUpdatingProbe, mUpdatingFace);
+ }
+ else
+ {
+ if(isRadiancePass()) updateProbeRadiance(mUpdatingProbe);
+ else updateProbeIrradiance(mUpdatingProbe);
+ }
bool debug_updates = gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PROBE_UPDATES) && mUpdatingProbe->mViewerObject;
- if (++mUpdatingFace == 6)
+ if (mUpdatingFace == 6)
{
if (debug_updates)
{
@@ -671,7 +795,23 @@ void LLReflectionMapManager::doProbeUpdate()
mUpdatingFace = 0;
if (isRadiancePass())
{
+ static LLCachedControl<F32> sMPUpdatePeriod(gSavedSettings, "MPRenderProbeUpdatePeriod", 15.0);
+
mUpdatingProbe->mComplete = true;
+ mUpdatingProbe->mCompletedCount++;
+
+ LL_WARNS() << "Probe updated (" << mUpdatingProbe->mCompletedCount << ")" << LL_ENDL;
+
+ if(mUpdatingProbe->mCompletedCount < 5)
+ {
+ //probe->mNextUpdateTime = gFrameTimeSeconds + fmax( ((F32)sMPUpdatePeriod / 2.0), 0.25);
+ mUpdatingProbe->mNextUpdateTime = gFrameTimeSeconds + 1.0;
+ }
+ else
+ {
+ mUpdatingProbe->mNextUpdateTime = gFrameTimeSeconds + fmax( (F32)sMPUpdatePeriod, 0.10);
+ }
+
mUpdatingProbe = nullptr;
mRadiancePass = false;
}
@@ -680,9 +820,14 @@ void LLReflectionMapManager::doProbeUpdate()
mRadiancePass = true;
}
}
- else if (debug_updates)
+ else
{
+ ++mUpdatingFace;
+
+ if (debug_updates)
+ {
mUpdatingProbe->mViewerObject->setDebugText(llformat("%.1f", (F32)gFrameTimeSeconds), LLColor4(1, 1, 0, 1));
+ }
}
}
@@ -696,6 +841,8 @@ void LLReflectionMapManager::doProbeUpdate()
// In effect this simulates single-bounce lighting.
void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ LL_PROFILE_GPU_ZONE("probe update");
// hacky hot-swap of camera specific render targets
gPipeline.mRT = &gPipeline.mAuxillaryRT;
@@ -722,7 +869,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
}
else
{
- llassert(gSavedSettings.getS32("RenderReflectionProbeLevel") > 0); // should never update a probe that's not the default probe if reflection coverage is none
+ llassert(mRenderReflectionProbeLevel > 0); // should never update a probe that's not the default probe if reflection coverage is none
probe->update(mRenderTarget.getWidth(), face);
}
@@ -735,7 +882,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
sourceIdx += 1;
}
- gGL.setColorMask(true, true);
+ gGL.setColorMask(true, false);
LLGLDepthTest depth(GL_FALSE, GL_FALSE);
LLGLDisable cull(GL_CULL_FACE);
LLGLDisable blend(GL_BLEND);
@@ -769,7 +916,8 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
// horizontal
gGaussianProgram.uniform2f(direction, 1.f, 0.f);
gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
- mRenderTarget.bindTarget();
+ mRenderTarget.bindTarget("", 1);
+ mRenderTarget.clear(0);
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
mRenderTarget.flush();
@@ -777,7 +925,8 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
// vertical
gGaussianProgram.uniform2f(direction, 0.f, 1.f);
gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget);
- screen_rt->bindTarget();
+ screen_rt->bindTarget("", 1);
+ screen_rt->clear(0);
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
screen_rt->flush();
@@ -792,7 +941,10 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
for (int i = 0; i < mMipChain.size(); ++i)
{
LL_PROFILE_GPU_ZONE("probe mip");
- mMipChain[i].bindTarget();
+
+ mMipChain[i].bindTarget("probe face ", 0);
+ mMipChain[i].clear(0);
+
if (i == 0)
{
gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
@@ -836,17 +988,118 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gGL.getTexUnit(diffuseChannel)->unbind(LLTexUnit::TT_TEXTURE);
gReflectionMipProgram.unbind();
}
+}
- if (face == 5)
- {
- mMipChain[0].bindTarget();
- static LLStaticHashedString sSourceIdx("sourceIdx");
+// ===================== IRRADIANCE ================================
- if (isRadiancePass())
+void LLReflectionMapManager::updateProbeIrradiance(LLReflectionMap* probe)
+{
+ LL_PROFILE_GPU_ZONE("probe irradiance gen");
+
+ static LLStaticHashedString sMipLevel("mipLevel");
+ static LLStaticHashedString sRoughness("roughness");
+ static LLStaticHashedString sWidth("u_width");
+
+ S32 sourceIdx = mReflectionProbeCount;
+
+ if (probe != mUpdatingProbe)
+ { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel
+ sourceIdx += 1;
+ }
+
+ gGL.setColorMask(true, false);
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+
+ static LLStaticHashedString sSourceIdx("sourceIdx");
+
+
+ mMipChain[0].bindTarget("irradiance", 0);
+ mMipChain[0].clear();
+
+ gIrradianceGenProgram.bind();
+
+#if GL_VERSION_4_0
+ S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTexture->bind(channel);
+#endif
+
+ gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
+ gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
+
+ mVertexBuffer->setBuffer();
+
+ int start_mip = 0;
+ // find the mip target to start with based on irradiance map resolution
+ for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip)
+ {
+ if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION)
{
- //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map)
- gRadianceGenProgram.bind();
- mVertexBuffer->setBuffer();
+ break;
+ }
+ }
+
+ int i = start_mip;
+
+ //LL_PROFILE_GPU_ZONE("probe irradiance gen");
+
+ glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight());
+
+ for (int cf = 0; cf < 6; ++cf)
+ {
+ LLCoordFrame frame;
+ frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]);
+
+ F32 mat[16];
+ frame.getOpenGLRotation(mat);
+ gGL.loadMatrix(mat);
+
+ mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
+
+ S32 res = mMipChain[i].getWidth();
+#if GL_VERSION_4_0
+ mIrradianceMaps->bind(channel);
+ glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
+ mTexture->bind(channel);
+#endif
+ //mMipChain[0].clear(0);
+ }
+
+ mMipChain[0].flush();
+ gIrradianceGenProgram.unbind();
+}
+
+// ==================== RADIANCE ===========================
+
+void LLReflectionMapManager::updateProbeRadiance(LLReflectionMap* probe)
+{
+ LL_PROFILE_GPU_ZONE("probe radiance gen");
+ static LLStaticHashedString sMipLevel("mipLevel");
+ static LLStaticHashedString sRoughness("roughness");
+ static LLStaticHashedString sWidth("u_width");
+
+ S32 sourceIdx = mReflectionProbeCount;
+
+ if (probe != mUpdatingProbe)
+ { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel
+ sourceIdx += 1;
+ }
+
+ gGL.setColorMask(true, false);
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+
+ static LLStaticHashedString sSourceIdx("sourceIdx");
+
+ //LL_RECORD_BLOCK_TIME(FTM_RENDER_RADIANCE);
+
+ mMipChain[0].bindTarget("radiance", 0);
+ mMipChain[0].clear();
+
+ gRadianceGenProgram.bind();
+ mVertexBuffer->setBuffer();
#if GL_VERSION_4_0
S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
@@ -855,22 +1108,19 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, 1.f);
+ gRadianceGenProgram.uniform1i(sWidth, mProbeResolution);
U32 res = mMipChain[0].getWidth();
for (int i = 0; i < mMipChain.size(); ++i)
{
- LL_PROFILE_GPU_ZONE("probe radiance gen");
- static LLStaticHashedString sMipLevel("mipLevel");
- static LLStaticHashedString sRoughness("roughness");
- static LLStaticHashedString sWidth("u_width");
+ glViewport(0, 0, res, res);
- gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
gRadianceGenProgram.uniform1f(sMipLevel, (GLfloat)i);
- gRadianceGenProgram.uniform1i(sWidth, mProbeResolution);
+ gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
for (int cf = 0; cf < 6; ++cf)
- { // for each cube face
+ {
LLCoordFrame frame;
frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]);
@@ -883,70 +1133,18 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
#if GL_VERSION_4_0
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
#endif
+ LOG_GLERROR("glCopyTexSubImage3D");
}
if (i != mMipChain.size() - 1)
{
res /= 2;
- glViewport(0, 0, res, res);
}
- }
+ }
gRadianceGenProgram.unbind();
- }
- else
- {
- //generate irradiance map
- gIrradianceGenProgram.bind();
-#if GL_VERSION_4_0
- S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
- mTexture->bind(channel);
-#endif
-
- gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
- gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
-
- mVertexBuffer->setBuffer();
- int start_mip = 0;
- // find the mip target to start with based on irradiance map resolution
- for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip)
- {
- if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION)
- {
- break;
- }
- }
-
- //for (int i = start_mip; i < mMipChain.size(); ++i)
- {
- int i = start_mip;
- LL_PROFILE_GPU_ZONE("probe irradiance gen");
- glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight());
- for (int cf = 0; cf < 6; ++cf)
- { // for each cube face
- LLCoordFrame frame;
- frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]);
-
- F32 mat[16];
- frame.getOpenGLRotation(mat);
- gGL.loadMatrix(mat);
-
- mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
-
- S32 res = mMipChain[i].getWidth();
-#if GL_VERSION_4_0
- mIrradianceMaps->bind(channel);
- glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
- mTexture->bind(channel);
-#endif
- }
- }
- }
-
- mMipChain[0].flush();
-
- gIrradianceGenProgram.unbind();
- }
+ mMipChain[0].flush();
+ //mTexture->unbind();
}
void LLReflectionMapManager::reset()
@@ -1021,61 +1219,20 @@ void LLReflectionMapManager::updateUniforms()
}
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ LL_PROFILE_GPU_ZONE("rmmu - uniforms")
- // 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;
}
@@ -1095,7 +1252,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)
{
@@ -1121,7 +1282,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;
}
}
}
@@ -1134,7 +1295,7 @@ void LLReflectionMapManager::updateUniforms()
{
if (refmap->mViewerObject && refmap->mViewerObject->getVolume())
{ // have active manual probes live-track the object they're associated with
- LLVOVolume* vobj = (LLVOVolume*)refmap->mViewerObject;
+ LLVOVolume* vobj = (LLVOVolume*)refmap->mViewerObject.get();
refmap->mOrigin.load3(vobj->getPositionAgent().mV);
@@ -1149,23 +1310,23 @@ 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(
+ mProbeData.refParams[count].set(
llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale
radscale, // radiance scale
refmap->mFadeIn, // fade in weight
@@ -1192,7 +1353,7 @@ void LLReflectionMapManager::updateUniforms()
}
// this neighbor may be sampled
- rpd.refNeighbor[ni++] = idx;
+ mProbeData.refNeighbor[ni++] = idx;
neighbor_count++;
if (neighbor_count >= max_neighbors)
@@ -1205,11 +1366,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;
@@ -1247,19 +1408,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);
@@ -1268,7 +1429,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);
}
@@ -1402,12 +1563,15 @@ void LLReflectionMapManager::renderDebug()
void LLReflectionMapManager::initReflectionMaps()
{
- U32 count = LL_MAX_REFLECTION_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)
+
+ bool shouldInit = mTexture.isNull() || mReflectionProbeCount != mDynamicProbeCount || mProbeResolution != probe_resolution || mReset;
+
+ if (shouldInit)
{
+ //LL_WARNS() << "====== initReflectionMaps() =======" << LL_ENDL;
+
if(mProbeResolution != probe_resolution)
{
mRenderTarget.release();
@@ -1415,9 +1579,8 @@ void LLReflectionMapManager::initReflectionMaps()
}
gEXRImage = nullptr;
-
mReset = false;
- mReflectionProbeCount = count;
+ mReflectionProbeCount = mDynamicProbeCount;
mProbeResolution = probe_resolution;
mMaxProbeLOD = log2f((F32)mProbeResolution) - 1.f; // number of mips - 1
@@ -1425,15 +1588,25 @@ void LLReflectionMapManager::initReflectionMaps()
mTexture->getWidth() != mProbeResolution ||
mReflectionProbeCount + 2 != mTexture->getCount())
{
- mTexture = new LLCubeMapArray();
-
static LLCachedControl<bool> render_hdr(gSavedSettings, "RenderHDREnabled", true);
- // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source)
- mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr);
+ if (mTexture)
+ {
+ mTexture = new LLCubeMapArray(*mTexture, mProbeResolution, mReflectionProbeCount + 2);
- mIrradianceMaps = new LLCubeMapArray();
- mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false, render_hdr);
+ mIrradianceMaps = new LLCubeMapArray(*mIrradianceMaps, LL_IRRADIANCE_MAP_RESOLUTION, mReflectionProbeCount);
+ }
+ else
+ {
+ mTexture = new LLCubeMapArray();
+
+ // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation
+ // source)
+ mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr);
+
+ mIrradianceMaps = new LLCubeMapArray();
+ mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false, render_hdr);
+ }
}
// reset probe state
@@ -1448,11 +1621,14 @@ void LLReflectionMapManager::initReflectionMaps()
for (auto& probe : mProbes)
{
probe->mLastUpdateTime = 0.f;
+ probe->mNextUpdateTime = 0.f;
probe->mComplete = false;
+ probe->mCompletedCount = 0;
probe->mProbeIndex = -1;
probe->mCubeArray = nullptr;
probe->mCubeIndex = -1;
probe->mNeighbors.clear();
+ probe->mFadeIn = 0;
}
mCubeFree.clear();
@@ -1473,6 +1649,9 @@ void LLReflectionMapManager::initReflectionMaps()
mDefaultProbe->mRadius = 4096.f;
mDefaultProbe->mProbeIndex = 0;
mDefaultProbe->mComplete = default_complete;
+ mDefaultProbe->mCompletedCount = 0;
+ mDefaultProbe->mLastUpdateTime = 0.f;
+ mDefaultProbe->mNextUpdateTime = 0.f;
touch_default_probe(mDefaultProbe);
}