diff options
author | ruslantproductengine <ruslantproductengine@lindenlab.com> | 2017-01-24 15:56:25 +0200 |
---|---|---|
committer | ruslantproductengine <ruslantproductengine@lindenlab.com> | 2017-01-24 15:56:25 +0200 |
commit | 6770c27321cf674af57c45ffee6faf09db788a6d (patch) | |
tree | 7fe838baabaea1da6cb188e9a7b933e527154cfb /indra | |
parent | 65161e6b393a6df6fa0a932aeb940fb7ac7ea084 (diff) |
MAINT-6645 - Improvement - Agents that render as jelly dolls should have their attachments render at 0 LoD to prevent loading higher LoD complexity in memory thus deterring crashes.
Comments:
- Fix based on "RenderAutoMuteByteLimit" setting.
- File indra/llxml/llcontrol.h - add all signals to 0 group.
It garanty that handlers (in indra/newview/llviewercontrol.cpp) will be called last.
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llmath/llvolume.cpp | 7 | ||||
-rw-r--r-- | indra/llmath/llvolume.h | 2 | ||||
-rw-r--r-- | indra/llprimitive/llprimitive.cpp | 10 | ||||
-rw-r--r-- | indra/llprimitive/llprimitive.h | 5 | ||||
-rw-r--r-- | indra/llxml/llcontrol.h | 3 | ||||
-rw-r--r-- | indra/newview/app_settings/settings.xml | 4 | ||||
-rw-r--r-- | indra/newview/lldrawable.cpp | 23 | ||||
-rw-r--r-- | indra/newview/lldrawable.h | 3 | ||||
-rw-r--r-- | indra/newview/llface.cpp | 15 | ||||
-rw-r--r-- | indra/newview/llmeshrepository.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llspatialpartition.h | 2 | ||||
-rw-r--r-- | indra/newview/llviewercontrol.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llviewerobject.cpp | 8 | ||||
-rw-r--r-- | indra/newview/llviewerobject.h | 1 | ||||
-rw-r--r-- | indra/newview/llvovolume.cpp | 215 | ||||
-rw-r--r-- | indra/newview/llvovolume.h | 92 | ||||
-rw-r--r-- | indra/newview/pipeline.cpp | 6 |
17 files changed, 374 insertions, 28 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 8b73f0ae8e..8d5e9de76b 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -545,7 +545,7 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3 { // Generate an n-sided "circular" path. // 0 is (1,0), and we go counter-clockwise along a circular path from there. - const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; + static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; F32 scale = 0.5f; F32 t, t_step, t_first, t_fraction, ang, ang_step; LLVector4a pt1,pt2; @@ -1304,7 +1304,7 @@ S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) { // Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. - const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; + static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; F32 revolutions = params.getRevolutions(); F32 skew = params.getSkew(); @@ -1602,7 +1602,8 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, if (is_sculpted) sides = llmax(sculpt_size, 1); - genNGon(params, sides); + if (0 < sides) + genNGon(params, sides); } break; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index bba691d243..65fbc4685e 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1088,7 +1088,7 @@ public: F32 mSurfaceArea; //unscaled surface area BOOL mIsMeshAssetLoaded; - LLVolumeParams mParams; + const LLVolumeParams mParams; LLPath *mPathp; LLProfile *mProfilep; LLAlignedArray<LLVector4a,64> mMesh; diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index bfa65666b5..ee17ee5a91 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -732,6 +732,16 @@ S32 face_index_from_id(LLFaceID face_ID, const std::vector<LLProfile::Face>& fac BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume) { + if (NO_LOD == detail) + { + // build the new object + setChanged(GEOMETRY); + sVolumeManager->unrefVolume(mVolumep); + mVolumep = new LLVolume(volume_params, 0, TRUE, TRUE); + setNumTEs(mVolumep->getNumFaces()); + return FALSE; + } + LLVolume *volumep; if (unique_volume) { diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 19d9d52817..99a32e614c 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -489,6 +489,11 @@ protected: public: static LLVolumeMgr* sVolumeManager; + + enum + { + NO_LOD = -1 + }; }; inline BOOL LLPrimitive::isAvatar() const diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 77065dcf8d..8136a3e88a 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -357,7 +357,8 @@ private: mCachedValue = convert_from_llsd<T>(controlp->get(), mType, name); // Add a listener to the controls signal... - mConnection = controlp->getSignal()->connect( + // NOTE: All listeners connected to 0 group, for guaranty that variable handlers (gSavedSettings) call last + mConnection = controlp->getSignal()->connect(0, boost::bind(&LLControlCache<T>::handleValueChange, this, _2) ); mType = controlp->type(); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 63fa93df02..7c3867bdfb 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10169,9 +10169,9 @@ <key>RenderAutoMuteByteLimit</key> <map> <key>Comment</key> - <string>OBSOLETE and UNUSED.</string> + <string>If avatar attachment size exceed this value (in bytes) attachment will not be rendered. Excludes attachments worn by own avatar.</string> <key>Persist</key> - <integer>0</integer> + <integer>1</integer> <key>Type</key> <string>U32</string> <key>Value</key> diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 3bb2c45a24..aa67ea2524 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -50,6 +50,7 @@ #include "llviewerobjectlist.h" #include "llviewerwindow.h" #include "llvocache.h" +#include "lldrawpoolavatar.h" const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f; const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f; @@ -143,6 +144,28 @@ void LLDrawable::init(bool new_entry) initVisible(sCurVisible - 2);//invisible for the current frame and the last frame. } +void LLDrawable::unload() +{ + LLVOVolume *pVVol = getVOVolume(); + pVVol->setNoLOD(); + + for (S32 i = 0; i < getNumFaces(); i++) + { + LLFace* facep = getFace(i); + if (facep->isState(LLFace::RIGGED)) + { + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*)facep->getPool(); + if (pool) { + pool->removeRiggedFace(facep); + } + facep->setVertexBuffer(NULL); + } + facep->clearState(LLFace::RIGGED); + } + + pVVol->markForUpdate(TRUE); +} + // static void LLDrawable::initClass() { diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index a3461d4c01..14d782d6f2 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -84,6 +84,7 @@ public: void markDead(); // Mark this drawable as dead BOOL isDead() const { return isState(DEAD); } BOOL isNew() const { return !isState(BUILT); } + BOOL isUnload() const { return isState(FOR_UNLOAD); } BOOL isLight() const; @@ -141,6 +142,7 @@ public: void mergeFaces(LLDrawable* src); void init(bool new_entry); + void unload(); void destroy(); void update(); @@ -282,6 +284,7 @@ public: PARTITION_MOVE = 0x10000000, ANIMATED_CHILD = 0x20000000, ACTIVE_CHILD = 0x40000000, + FOR_UNLOAD = 0x80000000, //should be unload from memory } EDrawableFlags; public: diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 50a4925c37..51bb2e3087 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2650,12 +2650,27 @@ LLViewerTexture* LLFace::getTexture(U32 ch) const void LLFace::setVertexBuffer(LLVertexBuffer* buffer) { + if (buffer) + { + LLSculptIDSize::instance().inc(mDrawablep, buffer->getSize() + buffer->getIndicesSize()); + } + + if (mVertexBuffer) + { + LLSculptIDSize::instance().dec(mDrawablep); + } + mVertexBuffer = buffer; llassert(verify()); } void LLFace::clearVertexBuffer() { + if (mVertexBuffer) + { + LLSculptIDSize::instance().dec(mDrawablep); + } + mVertexBuffer = NULL; } diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index df708013fc..9edffea1c1 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -3945,7 +3945,7 @@ void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3 S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod) { - if (mThread && mesh_id.notNull()) + if (mThread && mesh_id.notNull() && LLPrimitive::NO_LOD != lod) { LLMutexLock lock(mThread->mHeaderMutex); LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 7633e46200..f7bcce6daf 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -646,7 +646,7 @@ class LLVolumeGeometryManager: public LLGeometryManager virtual void rebuildGeom(LLSpatialGroup* group); virtual void rebuildMesh(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); - void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE); + U32 genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE); void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); private: diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index d9d66ef254..3280aa718d 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -582,6 +582,7 @@ bool toggle_show_object_render_cost(const LLSD& newvalue) return true; } +void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value); //////////////////////////////////////////////////////////////////////////// void settings_setup_listeners() @@ -734,7 +735,8 @@ void settings_setup_listeners() gSavedSettings.getControl("SpellCheck")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged)); - gSavedSettings.getControl("DebugAvatarJoints")->getCommitSignal()->connect(boost::bind(&handleDebugAvatarJointsChanged, _2)); + gSavedSettings.getControl("DebugAvatarJoints")->getCommitSignal()->connect(boost::bind(&handleDebugAvatarJointsChanged, _2)); + gSavedSettings.getControl("RenderAutoMuteByteLimit")->getSignal()->connect(boost::bind(&handleRenderAutoMuteByteLimitChanged, _2)); } #if TEST_CACHED_CONTROL diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 6c2d4d7fea..293df89bf0 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5868,6 +5868,14 @@ void LLViewerObject::markForUpdate(BOOL priority) } } +void LLViewerObject::markForUnload(BOOL priority) +{ + if (mDrawable.notNull()) + { + gPipeline.markRebuild(mDrawable, LLDrawable::FOR_UNLOAD, priority); + } +} + bool LLViewerObject::isPermanentEnforced() const { return flagObjectPermanent() && (mRegionp != gAgent.getRegion()) && !gAgent.isGodlike(); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 7a490f6957..e4224a79d1 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -412,6 +412,7 @@ public: void clearIcon(); void markForUpdate(BOOL priority); + void markForUnload(BOOL priority); void updateVolume(const LLVolumeParams& volume_params); virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); virtual F32 getBinRadius(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 9c77a76683..5292eb7067 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -249,6 +249,8 @@ void LLVOVolume::markDead() { if (!mDead) { + LLSculptIDSize::instance().rem(getVolume()->getParams().getSculptID()); + if(getMDCImplCount() > 0) { LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false); @@ -951,13 +953,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo // if it's a mesh if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { //meshes might not have all LODs, get the force detail to best existing LOD - LLUUID mesh_id = volume_params.getSculptID(); - - lod = gMeshRepo.getActualMeshLOD(volume_params, lod); - if (lod == -1) + if (NO_LOD != lod) { - is404 = TRUE; - lod = 0; + lod = gMeshRepo.getActualMeshLOD(volume_params, lod); + if (lod == -1) + { + is404 = TRUE; + lod = 0; + } } } } @@ -4652,10 +4655,79 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) return NULL; } -void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) +void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value) { - + static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); + + if (0 != render_auto_mute_byte_limit) + { + //for unload + LLSculptIDSize::container_BY_SIZE_view::iterator + itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().lower_bound(render_auto_mute_byte_limit), + itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().end(); + + for (; itL != itU; ++itL) + { + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD != pVVol->getLOD() + ) + { + //postponed + pVVol->markForUnload(); + } + } + + //for load if it was unload + itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().begin(); + itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().upper_bound(render_auto_mute_byte_limit); + + for (; itL != itU; ++itL) + { + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD == pVVol->getLOD() + ) + { + pVVol->updateLOD(); + pVVol->markForUpdate(TRUE); + } + } + } + else + { + LLSculptIDSize::container_BY_SIZE_view::iterator + itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().begin(), + itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().end(); + + for (; itL != itU; ++itL) + { + const LLSculptIDSize::Info &nfo = *itL; + LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD == pVVol->getLOD() + ) + { + pVVol->updateLOD(); + pVVol->markForUpdate(TRUE); + } + } + } +} +void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) +{ if (group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; @@ -5216,13 +5288,19 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; } - genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE); - genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures); - genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures); - genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE); - genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE); - genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE); - genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE); + group->mGeometryBytes = 0; + + U32 geometryBytes = 0; + + geometryBytes += genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE); + geometryBytes += genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures); + geometryBytes += genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures); + geometryBytes += genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE); + geometryBytes += genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE); + geometryBytes += genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE); + geometryBytes += genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE); + + group->mGeometryBytes = geometryBytes; if (!LLPipeline::sDelayVBUpdate) { @@ -5412,10 +5490,11 @@ static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); -void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials) +U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials) { LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); + U32 geometryBytes = 0; U32 buffer_usage = group->mBufferUsage; static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); @@ -5665,7 +5744,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac if (buffer) { - group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize(); + geometryBytes += buffer->getSize() + buffer->getIndicesSize(); buffer_map[mask][*face_iter].push_back(buffer); } @@ -6021,6 +6100,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac { group->mBufferMap[mask][i->first] = i->second; } + + return geometryBytes; } void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) @@ -6088,3 +6169,103 @@ void LLHUDPartition::shift(const LLVector4a &offset) //HUD objects don't shift with region crossing. That would be silly. } + +//........... + +void _nothing_to_do_func(int) { /*nothing todo here because of the size it's a shared member*/ } + +void LLSculptIDSize::inc(const LLDrawable *pdrawable, int sz) +{ + llassert(sz >= 0); + + if (!pdrawable) return; + LLVOVolume* vvol = pdrawable->getVOVolume(); + if (!vvol) return; + if (!vvol->isAttachment()) return; + if (!vvol->getAvatar()) return; + if (vvol->getAvatar()->isSelf()) return; + LLVolume *vol = vvol->getVolume(); + if (!vol) return; + + const LLUUID &sculptId = vol->getParams().getSculptID(); + + unsigned int total_size = 0; + + typedef std::pair<container_BY_SCULPT_ID_view::iterator, container_BY_SCULPT_ID_view::iterator> pair_iter_iter_t; + + pair_iter_iter_t itLU = m_size_info.get<tag_BY_SCULPT_ID>().equal_range(sculptId); + if (itLU.first == itLU.second) + { //register + llassert(m_size_info.get<tag_BY_DRAWABLE>().end() == m_size_info.get<tag_BY_DRAWABLE>().find(pdrawable)); + m_size_info.get<tag_BY_DRAWABLE>().insert(Info( pdrawable, sz, boost::make_shared<SizeInfo>(sz), sculptId )); + total_size = sz; + } + else + { //update + register + Info &nfo = const_cast<Info &>(*itLU.first); + //calc new size + total_size = nfo.getTotalSize() + sz; + nfo.m_p_size_info->m_size = total_size; + nfo.m_size = sz; + //update size for all LLDrwable in range of sculptId + for (pair_iter_iter_t::first_type it = itLU.first; it != itLU.second; ++it) + { + m_size_info.get<tag_BY_SIZE>().modify_key(m_size_info.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1)); + } + + //trying insert the LLDrawable + m_size_info.get<tag_BY_DRAWABLE>().insert(Info(pdrawable, sz, nfo.m_p_size_info, sculptId)); + } + + static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); + + if (0 != render_auto_mute_byte_limit && total_size > render_auto_mute_byte_limit) + { + pair_iter_iter_t it_eqr = m_size_info.get<tag_BY_SCULPT_ID>().equal_range(sculptId); + for (; it_eqr.first != it_eqr.second; ++it_eqr.first) + { + const Info &i = *it_eqr.first; + LLVOVolume *pVVol = i.m_p_drawable->getVOVolume(); + if (pVVol + && !pVVol->isDead() + && pVVol->isAttachment() + && !pVVol->getAvatar()->isSelf() + && LLVOVolume::NO_LOD != pVVol->getLOD() + ) + { + //immediately + const_cast<LLDrawable*>(i.m_p_drawable)->unload(); + } + } + } +} + +void LLSculptIDSize::dec(const LLDrawable *pdrawable) +{ + container_BY_DRAWABLE_view::iterator it = m_size_info.get<tag_BY_DRAWABLE>().find(pdrawable); + if (m_size_info.get<tag_BY_DRAWABLE>().end() == it) return; + + unsigned int size = it->getTotalSize() - it->getSize(); + + if (0 == size) + { + m_size_info.get<tag_BY_SCULPT_ID>().erase(it->getSculptId()); + } + else + { + Info &nfo = const_cast<Info &>(*it); + nfo.m_size = 0; + typedef std::pair<container_BY_SCULPT_ID_view::iterator, container_BY_SCULPT_ID_view::iterator> pair_iter_iter_t; + pair_iter_iter_t itLU = m_size_info.get<tag_BY_SCULPT_ID>().equal_range(it->getSculptId()); + it->m_p_size_info->m_size = size; + for (pair_iter_iter_t::first_type it = itLU.first; it != itLU.second; ++it) + { + m_size_info.get<tag_BY_SIZE>().modify_key(m_size_info.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1)); + } + } +} + +void LLSculptIDSize::rem(LLUUID sculptId) +{ + m_size_info.get<tag_BY_SCULPT_ID>().erase(sculptId); +} diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 3b68d61ee9..3ae9ac5325 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -35,6 +35,12 @@ #include "m3math.h" // LLMatrix3 #include "m4math.h" // LLMatrix4 #include <map> +#include <set> +//boost +#include "boost/multi_index_container.hpp" +#include "boost/multi_index/ordered_index.hpp" +#include "boost/multi_index/mem_fun.hpp" + class LLViewerTextureAnim; class LLDrawPool; @@ -125,7 +131,8 @@ public: void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point); /*virtual*/ BOOL setParent(LLViewerObject* parent); - S32 getLOD() const { return mLOD; } + S32 getLOD() const { return mLOD; } + void setNoLOD() { mLOD = NO_LOD; mLODChanged = TRUE; } const LLVector3 getPivotPositionAgent() const; const LLMatrix4& getRelativeXform() const { return mRelativeXform; } const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; } @@ -160,6 +167,7 @@ public: const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; void markForUpdate(BOOL priority) { LLViewerObject::markForUpdate(priority); mVolumeChanged = TRUE; } + void markForUnload() { LLViewerObject::markForUnload(TRUE); mVolumeChanged = TRUE; } void faceMappingChanged() { mFaceMappingChanged=TRUE; }; /*virtual*/ void onShift(const LLVector4a &shift_vector); // Called when the drawable shifts @@ -410,5 +418,87 @@ private: }; +//........... + +class LLSculptIDSize +{ +public: + struct SizeInfo + { + SizeInfo(int size) : m_size(size) {} + unsigned int m_size; + }; + + struct Info + { + typedef boost::shared_ptr<SizeInfo> PtrSizeInfo; + + Info(const LLDrawable *pdrawable, int size, PtrSizeInfo psize_info, LLUUID sculpt_id) + : m_p_drawable(pdrawable) + , m_size(size) + , m_p_size_info(psize_info) + , m_sculpt_id(sculpt_id) + {} + + const LLDrawable *m_p_drawable; + unsigned int m_size; + PtrSizeInfo m_p_size_info; + LLUUID m_sculpt_id; + + inline const LLDrawable* getPtrLLDrawable() const { return m_p_drawable; } + inline unsigned int getSize() const { return m_size; } + inline unsigned int getTotalSize() const { return m_p_size_info->m_size; } + inline LLUUID getSculptId() const { return m_sculpt_id; } + PtrSizeInfo getSizeInfo() { return m_p_size_info; } + }; + +public: + //tags + struct tag_BY_DRAWABLE {}; + struct tag_BY_SCULPT_ID {}; + struct tag_BY_SIZE {}; + + //container + typedef boost::multi_index_container < + Info, + boost::multi_index::indexed_by < + boost::multi_index::ordered_unique< boost::multi_index::tag<tag_BY_DRAWABLE> + , boost::multi_index::const_mem_fun<Info, const LLDrawable*, &Info::getPtrLLDrawable> + > + , boost::multi_index::ordered_non_unique<boost::multi_index::tag<tag_BY_SCULPT_ID> + , boost::multi_index::const_mem_fun<Info, LLUUID, &Info::getSculptId> + > + , boost::multi_index::ordered_non_unique<boost::multi_index::tag<tag_BY_SIZE> + , boost::multi_index::const_mem_fun<Info, unsigned int, &Info::getTotalSize> + > + > + > container; + + //views + typedef container::template index<tag_BY_DRAWABLE>::type container_BY_DRAWABLE_view; + typedef container::template index<tag_BY_SCULPT_ID>::type container_BY_SCULPT_ID_view; + typedef container::template index<tag_BY_SIZE>::type container_BY_SIZE_view; + +private: + LLSculptIDSize() + {} + +public: + static LLSculptIDSize & instance() { + static LLSculptIDSize inst; + return inst; + } + +public: + void inc(const LLDrawable *pdrawable, int sz); + void dec(const LLDrawable *pdrawable); + void rem(LLUUID sculptId); + + const container & getSizeInfo() const { return m_size_info; } + +private: + container m_size_info; +}; + #endif // LL_LLVOVOLUME_H diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1777fcc0f2..205585b34e 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -3031,6 +3031,12 @@ void LLPipeline::updateGeom(F32 max_dtime) } } + if (drawablep->isUnload()) + { + drawablep->unload(); + drawablep->clearState(LLDrawable::FOR_UNLOAD); + } + if (updateDrawableGeom(drawablep, TRUE)) { drawablep->clearState(LLDrawable::IN_REBUILD_Q1); |