diff options
| author | Richard Linden <none@none> | 2013-04-11 19:42:32 -0700 | 
|---|---|---|
| committer | Richard Linden <none@none> | 2013-04-11 19:42:32 -0700 | 
| commit | 493b84f2fc34ab1bb798b20c022be6edf036b3d7 (patch) | |
| tree | a052293043390a7ff0250f2e8ac78bf33c8efe2a /indra/newview | |
| parent | 9b48f536c112dc68f8cbda9870587f0d16b9bc9d (diff) | |
| parent | 1459a412b9c9776daa7e6f3b5be35fe67970b3c5 (diff) | |
Automated merge with ssh://hg.lindenlab.com/richard/viewer-interesting-metrics
Diffstat (limited to 'indra/newview')
22 files changed, 747 insertions, 240 deletions
| diff --git a/indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl b/indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl index 050114b37e..6eeb2596b2 100644 --- a/indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl @@ -31,6 +31,10 @@ out vec4 frag_color;  uniform sampler2D tex0;  uniform sampler2D tex1; +uniform sampler2D dither_tex; +uniform float dither_scale; +uniform float dither_scale_s; +uniform float dither_scale_t;  VARYING vec2 vary_texcoord0;  VARYING vec2 vary_texcoord1; @@ -38,4 +42,17 @@ VARYING vec2 vary_texcoord1;  void main()   {  	frag_color = abs(texture2D(tex0, vary_texcoord0.xy) - texture2D(tex1, vary_texcoord0.xy)); + +	vec2 dither_coord; +	dither_coord[0] = vary_texcoord0[0] * dither_scale_s; +	dither_coord[1] = vary_texcoord0[1] * dither_scale_t; +	vec4 dither_vec = texture(dither_tex, dither_coord.xy); + +	for(int i = 0; i < 3; i++) +	{ +		if(frag_color[i] < dither_vec[i] * dither_scale) +		{ +			frag_color[i] = 0.f; +		} +	}  } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index cca94cdfd8..0b0db432c8 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4020,6 +4020,14 @@ void LLAppViewer::purgeCache()  	gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), "*.*");  } +//purge cache immediately, do not wait until the next login. +void LLAppViewer::purgeCacheImmediate() +{ +	LL_INFOS("AppCache") << "Purging Object Cache and Texture Cache immediately..." << LL_ENDL; +	LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE); +	LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true); +} +  std::string LLAppViewer::getSecondLifeTitle() const  {  	return LLTrans::getString("APP_NAME"); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 85a29925fb..627652dc30 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -170,6 +170,7 @@ public:  	void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle  	void purgeCache(); // Clear the local cache.  +	void purgeCacheImmediate(); //clear local cache immediately.  	// mute/unmute the system's master audio  	virtual void setMasterSystemAudioMute(bool mute); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 28e4b32793..56619563cf 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2346,8 +2346,6 @@ F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist)  			return 0.f ;  		} -		//F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ; -		  		S32 i = 0 ;  		for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i);  		i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 3a2171a014..15fe77f028 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -499,7 +499,7 @@ void LLSceneMonitor::fetchQueryResult()  	glGetQueryObjectuivARB(mQueryObject, GL_QUERY_RESULT_ARB, &count);  	mDiffResult = count * 0.5f / (mDiff->getWidth() * mDiff->getHeight() * mDiffPixelRatio * mDiffPixelRatio); //0.5 -> (front face + back face) -	 +  	addMonitorResult();  } @@ -511,19 +511,19 @@ void LLSceneMonitor::addMonitorResult()  		return;  	} -	mRecording->extend(); -	sample(sFramePixelDiff, mDiffResult); +		mRecording->extend(); +		sample(sFramePixelDiff, mDiffResult);  	ll_monitor_result_t result;  	result.mTimeStamp = LLImageGL::sLastFrameTime;  	result.mDiff = mDiffResult;  	mMonitorResults.push_back(result); -} +	}  //dump results to a file _scene_monitor_results.csv  void LLSceneMonitor::dumpToFile(std::string file_name)  { -	if(mMonitorResults.empty()) +	if(mMonitorResults.empty() || !getRecording())  	{  		return; //nothing to dump  	} diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index ffec284f72..d7835d8567 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -100,7 +100,7 @@ public:  	BOOL projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp = TRUE) const;  	BOOL projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLCoordGL &out_point) const; -	const LLVector3* getVelocityDir() const {return &mVelocityDir;} +	LLVector3 getVelocityDir() const {return mVelocityDir;}  	static LLTrace::CountStatHandle<>* getVelocityStat()		   {return &sVelocityStat; }  	static LLTrace::CountStatHandle<>* getAngularVelocityStat()  {return &sAngularVelocityStat; }  	F32     getCosHalfFov() {return mCosHalfCameraFOV;} diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 25907dcb52..eebf4f0bea 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7566,6 +7566,23 @@ void handle_web_browser_test(const LLSD& param)  	LLWeb::loadURLInternal(url);  } +bool callback_clear_cache_immediately(const LLSD& notification, const LLSD& response) +{ +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	if ( option == 0 ) // YES +	{ +		//clear cache +		LLAppViewer::instance()->purgeCacheImmediate(); +	} + +	return false; +} + +void handle_cache_clear_immediately() +{ +	LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately); +} +  void handle_web_content_test(const LLSD& param)  {  	std::string url = param.asString(); @@ -8489,6 +8506,8 @@ void initialize_menus()  	//Develop (Texture Fetch Debug Console)  	view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger"); +	//Develop (clear cache immediately) +	commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) );  	// Admin >Object  	view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 4b1c9c5574..8dc72ba5b4 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -4222,6 +4222,9 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)  	LLQuaternion head_rotation = gAgent.getHeadRotation();  	camera_pos_agent = gAgentCamera.getCameraPositionAgent(); +	LLVector3 camera_velocity = LLViewerCamera::getInstance()->getVelocityDir() * LLViewerCamera::getInstance()->getAverageSpeed(); +	F32 time_delta = 1.0f; //predict the camera position in 1 second +	camera_pos_agent += camera_velocity * time_delta;  	render_state = gAgent.getRenderState(); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 61c5a52f98..d5d804bc57 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, @@ -1718,14 +1836,10 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				// stores the extended permission info.  				if(mesgsys != NULL)  				{ -				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); -			} +					U32 flags; +					mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); +					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 933b017aa6..942eb67823 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 b26be5bc63..922d386818 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -262,7 +262,7 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,  	// so that the drawable parent is set properly  	if(msg != NULL)  	{ -	findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort()); +		findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort());  	}  	else  	{ @@ -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,24 +447,37 @@ 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)  		{ -			S32							uncompressed_length = 2048; -			compressed_dp.reset(); - +			S32	uncompressed_length = 2048; +			compressed_dp.reset();			 +			  			uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);  			mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i);  			compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length);  			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; @@ -601,11 +623,12 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  				if(!(flags & FLAGS_TEMPORARY_ON_REZ))  				{ -				bCached = true; -				LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); +					bCached = true; +					LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp, flags);  					recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size); +				}  			} -		} +#endif  		}  		else  		{ @@ -657,13 +680,15 @@ void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys,  		S32	msg_size = 0;  		U32 id;  		U32 crc; +		U32 flags;  		mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i);  		mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i); +		mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);  		msg_size += sizeof(U32) * 2;  		// Lookup data packer and add this id to cache miss lists if necessary.  		U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; -		if(!regionp->probeCache(id, crc, cache_miss_type)) +		if(!regionp->probeCache(id, crc, flags, cache_miss_type))  		{  			// Cache Miss.  			recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size); @@ -1324,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. @@ -1339,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;  	} @@ -2121,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/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index cfa24c32ed..926d791d1f 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -32,6 +32,7 @@  //static variables definitions  //-----------------------------------------------------------------------------------  U32 LLViewerOctreeEntryData::sCurVisible = 0; +BOOL LLViewerOctreeDebug::sInDebug = FALSE;  //-----------------------------------------------------------------------------------  //some global functions definitions @@ -528,7 +529,7 @@ void LLviewerOctreeGroup::handleChildAddition(const OctreeNode* parent, OctreeNo  	unbound(); -	//((LLviewerOctreeGroup*)child->getListener(0))->unbound(); +	((LLviewerOctreeGroup*)child->getListener(0))->unbound();  }  //virtual  @@ -798,3 +799,46 @@ void LLViewerOctreeCull::visit(const OctreeNode* branch)  	}  } +//-------------------------------------------------------------- +//class LLViewerOctreeDebug +//virtual  +void LLViewerOctreeDebug::visit(const OctreeNode* branch) +{ +#if 0 +	llinfos << "Node: " << (U32)branch << " # Elements: " << branch->getElementCount() << " # Children: " << branch->getChildCount() << llendl; +	for (U32 i = 0; i < branch->getChildCount(); i++) +	{ +		llinfos << "Child " << i << " : " << (U32)branch->getChild(i) << llendl; +	} +#endif +	LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) branch->getListener(0); +	processGroup(group);	 +} + +//virtual  +void LLViewerOctreeDebug::processGroup(LLviewerOctreeGroup* group) +{ +#if 0 +	const LLVector4a* vec4 = group->getBounds(); +	LLVector3 vec[2]; +	vec[0].set(vec4[0].getF32ptr()); +	vec[1].set(vec4[1].getF32ptr()); +	llinfos << "Bounds: " << vec[0] << " : " << vec[1] << llendl; + +	vec4 = group->getExtents(); +	vec[0].set(vec4[0].getF32ptr()); +	vec[1].set(vec4[1].getF32ptr()); +	llinfos << "Extents: " << vec[0] << " : " << vec[1] << llendl; + +	vec4 = group->getObjectBounds(); +	vec[0].set(vec4[0].getF32ptr()); +	vec[1].set(vec4[1].getF32ptr()); +	llinfos << "ObjectBounds: " << vec[0] << " : " << vec[1] << llendl; + +	vec4 = group->getObjectExtents(); +	vec[0].set(vec4[0].getF32ptr()); +	vec[1].set(vec4[1].getF32ptr()); +	llinfos << "ObjectExtents: " << vec[0] << " : " << vec[1] << llendl; +#endif +} +//-------------------------------------------------------------- diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h index a35c551949..b6faf4c7ba 100644 --- a/indra/newview/llvieweroctree.h +++ b/indra/newview/llvieweroctree.h @@ -324,4 +324,15 @@ protected:  	S32 mRes;  }; +//scan the octree, output the info of each node for debug use. +class LLViewerOctreeDebug : public OctreeTraveler +{ +public: +	virtual void processGroup(LLviewerOctreeGroup* group); +	virtual void visit(const OctreeNode* branch); + +public: +	static BOOL sInDebug; +}; +  #endif 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) diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 9252923aa3..2248cf5269 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -314,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); -	bool probeCache(U32 local_id, U32 crc, U8 &cache_miss_type); +	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(); @@ -346,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	 @@ -356,6 +360,8 @@ private:  	F32 createVisibleObjects(F32 max_time);  	F32 updateVisibleEntries(F32 max_time); //update visible entries +	void addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type); +	void decodeBoundingInfo(LLVOCacheEntry* entry);  public:  	struct CompareDistance  	{ @@ -393,6 +399,7 @@ public:  	static BOOL sVOCacheCullingEnabled; //vo cache culling enabled or not.  private:  	LLViewerRegionImpl * mImpl; +	LLFrameTimer         mRegionTimer;  	F32			mWidth;			// Width of region on a side (meters)  	U64			mHandle; @@ -441,8 +448,44 @@ private:  	BOOL    mReleaseNotesRequested;  	BOOL    mDead;  //if true, this region is in the process of deleting. -	LLDynamicArray<U32>						mCacheMissFull; -	LLDynamicArray<U32>						mCacheMissCRC; +	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) : mID(id), mType(miss_type){} + +		U32                            mID;     //local object id +		LLViewerRegion::eCacheMissType mType;   //cache miss type +	 +#if 0 +		struct Compare +		{ +			bool operator()(const CacheMissItem& lhs, const CacheMissItem& rhs) +			{ +				return lhs.mID < rhs.mID; //smaller ID first. +			} +		}; + +		typedef std::set<CacheMissItem, Compare> cache_miss_list_t; +#else +		typedef std::list<CacheMissItem> cache_miss_list_t; +#endif +	}; +	CacheMissItem::cache_miss_list_t        mCacheMissList;  	caps_received_signal_t mCapabilitiesReceivedSignal;		  	LLSD mSimulatorFeatures; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 28bd02c606..78775c7205 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -2724,6 +2724,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()  			gTwoTextureCompareProgram.bind();  			gTwoTextureCompareProgram.uniform1i("tex0", 0);  			gTwoTextureCompareProgram.uniform1i("tex1", 1); +			gTwoTextureCompareProgram.uniform1i("dither_tex", 2);  		}  	} diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index ae677f541b..759b0c580f 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -60,7 +60,7 @@  #include "llxuiparser.h"  #include "lltracerecording.h"  #include "llviewerdisplay.h" - +#include "llstartup.h"  ////////////////////////////////////////////////////////////////////////////  void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL; @@ -708,7 +708,17 @@ void LLViewerTextureList::updateImagesDecodePriorities()  {  	// Update the decode priority for N images each frame  	{ -        static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities");         // default: 32 +		F32 lazy_flush_timeout = 30.f; // stop decoding +		F32 max_inactive_time  = 20.f; // actually delete +		S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference +		if(LLStartUp::getStartupState() < STATE_STARTED) +		{ +			//do not remove pre-fetched images if viewer does not finish logging in. +			lazy_flush_timeout = 30000.f; +			max_inactive_time = 20000.f; +		} +         +		static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities");         // default: 32  		const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES);  		S32 update_counter = llmin(max_update_count, mUUIDMap.size());  		uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID); @@ -731,14 +741,10 @@ void LLViewerTextureList::updateImagesDecodePriorities()  			//  			// Flush formatted images using a lazy flush  			// -			const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding -			const F32 MAX_INACTIVE_TIME  = 20.f; // actually delete -			S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference -			  			S32 num_refs = imagep->getNumRefs();  			if (num_refs == min_refs)  			{ -				if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > LAZY_FLUSH_TIMEOUT) +				if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout)  				{  					// Remove the unused image from the image list  					deleteImage(imagep); @@ -750,7 +756,7 @@ void LLViewerTextureList::updateImagesDecodePriorities()  			{  				if(imagep->hasSavedRawImage())  				{ -					if(imagep->getElapsedLastReferencedSavedRawImageTime() > MAX_INACTIVE_TIME) +					if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time)  					{  						imagep->destroySavedRawImage() ;  					} @@ -767,7 +773,7 @@ void LLViewerTextureList::updateImagesDecodePriorities()  				}  				else if(imagep->isInactive())  				{ -					if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) +					if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time)  					{  						imagep->setDeletionCandidate() ;  					} diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 86cfbb1d74..1dd149631a 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -34,6 +34,8 @@  #include "llviewerregion.h"  #include "pipeline.h" +LLTrace::MemStatHandle	LLVOCachePartition::sMemStat("LLVOCachePartition"); +  BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes)   {  	return apr_file->read(src, n_bytes) == n_bytes ; @@ -53,13 +55,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 +75,7 @@ LLVOCacheEntry::LLVOCacheEntry()  	: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY),  	mLocalID(0),  	mCRC(0), +	mUpdateFlags(-1),  	mHitCount(0),  	mDupeCount(0),  	mCRCChangeCount(0), @@ -77,7 +83,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 +93,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 +126,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 +179,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 +210,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 +277,7 @@ LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP()  void LLVOCacheEntry::recordHit()  { +	setTouched();  	mHitCount++;  } @@ -341,33 +319,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 +353,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 +382,7 @@ LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp)  {  	mRegionp = regionp;  	mPartitionType = LLViewerRegion::PARTITION_VO_CACHE; -	mVisitedTime = 0; - +	  	new LLviewerOctreeGroup(mOctree);  } @@ -477,12 +449,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 @@ -599,13 +565,19 @@ void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version)  	}	  } -void LLVOCache::removeCache(ELLPath location)  +void LLVOCache::removeCache(ELLPath location, bool started)   { +	if(started) +	{ +		removeCache(); +		return; +	} +  	if(mReadOnly)  	{  		llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl;  		return ; -	} +	}	  	llinfos << "about to remove the object cache due to settings." << llendl ; @@ -628,10 +600,8 @@ void LLVOCache::removeCache()  		return ;  	} -	llinfos << "about to remove the object cache due to some error." << llendl ; -  	std::string mask = "*"; -	llinfos << "Removing cache at " << mObjectCacheDirName << llendl; +	llinfos << "Removing object cache at " << mObjectCacheDirName << llendl;  	gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask);   	clearCacheInMemory() ; @@ -938,7 +908,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 removal_enabled)   {  	if(!mEnabled)  	{ @@ -1011,7 +981,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(!removal_enabled || iter->second->isTouched()) +				{ +					success = iter->second->writeToFile(&apr_file) ; +				}  			}  		}  	} diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index c631e12739..4b775a4288 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,9 +143,11 @@ 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 +class LLVOCachePartition : public LLViewerOctreePartition, public LLTrace::MemTrackable<LLVOCachePartition>  {  public:  	LLVOCachePartition(LLViewerRegion* regionp); @@ -146,8 +156,7 @@ public:  	void removeEntry(LLViewerOctreeEntry* entry);  	/*virtual*/ S32 cull(LLCamera &camera); -private: -	U32 mVisitedTime; +	static	LLTrace::MemStatHandle	sMemStat;  };  // @@ -192,10 +201,10 @@ public:  	~LLVOCache() ;  	void initCache(ELLPath location, U32 size, U32 cache_version) ; -	void removeCache(ELLPath location) ; +	void removeCache(ELLPath location, bool started = false) ;  	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 removal_enabled);  	void removeEntry(U64 handle) ;  	void setReadOnly(BOOL read_only) {mReadOnly = read_only;}  diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 2f0acba23e..a52c2b3192 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2750,6 +2750,16 @@                   function="ToggleControl"                   parameter="RenderHoverGlowEnable" />              </menu_item_check> +          <menu_item_separator /> +           +          <menu_item_call +            enabled="true" +            label="Clear Cache Immediately" +            name="Cache Clear"> +            <menu_item_call.on_click +             function="Develop.ClearCache" /> +          </menu_item_call> +                    </menu>          <menu diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index 41d141255b..ae93778534 100644 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -39,7 +39,7 @@  namespace LLStatViewer  { -	LLTrace::<>		FPS_SAMPLE("fpssample"); +	LLTrace::MeasurementStatHandle<>		FPS_SAMPLE("fpssample");  }  void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts) | 
