summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerregion.cpp
diff options
context:
space:
mode:
authorRichard Linden <none@none>2013-04-12 16:35:14 -0700
committerRichard Linden <none@none>2013-04-12 16:35:14 -0700
commitdc261cbe4c7b1de8943f00218d62ab6180e7cfad (patch)
treee52a2ab6c7545ef90a7bd1dcca97adbfb0671d42 /indra/newview/llviewerregion.cpp
parent08b061dc1d9bfef8fc36ac25f260b291adda6d8c (diff)
parent06a953f7fece6e7c5cb8f9facd246580767f8591 (diff)
Automated merge with ssh://hg.lindenlab.com/richard/viewer-interesting-metrics
Diffstat (limited to 'indra/newview/llviewerregion.cpp')
-rw-r--r--indra/newview/llviewerregion.cpp344
1 files changed, 269 insertions, 75 deletions
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 914a201ffe..84e9c8ea9a 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -442,6 +442,10 @@ void LLViewerRegion::loadObjectCache()
if(LLVOCache::hasInstance())
{
LLVOCache::getInstance()->readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ;
+ if (mImpl->mCacheMap.empty())
+ {
+ mCacheDirty = TRUE;
+ }
}
}
@@ -460,7 +464,10 @@ void LLViewerRegion::saveObjectCache()
if(LLVOCache::hasInstance())
{
- LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ;
+ const F32 start_time_threshold = 600.0f; //seconds
+ bool removal_enabled = sVOCacheCullingEnabled && (mRegionTimer.getElapsedTimeF32() > start_time_threshold); //allow to remove invalid objects from object cache file.
+
+ LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty, removal_enabled) ;
mCacheDirty = FALSE;
}
@@ -744,11 +751,13 @@ void LLViewerRegion::dirtyHeights()
void LLViewerRegion::replaceCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry)
{
U32 state = LLVOCacheEntry::INACTIVE;
+ bool in_vo_tree = false;
if(old_entry)
{
old_entry->copyTo(new_entry);
- state = old_entry->getState();
+ state = old_entry->getState();
+ in_vo_tree = (state == LLVOCacheEntry::INACTIVE && old_entry->getGroup() != NULL);
killCacheEntry(old_entry);
}
@@ -763,7 +772,7 @@ void LLViewerRegion::replaceCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry
{
mImpl->mWaitingSet.insert(new_entry);
}
- else if(old_entry && new_entry->getEntry())
+ else if(!old_entry || in_vo_tree)
{
addToVOCacheTree(new_entry);
}
@@ -895,10 +904,6 @@ void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)
{
return;
}
- if(!entry->hasState(LLVOCacheEntry::ADD_TO_CACHE_TREE))
- {
- return; //can not add to vo cache tree.
- }
mImpl->mVOCachePartition->addEntry(entry->getEntry());
}
@@ -1039,6 +1044,17 @@ F32 LLViewerRegion::updateVisibleEntries(F32 max_time)
{
LLVOCacheEntry* vo_entry = (LLVOCacheEntry*)(*i)->getVOCacheEntry();
+ if(vo_entry->getParentID() > 0) //is a child
+ {
+ LLVOCacheEntry* parent = getCacheEntry(vo_entry->getParentID());
+
+ //make sure the parent is active
+ if(!parent || !parent->isState(LLVOCacheEntry::ACTIVE))
+ {
+ continue;
+ }
+ }
+
vo_entry->calcSceneContribution(camera_origin, needs_update, mImpl->mLastCameraUpdate);
mImpl->mWaitingList.insert(vo_entry);
}
@@ -1104,8 +1120,13 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
max_update_time -= update_timer.getElapsedTimeF32();
if(max_update_time < 0.f || mImpl->mCacheMap.empty())
{
- return did_update;
-}
+ return did_update;
+ }
+
+ if(!sVOCacheCullingEnabled)
+ {
+ return did_update;
+ }
sCurRegionp = this;
@@ -1140,7 +1161,7 @@ F32 LLViewerRegion::killInvisibleObjects(F32 max_time)
}
for(S32 i = 0; i < delete_list.size(); i++)
{
- gObjectList.killObject(delete_list[i]->getVObj(), true);
+ gObjectList.killObject(delete_list[i]->getVObj());
}
delete_list.clear();
@@ -1194,6 +1215,28 @@ LLViewerObject* LLViewerRegion::addNewObject(LLVOCacheEntry* entry)
return obj;
}
+//remove from object cache if the object receives a full-update or terse update
+LLViewerObject* LLViewerRegion::forceToRemoveFromCache(U32 local_id, LLViewerObject* objectp)
+{
+ LLVOCacheEntry* entry = getCacheEntry(local_id);
+ if (!entry)
+ {
+ return objectp; //not in the cache, do nothing.
+ }
+ if(!objectp) //object not created
+ {
+ entry->setTouched(FALSE); //mark this entry invalid
+
+ //create a new object before delete it from cache.
+ objectp = gObjectList.processObjectUpdateFromCache(entry, this);
+ }
+
+ //remove from cache.
+ killCacheEntry(entry);
+
+ return objectp;
+}
+
// As above, but forcibly do the update.
void LLViewerRegion::forceUpdate()
{
@@ -1647,14 +1690,136 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
mSimulatorFeatures = sim_features;
}
-LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
+//this is called when the parent is not cacheable.
+//move all orphan children out of cache and insert to rendering octree.
+void LLViewerRegion::findOrphans(U32 parent_id)
+{
+ std::map<U32, OrphanList>::iterator iter = mOrphanMap.find(parent_id);
+ if(iter != mOrphanMap.end())
+ {
+ std::set<U32>* children = mOrphanMap[parent_id].getChildList();
+ for(std::set<U32>::iterator child_iter = children->begin(); child_iter != children->end(); ++child_iter)
+ {
+ forceToRemoveFromCache(*child_iter, NULL);
+ }
+
+ mOrphanMap.erase(parent_id);
+ }
+}
+
+void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
+{
+ if(!sVOCacheCullingEnabled)
+ {
+ gObjectList.processObjectUpdateFromCache(entry, this);
+ return;
+ }
+
+ if(entry != NULL && !entry->getEntry())
+ {
+ entry->setOctreeEntry(NULL);
+ }
+ else if(entry->getGroup() != NULL)
+ {
+ return; //already in octree, no post processing.
+ }
+
+ LLVector3 pos;
+ LLVector3 scale;
+ LLQuaternion rot;
+ U32 parent_id = LLViewerObject::extractSpatialExtents(entry->getDP(), pos, scale, rot);
+
+ entry->setBoundingInfo(pos, scale);
+
+ if(parent_id > 0) //has parent
+ {
+ entry->setParentID(parent_id);
+
+ //1, find parent, update position
+ LLVOCacheEntry* parent = getCacheEntry(parent_id);
+
+ //2, if can not, put into the orphan list.
+ if(!parent || !parent->getGroup())
+ {
+ std::map<U32, OrphanList>::iterator iter = mOrphanMap.find(parent_id);
+ if(iter != mOrphanMap.end())
+ {
+ iter->second.addChild(entry->getLocalID());
+ }
+ else
+ {
+ //check if the parent is an uncacheable object
+ if(!parent)
+ {
+ LLUUID parent_uuid;
+ LLViewerObjectList::getUUIDFromLocal(parent_uuid,
+ parent_id,
+ getHost().getAddress(),
+ getHost().getPort());
+ LLViewerObject *parent_objp = gObjectList.findObject(parent_uuid);
+ if(parent_objp)
+ {
+ //parent is not cacheable, remove child from the cache.
+ forceToRemoveFromCache(entry->getLocalID(), NULL);
+ return;
+ }
+ }
+
+ //otherwise insert to the orphan list
+ OrphanList o_list(entry->getLocalID());
+ mOrphanMap[parent_id] = o_list;
+ }
+
+ return;
+ }
+ else
+ {
+ //update the child position to the region space.
+ entry->updateBoundingInfo(parent);
+ }
+ }
+
+ if(!entry->getGroup() && entry->isState(LLVOCacheEntry::INACTIVE))
+ {
+ addToVOCacheTree(entry);
+ }
+
+ if(!parent_id) //a potential parent
+ {
+ //find all children and update their bounding info
+ std::map<U32, OrphanList>::iterator iter = mOrphanMap.find(entry->getLocalID());
+ if(iter != mOrphanMap.end())
+ {
+ std::set<U32>* children = mOrphanMap[parent_id].getChildList();
+ for(std::set<U32>::iterator child_iter = children->begin(); child_iter != children->end(); ++child_iter)
+ {
+ LLVOCacheEntry* child = getCacheEntry(*child_iter);
+ if(child)
+ {
+ //update the child position to the region space.
+ child->updateBoundingInfo(entry);
+ addToVOCacheTree(child);
+ }
+ }
+
+ mOrphanMap.erase(entry->getLocalID());
+ }
+ }
+
+ return ;
+}
+
+LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags)
{
- U32 local_id = objectp->getLocalID();
- U32 crc = objectp->getCRC();
eCacheUpdateResult result;
+ U32 crc;
+ U32 local_id;
- LLVOCacheEntry* entry = getCacheEntry(local_id);
+ LLViewerObject::unpackU32(&dp, local_id, "LocalID");
+ LLViewerObject::unpackU32(&dp, crc, "CRC");
+ LLVOCacheEntry* entry = getCacheEntry(local_id);
+
if (entry)
{
// we've seen this object before
@@ -1668,9 +1833,22 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
{
// Update the cache entry
LLPointer<LLVOCacheEntry> new_entry = new LLVOCacheEntry(local_id, crc, dp);
- replaceCacheEntry(entry, new_entry);
- entry = new_entry;
-
+
+ //if visible, update it
+ if(!entry->isState(LLVOCacheEntry::INACTIVE))
+ {
+ replaceCacheEntry(entry, new_entry);
+ }
+ else //invisible
+ {
+ //remove old entry
+ killCacheEntry(entry);
+ entry = new_entry;
+
+ mImpl->mCacheMap[local_id] = entry;
+ decodeBoundingInfo(entry);
+ }
+
result = CACHE_UPDATE_CHANGED;
}
}
@@ -1679,16 +1857,26 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
// we haven't seen this object before
// Create new entry and add to map
result = CACHE_UPDATE_ADDED;
- //if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
- //{
- // delete mImpl->mCacheMap.begin()->second ;
- // mImpl->mCacheMap.erase(mImpl->mCacheMap.begin());
- // result = CACHE_UPDATE_REPLACED;
- //
- //}
entry = new LLVOCacheEntry(local_id, crc, dp);
-
+
mImpl->mCacheMap[local_id] = entry;
+
+ decodeBoundingInfo(entry);
+ }
+ entry->setUpdateFlags(flags);
+
+ return result;
+}
+
+LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags)
+{
+ eCacheUpdateResult result = cacheFullUpdate(dp, flags);
+
+#if 0
+ LLVOCacheEntry* entry = mImpl->mCacheMap[objectp->getLocalID()];
+ if(!entry)
+ {
+ return result;
}
if(objectp->mDrawable.notNull() && !entry->getEntry())
@@ -1699,17 +1887,23 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
{
addActiveCacheEntry(entry);
}
+#endif
return result;
}
LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id)
+{
+ if(!sVOCacheCullingEnabled)
{
+ return NULL;
+ }
+
LLVOCacheEntry* entry = getCacheEntry(local_id);
removeFromVOCacheTree(entry);
return entry;
- }
+}
LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id)
{
@@ -1721,9 +1915,18 @@ LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id)
return NULL;
}
+void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type)
+{
+#if 0
+ mCacheMissList.insert(CacheMissItem(id, miss_type));
+#else
+ mCacheMissList.push_back(CacheMissItem(id, miss_type));
+#endif
+}
+
// Get data packer for this object, if we have cached data
// AND the CRC matches. JC
-bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U8 &cache_miss_type)
+bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type)
{
//llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18
@@ -1736,28 +1939,34 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U8 &cache_miss_type)
{
// Record a hit
entry->recordHit();
- cache_miss_type = CACHE_MISS_TYPE_NONE;
+ cache_miss_type = CACHE_MISS_TYPE_NONE;
+ entry->setUpdateFlags(flags);
+
+ if(entry->isState(LLVOCacheEntry::ACTIVE))
+ {
+ ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj()->loadFlags(flags);
+ return true;
+ }
if(entry->getGroup() || !entry->isState(LLVOCacheEntry::INACTIVE))
{
return true;
}
- addVisibleCacheEntry(entry);
+ decodeBoundingInfo(entry);
return true;
}
else
{
// llinfos << "CRC miss for " << local_id << llendl;
- cache_miss_type = CACHE_MISS_TYPE_CRC;
- mCacheMissCRC.put(local_id);
+
+ addCacheMiss(local_id, CACHE_MISS_TYPE_CRC);
}
}
else
{
// llinfos << "Cache miss for " << local_id << llendl;
- cache_miss_type = CACHE_MISS_TYPE_FULL;
- mCacheMissFull.put(local_id);
+ addCacheMiss(local_id, CACHE_MISS_TYPE_FULL);
}
return false;
@@ -1765,49 +1974,22 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U8 &cache_miss_type)
void LLViewerRegion::addCacheMissFull(const U32 local_id)
{
- mCacheMissFull.put(local_id);
+ addCacheMiss(local_id, CACHE_MISS_TYPE_FULL);
}
void LLViewerRegion::requestCacheMisses()
{
- S32 full_count = mCacheMissFull.count();
- S32 crc_count = mCacheMissCRC.count();
- if (full_count == 0 && crc_count == 0) return;
+ if (!mCacheMissList.size())
+ {
+ return;
+ }
LLMessageSystem* msg = gMessageSystem;
BOOL start_new_message = TRUE;
S32 blocks = 0;
- S32 i;
-
- // Send full cache miss updates. For these, we KNOW we don't
- // have a viewer object.
- for (i = 0; i < full_count; i++)
- {
- if (start_new_message)
- {
- msg->newMessageFast(_PREHASH_RequestMultipleObjects);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- start_new_message = FALSE;
- }
-
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_FULL);
- msg->addU32Fast(_PREHASH_ID, mCacheMissFull[i]);
- blocks++;
-
- if (blocks >= 255)
- {
- sendReliableMessage();
- start_new_message = TRUE;
- blocks = 0;
- }
- }
-
- // Send CRC miss updates. For these, we _might_ have a viewer object,
- // but probably not.
- for (i = 0; i < crc_count; i++)
+
+ //send requests for all cache-missed objects
+ for (CacheMissItem::cache_miss_list_t::iterator iter = mCacheMissList.begin(); iter != mCacheMissList.end(); ++iter)
{
if (start_new_message)
{
@@ -1819,8 +2001,8 @@ void LLViewerRegion::requestCacheMisses()
}
msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_CRC);
- msg->addU32Fast(_PREHASH_ID, mCacheMissCRC[i]);
+ msg->addU8Fast(_PREHASH_CacheMissType, (*iter).mType);
+ msg->addU32Fast(_PREHASH_ID, (*iter).mID);
blocks++;
if (blocks >= 255)
@@ -1835,14 +2017,14 @@ void LLViewerRegion::requestCacheMisses()
if (!start_new_message)
{
sendReliableMessage();
- }
- mCacheMissFull.reset();
- mCacheMissCRC.reset();
+ }
mCacheDirty = TRUE ;
// llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl;
- LLViewerStatsRecorder::instance().requestCacheMissesEvent(full_count + crc_count);
+ LLViewerStatsRecorder::instance().requestCacheMissesEvent(mCacheMissList.size());
LLViewerStatsRecorder::instance().log(0.2f);
+
+ mCacheMissList.clear();
}
void LLViewerRegion::dumpCache()
@@ -2005,8 +2187,20 @@ void LLViewerRegion::unpackRegionHandshake()
msg->addUUID("AgentID", gAgent.getID());
msg->addUUID("SessionID", gAgent.getSessionID());
msg->nextBlock("RegionInfo");
- msg->addU32("Flags", 0x0 );
+
+ U32 flags = 0;
+ if(sVOCacheCullingEnabled)
+ {
+ flags = 0x00000001; //set the bit 0 to be 1 to ask sim to send all cacheable objects.
+ if(mImpl->mCacheMap.empty())
+ {
+ flags |= 0x00000002; //set the bit 1 to be 1 to tell sim the cache file is empty, no need to send cache probes.
+ }
+ }
+ msg->addU32("Flags", flags );
msg->sendReliable(host);
+
+ mRegionTimer.reset(); //reset region timer.
}
void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)