fix for SH-4402: interesting: lower FPS with lots of objects in view
parent
a2c7b04855
commit
a6711a894c
|
|
@ -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<std::string, std::string> 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<S32> 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<S32> 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<LLDrawable*> 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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<LLOcclusionCullingGroup*> mOccludedGroups;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue