From 6b88a2bec27e24debb4eb4fe986850f36f8689a9 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 24 Mar 2025 18:05:06 +0200 Subject: [PATCH 01/14] #3780 disable water exclusion if user applies PBR or Media --- indra/newview/llpanelface.cpp | 5 +---- indra/newview/llselectmgr.cpp | 11 ++++++++++- indra/newview/llselectmgr.h | 1 + indra/newview/llviewerobject.cpp | 25 +++++++++++++++++++++++++ indra/newview/llviewerobject.h | 2 ++ 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index c4f118fed8..b7d9df6ea6 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -3075,10 +3075,7 @@ void LLPanelFace::onCommitHideWater() } else { - // reset texture to default plywood - LLSelectMgr::getInstance()->selectionSetImage(DEFAULT_OBJECT_TEXTURE); - // reset texture repeats, that might be altered by invisiprim script from wiki - LLSelectMgr::getInstance()->selectionTexScaleAutofit(2.f); + LLSelectMgr::getInstance()->clearWaterExclusion(); } } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index b307de787c..cc88d31aee 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1995,7 +1995,7 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) asset_id = BLANK_MATERIAL_ASSET_ID; } } - + objectp->clearTEWaterExclusion(te); // Blank out most override data on the object and send to server objectp->setRenderMaterialID(te, asset_id); @@ -2477,6 +2477,7 @@ void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) } else { // Add/update media + object->clearTEWaterExclusion(te); object->setTEMediaFlags(te, mMediaFlags); LLVOVolume *vo = dynamic_cast(object); llassert(NULL != vo); @@ -7724,6 +7725,14 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom) gAgentCamera.mHUDCurZoom = current_zoom; } +void LLSelectMgr::clearWaterExclusion() +{ + // reset texture to default plywood + LLSelectMgr::getInstance()->selectionSetImage(DEFAULT_OBJECT_TEXTURE); + // reset texture repeats, that might be altered by invisiprim script from wiki + LLSelectMgr::getInstance()->selectionTexScaleAutofit(2.f); +} + ///////////////////////////////////////////////////////////////////////////// // Object selection iterator helpers ///////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index b70ec3dbea..0dbdc133e3 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -836,6 +836,7 @@ public: void getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const; void updatePointAt(); + void clearWaterExclusion(); // Internal list maintenance functions. TODO: Make these private! void remove(std::vector& objects); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 3d88cc5f39..c5e81dd179 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -7682,6 +7682,31 @@ void LLViewerObject::setGLTFAsset(const LLUUID& id) updateVolume(volume_params); } +void LLViewerObject::clearTEWaterExclusion(const U8 te) +{ + if (permModify()) + { + LLViewerTexture* image = getTEImage(te); + if (image && (IMG_ALPHA_GRAD == image->getID())) + { + // reset texture to default plywood + setTEImage(te, LLViewerTextureManager::getFetchedTexture(DEFAULT_OBJECT_TEXTURE, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + + // reset texture repeats, that might be altered by invisiprim script from wiki + U32 s_axis, t_axis; + if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis)) + { + return; + } + F32 DEFAULT_REPEATS = 2.f; + F32 new_s = getScale().mV[s_axis] * DEFAULT_REPEATS; + F32 new_t = getScale().mV[t_axis] * DEFAULT_REPEATS; + + setTEScale(te, new_s, new_t); + sendTEUpdate(); + } + } +} class ObjectPhysicsProperties : public LLHTTPNode { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 63458e60ea..2b52ea2076 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -405,6 +405,8 @@ public: LLViewerTexture *getTENormalMap(const U8 te) const; LLViewerTexture *getTESpecularMap(const U8 te) const; + void clearTEWaterExclusion(const U8 te); + bool isImageAlphaBlended(const U8 te) const; void fitFaceTexture(const U8 face); From 7fc9c0baa430875dce44778d5d72b302858f9f4e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 24 Mar 2025 22:20:53 +0200 Subject: [PATCH 02/14] #3796 Crash at assetRequestCoro Coroutine doesn't own req pointer, don't use it --- indra/llmessage/llassetstorage.cpp | 22 +++++++++------------- indra/llmessage/llassetstorage.h | 3 ++- indra/newview/llviewerassetstorage.cpp | 14 +++++++------- indra/newview/llviewerassetstorage.h | 3 +-- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 2de59c1b6a..10fd56a68e 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -585,7 +585,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, // static void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type, const LLUUID& callback_id, LLAssetType::EType callback_type, - S32 result_code, LLExtStat ext_status) + S32 result_code, LLExtStat ext_status, + S32 bytes_fetched) { // find and callback ALL pending requests for this UUID // SJB: We process the callbacks in reverse order, I do not know if this is important, @@ -598,6 +599,10 @@ void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LL LLAssetRequest* tmp = *curiter; if ((tmp->getUUID() == file_id) && (tmp->getType()== file_type)) { + if (bytes_fetched > 0) + { + tmp->mBytesFetched = bytes_fetched; + } requests.push_front(tmp); iter = gAssetStorage->mPendingDownloads.erase(curiter); } @@ -664,6 +669,7 @@ void LLAssetStorage::downloadCompleteCallback( callback_type = req->getType(); } + S32 bytes_fetched = 0; if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file @@ -677,21 +683,11 @@ void LLAssetStorage::downloadCompleteCallback( } else { -#if 1 - for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin(); - iter != gAssetStorage->mPendingDownloads.end(); ++iter ) - { - LLAssetRequest* dlreq = *iter; - if ((dlreq->getUUID() == file_id) && (dlreq->getType()== file_type)) - { - dlreq->mBytesFetched = vfile.getSize(); - } - } -#endif + bytes_fetched = vfile.getSize(); } } - removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, result, ext_status); + removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, result, ext_status, bytes_fetched); } void LLAssetStorage::getEstateAsset( diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index 88fa572092..6d6526757d 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -324,7 +324,8 @@ public: static void removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type, const LLUUID& callback_id, LLAssetType::EType callback_type, - S32 result_code, LLExtStat ext_status); + S32 result_code, LLExtStat ext_status, + S32 bytes_fetched); // download process callbacks static void downloadCompleteCallback( diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 5ab9f76e47..255cfc998a 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -402,10 +402,10 @@ void LLViewerAssetStorage::queueRequestHttp( manager->enqueueCoprocedure( VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro", - [this, req, uuid, atype, callback, user_data] + [this, uuid, atype, callback, user_data] (LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t&, const LLUUID&) { - assetRequestCoro(req, uuid, atype, callback, user_data); + assetRequestCoro(uuid, atype, callback, user_data); }); } } @@ -440,7 +440,6 @@ struct LLScopedIncrement }; void LLViewerAssetStorage::assetRequestCoro( - LLViewerAssetRequest *req, const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback callback, @@ -464,7 +463,7 @@ void LLViewerAssetStorage::assetRequestCoro( LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL; result_code = LL_ERR_ASSET_REQUEST_FAILED; ext_status = LLExtStat::NONE; - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); return; } else if (!gAgent.getRegion()->capabilitiesReceived()) @@ -495,7 +494,7 @@ void LLViewerAssetStorage::assetRequestCoro( LL_WARNS_ONCE("ViewerAsset") << "asset request fails: caps received but no viewer asset cap found" << LL_ENDL; result_code = LL_ERR_ASSET_REQUEST_FAILED; ext_status = LLExtStat::NONE; - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); return; } std::string url = getAssetURL(mViewerAssetUrl, uuid,atype); @@ -517,6 +516,7 @@ void LLViewerAssetStorage::assetRequestCoro( mCountCompleted++; + S32 bytes_fetched = 0; LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); if (!status) @@ -554,7 +554,7 @@ void LLViewerAssetStorage::assetRequestCoro( LLUUID temp_id; temp_id.generate(); LLFileSystem vf(temp_id, atype, LLFileSystem::WRITE); - req->mBytesFetched = size; + bytes_fetched = size; if (!vf.write(raw.data(),size)) { // TODO asset-http: handle error @@ -583,7 +583,7 @@ void LLViewerAssetStorage::assetRequestCoro( } // Clean up pending downloads and trigger callbacks - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, bytes_fetched); } std::string LLViewerAssetStorage::getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype) diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index fdb8af7457..42dd9d1dd8 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -82,8 +82,7 @@ protected: void capsRecvForRegion(const LLUUID& region_id, std::string pumpname); - void assetRequestCoro(LLViewerAssetRequest *req, - const LLUUID uuid, + void assetRequestCoro(const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback callback, void *user_data); From 5e5d466628f3576bb48b63f143502ea914f79bca Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 24 Mar 2025 17:59:13 -0400 Subject: [PATCH 03/14] Readd probe count setting (#3793) * Readd max probe count. Disable dynamic probe allocation by default (for now). --- indra/llrender/llcubemaparray.cpp | 32 +++++++ indra/llrender/llcubemaparray.h | 2 + indra/newview/app_settings/settings.xml | 11 +++ .../shaders/class3/environment/waterF.glsl | 3 +- indra/newview/featuretable.txt | 10 +++ indra/newview/featuretable_mac.txt | 10 +++ indra/newview/llreflectionmapmanager.cpp | 90 +++++++++++-------- .../floater_preferences_graphics_advanced.xml | 45 ++++++++++ 8 files changed, 165 insertions(+), 38 deletions(-) diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index d0a97dc2c6..998b57217d 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -105,6 +105,36 @@ LLCubeMapArray::LLCubeMapArray() } +LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTextureStage(0) +{ + mWidth = width; + mCount = count; + + // Allocate a new cubemap array with the same criteria as the incoming cubemap array + allocate(mWidth, lhs.mImage->getComponents(), count, lhs.mImage->getUseMipMaps(), lhs.mHDR); + + // Copy each cubemap from the incoming array to the new array + U32 min_count = std::min(count, lhs.mCount); + for (U32 i = 0; i < min_count * 6; ++i) + { + U32 src_resolution = lhs.mWidth; + U32 dst_resolution = mWidth; + { + GLint components = GL_RGB; + if (mImage->getComponents() == 4) + components = GL_RGBA; + GLint format = GL_RGB; + + // Handle different resolutions by scaling the image + LLPointer src_image = new LLImageRaw(lhs.mWidth, lhs.mWidth, lhs.mImage->getComponents()); + glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, components, GL_UNSIGNED_BYTE, src_image->getData()); + + LLPointer scaled_image = src_image->scaled(mWidth, mWidth); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, i, mWidth, mWidth, 1, components, GL_UNSIGNED_BYTE, scaled_image->getData()); + } + } +} + LLCubeMapArray::~LLCubeMapArray() { } @@ -115,6 +145,8 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us mWidth = resolution; mCount = count; + mHDR = hdr; + LLImageGL::generateTextures(1, &texname); mImage = new LLImageGL(resolution, resolution, components, use_mips); diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h index bfc72a321d..6b4288cb23 100644 --- a/indra/llrender/llcubemaparray.h +++ b/indra/llrender/llcubemaparray.h @@ -36,6 +36,7 @@ class LLCubeMapArray : public LLRefCount { public: LLCubeMapArray(); + LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count); static GLenum sTargets[6]; @@ -73,4 +74,5 @@ protected: U32 mWidth = 0; U32 mCount = 0; S32 mTextureStage; + bool mHDR; }; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4ce7e0f729..b7127adc53 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9087,6 +9087,17 @@ Value 1 + RenderReflectionProbeDynamicAllocation + + Comment + Enable dynamic allocation of reflection probes. -1 means no dynamic allocation. Sets a buffer to allocate when a dynamic allocation occurs otherwise. + Persist + 1 + Type + S32 + Value + -1 + RenderReflectionProbeCount Comment diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index 1b7b0c1937..e57aa69731 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -26,6 +26,7 @@ // class3/environment/waterF.glsl #define WATER_MINIMAL 1 +#define SHORELINE_FADE 1 out vec4 frag_color; @@ -264,7 +265,7 @@ void main() // Calculate some distance fade in the water to better assist with refraction blending and reducing the refraction texture's "disconnect". #ifdef SHORELINE_FADE - fade = max(0,min(1, (pos.z - refPos.z) / 10)) + fade = max(0,min(1, (pos.z - refPos.z) / 10)); #else fade = 1 * water_mask; #endif diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 443a7ae914..c0009d24ee 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 32 // // Medium Graphics Settings (standard) @@ -211,6 +214,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 64 // // 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..5940d1ec12 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 32 // // Medium Graphics Settings (standard) @@ -211,6 +214,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 64 // // 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 34c6034e9e..f2abc7b8b7 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -224,48 +224,54 @@ void LLReflectionMapManager::update() static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); + static LLCachedControl sReflectionProbeCount(gSavedSettings, "RenderReflectionProbeCount", 256U); + static LLCachedControl sProbeDynamicAllocation(gSavedSettings, "RenderReflectionProbeDynamicAllocation", -1); + mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f); - // Once every 20 frames, update the dynamic probe count. - if (gFrameCount % 20) { U32 probe_count_temp = mDynamicProbeCount; - if (sLevel == 0) + if (sProbeDynamicAllocation > -1) { - mDynamicProbeCount = 1; - } - else if (sLevel == 1) - { - mDynamicProbeCount = (U32)mProbes.size(); + 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; + } - } - else if (sLevel == 2) - { - mDynamicProbeCount = llmax((U32)mProbes.size(), 128); + if (sProbeDynamicAllocation > 1) + { + // Round mDynamicProbeCount to the nearest increment of 16 + mDynamicProbeCount = ((mDynamicProbeCount + sProbeDynamicAllocation / 2) / sProbeDynamicAllocation) * 16; + mDynamicProbeCount = llclamp(mDynamicProbeCount, 1, sReflectionProbeCount); + } + else + { + mDynamicProbeCount = llclamp(mDynamicProbeCount + sProbeDynamicAllocation, 1, sReflectionProbeCount); + } } else { - mDynamicProbeCount = 256; + mDynamicProbeCount = sReflectionProbeCount; } - // Round mDynamicProbeCount to the nearest increment of 32 - mDynamicProbeCount = ((mDynamicProbeCount + 16) / 32) * 32; - mDynamicProbeCount = llclamp(mDynamicProbeCount, 1, LL_MAX_REFLECTION_PROBE_COUNT); + mDynamicProbeCount = llmin(mDynamicProbeCount, 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; + if (mDynamicProbeCount != probe_count_temp) + mResetFade = 1.f; } - if (mGlobalFadeTarget < mResetFade) - mResetFade = llmax(mGlobalFadeTarget, mResetFade - (F32)gFrameIntervalSeconds * 2); - else - mResetFade = llmin(mGlobalFadeTarget, mResetFade + (F32)gFrameIntervalSeconds * 2); - - if (mResetFade == mGlobalFadeTarget) - { - initReflectionMaps(); - } + initReflectionMaps(); static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); @@ -356,6 +362,7 @@ void LLReflectionMapManager::update() probe->mCubeArray = nullptr; probe->mCubeIndex = -1; probe->mComplete = false; + probe->mFadeIn = 0; } } @@ -1418,8 +1425,6 @@ void LLReflectionMapManager::initReflectionMaps() } gEXRImage = nullptr; - mGlobalFadeTarget = 1.f; - mResetFade = -0.125f; mReset = false; mReflectionProbeCount = mDynamicProbeCount; mProbeResolution = probe_resolution; @@ -1429,15 +1434,25 @@ void LLReflectionMapManager::initReflectionMaps() mTexture->getWidth() != mProbeResolution || mReflectionProbeCount + 2 != mTexture->getCount()) { - mTexture = new LLCubeMapArray(); + if (mTexture) + { + mTexture = new LLCubeMapArray(*mTexture, mProbeResolution, mReflectionProbeCount + 2); - static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); + 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); + static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); - mIrradianceMaps = new LLCubeMapArray(); - mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false, render_hdr); + // 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 @@ -1457,6 +1472,7 @@ void LLReflectionMapManager::initReflectionMaps() probe->mCubeArray = nullptr; probe->mCubeIndex = -1; probe->mNeighbors.clear(); + probe->mFadeIn = 0; } mCubeFree.clear(); 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 78d13293a8..6877ce6411 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,6 +858,51 @@ value="3"/> + + Max Reflection Probes: + + + + + + + + + + Date: Mon, 24 Mar 2025 23:50:34 +0200 Subject: [PATCH 04/14] #3798 Crash at getAvatar() --- indra/newview/llface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 811aacb2ed..373a556f86 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2218,7 +2218,7 @@ bool LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("calcPixelArea - rigged"); //override with joint volume face joint bounding boxes - LLVOAvatar* avatar = mVObjp->getAvatar(); + LLVOAvatar* avatar = mVObjp.notNull() ? mVObjp->getAvatar() : nullptr; bool hasRiggedExtents = false; if (avatar && avatar->mDrawable) From d484fff77d73931e70c896b9a88db547c4922dbd Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Mar 2025 14:30:29 +0200 Subject: [PATCH 05/14] #3596 Don't supress exceptions in WorkQueue We need those to know about problems. --- indra/llcommon/workqueue.cpp | 83 ++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp index 6066e74fb5..dace95aaf2 100644 --- a/indra/llcommon/workqueue.cpp +++ b/indra/llcommon/workqueue.cpp @@ -17,6 +17,7 @@ // std headers // external library headers // other Linden headers +#include "llapp.h" #include "llcoros.h" #include LLCOROS_MUTEX_HEADER #include "llerror.h" @@ -102,19 +103,95 @@ std::string LL::WorkQueueBase::makeName(const std::string& name) return STRINGIZE("WorkQueue" << num); } +namespace +{ +#if LL_WINDOWS + + static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific + + U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop) + { + if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop)) + { + // Handled + return EXCEPTION_CONTINUE_SEARCH; + } + else if (code == STATUS_MSC_EXCEPTION) + { + // C++ exception, go on + return EXCEPTION_CONTINUE_SEARCH; + } + else + { + // handle it, convert to std::exception + return EXCEPTION_EXECUTE_HANDLER; + } + + return EXCEPTION_CONTINUE_SEARCH; + } + + void cpphandle(const LL::WorkQueueBase::Work& work) + { + // SE and C++ can not coexists, thus two handlers + try + { + work(); + } + catch (const LLContinueError&) + { + // Any uncaught exception derived from LLContinueError will be caught + // here and logged. This coroutine will terminate but the rest of the + // viewer will carry on. + LOG_UNHANDLED_EXCEPTION(STRINGIZE("LLContinue in work queue")); + } + } + + void sehandle(const LL::WorkQueueBase::Work& work) + { + __try + { + // handle stop and continue exceptions first + cpphandle(work); + } + __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) + { + // convert to C++ styled exception + char integer_string[512]; + sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); + throw std::exception(integer_string); + } + } +#endif // LL_WINDOWS +} // anonymous namespace + void LL::WorkQueueBase::callWork(const Work& work) { LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + +#ifdef LL_WINDOWS + // can not use __try directly, toplevel requires unwinding, thus use of a wrapper + sehandle(work); +#else // LL_WINDOWS try { work(); } - catch (...) + catch (LLContinueError&) { - // No matter what goes wrong with any individual work item, the worker - // thread must go on! Log our own instance name with the exception. LOG_UNHANDLED_EXCEPTION(getKey()); } + catch (...) + { + // Stash any other kind of uncaught exception to be rethrown by main thread. + LL_WARNS("LLCoros") << "Capturing uncaught exception in WorkQueueBase " + << getKey() << LL_ENDL; + + LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); + main_queue->post( + // Bind the current exception rethrow it in main loop. + [exc = std::current_exception()]() { std::rethrow_exception(exc); }); + } +#endif // else LL_WINDOWS } void LL::WorkQueueBase::error(const std::string& msg) From 8705c16cb2559fc00f907da6ad801b2fae4970fa Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Mar 2025 20:19:25 +0200 Subject: [PATCH 06/14] #3643 Make sure attribute names match between OSs On Mac spaces aren't permitted. --- indra/newview/llappviewerwin32.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index b4a2479520..aaf2a7ea3e 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -155,10 +155,10 @@ namespace sBugSplatSender->setAttribute(WCSTR(L"OS"), WCSTR(LLOSInfo::instance().getOSStringSimple())); // In case we ever stop using email for this sBugSplatSender->setAttribute(WCSTR(L"AppState"), WCSTR(LLStartUp::getStartupStateString())); - sBugSplatSender->setAttribute(WCSTR(L"GL Vendor"), WCSTR(gGLManager.mGLVendor)); - sBugSplatSender->setAttribute(WCSTR(L"GL Version"), WCSTR(gGLManager.mGLVersionString)); - sBugSplatSender->setAttribute(WCSTR(L"GPU Version"), WCSTR(gGLManager.mDriverVersionVendorString)); - sBugSplatSender->setAttribute(WCSTR(L"GL Renderer"), WCSTR(gGLManager.mGLRenderer)); + sBugSplatSender->setAttribute(WCSTR(L"GLVendor"), WCSTR(gGLManager.mGLVendor)); + sBugSplatSender->setAttribute(WCSTR(L"GLVersion"), WCSTR(gGLManager.mGLVersionString)); + sBugSplatSender->setAttribute(WCSTR(L"GPUVersion"), WCSTR(gGLManager.mDriverVersionVendorString)); + sBugSplatSender->setAttribute(WCSTR(L"GLRenderer"), WCSTR(gGLManager.mGLRenderer)); sBugSplatSender->setAttribute(WCSTR(L"VRAM"), WCSTR(STRINGIZE(gGLManager.mVRAM))); sBugSplatSender->setAttribute(WCSTR(L"RAM"), WCSTR(STRINGIZE(gSysMemory.getPhysicalMemoryKB().value()))); From 8eff224c121f8e08514b28326d4c886e4acd35ab Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Mar 2025 22:11:16 +0200 Subject: [PATCH 07/14] #3795 Fix macos shutdown crash --- indra/llwindow/llwindowmacosx.cpp | 86 +++++++++++++++++++++++++++---- indra/newview/llviewerwindow.cpp | 11 ++-- 2 files changed, 82 insertions(+), 15 deletions(-) diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 6c3be3eef8..dadbc83f45 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -279,6 +279,10 @@ void callResetKeys() bool callUnicodeCallback(wchar_t character, unsigned int mask) { + if (!gWindowImplementation) + { + return false; + } NativeKeyEventData eventData; memset(&eventData, 0, sizeof(NativeKeyEventData)); @@ -300,7 +304,7 @@ bool callUnicodeCallback(wchar_t character, unsigned int mask) void callFocus() { - if (gWindowImplementation) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); } @@ -308,7 +312,7 @@ void callFocus() void callFocusLost() { - if (gWindowImplementation) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); } @@ -316,6 +320,10 @@ void callFocusLost() void callRightMouseDown(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -329,6 +337,10 @@ void callRightMouseDown(float *pos, MASK mask) void callRightMouseUp(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -342,6 +354,10 @@ void callRightMouseUp(float *pos, MASK mask) void callLeftMouseDown(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -355,6 +371,10 @@ void callLeftMouseDown(float *pos, MASK mask) void callLeftMouseUp(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -369,6 +389,10 @@ void callLeftMouseUp(float *pos, MASK mask) void callDoubleClick(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -382,7 +406,7 @@ void callDoubleClick(float *pos, MASK mask) void callResize(unsigned int width, unsigned int height) { - if (gWindowImplementation != NULL) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height); } @@ -390,6 +414,10 @@ void callResize(unsigned int width, unsigned int height) void callMouseMoved(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -403,6 +431,10 @@ void callMouseMoved(float *pos, MASK mask) void callMouseDragged(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -424,6 +456,10 @@ void callScrollMoved(float deltaX, float deltaY) void callMouseExit() { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation); } @@ -475,11 +511,19 @@ void callWindowDidChangeScreen() void callDeltaUpdate(float *delta, MASK mask) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->updateMouseDeltas(delta); } void callOtherMouseDown(float *pos, MASK mask, int button) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -500,6 +544,10 @@ void callOtherMouseDown(float *pos, MASK mask, int button) void callOtherMouseUp(float *pos, MASK mask, int button) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -524,27 +572,43 @@ void callModifier(MASK mask) void callHandleDragEntered(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING); } void callHandleDragExited(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING); } void callHandleDragUpdated(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK); } void callHandleDragDropped(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED); } void callQuitHandler() { - if (gWindowImplementation) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation)) { @@ -555,7 +619,7 @@ void callQuitHandler() void getPreeditSelectionRange(int *position, int *length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->getSelectionRange(position, length); } @@ -563,7 +627,7 @@ void getPreeditSelectionRange(int *position, int *length) void getPreeditMarkedRange(int *position, int *length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->getPreeditRange(position, length); } @@ -571,7 +635,7 @@ void getPreeditMarkedRange(int *position, int *length) void setPreeditMarkedRange(int position, int length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->markAsPreedit(position, length); } @@ -580,7 +644,7 @@ void setPreeditMarkedRange(int position, int length) bool handleUnicodeCharacter(wchar_t c) { bool success = false; - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); } @@ -590,7 +654,7 @@ bool handleUnicodeCharacter(wchar_t c) void resetPreedit() { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->resetPreedit(); } @@ -600,7 +664,7 @@ void resetPreedit() // This largely mirrors the old implementation, only sans the carbon parameters. void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); preeditor->resetPreedit(); @@ -623,7 +687,7 @@ void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigne void getPreeditLocation(float *location, unsigned int length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); LLCoordGL coord; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 4194dd00e7..70c06af89b 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1450,10 +1450,13 @@ void LLViewerWindow::handleMouseLeave(LLWindow *window) bool LLViewerWindow::handleCloseRequest(LLWindow *window) { - // User has indicated they want to close, but we may need to ask - // about modified documents. - LLAppViewer::instance()->userQuit(); - // Don't quit immediately + if (!LLApp::isExiting()) + { + // User has indicated they want to close, but we may need to ask + // about modified documents. + LLAppViewer::instance()->userQuit(); + // Don't quit immediately + } return false; } From 74254c9524e66d13a061312a629cc404a6c64a54 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 26 Mar 2025 10:28:01 -0400 Subject: [PATCH 08/14] Disable shoreline fade. (#3811) --- .../app_settings/shaders/class3/environment/waterF.glsl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index e57aa69731..349f3b9a67 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -26,7 +26,6 @@ // class3/environment/waterF.glsl #define WATER_MINIMAL 1 -#define SHORELINE_FADE 1 out vec4 frag_color; @@ -267,9 +266,9 @@ void main() #ifdef SHORELINE_FADE fade = max(0,min(1, (pos.z - refPos.z) / 10)); #else - fade = 1 * water_mask; + fade = 1; #endif - + fade *= water_mask; distort2 = mix(distort, distort2, min(1, fade * 10)); depth = texture(depthMap, distort2).r; From b976d261edaeb8fa96f3726ab6530b7866755c67 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 26 Mar 2025 20:01:30 +0200 Subject: [PATCH 09/14] #3803 Crash at LLTabContainer::setTab --- indra/newview/llfloaterimcontainer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index e55bf50724..e4b14d8df6 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1939,7 +1939,7 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c mConversationEventQueue.erase(uuid); // Don't let the focus fall IW, select and refocus on the first conversation in the list - if (change_focus) + if (change_focus && isInVisibleChain()) { setFocus(true); if (new_selection) @@ -1959,6 +1959,10 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c } } } + else + { + LL_INFOS() << "Conversation widgets: " << (S32)mConversationsWidgets.size() << LL_ENDL; + } return is_widget_selected; } From 4e80ec7e962dde43c8d7379f0167a242704336ad Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 26 Mar 2025 19:51:59 +0200 Subject: [PATCH 10/14] #3814 Out of range exception in TextCmdRemove::execute --- indra/llui/lltexteditor.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3537c764b9..77a4976f6b 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -209,8 +209,15 @@ public: } virtual bool execute( LLTextBase* editor, S32* delta ) { - mWString = editor->getWText().substr(getPosition(), mLen); - *delta = remove(editor, getPosition(), mLen ); + try + { + mWString = editor->getWText().substr(getPosition(), mLen); + *delta = remove(editor, getPosition(), mLen); + } + catch (std::out_of_range&) + { + return false; + } return (*delta != 0); } virtual S32 undo( LLTextBase* editor ) From 695247539b54dee648d71417295e5ca753eaa74e Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 26 Mar 2025 19:01:30 -0400 Subject: [PATCH 11/14] Mitigate some of the frame stuttering we're seeing by setting the VRAM divisor to 1. tl;dr - this helps avoid frequent texture reuploads to VRAM in some texture heavy areas. This speaks to some bigger problems we're seeing in our texture streaming system however. You will see similar problems by manually setting the texture VRAM manually. --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b7127adc53..60ae8ac691 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7814,7 +7814,7 @@ Type U32 Value - 2 + 1 RenderMinFreeMainMemoryThreshold From 7d5a5e939a7427fb0cabc99e10f75d7d99c5f133 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 27 Mar 2025 18:02:19 +0200 Subject: [PATCH 12/14] #3820 crash at LLNotificationTemplate --- indra/llui/llnotifications.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 7405413a3d..6fc9b90fb8 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1251,7 +1251,8 @@ LLNotifications::LLNotifications() void LLNotifications::clear() { - mDefaultChannels.clear(); + mDefaultChannels.clear(); + mTemplates.clear(); } // The expiration channel gets all notifications that are cancelled From d67859e48351a4db498f658030c0eb2866d59e77 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 26 Mar 2025 21:05:36 +0200 Subject: [PATCH 13/14] Use LLCachedControl in llviewerwindow and llappviewer Getting from gSavedSettings is expensive to do so often --- indra/llappearance/llwearable.cpp | 13 +++++++------ indra/newview/llappviewer.cpp | 11 +++++++---- indra/newview/llviewerwindow.cpp | 24 ++++++++++++++++-------- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index f30c147b91..4acb0ef3d4 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -645,9 +645,10 @@ void LLWearable::addVisualParam(LLVisualParam *param) void LLWearable::setVisualParamWeight(S32 param_index, F32 value) { - if( is_in_map(mVisualParamIndexMap, param_index ) ) + visual_param_index_map_t::iterator found = mVisualParamIndexMap.find(param_index); + if(found != mVisualParamIndexMap.end()) { - LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; + LLVisualParam *wearable_param = found->second; wearable_param->setWeight(value); } else @@ -658,10 +659,10 @@ void LLWearable::setVisualParamWeight(S32 param_index, F32 value) F32 LLWearable::getVisualParamWeight(S32 param_index) const { - if( is_in_map(mVisualParamIndexMap, param_index ) ) + visual_param_index_map_t::const_iterator found = mVisualParamIndexMap.find(param_index); + if(found != mVisualParamIndexMap.end()) { - const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second; - return wearable_param->getWeight(); + return found->second->getWeight(); } else { @@ -726,7 +727,7 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp) if (!avatarp) return; // Pull params - for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) + for( const LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) { // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 4cf651de33..0ffe675a7b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -445,8 +445,8 @@ void idle_afk_check() { // check idle timers F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32(); - F32 afk_timeout = (F32)gSavedSettings.getS32("AFKTimeout"); - if (afk_timeout && (current_idle > afk_timeout) && ! gAgent.getAFK()) + static LLCachedControl afk_timeout(gSavedSettings, "AFKTimeout", 300); + if (afk_timeout() && (current_idle > (F32)afk_timeout()) && !gAgent.getAFK()) { LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL; gAgent.setAFK(); @@ -5376,7 +5376,8 @@ void LLAppViewer::idleNetwork() gObjectList.mNumNewObjects = 0; S32 total_decoded = 0; - if (!gSavedSettings.getBOOL("SpeedTest")) + static LLCachedControl speed_test(gSavedSettings, "SpeedTest", false); + if (!speed_test()) { LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("idle network"); //LL_RECORD_BLOCK_TIME(FTM_IDLE_NETWORK); // decode @@ -5435,7 +5436,9 @@ void LLAppViewer::idleNetwork() } // Handle per-frame message system processing. - lmc.processAcks(gSavedSettings.getF32("AckCollectTime")); + + static LLCachedControl ack_collection_time(gSavedSettings, "AckCollectTime", 0.1f); + lmc.processAcks(ack_collection_time()); } } add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 70c06af89b..fe5a0667a5 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -489,7 +489,8 @@ public: clearText(); - if (gSavedSettings.getBOOL("DebugShowTime")) + static LLCachedControl debug_show_time(gSavedSettings, "DebugShowTime", false); + if (debug_show_time()) { F32 time = gFrameTimeSeconds; S32 hours = (S32)(time / (60*60)); @@ -498,7 +499,8 @@ public: addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; } - if (gSavedSettings.getBOOL("DebugShowMemory")) + static LLCachedControl debug_show_memory(gSavedSettings, "DebugShowMemory", false); + if (debug_show_memory()) { addText(xpos, ypos, STRINGIZE("Memory: " << (LLMemory::getCurrentRSS() / 1024) << " (KB)")); @@ -591,7 +593,8 @@ public: ypos += y_inc; }*/ - if (gSavedSettings.getBOOL("DebugShowRenderInfo")) + static LLCachedControl debug_show_render_info(gSavedSettings, "DebugShowRenderInfo", false); + if (debug_show_render_info()) { LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording(); @@ -730,7 +733,8 @@ public: gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; } - if (gSavedSettings.getBOOL("DebugShowAvatarRenderInfo")) + static LLCachedControl debug_show_avatar_render_info(gSavedSettings, "DebugShowAvatarRenderInfo", false); + if (debug_show_avatar_render_info()) { std::map sorted_avs; { @@ -763,7 +767,8 @@ public: av_iter++; } } - if (gSavedSettings.getBOOL("DebugShowRenderMatrices")) + static LLCachedControl debug_show_render_matrices(gSavedSettings, "DebugShowRenderMatrices", false); + if (debug_show_render_matrices()) { char camera_lines[8][32]; memset(camera_lines, ' ', sizeof(camera_lines)); @@ -789,7 +794,8 @@ public: ypos += y_inc; } // disable use of glReadPixels which messes up nVidia nSight graphics debugging - if (gSavedSettings.getBOOL("DebugShowColor") && !LLRender::sNsightDebugSupport) + static LLCachedControl debug_show_color(gSavedSettings, "DebugShowColor", false); + if (debug_show_color() && !LLRender::sNsightDebugSupport) { U8 color[4]; LLCoordGL coord = gViewerWindow->getCurrentMouse(); @@ -881,7 +887,8 @@ public: } } - if (gSavedSettings.getBOOL("DebugShowTextureInfo")) + static LLCachedControl debug_show_texture_info(gSavedSettings, "DebugShowTextureInfo", false); + if (debug_show_texture_info()) { LLViewerObject* objectp = NULL ; @@ -1600,7 +1607,8 @@ bool LLViewerWindow::handleActivate(LLWindow *window, bool activated) mActive = false; // if the user has chosen to go Away automatically after some time, then go Away when minimizing - if (gSavedSettings.getS32("AFKTimeout")) + static LLCachedControl afk_time(gSavedSettings, "AFKTimeout", 300); + if (afk_time()) { gAgent.setAFK(); } From 2b44a97a16dcf5f2a3356f1a4ccf29a47bbe9c87 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 26 Mar 2025 21:07:20 +0200 Subject: [PATCH 14/14] Avoid recalculating pixel area when possible --- indra/newview/llviewertexturelist.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index db530a3943..63d5a2d778 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -899,6 +899,9 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag { llassert(!gCubeSnapshot); + constexpr F32 BIAS_TRS_OUT_OF_SCREEN = 1.5f; + constexpr F32 BIAS_TRS_ON_SCREEN = 1.f; + if (imagep->getBoostLevel() < LLViewerFetchedTexture::BOOST_HIGH) // don't bother checking face list for boosted textures { static LLCachedControl texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.0095f); @@ -940,7 +943,7 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag F32 vsize = face->getPixelArea(); - on_screen = face->mInFrustum; + on_screen |= face->mInFrustum; // Scale desired texture resolution higher or lower depending on texture scale // @@ -972,14 +975,28 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag } max_vsize = llmax(max_vsize, vsize); + + // addTextureStats limits size to sMaxVirtualSize + if (max_vsize >= LLViewerFetchedTexture::sMaxVirtualSize + && (on_screen || LLViewerTexture::sDesiredDiscardBias <= BIAS_TRS_ON_SCREEN)) + { + break; + } } } + + if (max_vsize >= LLViewerFetchedTexture::sMaxVirtualSize + && (on_screen || LLViewerTexture::sDesiredDiscardBias <= BIAS_TRS_ON_SCREEN)) + { + break; + } } if (face_count > 1024) { // this texture is used in so many places we should just boost it and not bother checking its vsize // this is especially important because the above is not time sliced and can hit multiple ms for a single texture imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_HIGH); + // Do we ever remove it? This also sets texture nodelete! } if (imagep->getType() == LLViewerTexture::LOD_TEXTURE && imagep->getBoostLevel() == LLViewerTexture::BOOST_NONE) @@ -987,8 +1004,8 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag // this is an alternative to decaying mMaxVirtualSize over time // that keeps textures from continously downrezzing and uprezzing in the background - if (LLViewerTexture::sDesiredDiscardBias > 1.5f || - (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) + if (LLViewerTexture::sDesiredDiscardBias > BIAS_TRS_OUT_OF_SCREEN || + (!on_screen && LLViewerTexture::sDesiredDiscardBias > BIAS_TRS_ON_SCREEN)) { imagep->mMaxVirtualSize = 0.f; }