summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorRichard Linden <none@none>2013-04-11 19:42:32 -0700
committerRichard Linden <none@none>2013-04-11 19:42:32 -0700
commit493b84f2fc34ab1bb798b20c022be6edf036b3d7 (patch)
treea052293043390a7ff0250f2e8ac78bf33c8efe2a /indra/newview
parent9b48f536c112dc68f8cbda9870587f0d16b9bc9d (diff)
parent1459a412b9c9776daa7e6f3b5be35fe67970b3c5 (diff)
Automated merge with ssh://hg.lindenlab.com/richard/viewer-interesting-metrics
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl17
-rw-r--r--indra/newview/llappviewer.cpp8
-rw-r--r--indra/newview/llappviewer.h1
-rw-r--r--indra/newview/llface.cpp2
-rw-r--r--indra/newview/llscenemonitor.cpp10
-rw-r--r--indra/newview/llviewercamera.h2
-rw-r--r--indra/newview/llviewermenu.cpp19
-rwxr-xr-xindra/newview/llviewermessage.cpp3
-rw-r--r--indra/newview/llviewerobject.cpp176
-rw-r--r--indra/newview/llviewerobject.h16
-rw-r--r--indra/newview/llviewerobjectlist.cpp60
-rw-r--r--indra/newview/llviewerobjectlist.h2
-rw-r--r--indra/newview/llvieweroctree.cpp46
-rw-r--r--indra/newview/llvieweroctree.h11
-rw-r--r--indra/newview/llviewerregion.cpp344
-rw-r--r--indra/newview/llviewerregion.h55
-rw-r--r--indra/newview/llviewershadermgr.cpp1
-rw-r--r--indra/newview/llviewertexturelist.cpp24
-rw-r--r--indra/newview/llvocache.cpp137
-rw-r--r--indra/newview/llvocache.h41
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml10
-rw-r--r--indra/newview/tests/llviewerassetstats_test.cpp2
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)