diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llmessage/lldatapacker.h | 1 | ||||
-rw-r--r-- | indra/newview/llviewerobject.cpp | 170 | ||||
-rw-r--r-- | indra/newview/llviewerobject.h | 16 | ||||
-rw-r--r-- | indra/newview/llviewerobjectlist.cpp | 44 | ||||
-rw-r--r-- | indra/newview/llviewerobjectlist.h | 2 | ||||
-rw-r--r-- | indra/newview/llviewerregion.cpp | 260 | ||||
-rw-r--r-- | indra/newview/llviewerregion.h | 43 | ||||
-rw-r--r-- | indra/newview/llvocache.cpp | 121 | ||||
-rw-r--r-- | indra/newview/llvocache.h | 37 |
9 files changed, 511 insertions, 183 deletions
diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h index b0a638c16e..226752d52e 100644 --- a/indra/llmessage/lldatapacker.h +++ b/indra/llmessage/lldatapacker.h @@ -170,6 +170,7 @@ public: S32 getBufferSize() const { return mBufferSize; } const U8* getBuffer() const { return mBufferp; } void reset() { mCurBufferp = mBufferp; mWriteEnabled = (mCurBufferp != NULL); } + void shift(S32 offset) { reset(); mCurBufferp += offset;} void freeBuffer() { delete [] mBufferp; mBufferp = mCurBufferp = NULL; mBufferSize = 0; mWriteEnabled = FALSE; } void assignBuffer(U8 *bufferp, S32 size) { diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index a5bd57145d..556b4375a9 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -123,6 +123,7 @@ BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE F64 LLViewerObject::sMaxUpdateInterpolationTime = 3.0; // For motion interpolation: after X seconds with no updates, don't predict object motion F64 LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0; // For motion interpolation: after Y seconds with no updates, taper off motion prediction +std::map<std::string, U32> LLViewerObject::sObjectDataMap; static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object"); @@ -327,22 +328,6 @@ void LLViewerObject::deleteTEImages() mTEImages = NULL; } -//if enabled, add this object to vo cache tree when removed from rendering. -void LLViewerObject::EnableToCacheTree(bool enabled) -{ - if(mDrawable.notNull() && mDrawable->getEntry() && mDrawable->getEntry()->hasVOCacheEntry()) - { - if(enabled) - { - ((LLVOCacheEntry*)mDrawable->getEntry()->getVOCacheEntry())->addState(LLVOCacheEntry::ADD_TO_CACHE_TREE); - } - else - { - ((LLVOCacheEntry*)mDrawable->getEntry()->getVOCacheEntry())->clearState(LLVOCacheEntry::ADD_TO_CACHE_TREE); - } - } -} - void LLViewerObject::markDead() { if (!mDead) @@ -501,6 +486,8 @@ void LLViewerObject::initVOClasses() LLVOGrass::initClass(); LLVOWater::initClass(); LLVOVolume::initClass(); + + initObjectDataMap(); } void LLViewerObject::cleanupVOClasses() @@ -510,6 +497,118 @@ void LLViewerObject::cleanupVOClasses() LLVOTree::cleanupClass(); LLVOAvatar::cleanupClass(); LLVOVolume::cleanupClass(); + + sObjectDataMap.clear(); +} + +//object data map for compressed && !OUT_TERSE_IMPROVED +//static +void LLViewerObject::initObjectDataMap() +{ + U32 count = 0; + + sObjectDataMap["ID"] = count; //full id //LLUUID + count += sizeof(LLUUID); + + sObjectDataMap["LocalID"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["PCode"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["State"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["CRC"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["Material"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["ClickAction"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["Scale"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["Pos"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["Rot"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["SpecialCode"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["Owner"] = count; //LLUUID + count += sizeof(LLUUID); + + sObjectDataMap["Omega"] = count; //LLVector3, when SpecialCode & 0x80 is set + count += sizeof(LLVector3); + + //ParentID is after Omega if there is Omega, otherwise is after Owner + sObjectDataMap["ParentID"] = count;//U32, when SpecialCode & 0x20 is set + count += sizeof(U32); + + //------- + //The rest items are not included here + //------- +} + +//static +void LLViewerObject::unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackVector3(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackUUID(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackU32(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackU8(value, name.c_str()); + dp->reset(); +} + +//static +U32 LLViewerObject::unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id) +{ + dp->shift(sObjectDataMap["SpecialCode"]); + U32 value; + dp->unpackU32(value, "SpecialCode"); + + parent_id = 0; + if(value & 0x20) + { + S32 offset = sObjectDataMap["ParentID"]; + if(!(value & 0x80)) + { + offset -= sizeof(LLVector3); + } + + dp->shift(offset); + dp->unpackU32(parent_id, "ParentID"); + } + dp->reset(); + + return parent_id; } // Replaces all name value pairs with data from \n delimited list @@ -890,6 +989,25 @@ U32 LLViewerObject::checkMediaURL(const std::string &media_url) return retval; } +//extract spatial information from object update message +//return parent_id +//static +U32 LLViewerObject::extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot) +{ + U32 parent_id = 0; + + LLViewerObject::unpackVector3(dp, scale, "Scale"); + LLViewerObject::unpackVector3(dp, pos, "Pos"); + + LLVector3 vec; + LLViewerObject::unpackVector3(dp, vec, "Rot"); + rot.unpackFromVector3(vec); + + LLViewerObject::unpackParentID(dp, parent_id); + + return parent_id; +} + U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -1720,11 +1838,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { U32 flags; mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); - // keep local flags and overwrite remote-controlled flags - mFlags = (mFlags & FLAGS_LOCAL) | flags; - - // ...new objects that should come in selected need to be added to the selected list - mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + loadFlags(flags); } } break; @@ -2225,7 +2339,21 @@ BOOL LLViewerObject::isActive() const return TRUE; } +//load flags from cache or from message +void LLViewerObject::loadFlags(U32 flags) +{ + if(flags == (U32)(-1)) + { + return; //invalid + } + + // keep local flags and overwrite remote-controlled flags + mFlags = (mFlags & FLAGS_LOCAL) | flags; + // ...new objects that should come in selected need to be added to the selected list + mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + return; +} void LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index aa30d1c790..1e79042012 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -70,6 +70,7 @@ class LLViewerRegion; class LLViewerObjectMedia; class LLVOInventoryListener; class LLVOAvatar; +class LLDataPackerBinaryBuffer; typedef enum e_object_update_type { @@ -136,8 +137,7 @@ public: BOOL isDead() const {return mDead;} BOOL isOrphaned() const { return mOrphaned; } BOOL isParticleSource() const; - void EnableToCacheTree(bool enabled); - + virtual LLVOAvatar* asAvatar(); static void initVOClasses(); @@ -162,6 +162,7 @@ public: INVALID_UPDATE = 0x80000000 }; + static U32 extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot); virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -510,6 +511,7 @@ public: virtual void updateRegion(LLViewerRegion *regionp); void updateFlags(BOOL physics_changed = FALSE); + void loadFlags(U32 flags); //load flags from cache or from message BOOL setFlags(U32 flag, BOOL state); BOOL setFlagsWithoutUpdate(U32 flag, BOOL state); void setPhysicsShapeType(U8 type); @@ -540,6 +542,13 @@ public: friend class LLViewerMediaList; public: + static void unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name); + static void unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name); + static void unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name); + static void unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name); + static U32 unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id); + +public: //counter-translation void resetChildrenPosition(const LLVector3& offset, BOOL simplified = FALSE) ; //counter-rotation @@ -562,6 +571,8 @@ private: // Motion prediction between updates void interpolateLinearMotion(const F64 & time, const F32 & dt); + static void initObjectDataMap(); + public: // // Viewer-side only types - use the LL_PCODE_APP mask. @@ -610,6 +621,7 @@ private: // Grabbed from UPDATE_FLAGS U32 mFlags; + static std::map<std::string, U32> sObjectDataMap; public: // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties U8 mPhysicsShapeType; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index e0063cf4f1..0700ac025c 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -365,7 +365,8 @@ LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* } processUpdateCore(objectp, NULL, 0, OUT_FULL_CACHED, cached_dpp, justCreated, true); - + objectp->loadFlags(entry->getUpdateFlags()); //just in case, reload update flags from cache. + recorder.log(0.2f); LLVOAvatar::cullAvatarsByPixelArea(); @@ -446,6 +447,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, LLTimer update_timer; BOOL justCreated = FALSE; S32 msg_size = 0; + bool remove_from_cache = false; //remove from object cache if it is a full-update or terse update if (compressed) { @@ -458,12 +460,24 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { - compressed_dp.unpackUUID(fullid, "ID"); - compressed_dp.unpackU32(local_id, "LocalID"); - compressed_dp.unpackU8(pcode, "PCode"); + U32 flags = 0; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); + + if(flags & FLAGS_TEMPORARY_ON_REZ) + { + compressed_dp.unpackUUID(fullid, "ID"); + compressed_dp.unpackU32(local_id, "LocalID"); + compressed_dp.unpackU8(pcode, "PCode"); + } + else //send to object cache + { + regionp->cacheFullUpdate(compressed_dp, flags); + continue; + } } else { + remove_from_cache = true; compressed_dp.unpackU32(local_id, "LocalID"); getUUIDFromLocal(fullid, local_id, @@ -493,6 +507,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } else // OUT_FULL only? { + remove_from_cache = true; mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); msg_size += sizeof(LLUUID); @@ -500,6 +515,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, // llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl; } objectp = findObject(fullid); + + if(remove_from_cache) + { + objectp = regionp->forceToRemoveFromCache(local_id, objectp); + } // This looks like it will break if the local_id of the object doesn't change // upon boundary crossing, but we check for region id matching later... @@ -576,11 +596,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, recorder.objectUpdateFailure(local_id, update_type, msg_size); continue; } + justCreated = TRUE; mNumNewObjects++; } - if (objectp->isDead()) { llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl; @@ -594,6 +614,8 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, objectp->mLocalID = local_id; } processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); + +#if 0 if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { U32 flags = 0; @@ -602,10 +624,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if(!(flags & FLAGS_TEMPORARY_ON_REZ)) { bCached = true; - LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); + LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp, flags); recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size); } } +#endif } else { @@ -1326,7 +1349,7 @@ void LLViewerObjectList::removeDrawable(LLDrawable* drawablep) } } -BOOL LLViewerObjectList::killObject(LLViewerObject *objectp, bool cache_enabled) +BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) { // Don't ever kill gAgentAvatarp, just force it to the agent's region // unless region is NULL which is assumed to mean you are logging out. @@ -1341,7 +1364,6 @@ BOOL LLViewerObjectList::killObject(LLViewerObject *objectp, bool cache_enabled) if (objectp) { - objectp->EnableToCacheTree(cache_enabled); //enable to add to VO cache tree if set. objectp->markDead(); // does the right thing if object already dead return TRUE; } @@ -2123,6 +2145,12 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) return; } + //search object cache to get orphans + if(objectp->getRegion()) + { + objectp->getRegion()->findOrphans(objectp->getLocalID()); + } + // See if we are a parent of an orphan. // Note: This code is fairly inefficient but it should happen very rarely. // It can be sped up if this is somehow a performance issue... diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index cb11ef1f5e..a7a4969768 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -72,7 +72,7 @@ public: LLViewerObject *replaceObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); // TomY: hack to switch VO instances on the fly - BOOL killObject(LLViewerObject *objectp, bool cache_enabled = false); + BOOL killObject(LLViewerObject *objectp); void killObjects(LLViewerRegion *regionp); // Kill all objects owned by a particular region. void killAllObjects(); void removeDrawable(LLDrawable* drawablep); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e5cb2a1b08..bca2108964 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -460,7 +460,11 @@ void LLViewerRegion::saveObjectCache() if(LLVOCache::hasInstance()) { - LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ; + //NOTE: !!!!!!!!!! + //set this to be true when support full region cache probe!!!! + BOOL full_region_cache_probe = FALSE; + + LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty, full_region_cache_probe) ; mCacheDirty = FALSE; } @@ -744,11 +748,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 +769,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 +901,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 +1041,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); } @@ -1140,7 +1153,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 +1207,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 +1682,130 @@ 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(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 +1819,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 +1843,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,6 +1873,7 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec { addActiveCacheEntry(entry); } +#endif return result; } @@ -1721,21 +1896,9 @@ LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id) return NULL; } -//estimate weight of cache missed object -F32 LLViewerRegion::calcObjectWeight(U32 flags) +void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type) { - LLVector3 pos((F32)(flags & 0xff) + 0.5f, (F32)((flags >> 8) & 0xff) + 0.5f, (F32)((flags >> 16) & 0xff) * 16.f + 8.0f); - F32 rad = (F32)((flags >> 24) & 0xff); - - pos += getOriginAgent(); - pos -= LLViewerCamera::getInstance()->getOrigin(); - - return 100.f * rad * rad / pos.lengthSquared(); -} - -void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type, F32 weight) -{ - mCacheMissList.insert(CacheMissItem(id, miss_type, weight)); + mCacheMissList.insert(CacheMissItem(id, miss_type)); } // Get data packer for this object, if we have cached data @@ -1754,26 +1917,33 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss // Record a hit entry->recordHit(); 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; - addCacheMiss(local_id, CACHE_MISS_TYPE_CRC, calcObjectWeight(flags)); + addCacheMiss(local_id, CACHE_MISS_TYPE_CRC); } } else { // llinfos << "Cache miss for " << local_id << llendl; - addCacheMiss(local_id, CACHE_MISS_TYPE_FULL, calcObjectWeight(flags)); + addCacheMiss(local_id, CACHE_MISS_TYPE_FULL); } return false; @@ -1781,7 +1951,7 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss void LLViewerRegion::addCacheMissFull(const U32 local_id) { - addCacheMiss(local_id, CACHE_MISS_TYPE_FULL, 100.f); + addCacheMiss(local_id, CACHE_MISS_TYPE_FULL); } void LLViewerRegion::requestCacheMisses() @@ -1994,7 +2164,13 @@ void LLViewerRegion::unpackRegionHandshake() msg->addUUID("AgentID", gAgent.getID()); msg->addUUID("SessionID", gAgent.getSessionID()); msg->nextBlock("RegionInfo"); - msg->addU32("Flags", 0x0 ); + + U32 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); } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index de14c0fe27..15c2b36e38 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -169,9 +169,6 @@ public: const LLVector3d &getOriginGlobal() const; LLVector3 getOriginAgent() const; - //estimate weight of cache missed object - F32 calcObjectWeight(U32 flags); - // Center is at the height of the water table. const LLVector3d &getCenterGlobal() const; LLVector3 getCenterAgent() const; @@ -317,11 +314,16 @@ public: } eCacheUpdateResult; // handle a full update message - eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp); + eCacheUpdateResult cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags); + eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags); LLVOCacheEntry* getCacheEntryForOctree(U32 local_id); + LLVOCacheEntry* getCacheEntry(U32 local_id); bool probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type); void requestCacheMisses(); void addCacheMissFull(const U32 local_id); + //remove from object cache if the object receives a full-update or terse update + LLViewerObject* forceToRemoveFromCache(U32 local_id, LLViewerObject* objectp); + void findOrphans(U32 parent_id); void dumpCache(); @@ -349,8 +351,7 @@ public: private: void addToVOCacheTree(LLVOCacheEntry* entry); LLViewerObject* addNewObject(LLVOCacheEntry* entry); - void killObject(LLVOCacheEntry* entry, std::vector<LLDrawable*>& delete_list); - LLVOCacheEntry* getCacheEntry(U32 local_id); + void killObject(LLVOCacheEntry* entry, std::vector<LLDrawable*>& delete_list); void removeFromVOCacheTree(LLVOCacheEntry* entry); void replaceCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry); void killCacheEntry(LLVOCacheEntry* entry); //physically delete the cache entry @@ -359,7 +360,8 @@ private: F32 createVisibleObjects(F32 max_time); F32 updateVisibleEntries(F32 max_time); //update visible entries - void addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type, F32 weight); + void addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type); + void decodeBoundingInfo(LLVOCacheEntry* entry); public: struct CompareDistance { @@ -445,27 +447,34 @@ private: BOOL mReleaseNotesRequested; BOOL mDead; //if true, this region is in the process of deleting. + class OrphanList + { + public: + OrphanList(){} + OrphanList(U32 child_id){addChild(child_id);} + + void addChild(U32 child_id) {mChildList.insert(child_id);} + std::set<U32>* getChildList() {return &mChildList;} + + private: + std::set<U32> mChildList; + }; + + std::map<U32, OrphanList> mOrphanMap; + class CacheMissItem { public: - CacheMissItem(U32 id, LLViewerRegion::eCacheMissType miss_type, F32 weight) : mID(id), mType(miss_type), mWeight(weight){} + CacheMissItem(U32 id, LLViewerRegion::eCacheMissType miss_type) : mID(id), mType(miss_type){} U32 mID; //local object id LLViewerRegion::eCacheMissType mType; //cache miss type - F32 mWeight; //importance of this object to the current camera. struct Compare { bool operator()(const CacheMissItem& lhs, const CacheMissItem& rhs) { - if(lhs.mWeight == rhs.mWeight) //larger weight first - { - return &lhs < &rhs; - } - else - { - return lhs.mWeight > rhs.mWeight; //larger weight first - } + return lhs.mID < rhs.mID; //smaller ID first. } }; diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 86cfbb1d74..5f112675dc 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -53,13 +53,16 @@ LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer & : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mLocalID(local_id), mCRC(crc), + mUpdateFlags(-1), mHitCount(0), mDupeCount(0), mCRCChangeCount(0), mState(INACTIVE), mRepeatedVisCounter(0), mVisFrameRange(64), - mSceneContrib(0.f) + mSceneContrib(0.f), + mTouched(TRUE), + mParentID(0) { mBuffer = new U8[dp.getBufferSize()]; mDP.assignBuffer(mBuffer, dp.getBufferSize()); @@ -70,6 +73,7 @@ LLVOCacheEntry::LLVOCacheEntry() : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mLocalID(0), mCRC(0), + mUpdateFlags(-1), mHitCount(0), mDupeCount(0), mCRCChangeCount(0), @@ -77,7 +81,9 @@ LLVOCacheEntry::LLVOCacheEntry() mState(INACTIVE), mRepeatedVisCounter(0), mVisFrameRange(64), - mSceneContrib(0.f) + mSceneContrib(0.f), + mTouched(TRUE), + mParentID(0) { mDP.assignBuffer(mBuffer, 0); } @@ -85,10 +91,13 @@ LLVOCacheEntry::LLVOCacheEntry() LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mBuffer(NULL), + mUpdateFlags(-1), mState(INACTIVE), mRepeatedVisCounter(0), mVisFrameRange(64), - mSceneContrib(0.f) + mSceneContrib(0.f), + mTouched(FALSE), + mParentID(0) { S32 size = -1; BOOL success; @@ -115,36 +124,6 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) } if(success) { - success = check_read(apr_file, &mState, sizeof(U32)); - } - if(success) - { - F32 ext[8]; - success = check_read(apr_file, (void*)ext, sizeof(F32) * 8); - - LLVector4a exts[2]; - exts[0].load4a(ext); - exts[1].load4a(&ext[4]); - - setSpatialExtents(exts[0], exts[1]); - } - if(success) - { - LLVector4 pos; - success = check_read(apr_file, (void*)pos.mV, sizeof(LLVector4)); - - LLVector4a pos_; - pos_.load4a(pos.mV); - setPositionGroup(pos_); - } - if(success) - { - F32 rad; - success = check_read(apr_file, &rad, sizeof(F32)); - setBinRadius(rad); - } - if(success) - { success = check_read(apr_file, &size, sizeof(S32)); // Corruption in the cache entries @@ -198,10 +177,8 @@ void LLVOCacheEntry::setOctreeEntry(LLViewerOctreeEntry* entry) if(!entry && mDP.getBufferSize() > 0) { LLUUID fullid; - mDP.reset(); - mDP.unpackUUID(fullid, "ID"); - mDP.reset(); - + LLViewerObject::unpackUUID(&mDP, fullid, "ID"); + LLViewerObject* obj = gObjectList.findObject(fullid); if(obj && obj->mDrawable) { @@ -231,9 +208,7 @@ void LLVOCacheEntry::copyTo(LLVOCacheEntry* new_entry) void LLVOCacheEntry::setState(U32 state) { - mState &= 0xffff0000; //clear the low 16 bits - state &= 0x0000ffff; //clear the high 16 bits; - mState |= state; + mState = state; if(getState() == ACTIVE) { @@ -300,6 +275,7 @@ LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP() void LLVOCacheEntry::recordHit() { + setTouched(); mHitCount++; } @@ -341,33 +317,6 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const } if(success) { - U32 state = mState & 0xffff0000; //only store the high 16 bits. - success = check_write(apr_file, (void*)&state, sizeof(U32)); - } - if(success) - { - const LLVector4a* exts = getSpatialExtents() ; - LLVector4 ext(exts[0][0], exts[0][1], exts[0][2], exts[0][3]); - success = check_write(apr_file, ext.mV, sizeof(LLVector4)); - if(success) - { - ext.set(exts[1][0], exts[1][1], exts[1][2], exts[1][3]); - success = check_write(apr_file, ext.mV, sizeof(LLVector4)); - } - } - if(success) - { - const LLVector4a pos_ = getPositionGroup() ; - LLVector4 pos(pos_[0], pos_[1], pos_[2], pos_[3]); - success = check_write(apr_file, pos.mV, sizeof(LLVector4)); - } - if(success) - { - F32 rad = getBinRadius(); - success = check_write(apr_file, (void*)&rad, sizeof(F32)); - } - if(success) - { S32 size = mDP.getBufferSize(); success = check_write(apr_file, (void*)&size, sizeof(S32)); @@ -402,6 +351,28 @@ void LLVOCacheEntry::calcSceneContribution(const LLVector3& camera_origin, bool setVisible(); } +void LLVOCacheEntry::setBoundingInfo(const LLVector3& pos, const LLVector3& scale) +{ + LLVector4a center, newMin, newMax; + center.load3(pos.mV); + LLVector4a size; + size.load3(scale.mV); + newMin.setSub(center, size); + newMax.setAdd(center, size); + + setPositionGroup(center); + setSpatialExtents(newMin, newMax); + setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f)); +} + +void LLVOCacheEntry::updateBoundingInfo(LLVOCacheEntry* parent) +{ + //LLVector4a old_pos = getPositionGroup(); + //parent->getPositionRegion() + (getPosition() * parent->getRotation()); + + shift(parent->getPositionGroup()); +} + //------------------------------------------------------------------- //LLVOCachePartition //------------------------------------------------------------------- @@ -409,8 +380,7 @@ LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp) { mRegionp = regionp; mPartitionType = LLViewerRegion::PARTITION_VO_CACHE; - mVisitedTime = 0; - + new LLviewerOctreeGroup(mOctree); } @@ -477,12 +447,6 @@ S32 LLVOCachePartition::cull(LLCamera &camera) return 0; } - if(mVisitedTime == LLViewerOctreeEntryData::getCurrentFrame()) - { - return 0; //already visited. - } - mVisitedTime = LLViewerOctreeEntryData::getCurrentFrame(); - ((LLviewerOctreeGroup*)mOctree->getListener(0))->rebound(); //localize the camera @@ -938,7 +902,7 @@ void LLVOCache::purgeEntries(U32 size) mNumEntries = mHandleEntryMap.size() ; } -void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) +void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, BOOL full_region_cache_probe) { if(!mEnabled) { @@ -1011,7 +975,10 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter) { - success = iter->second->writeToFile(&apr_file) ; + if(!full_region_cache_probe || iter->second->isTouched()) + { + success = iter->second->writeToFile(&apr_file) ; + } } } } diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index c631e12739..64eb876919 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -41,7 +41,7 @@ class LLCamera; class LLVOCacheEntry : public LLViewerOctreeEntryData { public: - enum + enum //low 16-bit state { INACTIVE = 0x00000000, //not visible IN_QUEUE = 0x00000001, //in visible queue, object to be created @@ -49,11 +49,6 @@ public: ACTIVE = 0x00000004 //object created, and in rendering pipeline. }; - enum - { - ADD_TO_CACHE_TREE = 0x00010000, //has parent - }; - struct CompareVOCacheEntry { bool operator()(const LLVOCacheEntry* const& lhs, const LLVOCacheEntry* const& rhs) @@ -84,12 +79,10 @@ public: LLVOCacheEntry(); void setState(U32 state); - void clearState(U32 state) {mState &= ~state;} - void addState(U32 state) {mState |= state;} - bool isState(U32 state) {return (mState & 0xffff) == state;} + //void clearState(U32 state) {mState &= ~state;} + bool isState(U32 state) {return mState == state;} bool hasState(U32 state) {return mState & state;} - U32 getState() const {return (mState & 0xffff);} - U32 getFullState() const {return mState;} + U32 getState() const {return mState;} U32 getLocalID() const { return mLocalID; } U32 getCRC() const { return mCRC; } @@ -111,11 +104,24 @@ public: void copyTo(LLVOCacheEntry* new_entry); //copy variables /*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry); + void setParentID(U32 id) {mParentID = id;} + U32 getParentID() const {return mParentID;} + void addChild(LLVOCacheEntry* entry); LLVOCacheEntry* getChild(S32 i) {return mChildrenList[i];} S32 getNumOfChildren() {return mChildrenList.size();} void clearChildrenList() {mChildrenList.clear();} + //called from processing object update message + void setBoundingInfo(const LLVector3& pos, const LLVector3& scale); + void updateBoundingInfo(LLVOCacheEntry* parent); + + void setTouched(BOOL touched = TRUE) {mTouched = touched;} + BOOL isTouched() const {return mTouched;} + + void setUpdateFlags(U32 flags) {mUpdateFlags = flags;} + U32 getUpdateFlags() const {return mUpdateFlags;} + public: typedef std::map<U32, LLPointer<LLVOCacheEntry> > vocache_entry_map_t; typedef std::set<LLVOCacheEntry*> vocache_entry_set_t; @@ -123,7 +129,9 @@ public: protected: U32 mLocalID; + U32 mParentID; U32 mCRC; + U32 mUpdateFlags; //receive from sim S32 mHitCount; S32 mDupeCount; S32 mCRCChangeCount; @@ -135,6 +143,8 @@ protected: S32 mRepeatedVisCounter; //number of repeatedly visible within a short time. U32 mState; //high 16 bits reserved for special use. std::vector<LLVOCacheEntry*> mChildrenList; //children entries in a linked set. + + BOOL mTouched; //if set, this entry is valid, otherwise it is invalid. }; class LLVOCachePartition : public LLViewerOctreePartition @@ -145,9 +155,6 @@ public: void addEntry(LLViewerOctreeEntry* entry); void removeEntry(LLViewerOctreeEntry* entry); /*virtual*/ S32 cull(LLCamera &camera); - -private: - U32 mVisitedTime; }; // @@ -195,7 +202,7 @@ public: void removeCache(ELLPath location) ; void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; - void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) ; + void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, BOOL full_region_cache_probe); void removeEntry(U64 handle) ; void setReadOnly(BOOL read_only) {mReadOnly = read_only;} |