From 7a9cdf2b52ca95c8e269e2bb4ed01379b76434d6 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 15 Feb 2024 09:38:29 -0800 Subject: #682 Do conservative updates on probes. --- indra/newview/llheroprobemanager.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 2a81919856..1f050a5166 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -155,6 +155,25 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); + + // Collect the list of faces that need updating based upon the camera's rotation. + LLVector3 cam_direction = LLVector3(0, 0, -1) * LLViewerCamera::instance().getQuaternion(); + + static LLVector3 cubeFaces[6] = { + LLVector3(1, 0, 0), + LLVector3(-1, 0, 0), + LLVector3(0, 1, 0), + LLVector3(0, -1, 0), + LLVector3(0, 0, 1), + LLVector3(0, 0, -1) + }; + + for (int i = 0; i < 6; i++) + { + bool shouldUpdate = (cam_direction * cubeFaces[i]) > 0; + + mFaceUpdateList[i] = shouldUpdate; + } } else { @@ -185,7 +204,8 @@ void LLHeroProbeManager::update() { for (U32 i = 0; i < 6; ++i) { - updateProbeFace(mProbes[j], i, near_clip); + if (mFaceUpdateList[i]) + updateProbeFace(mProbes[j], i, near_clip); } } mRenderingMirror = false; -- cgit v1.2.3 From 8cea28511448eb750561252f202f96ae815e37f8 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 20 Feb 2024 18:21:45 -0800 Subject: #682 Separate out the radiance gen. --- indra/newview/llheroprobemanager.cpp | 45 ++++++++++++------------------------ 1 file changed, 15 insertions(+), 30 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 1f050a5166..929364be44 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -157,7 +157,7 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); // Collect the list of faces that need updating based upon the camera's rotation. - LLVector3 cam_direction = LLVector3(0, 0, -1) * LLViewerCamera::instance().getQuaternion(); + LLVector3 cam_direction = LLVector3(-1, -1, -1) * LLViewerCamera::instance().getQuaternion(); static LLVector3 cubeFaces[6] = { LLVector3(1, 0, 0), @@ -207,6 +207,7 @@ void LLHeroProbeManager::update() if (mFaceUpdateList[i]) updateProbeFace(mProbes[j], i, near_clip); } + generateRadiance(mProbes[j]); } mRenderingMirror = false; @@ -262,30 +263,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; - - // perform a gaussian blur on the super sampled render before downsampling - { - gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); - S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); - - // horizontal - gGaussianProgram.uniform2f(direction, 1.f, 0.f); - gGL.getTexUnit(diffuseChannel)->bind(screen_rt); - mRenderTarget.bindTarget(); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - mRenderTarget.flush(); - - // vertical - gGaussianProgram.uniform2f(direction, 0.f, 1.f); - gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); - screen_rt->bindTarget(); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - screen_rt->flush(); - gGaussianProgram.unbind(); - } S32 mips = log2((F32)mProbeResolution) + 0.5f; @@ -338,14 +315,22 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gGL.getTexUnit(diffuseChannel)->unbind(LLTexUnit::TT_TEXTURE); gReflectionMipProgram.unbind(); } +} - if (face == 5) +void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) +{ + S32 sourceIdx = mReflectionProbeCount; + + // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. + sourceIdx += 1; { mMipChain[0].bindTarget(); static LLStaticHashedString sSourceIdx("sourceIdx"); { - //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) + + + // generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) gHeroRadianceGenProgram.bind(); mVertexBuffer->setBuffer(); @@ -354,10 +339,10 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gHeroRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, mHeroProbeStrength); - + U32 res = mMipChain[0].getWidth(); - for (int i = 0; i < mMipChain.size(); ++i) + for (int i = 0; i < mMipChain.size() / 4; ++i) { LL_PROFILE_GPU_ZONE("probe radiance gen"); static LLStaticHashedString sMipLevel("mipLevel"); @@ -371,7 +356,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gHeroRadianceGenProgram.uniform1f(sStrength, 1); for (int cf = 0; cf < 6; ++cf) - { // for each cube face + { // for each cube face LLCoordFrame frame; frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); -- cgit v1.2.3 From e68735ad3a6da635a447eb9ed1981e5c360fd2f2 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 21 Feb 2024 11:51:46 -0800 Subject: #682 Add an update rate parameter to help throttle mirror updates. So far 4 seems like a good balance for performance and quality. 2 is great for quality, with 6 or 8 being for higher performance. Also bring back the gaussian filter - may end up adding the FXAA filter though instead. --- indra/newview/llheroprobemanager.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 929364be44..0d9efb860a 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -264,6 +264,30 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; + // perform a gaussian blur on the super sampled render before downsampling + { + gGaussianProgram.bind(); + gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); + S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + + // horizontal + gGaussianProgram.uniform2f(direction, 1.f, 0.f); + gGL.getTexUnit(diffuseChannel)->bind(screen_rt); + mRenderTarget.bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + mRenderTarget.flush(); + + // vertical + gGaussianProgram.uniform2f(direction, 0.f, 1.f); + gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); + screen_rt->bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + screen_rt->flush(); + gGaussianProgram.unbind(); + } + S32 mips = log2((F32)mProbeResolution) + 0.5f; gReflectionMipProgram.bind(); -- cgit v1.2.3 From 320258729757e9ef14e9509c22eca1ce6a0da856 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sun, 25 Feb 2024 22:52:23 -0800 Subject: #682 Add a low priority path for conservative probe face updates. This will update the "low priority" faces at half of the the probe update rate. Useful for less planar reflection geometry. --- indra/newview/llheroprobemanager.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 0d9efb860a..f350b28bf5 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -114,7 +114,7 @@ void LLHeroProbeManager::update() for (auto vo : mHeroVOList) { - if (vo && !vo->isDead()) + if (vo && (!vo->isDead() || vo != nullptr)) { if (vo->mDrawable.notNull()) { @@ -135,7 +135,7 @@ void LLHeroProbeManager::update() unregisterViewerObject(vo); } } - + if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); @@ -205,7 +205,16 @@ void LLHeroProbeManager::update() for (U32 i = 0; i < 6; ++i) { if (mFaceUpdateList[i]) + { updateProbeFace(mProbes[j], i, near_clip); + } + else + { + if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) { + updateProbeFace(mProbes[j], i, near_clip); + mCurrentProbeUpdateFrame = 0; + } + } } generateRadiance(mProbes[j]); } @@ -213,6 +222,8 @@ void LLHeroProbeManager::update() gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; } + + mCurrentProbeUpdateFrame++; } // Do the reflection map update render passes. @@ -568,21 +579,25 @@ void LLHeroProbeManager::doOcclusion() } } -void LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) +bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) { llassert(drawablep != nullptr); - if (mHeroVOList.find(drawablep) == mHeroVOList.end()) + if (std::find(mHeroVOList.begin(), mHeroVOList.end(), drawablep) == mHeroVOList.end()) { // Probe isn't in our list for consideration. Add it. - mHeroVOList.insert(drawablep); + mHeroVOList.push_back(drawablep); + return true; } + + return false; } void LLHeroProbeManager::unregisterViewerObject(LLVOVolume* drawablep) { - if (mHeroVOList.find(drawablep) != mHeroVOList.end()) + std::vector::iterator found_itr = std::find(mHeroVOList.begin(), mHeroVOList.end(), drawablep); + if (found_itr != mHeroVOList.end()) { - mHeroVOList.erase(drawablep); + mHeroVOList.erase(found_itr); } } -- cgit v1.2.3 From 2ba5449b8b888b64ed87ef801426f7eab6e0be95 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sun, 25 Feb 2024 23:38:11 -0800 Subject: #889 Start removing mDrawable references. These may be null. --- indra/newview/llheroprobemanager.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index f350b28bf5..feb81394cf 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -116,18 +116,11 @@ void LLHeroProbeManager::update() { if (vo && (!vo->isDead() || vo != nullptr)) { - if (vo->mDrawable.notNull()) + float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec(); + if (distance < last_distance) { - if (vo->mDrawable->mDistanceWRTCamera < last_distance) - { - mNearestHero = vo; - last_distance = vo->mDrawable->mDistanceWRTCamera; - } - } - else - { - // Valid drawables only please. Unregister this one. - unregisterViewerObject(vo); + mNearestHero = vo; + last_distance = distance; } } else @@ -136,12 +129,12 @@ void LLHeroProbeManager::update() } } - if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) + if (mNearestHero != nullptr && !mNearestHero->isDead()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); LLVector3 face_normal = LLVector3(0, 0, 1); - face_normal *= mNearestHero->mDrawable->getXform()->getWorldRotation(); + face_normal *= mNearestHero->getWorldRotation(); face_normal.normalize(); LLVector3 offset = camera_pos - hero_pos; @@ -210,7 +203,8 @@ void LLHeroProbeManager::update() } else { - if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) { + if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) + { updateProbeFace(mProbes[j], i, near_clip); mCurrentProbeUpdateFrame = 0; } @@ -352,6 +346,9 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n } } +// Separate out radiance generation as a separate stage. +// This is to better enable independent control over how we generate radiance vs. having it coupled with processing the final face of the probe. +// Useful when we may not always be rendering a full set of faces of the probe. void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) { S32 sourceIdx = mReflectionProbeCount; -- cgit v1.2.3 From 1b8523a7b6293db89b16ca8e08330969cf1d9166 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 26 Feb 2024 00:30:44 -0800 Subject: #890 Make sure we're doing the correct distance check. #682 Improve the conservative update functionality for mirror faces. Make it attenuate depending on how much the camera is facing that specific cubemap face. --- indra/newview/llheroprobemanager.cpp | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index feb81394cf..3adf460432 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -114,7 +114,7 @@ void LLHeroProbeManager::update() for (auto vo : mHeroVOList) { - if (vo && (!vo->isDead() || vo != nullptr)) + if (vo && !vo->isDead() && vo->mDrawable.notNull()) { float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec(); if (distance < last_distance) @@ -129,12 +129,12 @@ void LLHeroProbeManager::update() } } - if (mNearestHero != nullptr && !mNearestHero->isDead()) + if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); LLVector3 face_normal = LLVector3(0, 0, 1); - - face_normal *= mNearestHero->getWorldRotation(); + + face_normal *= mNearestHero->mDrawable->getWorldRotation(); face_normal.normalize(); LLVector3 offset = camera_pos - hero_pos; @@ -150,7 +150,7 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); // Collect the list of faces that need updating based upon the camera's rotation. - LLVector3 cam_direction = LLVector3(-1, -1, -1) * LLViewerCamera::instance().getQuaternion(); + LLVector3 cam_direction = LLVector3(0, 0, 1) * LLViewerCamera::instance().getQuaternion(); static LLVector3 cubeFaces[6] = { LLVector3(1, 0, 0), @@ -163,9 +163,11 @@ void LLHeroProbeManager::update() for (int i = 0; i < 6; i++) { - bool shouldUpdate = (cam_direction * cubeFaces[i]) > 0; - - mFaceUpdateList[i] = shouldUpdate; + float shouldUpdate = cam_direction * cubeFaces[i] * 0.5 + 0.5; + + int updateRate = fmaxf(1, (1 - shouldUpdate) * 8); + + mFaceUpdateList[i] = updateRate; } } else @@ -197,17 +199,10 @@ void LLHeroProbeManager::update() { for (U32 i = 0; i < 6; ++i) { - if (mFaceUpdateList[i]) + if (mFaceUpdateList[i] > 0 && mCurrentProbeUpdateFrame % mFaceUpdateList[i] == 0) { updateProbeFace(mProbes[j], i, near_clip); - } - else - { - if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) - { - updateProbeFace(mProbes[j], i, near_clip); - mCurrentProbeUpdateFrame = 0; - } + mCurrentProbeUpdateFrame = 0; } } generateRadiance(mProbes[j]); -- cgit v1.2.3 From 8c79297a8957fec13fadd2a2932b4b03b148d5a5 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 26 Feb 2024 01:21:41 -0800 Subject: #682 Further tweak the conservative update mechanism. --- indra/newview/llheroprobemanager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/newview/llheroprobemanager.cpp') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 3adf460432..a00b6d6b5d 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -165,7 +165,12 @@ void LLHeroProbeManager::update() { float shouldUpdate = cam_direction * cubeFaces[i] * 0.5 + 0.5; - int updateRate = fmaxf(1, (1 - shouldUpdate) * 8); + int updateRate = ceilf((1 - shouldUpdate) * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); + + // Chances are this is a face that's non-visible to the camera when it's being reflected. + // Set it to 0. It will be skipped below. + if (updateRate == gPipeline.RenderHeroProbeConservativeUpdateMultiplier) + updateRate = 0; mFaceUpdateList[i] = updateRate; } -- cgit v1.2.3