From 4ff1cbfbfffe17edbbf4e3b5a6c3984a0618c7ad Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 10 Jan 2025 20:13:21 +0200 Subject: #3316 Crash in LLReflectionMap::getIsDynamic() --- indra/newview/llreflectionmap.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'indra/newview/llreflectionmap.cpp') diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index f77d37f821..1196d138e9 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -65,8 +65,9 @@ void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 n } F32 clip = (near_clip > 0) ? near_clip : getNearClip(); + bool dynamic = force_dynamic || getIsDynamic(); - gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic, useClipPlane, clipPlane); + gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, dynamic, useClipPlane, clipPlane); } void LLReflectionMap::autoAdjustOrigin() @@ -185,7 +186,7 @@ void LLReflectionMap::autoAdjustOrigin() } } -bool LLReflectionMap::intersects(LLReflectionMap* other) +bool LLReflectionMap::intersects(LLReflectionMap* other) const { LLVector4a delta; delta.setSub(other->mOrigin, mOrigin); @@ -201,24 +202,24 @@ bool LLReflectionMap::intersects(LLReflectionMap* other) extern LLControlGroup gSavedSettings; -F32 LLReflectionMap::getAmbiance() +F32 LLReflectionMap::getAmbiance() const { F32 ret = 0.f; - if (mViewerObject && mViewerObject->getVolume()) + if (mViewerObject && mViewerObject->getVolumeConst()) { - ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeAmbiance(); + ret = mViewerObject->getReflectionProbeAmbiance(); } return ret; } -F32 LLReflectionMap::getNearClip() +F32 LLReflectionMap::getNearClip() const { const F32 MINIMUM_NEAR_CLIP = 0.1f; F32 ret = 0.f; - if (mViewerObject && mViewerObject->getVolume()) + if (mViewerObject && mViewerObject->getVolumeConst()) { ret = mViewerObject->getReflectionProbeNearClip(); } @@ -234,11 +235,13 @@ F32 LLReflectionMap::getNearClip() return llmax(ret, MINIMUM_NEAR_CLIP); } -bool LLReflectionMap::getIsDynamic() +bool LLReflectionMap::getIsDynamic() const { - if (gSavedSettings.getS32("RenderReflectionProbeDetail") > (S32) LLReflectionMapManager::DetailLevel::STATIC_ONLY && + static LLCachedControl detail(gSavedSettings, "RenderReflectionProbeDetail", 1); + if (detail() > (S32)LLReflectionMapManager::DetailLevel::STATIC_ONLY && mViewerObject && - mViewerObject->getVolume()) + !mViewerObject->isDead() && + mViewerObject->getVolumeConst()) { return mViewerObject->getReflectionProbeIsDynamic(); } @@ -278,12 +281,12 @@ bool LLReflectionMap::getBox(LLMatrix4& box) return false; } -bool LLReflectionMap::isActive() +bool LLReflectionMap::isActive() const { return mCubeIndex != -1; } -bool LLReflectionMap::isRelevant() +bool LLReflectionMap::isRelevant() const { static LLCachedControl RenderReflectionProbeLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); -- cgit v1.3 From 4763195e186f8c56c2ee92d4e0154c95aa011997 Mon Sep 17 00:00:00 2001 From: Rye Date: Thu, 23 Jan 2025 18:40:19 -0500 Subject: Fix potential undefined behavior when converting to and from glm types from LLVector3/4 and fall back mul_mat4_vec3 to scalar implementation to attempt crash mitigation (#3339) --- indra/llmath/llvector4a.h | 13 ++++++++ indra/llmath/v3math.h | 51 ++++++++++++++++++++++++++++++ indra/llmath/v4math.h | 51 ++++++++++++++++++++++++++++++ indra/llrender/llrender.cpp | 22 +++++++------ indra/newview/gltfscenemanager.cpp | 4 +-- indra/newview/llgltfmaterialpreviewmgr.cpp | 4 +-- indra/newview/llhudrender.cpp | 2 +- indra/newview/llpanelprimmediacontrols.cpp | 4 +-- indra/newview/llreflectionmap.cpp | 2 +- indra/newview/llsettingsvo.cpp | 4 +-- indra/newview/llviewercamera.cpp | 4 +-- indra/newview/llvoavatar.cpp | 10 +++--- indra/newview/pipeline.cpp | 30 ++++++++---------- 13 files changed, 157 insertions(+), 44 deletions(-) (limited to 'indra/newview/llreflectionmap.cpp') diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h index 8ef560dadf..4004852e06 100644 --- a/indra/llmath/llvector4a.h +++ b/indra/llmath/llvector4a.h @@ -33,6 +33,9 @@ class LLRotation; #include #include "llpreprocessor.h" #include "llmemory.h" +#include "glm/vec3.hpp" +#include "glm/vec4.hpp" +#include "glm/gtc/type_ptr.hpp" /////////////////////////////////// // FIRST TIME USERS PLEASE READ @@ -364,6 +367,16 @@ public: inline operator LLQuad() const; + explicit inline operator glm::vec3() const + { + return glm::make_vec3(getF32ptr()); + }; + + explicit inline operator glm::vec4() const + { + return glm::make_vec4(getF32ptr()); + }; + private: LLQuad mQ{}; }; diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index d063b15c74..a3bfa68060 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -31,6 +31,11 @@ #include "llmath.h" #include "llsd.h" + +#include "glm/vec3.hpp" +#include "glm/vec4.hpp" +#include "glm/gtc/type_ptr.hpp" + class LLVector2; class LLVector4; class LLVector4a; @@ -66,6 +71,11 @@ class LLVector3 explicit LLVector3(const LLVector4a& vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2]) explicit LLVector3(const LLSD& sd); + // GLM interop + explicit LLVector3(const glm::vec3& vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) + explicit LLVector3(const glm::vec4& vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) + explicit inline operator glm::vec3() const; // Initializes glm::vec3 to (vec[0]. vec[1], vec[2]) + explicit inline operator glm::vec4() const; // Initializes glm::vec4 to (vec[0]. vec[1], vec[2], 1) LLSD getValue() const; @@ -92,6 +102,8 @@ class LLVector3 inline void set(const F32 *vec); // Sets LLVector3 to vec const LLVector3& set(const LLVector4 &vec); const LLVector3& set(const LLVector3d &vec);// Sets LLVector3 to vec + inline void set(const glm::vec4& vec); // Sets LLVector3 to vec + inline void set(const glm::vec3& vec); // Sets LLVector3 to vec inline void setVec(F32 x, F32 y, F32 z); // deprecated inline void setVec(const LLVector3 &vec); // deprecated @@ -190,6 +202,20 @@ inline LLVector3::LLVector3(const F32 *vec) mV[VZ] = vec[VZ]; } +inline LLVector3::LLVector3(const glm::vec3& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; +} + +inline LLVector3::LLVector3(const glm::vec4& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; +} + /* inline LLVector3::LLVector3(const LLVector3 ©) { @@ -259,6 +285,20 @@ inline void LLVector3::set(const F32 *vec) mV[2] = vec[2]; } +inline void LLVector3::set(const glm::vec4& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; +} + +inline void LLVector3::set(const glm::vec3& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; +} + // deprecated inline void LLVector3::setVec(F32 x, F32 y, F32 z) { @@ -471,6 +511,17 @@ inline LLVector3 operator-(const LLVector3 &a) return LLVector3( -a.mV[0], -a.mV[1], -a.mV[2] ); } +inline LLVector3::operator glm::vec3() const +{ + // Do not use glm::make_vec3 it can result in a buffer overrun on some platforms due to glm::vec3 being a simd vector internally + return glm::vec3(mV[VX], mV[VY], mV[VZ]); +} + +inline LLVector3::operator glm::vec4() const +{ + return glm::vec4(mV[VX], mV[VY], mV[VZ], 1.f); +} + inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b) { F32 x = a.mV[0] - b.mV[0]; diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h index a5b6f506d7..a4c9668fdd 100644 --- a/indra/llmath/v4math.h +++ b/indra/llmath/v4math.h @@ -32,6 +32,10 @@ #include "v3math.h" #include "v2math.h" +#include "glm/vec3.hpp" +#include "glm/vec4.hpp" +#include "glm/gtc/type_ptr.hpp" + class LLMatrix3; class LLMatrix4; class LLQuaternion; @@ -73,6 +77,11 @@ class LLVector4 mV[3] = (F32)sd[3].asReal(); } + // GLM interop + explicit LLVector4(const glm::vec3& vec); // Initializes LLVector4 to (vec, 1) + explicit LLVector4(const glm::vec4& vec); // Initializes LLVector4 to vec + explicit operator glm::vec3() const; // Initializes glm::vec3 to (vec[0]. vec[1], vec[2]) + explicit operator glm::vec4() const; // Initializes glm::vec4 to (vec[0]. vec[1], vec[2], vec[3]) inline bool isFinite() const; // checks to see if all values of LLVector3 are finite @@ -85,6 +94,8 @@ class LLVector4 inline void set(const LLVector4 &vec); // Sets LLVector4 to vec inline void set(const LLVector3 &vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec inline void set(const F32 *vec); // Sets LLVector4 to vec + inline void set(const glm::vec4& vec); // Sets LLVector4 to vec + inline void set(const glm::vec3& vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec with w defaulted to 1 inline void setVec(F32 x, F32 y, F32 z); // deprecated inline void setVec(F32 x, F32 y, F32 z, F32 w); // deprecated @@ -223,6 +234,21 @@ inline LLVector4::LLVector4(const LLSD &sd) setValue(sd); } +inline LLVector4::LLVector4(const glm::vec3& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; + mV[VW] = 1.f; +} + +inline LLVector4::LLVector4(const glm::vec4& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; + mV[VW] = vec.w; +} inline bool LLVector4::isFinite() const { @@ -297,6 +323,21 @@ inline void LLVector4::set(const F32 *vec) mV[VW] = vec[VW]; } +inline void LLVector4::set(const glm::vec4& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; + mV[VW] = vec.w; +} + +inline void LLVector4::set(const glm::vec3& vec, F32 w) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; + mV[VW] = w; +} // deprecated inline void LLVector4::setVec(F32 x, F32 y, F32 z) @@ -466,6 +507,16 @@ inline LLVector4 operator-(const LLVector4 &a) return LLVector4( -a.mV[VX], -a.mV[VY], -a.mV[VZ] ); } +inline LLVector4::operator glm::vec3() const +{ + return glm::vec3(mV[VX], mV[VY], mV[VZ]); +} + +inline LLVector4::operator glm::vec4() const +{ + return glm::make_vec4(mV); +} + inline F32 dist_vec(const LLVector4 &a, const LLVector4 &b) { LLVector4 vec = a - b; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 1d53850f74..1dc87a66ce 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -737,9 +737,8 @@ void LLLightState::setPosition(const LLVector4& position) ++gGL.mLightHash; mPosition = position; //transform position by current modelview matrix - glm::vec4 pos(glm::make_vec4(position.mV)); - const glm::mat4& mat = gGL.getModelviewMatrix(); - pos = mat * pos; + glm::vec4 pos(position); + pos = gGL.getModelviewMatrix() * pos; mPosition.set(glm::value_ptr(pos)); } @@ -794,7 +793,7 @@ void LLLightState::setSpotDirection(const LLVector3& direction) ++gGL.mLightHash; //transform direction by current modelview matrix - glm::vec3 dir(glm::make_vec3(direction.mV)); + glm::vec3 dir(direction); const glm::mat3 mat(gGL.getModelviewMatrix()); dir = mat * dir; @@ -2088,12 +2087,14 @@ void set_last_projection(const glm::mat4& mat) glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec) { - //const float w = vec[0] * mat[0][3] + vec[1] * mat[1][3] + vec[2] * mat[2][3] + mat[3][3]; - //return glm::vec3( - // (vec[0] * mat[0][0] + vec[1] * mat[1][0] + vec[2] * mat[2][0] + mat[3][0]) / w, - // (vec[0] * mat[0][1] + vec[1] * mat[1][1] + vec[2] * mat[2][1] + mat[3][1]) / w, - // (vec[0] * mat[0][2] + vec[1] * mat[1][2] + vec[2] * mat[2][2] + mat[3][2]) / w - //); +#if 1 // SIMD path results in strange crashes. Fall back to scalar for now. + const float w = vec[0] * mat[0][3] + vec[1] * mat[1][3] + vec[2] * mat[2][3] + mat[3][3]; + return glm::vec3( + (vec[0] * mat[0][0] + vec[1] * mat[1][0] + vec[2] * mat[2][0] + mat[3][0]) / w, + (vec[0] * mat[0][1] + vec[1] * mat[1][1] + vec[2] * mat[2][1] + mat[3][1]) / w, + (vec[0] * mat[0][2] + vec[1] * mat[1][2] + vec[2] * mat[2][2] + mat[3][2]) / w + ); +#else LLVector4a x, y, z, s, t, p, q; x.splat(vec.x); @@ -2123,4 +2124,5 @@ glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec) res.setAdd(x, z); res.div(q); return glm::make_vec3(res.getF32ptr()); +#endif } diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index ed66753267..2d6d9a153e 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -975,9 +975,9 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset) LLVector4a t; agent_to_asset.affineTransform(gDebugRaycastStart, t); - start = glm::make_vec4(t.getF32ptr()); + start = vec4(t); agent_to_asset.affineTransform(gDebugRaycastEnd, t); - end = glm::make_vec4(t.getF32ptr()); + end = vec4(t); start.w = end.w = 1.0; diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index cf6b08797d..da1f1a466f 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -472,9 +472,9 @@ bool LLGLTFPreviewTexture::render() gPipeline.setupHWLights(); glm::mat4 mat = get_current_modelview(); - glm::vec4 transformed_light_dir = glm::make_vec4(light_dir.mV); + glm::vec4 transformed_light_dir(light_dir); transformed_light_dir = mat * transformed_light_dir; - SetTemporarily force_sun_direction_high_graphics(&gPipeline.mTransformedSunDir, LLVector4(glm::value_ptr(transformed_light_dir))); + SetTemporarily force_sun_direction_high_graphics(&gPipeline.mTransformedSunDir, LLVector4(transformed_light_dir)); // Override lights to ensure the sun is always shining from a certain direction (low graphics) // See also force_sun_direction_high_graphics and fixup_shader_constants { diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index 135fba7897..6850e57b94 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -106,7 +106,7 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent, LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); glm::ivec4 viewport(world_view_rect.mLeft, world_view_rect.mBottom, world_view_rect.getWidth(), world_view_rect.getHeight()); - glm::vec3 win_coord = glm::project(glm::make_vec3(render_pos.mV), get_current_modelview(), get_current_projection(), viewport); + glm::vec3 win_coord = glm::project(glm::vec3(render_pos), get_current_modelview(), get_current_projection(), viewport); //fonts all render orthographically, set up projection`` gGL.matrixMode(LLRender::MM_PROJECTION); diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 4db0a5b59d..b8c12ce0b9 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -660,11 +660,11 @@ void LLPanelPrimMediaControls::updateShape() for(; vert_it != vert_end; ++vert_it) { // project silhouette vertices into screen space - glm::vec3 screen_vert(glm::make_vec3(vert_it->mV)); + glm::vec3 screen_vert(*vert_it); screen_vert = mul_mat4_vec3(mat, screen_vert); // add to screenspace bounding box - update_min_max(min, max, LLVector3(glm::value_ptr(screen_vert))); + update_min_max(min, max, LLVector3(screen_vert)); } // convert screenspace bbox to pixels (in screen coords) diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 1196d138e9..f3adb52d5e 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -259,7 +259,7 @@ bool LLReflectionMap::getBox(LLMatrix4& box) glm::mat4 mv(get_current_modelview()); LLVector3 s = mViewerObject->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f)); mRadius = s.magVec(); - glm::mat4 scale = glm::scale(glm::make_vec3(s.mV)); + glm::mat4 scale = glm::scale(glm::vec3(s)); if (mViewerObject->mDrawable != nullptr) { // object to agent space (no scale) diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 6f9d4a24bc..62df6cd275 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -1093,8 +1093,8 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) LLVector4 waterPlane(enorm.x, enorm.y, enorm.z, -glm::dot(ep, enorm)); - norm = glm::make_vec3(gPipeline.mHeroProbeManager.mMirrorNormal.mV); - p = glm::make_vec3(gPipeline.mHeroProbeManager.mMirrorPosition.mV); + norm = glm::vec3(gPipeline.mHeroProbeManager.mMirrorNormal); + p = glm::vec3(gPipeline.mHeroProbeManager.mMirrorPosition); enorm = mul_mat4_vec3(invtrans, norm); enorm = glm::normalize(enorm); ep = mul_mat4_vec3(mat, p); diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index aa43b2dbad..7d777162ed 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -420,7 +420,7 @@ bool LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); glm::ivec4 viewport(world_view_rect.mLeft, world_view_rect.mBottom, world_view_rect.getWidth(), world_view_rect.getHeight()); - glm::vec3 win_coord = glm::project(glm::make_vec3(pos_agent.mV), get_current_modelview(), get_current_projection(), viewport); + glm::vec3 win_coord = glm::project(glm::vec3(pos_agent), get_current_modelview(), get_current_projection(), viewport); { // convert screen coordinates to virtual UI coordinates @@ -514,7 +514,7 @@ bool LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); glm::ivec4 viewport(world_view_rect.mLeft, world_view_rect.mBottom, world_view_rect.getWidth(), world_view_rect.getHeight()); - glm::vec3 win_coord = glm::project(glm::make_vec3(pos_agent.mV), get_current_modelview(), get_current_projection(), viewport); + glm::vec3 win_coord = glm::project(glm::vec3(pos_agent), get_current_modelview(), get_current_projection(), viewport); { win_coord.x /= gViewerWindow->getDisplayScale().mV[VX]; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7bc9d06f9a..7bf9c88b99 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1928,8 +1928,8 @@ bool LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& glm::mat4 inverse = glm::inverse(mat); glm::mat4 norm_mat = glm::transpose(inverse); - glm::vec3 p1(glm::make_vec3(start.getF32ptr())); - glm::vec3 p2(glm::make_vec3(end.getF32ptr())); + glm::vec3 p1(start); + glm::vec3 p2(end); p1 = mul_mat4_vec3(inverse, p1); p2 = mul_mat4_vec3(inverse, p2); @@ -1937,12 +1937,12 @@ bool LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& LLVector3 position; LLVector3 norm; - if (linesegment_sphere(LLVector3(glm::value_ptr(p1)), LLVector3(glm::value_ptr(p2)), LLVector3(0,0,0), 1.f, position, norm)) + if (linesegment_sphere(LLVector3(p1), LLVector3(p2), LLVector3(0,0,0), 1.f, position, norm)) { - glm::vec3 res_pos(glm::make_vec3(position.mV)); + glm::vec3 res_pos(position); res_pos = mul_mat4_vec3(mat, res_pos); - glm::vec3 res_norm(glm::make_vec3(norm.mV)); + glm::vec3 res_norm(norm); res_norm = glm::normalize(res_norm); res_norm = glm::mat3(norm_mat) * res_norm; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c6e6c454de..f91b054dd7 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8396,13 +8396,13 @@ void LLPipeline::renderDeferredLighting() setupHWLights(); // to set mSun/MoonDir; - glm::vec4 tc(glm::make_vec4(mSunDir.mV)); + glm::vec4 tc(mSunDir); tc = mat * tc; - mTransformedSunDir.set(glm::value_ptr(tc)); + mTransformedSunDir.set(tc); - glm::vec4 tc_moon(glm::make_vec4(mMoonDir.mV)); + glm::vec4 tc_moon(mMoonDir); tc_moon = mat * tc_moon; - mTransformedMoonDir.set(glm::value_ptr(tc_moon)); + mTransformedMoonDir.set(tc_moon); if ((RenderDeferredSSAO && !gCubeSnapshot) || RenderShadowDetail > 0) { @@ -8655,7 +8655,7 @@ void LLPipeline::renderDeferredLighting() continue; } - glm::vec3 tc(glm::make_vec3(c)); + glm::vec3 tc(center); tc = mul_mat4_vec3(mat, tc); fullscreen_lights.push_back(LLVector4(tc.x, tc.y, tc.z, s)); @@ -8762,13 +8762,12 @@ void LLPipeline::renderDeferredLighting() LLDrawable* drawablep = *iter; LLVOVolume* volume = drawablep->getVOVolume(); LLVector3 center = drawablep->getPositionAgent(); - F32* c = center.mV; F32 light_size_final = volume->getLightRadius() * 1.5f; F32 light_falloff_final = volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF); sVisibleLightCount++; - glm::vec3 tc(glm::make_vec3(c)); + glm::vec3 tc(center); tc = mul_mat4_vec3(mat, tc); setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); @@ -9903,10 +9902,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLVector3 lightDir = -caster_dir; lightDir.normVec(); - glm::vec3 light_dir(glm::make_vec3(lightDir.mV)); - //create light space camera matrix - LLVector3 at = lightDir; LLVector3 up = camera.getAtAxis(); @@ -9958,9 +9954,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera) //get good split distances for frustum for (U32 i = 0; i < fp.size(); ++i) { - glm::vec3 v(glm::make_vec3(fp[i].mV)); + glm::vec3 v(fp[i]); v = mul_mat4_vec3(saved_view, v); - fp[i].setVec(glm::value_ptr(v)); + fp[i] = LLVector3(v); } min = fp[0]; @@ -10109,9 +10105,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera) for (U32 i = 0; i < fp.size(); i++) { - glm::vec3 p = glm::make_vec3(fp[i].mV); + glm::vec3 p(fp[i]); p = mul_mat4_vec3(view[j], p); - wpf.push_back(LLVector3(glm::value_ptr(p))); + wpf.push_back(LLVector3(p)); } min = wpf[0]; @@ -10312,19 +10308,19 @@ void LLPipeline::generateSunShadow(LLCamera& camera) view[j] = glm::inverse(view[j]); //llassert(origin.isFinite()); - glm::vec3 origin_agent(glm::make_vec3(origin.mV)); + glm::vec3 origin_agent(origin); //translate view to origin origin_agent = mul_mat4_vec3(view[j], origin_agent); - eye = LLVector3(glm::value_ptr(origin_agent)); + eye = LLVector3(origin_agent); //llassert(eye.isFinite()); if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) { mShadowFrustOrigin[j] = eye; } - view[j] = look(LLVector3(glm::value_ptr(origin_agent)), lightDir, -up); + view[j] = look(LLVector3(origin_agent), lightDir, -up); F32 fx = 1.f/tanf(fovx); F32 fz = 1.f/tanf(fovz); -- cgit v1.3 From 32c7d3064f04899547ee4dea48969c6ceb8554e9 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 21 Mar 2025 09:33:23 -0400 Subject: Dynamic Probe Allocation (#3787) * #3788 Support dynamic probe allocation. * #3738 Mitigate probe flashing * #3735 Mitigate realtime probes flashing --- .../class1/windlight/atmosphericsFuncs.glsl | 1 + indra/newview/featuretable.txt | 14 +--- indra/newview/featuretable_mac.txt | 10 --- indra/newview/llreflectionmap.cpp | 3 + indra/newview/llreflectionmapmanager.cpp | 86 ++++++++++++++++------ indra/newview/llreflectionmapmanager.h | 11 ++- indra/newview/lltextureview.cpp | 4 +- indra/newview/llviewertexture.cpp | 7 +- .../en/floater_preferences_graphics_advanced.xml | 17 ----- 9 files changed, 87 insertions(+), 66 deletions(-) (limited to 'indra/newview/llreflectionmap.cpp') diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl index 205d4bff6d..5089b9e31e 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl @@ -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); } diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 883963d558..443a7ae914 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -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 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 103d24a26d..dc9473b042 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -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 diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index f3adb52d5e..910509928d 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -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); diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 48b73531ea..34c6034e9e 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -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 probe_count(gSavedSettings, "RenderReflectionProbeCount", 256U); - bool countReset = mReflectionProbeCount != probe_count; + static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); + static LLCachedControl 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 render_hdr(gSavedSettings, "RenderHDREnabled", true); @@ -286,9 +322,6 @@ void LLReflectionMapManager::update() bool did_update = false; - static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); - static LLCachedControl 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 probe_count(gSavedSettings, "RenderReflectionProbeCount", 256U); - U32 count = probe_count(); - static LLCachedControl 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 diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 9f88776ac2..0719c28134 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -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; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 78d930c05c..8560a01c4b 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -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); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 0782192858..4a9dd1c1b6 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -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 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 34ed3fa80d..78d13293a8 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 @@ -858,23 +858,6 @@ value="3"/> - -