From a6711a894c3c32ad24b47e36b2a52225713fd3ed Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Thu, 8 Aug 2013 16:45:55 -0600 Subject: fix for SH-4402: interesting: lower FPS with lots of objects in view --- indra/newview/llviewerregion.cpp | 108 ++++++++++++++++++++++++--------------- indra/newview/llviewerregion.h | 18 +++++-- indra/newview/llvocache.cpp | 37 ++++++++++++-- indra/newview/llvocache.h | 6 +++ indra/newview/llworld.cpp | 3 +- indra/newview/pipeline.cpp | 2 +- 6 files changed, 126 insertions(+), 48 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 117ccdea33..cfe765a1cb 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -90,6 +90,7 @@ const U32 DEFAULT_MAX_REGION_WIDE_PRIM_COUNT = 15000; BOOL LLViewerRegion::sVOCacheCullingEnabled = FALSE; S32 LLViewerRegion::sLastCameraUpdated = 0; +S32 LLViewerRegion::sNewObjectCreationThrottle = 0; typedef std::map CapabilityMap; @@ -372,7 +373,9 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mCapabilitiesReceived(false), mBitsReceived(0.f), mPacketsReceived(0.f), - mDead(FALSE) + mDead(FALSE), + mLastVisitedEntry(NULL), + mInvisibilityCheckHistory(-1) { mWidth = region_width_meters; mImpl->mOriginGlobal = from_region_handle(handle); @@ -968,6 +971,11 @@ void LLViewerRegion::addVisibleGroup(LLviewerOctreeGroup* group) mImpl->mVisibleGroups.insert(group); } +U32 LLViewerRegion::getNumOfVisibleGroups() const +{ + return mImpl ? mImpl->mVisibleGroups.size() : 0; +} + void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry) { if(!sVOCacheCullingEnabled) @@ -1139,7 +1147,7 @@ F32 LLViewerRegion::updateVisibleEntries(F32 max_time) return 2.0f * max_time - update_timer.getElapsedTimeF32(); } -F32 LLViewerRegion::createVisibleObjects(F32 max_time, S32 throttle) +F32 LLViewerRegion::createVisibleObjects(F32 max_time) { if(mDead) { @@ -1150,6 +1158,7 @@ F32 LLViewerRegion::createVisibleObjects(F32 max_time, S32 throttle) return max_time; } + S32 throttle = sNewObjectCreationThrottle; LLTimer update_timer; for(LLVOCacheEntry::vocache_entry_priority_list_t::iterator iter = mImpl->mWaitingList.begin(); iter != mImpl->mWaitingList.end(); ++iter) @@ -1170,9 +1179,7 @@ F32 LLViewerRegion::createVisibleObjects(F32 max_time, S32 throttle) } BOOL LLViewerRegion::idleUpdate(F32 max_update_time) -{ - static LLCachedControl new_object_creation_throttle(gSavedSettings,"NewObjectCreationThrottle"); - +{ LLTimer update_timer; // did_update returns TRUE if we did at least one significant update @@ -1191,44 +1198,28 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time) if(mImpl->mCacheMap.empty()) { return did_update; - } - - max_update_time -= update_timer.getElapsedTimeF32(); + } //reset all occluders mImpl->mVOCachePartition->resetOccluders(); - //update the throttling number - static S32 throttle = new_object_creation_throttle; - if(LLStartUp::getStartupState() < STATE_STARTED || gTeleportDisplay) - { - throttle = -1; //cancel the throttling + max_update_time -= update_timer.getElapsedTimeF32(); + if(sNewObjectCreationThrottle < 0 && (LLStartUp::getStartupState() < STATE_STARTED || gTeleportDisplay)) + { //apply octree cullings here to pick up visible objects because rendering pipeline stops view culling at this moment mImpl->mVOCachePartition->cull(*LLViewerCamera::getInstance(), false); } - else if(throttle < 0) //just recoved from the login/teleport screen - { - if(new_object_creation_throttle > 0) - { - throttle = 4096; //a big number - } - } - else - { - throttle = llmax((S32)new_object_creation_throttle, (S32)(throttle >> 1)); - } - - if(max_update_time < 0.f && throttle > 0 && throttle < new_object_creation_throttle * 2) + else if(max_update_time < 0.f) { return did_update; } //kill invisible objects - max_update_time = killInvisibleObjects(max_update_time, throttle); + max_update_time = killInvisibleObjects(max_update_time); max_update_time = updateVisibleEntries(max_update_time); - createVisibleObjects(max_update_time, throttle); + createVisibleObjects(max_update_time); mImpl->mWaitingList.clear(); mImpl->mVisibleGroups.clear(); @@ -1236,7 +1227,35 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time) return did_update; } -F32 LLViewerRegion::killInvisibleObjects(F32 max_time, S32 throttle) +//update the throttling number for new object creation +void LLViewerRegion::calcNewObjectCreationThrottle() +{ + static LLCachedControl new_object_creation_throttle(gSavedSettings,"NewObjectCreationThrottle"); + + sNewObjectCreationThrottle = new_object_creation_throttle; + if(LLStartUp::getStartupState() < STATE_STARTED || gTeleportDisplay) + { + sNewObjectCreationThrottle = -1; //cancel the throttling + } + else if(sNewObjectCreationThrottle < 0) //just recoved from the login/teleport screen + { + if(new_object_creation_throttle > 0) + { + sNewObjectCreationThrottle = 4096; //a big number + } + } + else + { + sNewObjectCreationThrottle = llmax((S32)new_object_creation_throttle, (S32)(sNewObjectCreationThrottle >> 1)); + } +} + +BOOL LLViewerRegion::isViewerCameraStatic() +{ + return sLastCameraUpdated < LLViewerOctreeEntryData::getCurrentFrame(); +} + +F32 LLViewerRegion::killInvisibleObjects(F32 max_time) { #if 1 if(!sVOCacheCullingEnabled) @@ -1248,12 +1267,16 @@ F32 LLViewerRegion::killInvisibleObjects(F32 max_time, S32 throttle) return max_time; } - static LLVOCacheEntry* last_visited_entry = NULL; - - const size_t MAX_UPDATE = throttle < 0 ? mImpl->mActiveSet.size() : 64; + size_t max_update = sNewObjectCreationThrottle < 0 ? mImpl->mActiveSet.size() : 64; + if(!mInvisibilityCheckHistory && isViewerCameraStatic()) + { + //history is clean, reduce number of checking + max_update = llmax(max_update / 2, (size_t)8); + } + std::vector delete_list; - S32 update_counter = llmin(MAX_UPDATE, mImpl->mActiveSet.size()); - LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.upper_bound(last_visited_entry); + S32 update_counter = llmin(max_update, mImpl->mActiveSet.size()); + LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.upper_bound(mLastVisitedEntry); for(; update_counter > 0; --update_counter, ++iter) { @@ -1262,7 +1285,7 @@ F32 LLViewerRegion::killInvisibleObjects(F32 max_time, S32 throttle) iter = mImpl->mActiveSet.begin(); } - if(!(*iter)->isRecentlyVisible() && (*iter)->mLastCameraUpdated != sLastCameraUpdated) + if(!(*iter)->isRecentlyVisible() && (*iter)->mLastCameraUpdated < sLastCameraUpdated) { killObject((*iter), delete_list); } @@ -1270,18 +1293,23 @@ F32 LLViewerRegion::killInvisibleObjects(F32 max_time, S32 throttle) if(iter == mImpl->mActiveSet.end()) { - last_visited_entry = NULL; + mLastVisitedEntry = NULL; } else { - last_visited_entry = *iter; + mLastVisitedEntry = *iter; } - for(S32 i = 0; i < delete_list.size(); i++) + mInvisibilityCheckHistory <<= 2; + if(!delete_list.empty()) { - gObjectList.killObject(delete_list[i]->getVObj()); + mInvisibilityCheckHistory |= 1; + for(S32 i = 0; i < delete_list.size(); i++) + { + gObjectList.killObject(delete_list[i]->getVObj()); + } + delete_list.clear(); } - delete_list.clear(); #endif return max_time; } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index a8e0b7bba9..9d2a333b1b 100755 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -220,6 +220,10 @@ public: // can process the message. static void processRegionInfo(LLMessageSystem* msg, void**); + //check if the viewer camera is static + static BOOL isViewerCameraStatic(); + static void calcNewObjectCreationThrottle(); + void setCacheID(const LLUUID& id); F32 getWidth() const { return mWidth; } @@ -345,6 +349,7 @@ public: virtual std::string getDescription() const; std::string getHttpUrl() const { return mHttpUrl ;} + U32 getNumOfVisibleGroups() const; U32 getNumOfActiveCachedObjects() const; LLSpatialPartition* getSpatialPartition(U32 type); LLVOCachePartition* getVOCachePartition(); @@ -359,7 +364,7 @@ public: LLViewerRegionImpl * getRegionImplNC() { return mImpl; } void removeFromCreatedList(U32 local_id); - void addToCreatedList(U32 local_id); + void addToCreatedList(U32 local_id); private: void addToVOCacheTree(LLVOCacheEntry* entry); @@ -369,8 +374,8 @@ private: void replaceVisibleCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry); void killCacheEntry(LLVOCacheEntry* entry); //physically delete the cache entry - F32 killInvisibleObjects(F32 max_time, S32 throttle); - F32 createVisibleObjects(F32 max_time, S32 throttle); + F32 killInvisibleObjects(F32 max_time); + F32 createVisibleObjects(F32 max_time); F32 updateVisibleEntries(F32 max_time); //update visible entries void addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type); @@ -411,6 +416,10 @@ public: static BOOL sVOCacheCullingEnabled; //vo cache culling enabled or not. static S32 sLastCameraUpdated; + +private: + static S32 sNewObjectCreationThrottle; + private: LLViewerRegionImpl * mImpl; LLFrameTimer mRegionTimer; @@ -445,6 +454,9 @@ private: F32 mCameraDistanceSquared; // updated once per frame U8 mCentralBakeVersion; + LLVOCacheEntry* mLastVisitedEntry; + U32 mInvisibilityCheckHistory; + // Information for Homestead / CR-53 S32 mClassID; S32 mCPURatio; diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 82485d7fdc..7dfa131ebf 100755 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -34,6 +34,7 @@ #include "llviewerregion.h" #include "pipeline.h" +BOOL LLVOCachePartition::sNeedsOcclusionCheck = FALSE; LLTrace::MemStatHandle LLVOCachePartition::sMemStat("LLVOCachePartition"); BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) @@ -467,8 +468,14 @@ LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp) { mLODPeriod = 16; mRegionp = regionp; - mPartitionType = LLViewerRegion::PARTITION_VO_CACHE; - + mPartitionType = LLViewerRegion::PARTITION_VO_CACHE; + mDirty = FALSE; + + for(S32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mCulledTime[i] = 0; + mCullHistory[i] = -1; + } new LLOcclusionCullingGroup(mOctree, this); } @@ -477,6 +484,7 @@ void LLVOCachePartition::addEntry(LLViewerOctreeEntry* entry) llassert(entry->hasVOCacheEntry()); mOctree->insert(entry); + mDirty = TRUE; } void LLVOCachePartition::removeEntry(LLViewerOctreeEntry* entry) @@ -595,7 +603,19 @@ S32 LLVOCachePartition::cull(LLCamera &camera, bool do_occlusion) return 0; } + if(mCulledTime[LLViewerCamera::sCurCameraID] == LLViewerOctreeEntryData::getCurrentFrame()) + { + return 0; //already culled + } + mCulledTime[LLViewerCamera::sCurCameraID] = LLViewerOctreeEntryData::getCurrentFrame(); + + if(!mDirty && !mCullHistory[LLViewerCamera::sCurCameraID] && LLViewerRegion::isViewerCameraStatic()) + { + return 0; //nothing changed, skip culling + } + ((LLviewerOctreeGroup*)mOctree->getListener(0))->rebound(); + mCullHistory[LLViewerCamera::sCurCameraID] <<= 2; //localize the camera LLVector3 region_agent = mRegionp->getOriginAgent(); @@ -604,7 +624,16 @@ S32 LLVOCachePartition::cull(LLCamera &camera, bool do_occlusion) LLVOCacheOctreeCull culler(&camera, mRegionp, region_agent, do_occlusion && use_object_cache_occlusion, this); culler.traverse(mOctree); - return 0; + if(mRegionp->getNumOfVisibleGroups() > 0) + { + mCullHistory[LLViewerCamera::sCurCameraID] |= 1; + } + + if(!sNeedsOcclusionCheck) + { + sNeedsOcclusionCheck = !mOccludedGroups.empty(); + } + return 1; } void LLVOCachePartition::addOccluders(LLviewerOctreeGroup* gp) @@ -646,6 +675,8 @@ void LLVOCachePartition::resetOccluders() group->clearOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION); } mOccludedGroups.clear(); + mDirty = FALSE; + sNeedsOcclusionCheck = FALSE; } //------------------------------------------------------------------- diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 04463088fa..c448b97b80 100755 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -168,7 +168,13 @@ public: public: void processOccluders(LLCamera* camera); +public: + static BOOL sNeedsOcclusionCheck; + private: + BOOL mDirty; + U32 mCullHistory[LLViewerCamera::NUM_CAMERAS]; + U32 mCulledTime[LLViewerCamera::NUM_CAMERAS]; std::set mOccludedGroups; }; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index bfc5077c90..df5e3d835c 100755 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -668,8 +668,9 @@ void LLWorld::updateRegions(F32 max_update_time) if(LLViewerCamera::getInstance()->isChanged()) { - LLViewerRegion::sLastCameraUpdated = LLViewerOctreeEntryData::getCurrentFrame(); + LLViewerRegion::sLastCameraUpdated = LLViewerOctreeEntryData::getCurrentFrame() + 1; } + LLViewerRegion::calcNewObjectCreationThrottle(); // Perform idle time updates for the regions (and associated surfaces) for (region_list_t::iterator iter = mRegionList.begin(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1abaaa49ac..87c3bf7bdf 100755 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2724,7 +2724,7 @@ void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderT void LLPipeline::doOcclusion(LLCamera& camera) { - if (LLPipeline::sUseOcclusion > 1) + if (LLPipeline::sUseOcclusion > 1 && (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) { LLVertexBuffer::unbind(); -- cgit v1.2.3