diff options
-rw-r--r-- | indra/llcommon/lltracerecording.h | 2 | ||||
-rw-r--r-- | indra/llmessage/lldatapacker.h | 1 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl | 17 | ||||
-rwxr-xr-x | indra/newview/llagent.cpp | 8 | ||||
-rw-r--r-- | indra/newview/llagent.h | 2 | ||||
-rw-r--r-- | indra/newview/llscenemonitor.cpp | 108 | ||||
-rw-r--r-- | indra/newview/llscenemonitor.h | 13 | ||||
-rw-r--r-- | indra/newview/llviewerobject.cpp | 170 | ||||
-rw-r--r-- | indra/newview/llviewerobject.h | 16 | ||||
-rw-r--r-- | indra/newview/llviewerobjectlist.cpp | 48 | ||||
-rw-r--r-- | indra/newview/llviewerobjectlist.h | 2 | ||||
-rw-r--r-- | indra/newview/llviewerregion.cpp | 307 | ||||
-rw-r--r-- | indra/newview/llviewerregion.h | 50 | ||||
-rw-r--r-- | indra/newview/llviewershadermgr.cpp | 1 | ||||
-rw-r--r-- | indra/newview/llvocache.cpp | 121 | ||||
-rw-r--r-- | indra/newview/llvocache.h | 37 |
16 files changed, 700 insertions, 203 deletions
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 751ff298ce..01cc835d58 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -408,6 +408,8 @@ namespace LLTrace /*virtual*/ void reset(); /*virtual*/ void splitTo(ExtendableRecording& other); /*virtual*/ void splitFrom(ExtendableRecording& other); + + const Recording& getAcceptedRecording() const {return mAcceptedRecording;} private: Recording mAcceptedRecording; Recording mPotentialRecording; diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h index b0a638c16e..226752d52e 100644 --- a/indra/llmessage/lldatapacker.h +++ b/indra/llmessage/lldatapacker.h @@ -170,6 +170,7 @@ public: S32 getBufferSize() const { return mBufferSize; } const U8* getBuffer() const { return mBufferp; } void reset() { mCurBufferp = mBufferp; mWriteEnabled = (mCurBufferp != NULL); } + void shift(S32 offset) { reset(); mCurBufferp += offset;} void freeBuffer() { delete [] mBufferp; mBufferp = mCurBufferp = NULL; mBufferSize = 0; mWriteEnabled = FALSE; } void assignBuffer(U8 *bufferp, S32 size) { diff --git a/indra/newview/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/llagent.cpp b/indra/newview/llagent.cpp index 4fb298df13..4e60127ef3 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1046,6 +1046,14 @@ const LLVector3d &LLAgent::getPositionGlobal() const return mPositionGlobal; } +bool LLAgent::isPositionChanged() const +{ + LLVector3d diff; + diff = mPositionGlobal - mLastPositionGlobal; + + return diff.lengthSquared() > 1.0; +} + //----------------------------------------------------------------------------- // getPositionAgent() //----------------------------------------------------------------------------- diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 99904e118c..a1e899b45d 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -250,6 +250,8 @@ public: const LLVector3d &getLastPositionGlobal() const { return mLastPositionGlobal; } void setLastPositionGlobal(const LLVector3d &pos) { mLastPositionGlobal = pos; } + + bool isPositionChanged() const; private: std::set<U64> mRegionsVisited; // Stat - what distinct regions has the avatar been to? F64 mDistanceTraveled; // Stat - how far has the avatar moved? diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 189697dcf0..4eb44bcc00 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -37,6 +37,8 @@ #include "llwindow.h" #include "llpointer.h" #include "llspatialpartition.h" +#include "llagent.h" +#include "pipeline.h" LLSceneMonitorView* gSceneMonitorView = NULL; @@ -67,7 +69,10 @@ LLSceneMonitor::LLSceneMonitor() : mDiffPixelRatio(0.5f) { mFrames[0] = NULL; - mFrames[1] = NULL; + mFrames[1] = NULL; + + mRecording = new LLTrace::ExtendableRecording(); + mRecording->start(); } LLSceneMonitor::~LLSceneMonitor() @@ -78,6 +83,10 @@ LLSceneMonitor::~LLSceneMonitor() void LLSceneMonitor::destroyClass() { reset(); + + delete mRecording; + mRecording = NULL; + mDitheringTexture = NULL; } void LLSceneMonitor::reset() @@ -100,6 +109,67 @@ void LLSceneMonitor::reset() } } +void LLSceneMonitor::generateDitheringTexture(S32 width, S32 height) +{ +#if 1 + //4 * 4 matrix + mDitherMatrixWidth = 4; + S32 dither_matrix[4][4] = + { + {1, 9, 3, 11}, + {13, 5, 15, 7}, + {4, 12, 2, 10}, + {16, 8, 14, 6} + }; + + mDitherScale = 255.f / 17; +#else + //8 * 8 matrix + mDitherMatrixWidth = 16; + S32 dither_matrix[16][16] = + { + {1, 49, 13, 61, 4, 52, 16, 64, 1, 49, 13, 61, 4, 52, 16, 64}, + {33, 17, 45, 29, 36, 20, 48, 32, 33, 17, 45, 29, 36, 20, 48, 32}, + {9, 57, 5, 53, 12, 60, 8, 56, 9, 57, 5, 53, 12, 60, 8, 56}, + {41, 25, 37, 21, 44, 28, 40, 24, 41, 25, 37, 21, 44, 28, 40, 24}, + {3, 51, 15, 63, 2, 50, 14, 62, 3, 51, 15, 63, 2, 50, 14, 62}, + {35, 19, 47, 31, 34, 18, 46, 30, 35, 19, 47, 31, 34, 18, 46, 30}, + {11, 59, 7, 55, 10, 58, 6, 54, 11, 59, 7, 55, 10, 58, 6, 54}, + {43, 27, 39, 23, 42, 26, 38, 22, 43, 27, 39, 23, 42, 26, 38, 22}, + {1, 49, 13, 61, 4, 52, 16, 64, 1, 49, 13, 61, 4, 52, 16, 64}, + {33, 17, 45, 29, 36, 20, 48, 32, 33, 17, 45, 29, 36, 20, 48, 32}, + {9, 57, 5, 53, 12, 60, 8, 56, 9, 57, 5, 53, 12, 60, 8, 56}, + {41, 25, 37, 21, 44, 28, 40, 24, 41, 25, 37, 21, 44, 28, 40, 24}, + {3, 51, 15, 63, 2, 50, 14, 62, 3, 51, 15, 63, 2, 50, 14, 62}, + {35, 19, 47, 31, 34, 18, 46, 30, 35, 19, 47, 31, 34, 18, 46, 30}, + {11, 59, 7, 55, 10, 58, 6, 54, 11, 59, 7, 55, 10, 58, 6, 54}, + {43, 27, 39, 23, 42, 26, 38, 22, 43, 27, 39, 23, 42, 26, 38, 22} + }; + + mDitherScale = 255.f / 65; +#endif + + LLPointer<LLImageRaw> image_raw = new LLImageRaw(mDitherMatrixWidth, mDitherMatrixWidth, 3); + U8* data = image_raw->getData(); + for (S32 i = 0; i < mDitherMatrixWidth; i++) + { + for (S32 j = 0; j < mDitherMatrixWidth; j++) + { + U8 val = dither_matrix[i][j]; + *data++ = val; + *data++ = val; + *data++ = val; + } + } + + mDitheringTexture = LLViewerTextureManager::getLocalTexture(image_raw.get(), FALSE) ; + mDitheringTexture->setAddressMode(LLTexUnit::TAM_WRAP); + mDitheringTexture->setFilteringOption(LLTexUnit::TFO_POINT); + + mDitherScaleS = (F32)width / mDitherMatrixWidth; + mDitherScaleT = (F32)height / mDitherMatrixWidth; +} + void LLSceneMonitor::setDebugViewerVisible(BOOL visible) { mDebugViewerVisible = visible; @@ -137,6 +207,11 @@ bool LLSceneMonitor::preCapture() return false; } + if(gAgent.isPositionChanged()) + { + mRecording->reset(); + } + if(timer.getElapsedTimeF32() < mSamplingTime) { return false; @@ -197,6 +272,9 @@ void LLSceneMonitor::freezeScene() // freeze everything else gSavedSettings.setBOOL("FreezeTime", TRUE); + + gPipeline.clearRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::END_RENDER_TYPES); } void LLSceneMonitor::unfreezeScene() @@ -206,6 +284,9 @@ void LLSceneMonitor::unfreezeScene() // thaw everything else gSavedSettings.setBOOL("FreezeTime", FALSE); + + gPipeline.setRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::END_RENDER_TYPES); } void LLSceneMonitor::capture() @@ -268,10 +349,13 @@ void LLSceneMonitor::compare() { mDiff = new LLRenderTarget(); mDiff->allocate(width, height, GL_RGBA, false, false, LLTexUnit::TT_TEXTURE, true); + + generateDitheringTexture(width, height); } else if(mDiff->getWidth() != width || mDiff->getHeight() != height) { mDiff->resize(width, height, GL_RGBA); + generateDitheringTexture(width, height); } mDiff->bindTarget(); @@ -279,6 +363,10 @@ void LLSceneMonitor::compare() gTwoTextureCompareProgram.bind(); + gTwoTextureCompareProgram.uniform1f("dither_scale", mDitherScale); + gTwoTextureCompareProgram.uniform1f("dither_scale_s", mDitherScaleS); + gTwoTextureCompareProgram.uniform1f("dither_scale_t", mDitherScaleT); + gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->bind(mFrames[0]); @@ -289,6 +377,11 @@ void LLSceneMonitor::compare() gGL.getTexUnit(1)->bind(mFrames[1]); gGL.getTexUnit(1)->activate(); + gGL.getTexUnit(2)->activate(); + gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(2)->bind(mDitheringTexture); + gGL.getTexUnit(2)->activate(); + gl_rect_2d_simple_tex(width, height); mDiff->flush(); @@ -299,6 +392,8 @@ void LLSceneMonitor::compare() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->disable(); gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(2)->disable(); + gGL.getTexUnit(2)->unbind(LLTexUnit::TT_TEXTURE); mHasNewDiff = TRUE; @@ -368,6 +463,7 @@ void LLSceneMonitor::calcDiffAggregate() } } +static LLTrace::Measurement<> sFramePixelDiff("FramePixelDifference"); void LLSceneMonitor::fetchQueryResult() { if(!mHasNewQueryResult) @@ -388,6 +484,11 @@ void LLSceneMonitor::fetchQueryResult() mDiffResult = count * 0.5f / (mDiff->getWidth() * mDiff->getHeight() * mDiffPixelRatio * mDiffPixelRatio); //0.5 -> (front face + back face) + if(mDiffResult > 0.01f) + { + mRecording->extend(); + sFramePixelDiff.sample(mDiffResult); + } //llinfos << count << " : " << mDiffResult << llendl; } //------------------------------------------------------------------------------------------------------------- @@ -454,6 +555,11 @@ void LLSceneMonitorView::draw() num_str = llformat("Sampling time: %.3f seconds", LLSceneMonitor::getInstance()->getSamplingTime()); LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, 5, getRect().getHeight() - line_height * lines, color, LLFontGL::LEFT, LLFontGL::TOP); + lines++; + + num_str = llformat("Scene Loading time: %.3f seconds", (F32)LLSceneMonitor::getInstance()->getRecording()->getAcceptedRecording().getDuration().value()); + LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, 5, getRect().getHeight() - line_height * lines, color, LLFontGL::LEFT, LLFontGL::TOP); + lines++; LLView::draw(); } diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h index 02e3d57d46..709650e206 100644 --- a/indra/newview/llscenemonitor.h +++ b/indra/newview/llscenemonitor.h @@ -31,9 +31,11 @@ #include "llmath.h" #include "llfloater.h" #include "llcharacter.h" +#include "lltracerecording.h" class LLCharacter; class LLRenderTarget; +class LLViewerTexture; class LLSceneMonitor : public LLSingleton<LLSceneMonitor> { @@ -61,11 +63,14 @@ public: bool isEnabled()const {return mEnabled;} bool needsUpdate() const; + LLTrace::ExtendableRecording* getRecording() const {return mRecording;} + private: void freezeScene(); void unfreezeScene(); void reset(); bool preCapture(); + void generateDitheringTexture(S32 width, S32 height); private: BOOL mEnabled; @@ -85,7 +90,15 @@ private: F32 mSamplingTime; //time interval to capture frames, in seconds F32 mDiffPixelRatio; //ratio of pixels used for comparison against the original mDiff size along one dimension + LLPointer<LLViewerTexture> mDitheringTexture; + S32 mDitherMatrixWidth; + F32 mDitherScale; + F32 mDitherScaleS; + F32 mDitherScaleT; + std::vector<LLAnimPauseRequest> mAvatarPauseHandles; + + LLTrace::ExtendableRecording* mRecording; }; class LLSceneMonitorView : public LLFloater diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index a5bd57145d..556b4375a9 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -123,6 +123,7 @@ BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE F64 LLViewerObject::sMaxUpdateInterpolationTime = 3.0; // For motion interpolation: after X seconds with no updates, don't predict object motion F64 LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0; // For motion interpolation: after Y seconds with no updates, taper off motion prediction +std::map<std::string, U32> LLViewerObject::sObjectDataMap; static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object"); @@ -327,22 +328,6 @@ void LLViewerObject::deleteTEImages() mTEImages = NULL; } -//if enabled, add this object to vo cache tree when removed from rendering. -void LLViewerObject::EnableToCacheTree(bool enabled) -{ - if(mDrawable.notNull() && mDrawable->getEntry() && mDrawable->getEntry()->hasVOCacheEntry()) - { - if(enabled) - { - ((LLVOCacheEntry*)mDrawable->getEntry()->getVOCacheEntry())->addState(LLVOCacheEntry::ADD_TO_CACHE_TREE); - } - else - { - ((LLVOCacheEntry*)mDrawable->getEntry()->getVOCacheEntry())->clearState(LLVOCacheEntry::ADD_TO_CACHE_TREE); - } - } -} - void LLViewerObject::markDead() { if (!mDead) @@ -501,6 +486,8 @@ void LLViewerObject::initVOClasses() LLVOGrass::initClass(); LLVOWater::initClass(); LLVOVolume::initClass(); + + initObjectDataMap(); } void LLViewerObject::cleanupVOClasses() @@ -510,6 +497,118 @@ void LLViewerObject::cleanupVOClasses() LLVOTree::cleanupClass(); LLVOAvatar::cleanupClass(); LLVOVolume::cleanupClass(); + + sObjectDataMap.clear(); +} + +//object data map for compressed && !OUT_TERSE_IMPROVED +//static +void LLViewerObject::initObjectDataMap() +{ + U32 count = 0; + + sObjectDataMap["ID"] = count; //full id //LLUUID + count += sizeof(LLUUID); + + sObjectDataMap["LocalID"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["PCode"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["State"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["CRC"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["Material"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["ClickAction"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["Scale"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["Pos"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["Rot"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["SpecialCode"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["Owner"] = count; //LLUUID + count += sizeof(LLUUID); + + sObjectDataMap["Omega"] = count; //LLVector3, when SpecialCode & 0x80 is set + count += sizeof(LLVector3); + + //ParentID is after Omega if there is Omega, otherwise is after Owner + sObjectDataMap["ParentID"] = count;//U32, when SpecialCode & 0x20 is set + count += sizeof(U32); + + //------- + //The rest items are not included here + //------- +} + +//static +void LLViewerObject::unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackVector3(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackUUID(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackU32(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackU8(value, name.c_str()); + dp->reset(); +} + +//static +U32 LLViewerObject::unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id) +{ + dp->shift(sObjectDataMap["SpecialCode"]); + U32 value; + dp->unpackU32(value, "SpecialCode"); + + parent_id = 0; + if(value & 0x20) + { + S32 offset = sObjectDataMap["ParentID"]; + if(!(value & 0x80)) + { + offset -= sizeof(LLVector3); + } + + dp->shift(offset); + dp->unpackU32(parent_id, "ParentID"); + } + dp->reset(); + + return parent_id; } // Replaces all name value pairs with data from \n delimited list @@ -890,6 +989,25 @@ U32 LLViewerObject::checkMediaURL(const std::string &media_url) return retval; } +//extract spatial information from object update message +//return parent_id +//static +U32 LLViewerObject::extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot) +{ + U32 parent_id = 0; + + LLViewerObject::unpackVector3(dp, scale, "Scale"); + LLViewerObject::unpackVector3(dp, pos, "Pos"); + + LLVector3 vec; + LLViewerObject::unpackVector3(dp, vec, "Rot"); + rot.unpackFromVector3(vec); + + LLViewerObject::unpackParentID(dp, parent_id); + + return parent_id; +} + U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -1720,11 +1838,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { U32 flags; mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); - // keep local flags and overwrite remote-controlled flags - mFlags = (mFlags & FLAGS_LOCAL) | flags; - - // ...new objects that should come in selected need to be added to the selected list - mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + loadFlags(flags); } } break; @@ -2225,7 +2339,21 @@ BOOL LLViewerObject::isActive() const return TRUE; } +//load flags from cache or from message +void LLViewerObject::loadFlags(U32 flags) +{ + if(flags == (U32)(-1)) + { + return; //invalid + } + + // keep local flags and overwrite remote-controlled flags + mFlags = (mFlags & FLAGS_LOCAL) | flags; + // ...new objects that should come in selected need to be added to the selected list + mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + return; +} void LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index aa30d1c790..1e79042012 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -70,6 +70,7 @@ class LLViewerRegion; class LLViewerObjectMedia; class LLVOInventoryListener; class LLVOAvatar; +class LLDataPackerBinaryBuffer; typedef enum e_object_update_type { @@ -136,8 +137,7 @@ public: BOOL isDead() const {return mDead;} BOOL isOrphaned() const { return mOrphaned; } BOOL isParticleSource() const; - void EnableToCacheTree(bool enabled); - + virtual LLVOAvatar* asAvatar(); static void initVOClasses(); @@ -162,6 +162,7 @@ public: INVALID_UPDATE = 0x80000000 }; + static U32 extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot); virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -510,6 +511,7 @@ public: virtual void updateRegion(LLViewerRegion *regionp); void updateFlags(BOOL physics_changed = FALSE); + void loadFlags(U32 flags); //load flags from cache or from message BOOL setFlags(U32 flag, BOOL state); BOOL setFlagsWithoutUpdate(U32 flag, BOOL state); void setPhysicsShapeType(U8 type); @@ -540,6 +542,13 @@ public: friend class LLViewerMediaList; public: + static void unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name); + static void unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name); + static void unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name); + static void unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name); + static U32 unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id); + +public: //counter-translation void resetChildrenPosition(const LLVector3& offset, BOOL simplified = FALSE) ; //counter-rotation @@ -562,6 +571,8 @@ private: // Motion prediction between updates void interpolateLinearMotion(const F64 & time, const F32 & dt); + static void initObjectDataMap(); + public: // // Viewer-side only types - use the LL_PCODE_APP mask. @@ -610,6 +621,7 @@ private: // Grabbed from UPDATE_FLAGS U32 mFlags; + static std::map<std::string, U32> sObjectDataMap; public: // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties U8 mPhysicsShapeType; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 176ee49d31..0700ac025c 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -365,7 +365,8 @@ LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* } processUpdateCore(objectp, NULL, 0, OUT_FULL_CACHED, cached_dpp, justCreated, true); - + objectp->loadFlags(entry->getUpdateFlags()); //just in case, reload update flags from cache. + recorder.log(0.2f); LLVOAvatar::cullAvatarsByPixelArea(); @@ -446,6 +447,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, LLTimer update_timer; BOOL justCreated = FALSE; S32 msg_size = 0; + bool remove_from_cache = false; //remove from object cache if it is a full-update or terse update if (compressed) { @@ -458,12 +460,24 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { - compressed_dp.unpackUUID(fullid, "ID"); - compressed_dp.unpackU32(local_id, "LocalID"); - compressed_dp.unpackU8(pcode, "PCode"); + U32 flags = 0; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); + + if(flags & FLAGS_TEMPORARY_ON_REZ) + { + compressed_dp.unpackUUID(fullid, "ID"); + compressed_dp.unpackU32(local_id, "LocalID"); + compressed_dp.unpackU8(pcode, "PCode"); + } + else //send to object cache + { + regionp->cacheFullUpdate(compressed_dp, flags); + continue; + } } else { + remove_from_cache = true; compressed_dp.unpackU32(local_id, "LocalID"); getUUIDFromLocal(fullid, local_id, @@ -493,6 +507,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } else // OUT_FULL only? { + remove_from_cache = true; mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); msg_size += sizeof(LLUUID); @@ -500,6 +515,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, // llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl; } objectp = findObject(fullid); + + if(remove_from_cache) + { + objectp = regionp->forceToRemoveFromCache(local_id, objectp); + } // This looks like it will break if the local_id of the object doesn't change // upon boundary crossing, but we check for region id matching later... @@ -576,11 +596,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, recorder.objectUpdateFailure(local_id, update_type, msg_size); continue; } + justCreated = TRUE; mNumNewObjects++; } - if (objectp->isDead()) { llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl; @@ -594,6 +614,8 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, objectp->mLocalID = local_id; } processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); + +#if 0 if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { U32 flags = 0; @@ -602,10 +624,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if(!(flags & FLAGS_TEMPORARY_ON_REZ)) { bCached = true; - LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); + LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp, flags); recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size); } } +#endif } else { @@ -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/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 570bf9264c..bca2108964 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -460,7 +460,11 @@ void LLViewerRegion::saveObjectCache() if(LLVOCache::hasInstance()) { - LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ; + //NOTE: !!!!!!!!!! + //set this to be true when support full region cache probe!!!! + BOOL full_region_cache_probe = FALSE; + + LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty, full_region_cache_probe) ; mCacheDirty = FALSE; } @@ -744,11 +748,13 @@ void LLViewerRegion::dirtyHeights() void LLViewerRegion::replaceCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry) { U32 state = LLVOCacheEntry::INACTIVE; + bool in_vo_tree = false; if(old_entry) { old_entry->copyTo(new_entry); - state = old_entry->getState(); + state = old_entry->getState(); + in_vo_tree = (state == LLVOCacheEntry::INACTIVE && old_entry->getGroup() != NULL); killCacheEntry(old_entry); } @@ -763,7 +769,7 @@ void LLViewerRegion::replaceCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry { mImpl->mWaitingSet.insert(new_entry); } - else if(old_entry && new_entry->getEntry()) + else if(!old_entry || in_vo_tree) { addToVOCacheTree(new_entry); } @@ -895,10 +901,6 @@ void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry) { return; } - if(!entry->hasState(LLVOCacheEntry::ADD_TO_CACHE_TREE)) - { - return; //can not add to vo cache tree. - } mImpl->mVOCachePartition->addEntry(entry->getEntry()); } @@ -1039,6 +1041,17 @@ F32 LLViewerRegion::updateVisibleEntries(F32 max_time) { LLVOCacheEntry* vo_entry = (LLVOCacheEntry*)(*i)->getVOCacheEntry(); + if(vo_entry->getParentID() > 0) //is a child + { + LLVOCacheEntry* parent = getCacheEntry(vo_entry->getParentID()); + + //make sure the parent is active + if(!parent || !parent->isState(LLVOCacheEntry::ACTIVE)) + { + continue; + } + } + vo_entry->calcSceneContribution(camera_origin, needs_update, mImpl->mLastCameraUpdate); mImpl->mWaitingList.insert(vo_entry); } @@ -1140,7 +1153,7 @@ F32 LLViewerRegion::killInvisibleObjects(F32 max_time) } for(S32 i = 0; i < delete_list.size(); i++) { - gObjectList.killObject(delete_list[i]->getVObj(), true); + gObjectList.killObject(delete_list[i]->getVObj()); } delete_list.clear(); @@ -1194,6 +1207,28 @@ LLViewerObject* LLViewerRegion::addNewObject(LLVOCacheEntry* entry) return obj; } +//remove from object cache if the object receives a full-update or terse update +LLViewerObject* LLViewerRegion::forceToRemoveFromCache(U32 local_id, LLViewerObject* objectp) +{ + LLVOCacheEntry* entry = getCacheEntry(local_id); + if (!entry) + { + return objectp; //not in the cache, do nothing. + } + if(!objectp) //object not created + { + entry->setTouched(FALSE); //mark this entry invalid + + //create a new object before delete it from cache. + objectp = gObjectList.processObjectUpdateFromCache(entry, this); + } + + //remove from cache. + killCacheEntry(entry); + + return objectp; +} + // As above, but forcibly do the update. void LLViewerRegion::forceUpdate() { @@ -1647,14 +1682,130 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) mSimulatorFeatures = sim_features; } -LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp) +//this is called when the parent is not cacheable. +//move all orphan children out of cache and insert to rendering octree. +void LLViewerRegion::findOrphans(U32 parent_id) +{ + std::map<U32, OrphanList>::iterator iter = mOrphanMap.find(parent_id); + if(iter != mOrphanMap.end()) + { + std::set<U32>* children = mOrphanMap[parent_id].getChildList(); + for(std::set<U32>::iterator child_iter = children->begin(); child_iter != children->end(); ++child_iter) + { + forceToRemoveFromCache(*child_iter, NULL); + } + + mOrphanMap.erase(parent_id); + } +} + +void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry) +{ + if(entry != NULL && !entry->getEntry()) + { + entry->setOctreeEntry(NULL); + } + else if(entry->getGroup() != NULL) + { + return; //already in octree, no post processing. + } + + LLVector3 pos; + LLVector3 scale; + LLQuaternion rot; + U32 parent_id = LLViewerObject::extractSpatialExtents(entry->getDP(), pos, scale, rot); + + entry->setBoundingInfo(pos, scale); + + if(parent_id > 0) //has parent + { + entry->setParentID(parent_id); + + //1, find parent, update position + LLVOCacheEntry* parent = getCacheEntry(parent_id); + + //2, if can not, put into the orphan list. + if(!parent || !parent->getGroup()) + { + std::map<U32, OrphanList>::iterator iter = mOrphanMap.find(parent_id); + if(iter != mOrphanMap.end()) + { + iter->second.addChild(entry->getLocalID()); + } + else + { + //check if the parent is an uncacheable object + if(!parent) + { + LLUUID parent_uuid; + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + getHost().getAddress(), + getHost().getPort()); + LLViewerObject *parent_objp = gObjectList.findObject(parent_uuid); + if(parent_objp) + { + //parent is not cacheable, remove child from the cache. + forceToRemoveFromCache(entry->getLocalID(), NULL); + return; + } + } + + //otherwise insert to the orphan list + OrphanList o_list(entry->getLocalID()); + mOrphanMap[parent_id] = o_list; + } + + return; + } + else + { + //update the child position to the region space. + entry->updateBoundingInfo(parent); + } + } + + if(!entry->getGroup() && entry->isState(LLVOCacheEntry::INACTIVE)) + { + addToVOCacheTree(entry); + } + + if(!parent_id) //a potential parent + { + //find all children and update their bounding info + std::map<U32, OrphanList>::iterator iter = mOrphanMap.find(entry->getLocalID()); + if(iter != mOrphanMap.end()) + { + std::set<U32>* children = mOrphanMap[parent_id].getChildList(); + for(std::set<U32>::iterator child_iter = children->begin(); child_iter != children->end(); ++child_iter) + { + LLVOCacheEntry* child = getCacheEntry(*child_iter); + if(child) + { + //update the child position to the region space. + child->updateBoundingInfo(entry); + addToVOCacheTree(child); + } + } + + mOrphanMap.erase(entry->getLocalID()); + } + } + + return ; +} + +LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags) { - U32 local_id = objectp->getLocalID(); - U32 crc = objectp->getCRC(); eCacheUpdateResult result; + U32 crc; + U32 local_id; - LLVOCacheEntry* entry = getCacheEntry(local_id); + LLViewerObject::unpackU32(&dp, local_id, "LocalID"); + LLViewerObject::unpackU32(&dp, crc, "CRC"); + LLVOCacheEntry* entry = getCacheEntry(local_id); + if (entry) { // we've seen this object before @@ -1668,9 +1819,22 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec { // Update the cache entry LLPointer<LLVOCacheEntry> new_entry = new LLVOCacheEntry(local_id, crc, dp); - replaceCacheEntry(entry, new_entry); - entry = new_entry; - + + //if visible, update it + if(!entry->isState(LLVOCacheEntry::INACTIVE)) + { + replaceCacheEntry(entry, new_entry); + } + else //invisible + { + //remove old entry + killCacheEntry(entry); + entry = new_entry; + + mImpl->mCacheMap[local_id] = entry; + decodeBoundingInfo(entry); + } + result = CACHE_UPDATE_CHANGED; } } @@ -1679,16 +1843,26 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec // we haven't seen this object before // Create new entry and add to map result = CACHE_UPDATE_ADDED; - //if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) - //{ - // delete mImpl->mCacheMap.begin()->second ; - // mImpl->mCacheMap.erase(mImpl->mCacheMap.begin()); - // result = CACHE_UPDATE_REPLACED; - // - //} entry = new LLVOCacheEntry(local_id, crc, dp); - + mImpl->mCacheMap[local_id] = entry; + + decodeBoundingInfo(entry); + } + entry->setUpdateFlags(flags); + + return result; +} + +LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags) +{ + eCacheUpdateResult result = cacheFullUpdate(dp, flags); + +#if 0 + LLVOCacheEntry* entry = mImpl->mCacheMap[objectp->getLocalID()]; + if(!entry) + { + return result; } if(objectp->mDrawable.notNull() && !entry->getEntry()) @@ -1699,6 +1873,7 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec { addActiveCacheEntry(entry); } +#endif return result; } @@ -1721,9 +1896,14 @@ LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id) return NULL; } +void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type) +{ + mCacheMissList.insert(CacheMissItem(id, miss_type)); +} + // 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 @@ -1737,27 +1917,33 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U8 &cache_miss_type) // Record a hit entry->recordHit(); cache_miss_type = CACHE_MISS_TYPE_NONE; + entry->setUpdateFlags(flags); + + if(entry->isState(LLVOCacheEntry::ACTIVE)) + { + ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj()->loadFlags(flags); + return true; + } if(entry->getGroup() || !entry->isState(LLVOCacheEntry::INACTIVE)) { return true; } - addVisibleCacheEntry(entry); + decodeBoundingInfo(entry); return true; } else { // llinfos << "CRC miss for " << local_id << llendl; - 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 +1951,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 +1978,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 +1994,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,7 +2164,13 @@ void LLViewerRegion::unpackRegionHandshake() msg->addUUID("AgentID", gAgent.getID()); msg->addUUID("SessionID", gAgent.getSessionID()); msg->nextBlock("RegionInfo"); - msg->addU32("Flags", 0x0 ); + + U32 flags = 0x00000001; //set the bit 0 to be 1 to ask sim to send all cacheable objects. + if(mImpl->mCacheMap.empty()) + { + flags |= 0x00000002; //set the bit 1 to be 1 to tell sim the cache file is empty, no need to send cache probes. + } + msg->addU32("Flags", flags ); msg->sendReliable(host); } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 9252923aa3..15c2b36e38 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 { @@ -441,8 +447,40 @@ 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 + + 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; + }; + 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 1aa36eafee..dd86ef4f34 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -2723,6 +2723,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gTwoTextureCompareProgram.bind(); gTwoTextureCompareProgram.uniform1i("tex0", 0); gTwoTextureCompareProgram.uniform1i("tex1", 1); + gTwoTextureCompareProgram.uniform1i("dither_tex", 2); } } diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 86cfbb1d74..5f112675dc 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -53,13 +53,16 @@ LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer & : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mLocalID(local_id), mCRC(crc), + mUpdateFlags(-1), mHitCount(0), mDupeCount(0), mCRCChangeCount(0), mState(INACTIVE), mRepeatedVisCounter(0), mVisFrameRange(64), - mSceneContrib(0.f) + mSceneContrib(0.f), + mTouched(TRUE), + mParentID(0) { mBuffer = new U8[dp.getBufferSize()]; mDP.assignBuffer(mBuffer, dp.getBufferSize()); @@ -70,6 +73,7 @@ LLVOCacheEntry::LLVOCacheEntry() : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mLocalID(0), mCRC(0), + mUpdateFlags(-1), mHitCount(0), mDupeCount(0), mCRCChangeCount(0), @@ -77,7 +81,9 @@ LLVOCacheEntry::LLVOCacheEntry() mState(INACTIVE), mRepeatedVisCounter(0), mVisFrameRange(64), - mSceneContrib(0.f) + mSceneContrib(0.f), + mTouched(TRUE), + mParentID(0) { mDP.assignBuffer(mBuffer, 0); } @@ -85,10 +91,13 @@ LLVOCacheEntry::LLVOCacheEntry() LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mBuffer(NULL), + mUpdateFlags(-1), mState(INACTIVE), mRepeatedVisCounter(0), mVisFrameRange(64), - mSceneContrib(0.f) + mSceneContrib(0.f), + mTouched(FALSE), + mParentID(0) { S32 size = -1; BOOL success; @@ -115,36 +124,6 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) } if(success) { - success = check_read(apr_file, &mState, sizeof(U32)); - } - if(success) - { - F32 ext[8]; - success = check_read(apr_file, (void*)ext, sizeof(F32) * 8); - - LLVector4a exts[2]; - exts[0].load4a(ext); - exts[1].load4a(&ext[4]); - - setSpatialExtents(exts[0], exts[1]); - } - if(success) - { - LLVector4 pos; - success = check_read(apr_file, (void*)pos.mV, sizeof(LLVector4)); - - LLVector4a pos_; - pos_.load4a(pos.mV); - setPositionGroup(pos_); - } - if(success) - { - F32 rad; - success = check_read(apr_file, &rad, sizeof(F32)); - setBinRadius(rad); - } - if(success) - { success = check_read(apr_file, &size, sizeof(S32)); // Corruption in the cache entries @@ -198,10 +177,8 @@ void LLVOCacheEntry::setOctreeEntry(LLViewerOctreeEntry* entry) if(!entry && mDP.getBufferSize() > 0) { LLUUID fullid; - mDP.reset(); - mDP.unpackUUID(fullid, "ID"); - mDP.reset(); - + LLViewerObject::unpackUUID(&mDP, fullid, "ID"); + LLViewerObject* obj = gObjectList.findObject(fullid); if(obj && obj->mDrawable) { @@ -231,9 +208,7 @@ void LLVOCacheEntry::copyTo(LLVOCacheEntry* new_entry) void LLVOCacheEntry::setState(U32 state) { - mState &= 0xffff0000; //clear the low 16 bits - state &= 0x0000ffff; //clear the high 16 bits; - mState |= state; + mState = state; if(getState() == ACTIVE) { @@ -300,6 +275,7 @@ LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP() void LLVOCacheEntry::recordHit() { + setTouched(); mHitCount++; } @@ -341,33 +317,6 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const } if(success) { - U32 state = mState & 0xffff0000; //only store the high 16 bits. - success = check_write(apr_file, (void*)&state, sizeof(U32)); - } - if(success) - { - const LLVector4a* exts = getSpatialExtents() ; - LLVector4 ext(exts[0][0], exts[0][1], exts[0][2], exts[0][3]); - success = check_write(apr_file, ext.mV, sizeof(LLVector4)); - if(success) - { - ext.set(exts[1][0], exts[1][1], exts[1][2], exts[1][3]); - success = check_write(apr_file, ext.mV, sizeof(LLVector4)); - } - } - if(success) - { - const LLVector4a pos_ = getPositionGroup() ; - LLVector4 pos(pos_[0], pos_[1], pos_[2], pos_[3]); - success = check_write(apr_file, pos.mV, sizeof(LLVector4)); - } - if(success) - { - F32 rad = getBinRadius(); - success = check_write(apr_file, (void*)&rad, sizeof(F32)); - } - if(success) - { S32 size = mDP.getBufferSize(); success = check_write(apr_file, (void*)&size, sizeof(S32)); @@ -402,6 +351,28 @@ void LLVOCacheEntry::calcSceneContribution(const LLVector3& camera_origin, bool setVisible(); } +void LLVOCacheEntry::setBoundingInfo(const LLVector3& pos, const LLVector3& scale) +{ + LLVector4a center, newMin, newMax; + center.load3(pos.mV); + LLVector4a size; + size.load3(scale.mV); + newMin.setSub(center, size); + newMax.setAdd(center, size); + + setPositionGroup(center); + setSpatialExtents(newMin, newMax); + setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f)); +} + +void LLVOCacheEntry::updateBoundingInfo(LLVOCacheEntry* parent) +{ + //LLVector4a old_pos = getPositionGroup(); + //parent->getPositionRegion() + (getPosition() * parent->getRotation()); + + shift(parent->getPositionGroup()); +} + //------------------------------------------------------------------- //LLVOCachePartition //------------------------------------------------------------------- @@ -409,8 +380,7 @@ LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp) { mRegionp = regionp; mPartitionType = LLViewerRegion::PARTITION_VO_CACHE; - mVisitedTime = 0; - + new LLviewerOctreeGroup(mOctree); } @@ -477,12 +447,6 @@ S32 LLVOCachePartition::cull(LLCamera &camera) return 0; } - if(mVisitedTime == LLViewerOctreeEntryData::getCurrentFrame()) - { - return 0; //already visited. - } - mVisitedTime = LLViewerOctreeEntryData::getCurrentFrame(); - ((LLviewerOctreeGroup*)mOctree->getListener(0))->rebound(); //localize the camera @@ -938,7 +902,7 @@ void LLVOCache::purgeEntries(U32 size) mNumEntries = mHandleEntryMap.size() ; } -void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) +void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, BOOL full_region_cache_probe) { if(!mEnabled) { @@ -1011,7 +975,10 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter) { - success = iter->second->writeToFile(&apr_file) ; + if(!full_region_cache_probe || iter->second->isTouched()) + { + success = iter->second->writeToFile(&apr_file) ; + } } } } diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index c631e12739..64eb876919 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -41,7 +41,7 @@ class LLCamera; class LLVOCacheEntry : public LLViewerOctreeEntryData { public: - enum + enum //low 16-bit state { INACTIVE = 0x00000000, //not visible IN_QUEUE = 0x00000001, //in visible queue, object to be created @@ -49,11 +49,6 @@ public: ACTIVE = 0x00000004 //object created, and in rendering pipeline. }; - enum - { - ADD_TO_CACHE_TREE = 0x00010000, //has parent - }; - struct CompareVOCacheEntry { bool operator()(const LLVOCacheEntry* const& lhs, const LLVOCacheEntry* const& rhs) @@ -84,12 +79,10 @@ public: LLVOCacheEntry(); void setState(U32 state); - void clearState(U32 state) {mState &= ~state;} - void addState(U32 state) {mState |= state;} - bool isState(U32 state) {return (mState & 0xffff) == state;} + //void clearState(U32 state) {mState &= ~state;} + bool isState(U32 state) {return mState == state;} bool hasState(U32 state) {return mState & state;} - U32 getState() const {return (mState & 0xffff);} - U32 getFullState() const {return mState;} + U32 getState() const {return mState;} U32 getLocalID() const { return mLocalID; } U32 getCRC() const { return mCRC; } @@ -111,11 +104,24 @@ public: void copyTo(LLVOCacheEntry* new_entry); //copy variables /*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry); + void setParentID(U32 id) {mParentID = id;} + U32 getParentID() const {return mParentID;} + void addChild(LLVOCacheEntry* entry); LLVOCacheEntry* getChild(S32 i) {return mChildrenList[i];} S32 getNumOfChildren() {return mChildrenList.size();} void clearChildrenList() {mChildrenList.clear();} + //called from processing object update message + void setBoundingInfo(const LLVector3& pos, const LLVector3& scale); + void updateBoundingInfo(LLVOCacheEntry* parent); + + void setTouched(BOOL touched = TRUE) {mTouched = touched;} + BOOL isTouched() const {return mTouched;} + + void setUpdateFlags(U32 flags) {mUpdateFlags = flags;} + U32 getUpdateFlags() const {return mUpdateFlags;} + public: typedef std::map<U32, LLPointer<LLVOCacheEntry> > vocache_entry_map_t; typedef std::set<LLVOCacheEntry*> vocache_entry_set_t; @@ -123,7 +129,9 @@ public: protected: U32 mLocalID; + U32 mParentID; U32 mCRC; + U32 mUpdateFlags; //receive from sim S32 mHitCount; S32 mDupeCount; S32 mCRCChangeCount; @@ -135,6 +143,8 @@ protected: S32 mRepeatedVisCounter; //number of repeatedly visible within a short time. U32 mState; //high 16 bits reserved for special use. std::vector<LLVOCacheEntry*> mChildrenList; //children entries in a linked set. + + BOOL mTouched; //if set, this entry is valid, otherwise it is invalid. }; class LLVOCachePartition : public LLViewerOctreePartition @@ -145,9 +155,6 @@ public: void addEntry(LLViewerOctreeEntry* entry); void removeEntry(LLViewerOctreeEntry* entry); /*virtual*/ S32 cull(LLCamera &camera); - -private: - U32 mVisitedTime; }; // @@ -195,7 +202,7 @@ public: void removeCache(ELLPath location) ; void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; - void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) ; + void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, BOOL full_region_cache_probe); void removeEntry(U64 handle) ; void setReadOnly(BOOL read_only) {mReadOnly = read_only;} |