From 91ee5724ca2a3059b0ab3167530f0008f6d7beb9 Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Tue, 22 Jul 2014 03:39:01 -0400 Subject: [PATCH 1/9] Fix compile errors and warnings on linux after merging Shyotl. --- indra/llmath/llmatrix4a.h | 28 ++++++++++++++++----------- indra/llmath/lloctree.h | 4 ++-- indra/newview/lldrawpool.cpp | 3 ++- indra/newview/llflexibleobject.cpp | 6 ++++-- indra/newview/llviewercamera.h | 4 ++-- indra/newview/llviewerobjectlist.cpp | 3 ++- indra/newview/llviewerpartsim.cpp | 16 +++++++++------ indra/newview/llviewertextureanim.cpp | 3 ++- 8 files changed, 41 insertions(+), 26 deletions(-) diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index f322c087a..0af8105ec 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -663,22 +663,28 @@ public: } //======================Logic==================== +private: + template inline void init_foos(LLMatrix4a& foos) const + { + static bool done(false); + if (done) return; + const LLVector4a delta(0.0001f); + foos.setIdentity(); + foos.getRow<0>().sub(delta); + foos.getRow<1>().sub(delta); + foos.getRow<2>().sub(delta); + foos.getRow<3>().sub(delta); + done = true; + } + +public: inline bool isIdentity() const { static LLMatrix4a mins; static LLMatrix4a maxs; - static LLVector4a delta(0.0001f); - static bool init_mins = ( mins.setIdentity(), - mins.getRow<0>().sub(delta), - mins.getRow<1>().sub(delta), - mins.getRow<2>().sub(delta), - mins.getRow<3>().sub(delta), true ); - static bool init_maxs = ( maxs.setIdentity(), - maxs.getRow<0>().add(delta), - maxs.getRow<1>().add(delta), - maxs.getRow<2>().add(delta), - maxs.getRow<3>().add(delta), true ); + init_foos(mins); + init_foos(maxs); LLVector4a mask1 = _mm_and_ps(_mm_cmpgt_ps(mMatrix[0],mins.getRow<0>()), _mm_cmplt_ps(mMatrix[0],maxs.getRow<0>())); LLVector4a mask2 = _mm_and_ps(_mm_cmpgt_ps(mMatrix[1],mins.getRow<1>()), _mm_cmplt_ps(mMatrix[1],maxs.getRow<1>())); diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 5189d852b..0be162f5c 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -968,11 +968,11 @@ public: #ifdef LL_OCTREE_POOLS void* operator new(size_t size) { - return getPool(size).malloc(); + return LLOctreeNode::getPool(size).malloc(); } void operator delete(void* ptr) { - getPool(sizeof(LLOctreeNode)).free(ptr); + LLOctreeNode::getPool(sizeof(LLOctreeNode)).free(ptr); } #else void* operator new(size_t size) diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 7a6ca0e24..3a936eaf8 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -301,7 +301,8 @@ void LLFacePool::removeFaceReference(LLFace *facep) if (idx != -1) { facep->setReferenceIndex(-1); - std::vector::iterator iter = vector_replace_with_last(mReferences, mReferences.begin() + idx); + std::vector::iterator face_it(mReferences.begin() + idx); + std::vector::iterator iter = vector_replace_with_last(mReferences, face_it); if(iter != mReferences.end()) (*iter)->setReferenceIndex(idx); } diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index e378c4458..cf97d4e82 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -80,10 +80,12 @@ LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectD LLVolumeImplFlexible::~LLVolumeImplFlexible() { - std::vector::iterator iter = vector_replace_with_last(sInstanceList, sInstanceList.begin() + mInstanceIndex); + std::vector::iterator flex_it(sInstanceList.begin() + mInstanceIndex); + std::vector::iterator iter = vector_replace_with_last(sInstanceList, flex_it); if(iter != sInstanceList.end()) (*iter)->mInstanceIndex = mInstanceIndex; - vector_replace_with_last(sUpdateDelay,sUpdateDelay.begin() + mInstanceIndex); + std::vector::iterator update_it(sUpdateDelay.begin() + mInstanceIndex); + vector_replace_with_last(sUpdateDelay, update_it); } //static diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 8d4e9ce97..0c465592b 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -39,10 +39,10 @@ class LLViewerObject; // This rotation matrix moves the default OpenGL reference frame // (-Z at, Y up) to Cory's favorite reference frame (X at, Z up) -static LL_ALIGN_16(const LLMatrix4a OGL_TO_CFR_ROTATION(LLVector4a( 0.f, 0.f, -1.f, 0.f), // -Z becomes X +static LL_ALIGN_16(const LLMatrix4a) OGL_TO_CFR_ROTATION(LLVector4a( 0.f, 0.f, -1.f, 0.f), // -Z becomes X LLVector4a(-1.f, 0.f, 0.f, 0.f), // -X becomes Y LLVector4a( 0.f, 1.f, 0.f, 0.f), // Y becomes Z - LLVector4a( 0.f, 0.f, 0.f, 1.f) )); + LLVector4a( 0.f, 0.f, 0.f, 1.f) ); const BOOL FOR_SELECTION = TRUE; const BOOL NOT_FOR_SELECTION = FALSE; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index e42de793e..a97bc60aa 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1459,7 +1459,8 @@ void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) objectp->setListIndex(-1); - std::vector >::iterator iter = vector_replace_with_last(mActiveObjects,mActiveObjects.begin() + idx); + std::vector >::iterator it(mActiveObjects.begin() + idx); + std::vector >::iterator iter = vector_replace_with_last(mActiveObjects, it); if(iter != mActiveObjects.end()) (*iter)->setListIndex(idx); diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index a27e1ec4e..c3f49f69f 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -406,7 +406,8 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt) // Kill dead particles (either flagged dead, or too old) if ((part->mLastUpdateTime > part->mMaxAge) || (LLViewerPart::LL_PART_DEAD_MASK == part->mFlags)) { - vector_replace_with_last(mParticles,mParticles.begin() + i); + part_list_t::iterator it(mParticles.begin() + i); + vector_replace_with_last(mParticles, it); delete part ; } else @@ -416,7 +417,8 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt) { // Transfer particles between groups LLViewerPartSim::getInstance()->put(part) ; - vector_replace_with_last(mParticles,mParticles.begin() + i); + part_list_t::iterator it(mParticles.begin() + i); + vector_replace_with_last(mParticles, it); } else { @@ -721,8 +723,9 @@ void LLViewerPartSim::updateSimulation() if (mViewerPartSources[i]->isDead()) { - vector_replace_with_last(mViewerPartSources,mViewerPartSources.begin() + i); - //mViewerPartSources.erase(mViewerPartSources.begin() + i); + source_list_t::iterator it(mViewerPartSources.begin() + i); + vector_replace_with_last(mViewerPartSources, it); + //mViewerPartSources.erase(it); count--; } else @@ -758,8 +761,9 @@ void LLViewerPartSim::updateSimulation() if (!mViewerPartGroups[i]->getCount()) { delete mViewerPartGroups[i]; - vector_replace_with_last(mViewerPartGroups,mViewerPartGroups.begin() + i); - //mViewerPartGroups.erase(mViewerPartGroups.begin() + i); + group_list_t::iterator it(mViewerPartGroups.begin() + i); + vector_replace_with_last(mViewerPartGroups, it); + //mViewerPartGroups.erase(it); i--; count--; } diff --git a/indra/newview/llviewertextureanim.cpp b/indra/newview/llviewertextureanim.cpp index 525de0ed2..1e6b7a343 100644 --- a/indra/newview/llviewertextureanim.cpp +++ b/indra/newview/llviewertextureanim.cpp @@ -49,7 +49,8 @@ LLViewerTextureAnim::LLViewerTextureAnim(LLVOVolume* vobj) : LLTextureAnim() LLViewerTextureAnim::~LLViewerTextureAnim() { - std::vector::iterator iter = vector_replace_with_last(sInstanceList, sInstanceList.begin() + mInstanceIndex); + std::vector::iterator it(sInstanceList.begin() + mInstanceIndex); + std::vector::iterator iter = vector_replace_with_last(sInstanceList, it); if(iter != sInstanceList.end()) (*iter)->mInstanceIndex = mInstanceIndex; } From f82d12d38188530267919516d7b17b57a594557f Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Tue, 22 Jul 2014 04:24:26 -0400 Subject: [PATCH 2/9] Fix linker errors on linux after merging Shyotl --- indra/newview/pipeline.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 28950e8f3..7af2dc21e 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -249,12 +249,12 @@ void drawBoxOutline(const LLVector3& pos, const LLVector3& size); U32 nhpo2(U32 v); LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage); -inline const LLMatrix4a& glh_get_current_modelview() +const LLMatrix4a& glh_get_current_modelview() { return gGLModelView; } -inline const LLMatrix4a& glh_get_current_projection() +const LLMatrix4a& glh_get_current_projection() { return gGLProjection; } @@ -269,12 +269,12 @@ inline const LLMatrix4a& glh_get_last_projection() return gGLLastProjection; } -inline void glh_set_current_modelview(const LLMatrix4a& mat) +void glh_set_current_modelview(const LLMatrix4a& mat) { gGLModelView = mat; } -inline void glh_set_current_projection(const LLMatrix4a& mat) +void glh_set_current_projection(const LLMatrix4a& mat) { gGLProjection = mat; } From 398d8c52a2dc2066f2f73d62513a9cd9f8837881 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Thu, 7 Aug 2014 01:57:11 -0500 Subject: [PATCH 3/9] Minor cleanup. --- indra/llcommon/llstl.h | 2 +- indra/newview/lldrawpool.cpp | 3 +-- indra/newview/llflexibleobject.cpp | 3 +-- indra/newview/llviewerobjectlist.cpp | 3 +-- indra/newview/llviewerpartsim.cpp | 12 ++++-------- indra/newview/llviewertextureanim.cpp | 3 +-- 6 files changed, 9 insertions(+), 17 deletions(-) diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 2e3d52733..5afd5dc61 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -239,7 +239,7 @@ inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_ty // //Singu note: This has been generalized to support a broader range of sequence containers template -inline typename T::iterator vector_replace_with_last(T& invec, typename T::iterator& iter) +inline typename T::iterator vector_replace_with_last(T& invec, typename T::iterator iter) { typename T::iterator last = invec.end(); if (iter == invec.end()) diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 3a936eaf8..7a6ca0e24 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -301,8 +301,7 @@ void LLFacePool::removeFaceReference(LLFace *facep) if (idx != -1) { facep->setReferenceIndex(-1); - std::vector::iterator face_it(mReferences.begin() + idx); - std::vector::iterator iter = vector_replace_with_last(mReferences, face_it); + std::vector::iterator iter = vector_replace_with_last(mReferences, mReferences.begin() + idx); if(iter != mReferences.end()) (*iter)->setReferenceIndex(idx); } diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index cf97d4e82..6d985d386 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -80,8 +80,7 @@ LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectD LLVolumeImplFlexible::~LLVolumeImplFlexible() { - std::vector::iterator flex_it(sInstanceList.begin() + mInstanceIndex); - std::vector::iterator iter = vector_replace_with_last(sInstanceList, flex_it); + std::vector::iterator iter = vector_replace_with_last(sInstanceList, sInstanceList.begin() + mInstanceIndex); if(iter != sInstanceList.end()) (*iter)->mInstanceIndex = mInstanceIndex; std::vector::iterator update_it(sUpdateDelay.begin() + mInstanceIndex); diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index a97bc60aa..8cbd3c955 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1459,8 +1459,7 @@ void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) objectp->setListIndex(-1); - std::vector >::iterator it(mActiveObjects.begin() + idx); - std::vector >::iterator iter = vector_replace_with_last(mActiveObjects, it); + std::vector >::iterator iter = vector_replace_with_last(mActiveObjects, mActiveObjects.begin() + idx); if(iter != mActiveObjects.end()) (*iter)->setListIndex(idx); diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index c3f49f69f..3c0c37b3e 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -406,8 +406,7 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt) // Kill dead particles (either flagged dead, or too old) if ((part->mLastUpdateTime > part->mMaxAge) || (LLViewerPart::LL_PART_DEAD_MASK == part->mFlags)) { - part_list_t::iterator it(mParticles.begin() + i); - vector_replace_with_last(mParticles, it); + vector_replace_with_last(mParticles, mParticles.begin() + i); delete part ; } else @@ -417,8 +416,7 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt) { // Transfer particles between groups LLViewerPartSim::getInstance()->put(part) ; - part_list_t::iterator it(mParticles.begin() + i); - vector_replace_with_last(mParticles, it); + vector_replace_with_last(mParticles, mParticles.begin() + i); } else { @@ -723,8 +721,7 @@ void LLViewerPartSim::updateSimulation() if (mViewerPartSources[i]->isDead()) { - source_list_t::iterator it(mViewerPartSources.begin() + i); - vector_replace_with_last(mViewerPartSources, it); + vector_replace_with_last(mViewerPartSources, mViewerPartSources.begin() + i); //mViewerPartSources.erase(it); count--; } @@ -761,8 +758,7 @@ void LLViewerPartSim::updateSimulation() if (!mViewerPartGroups[i]->getCount()) { delete mViewerPartGroups[i]; - group_list_t::iterator it(mViewerPartGroups.begin() + i); - vector_replace_with_last(mViewerPartGroups, it); + vector_replace_with_last(mViewerPartGroups, mViewerPartGroups.begin() + i); //mViewerPartGroups.erase(it); i--; count--; diff --git a/indra/newview/llviewertextureanim.cpp b/indra/newview/llviewertextureanim.cpp index 1e6b7a343..525de0ed2 100644 --- a/indra/newview/llviewertextureanim.cpp +++ b/indra/newview/llviewertextureanim.cpp @@ -49,8 +49,7 @@ LLViewerTextureAnim::LLViewerTextureAnim(LLVOVolume* vobj) : LLTextureAnim() LLViewerTextureAnim::~LLViewerTextureAnim() { - std::vector::iterator it(sInstanceList.begin() + mInstanceIndex); - std::vector::iterator iter = vector_replace_with_last(sInstanceList, it); + std::vector::iterator iter = vector_replace_with_last(sInstanceList, sInstanceList.begin() + mInstanceIndex); if(iter != sInstanceList.end()) (*iter)->mInstanceIndex = mInstanceIndex; } From 54f05b409c5303bbb67e52a371038dce4f2cb9ab Mon Sep 17 00:00:00 2001 From: Shyotl Date: Wed, 13 Aug 2014 18:04:24 -0500 Subject: [PATCH 4/9] Always use dynamic_cast when casting from an LLJoint* --- indra/llappearance/llavatarjoint.cpp | 10 ++++++---- indra/llappearance/llavatarjointmesh.cpp | 5 +++-- indra/llappearance/llpolyskeletaldistortion.cpp | 14 +++++++------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp index 353857bc9..5153debff 100644 --- a/indra/llappearance/llavatarjoint.cpp +++ b/indra/llappearance/llavatarjoint.cpp @@ -105,8 +105,9 @@ void LLAvatarJoint::setValid( BOOL valid, BOOL recursive ) for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); ++iter) { - LLAvatarJoint* joint = (LLAvatarJoint*)(*iter); - joint->setValid(valid, TRUE); + LLAvatarJoint* joint = dynamic_cast(*iter); + if (joint) + joint->setValid(valid, TRUE); } } @@ -138,8 +139,9 @@ void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive) for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); ++iter) { - LLAvatarJoint* joint = (LLAvatarJoint*)(*iter); - joint->setVisible(visible, recursive); + LLAvatarJoint* joint = dynamic_cast(*iter); + if(joint) + joint->setVisible(visible, recursive); } } } diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index 4a5cff1dc..5099e5481 100644 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -366,8 +366,9 @@ void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint) for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin(); iter != current_joint->mChildren.end(); ++iter) { - LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter); - setupJoint(child_joint); + LLAvatarJoint* child_joint = dynamic_cast(*iter); + if(child_joint) + setupJoint(child_joint); } } diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index efdf5c577..3157cc965 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -154,13 +154,13 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); iter != joint->mChildren.end(); ++iter) { - LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter); - if (child_joint->inheritScale()) - { - LLVector3 childDeformation = LLVector3(child_joint->getScale()); - childDeformation.scaleVec(bone_info->mScaleDeformation); - mJointScales[child_joint] = childDeformation; - } + LLAvatarJoint* child_joint = dynamic_cast(*iter); + if (child_joint && child_joint->inheritScale()) + { + LLVector3 childDeformation = LLVector3(child_joint->getScale()); + childDeformation.scaleVec(bone_info->mScaleDeformation); + mJointScales[child_joint] = childDeformation; + } } if (bone_info->mHasPositionDeformation) From 0e86b696c5fca0a5c2495a47669473bda7100dc7 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Mon, 18 Aug 2014 00:54:01 -0500 Subject: [PATCH 5/9] Added more verbose statemachine debug output. --- indra/aistatemachine/aistatemachine.cpp | 82 +++++++++--- indra/aistatemachine/aistatemachine.h | 133 ++++++++++++++++++++ indra/aistatemachine/aistatemachinethread.h | 7 ++ indra/aistatemachine/aitimer.h | 2 + indra/llmessage/llurlrequest.cpp | 30 +---- indra/llmessage/llurlrequest.h | 4 +- indra/llui/llnotifications.cpp | 2 + indra/newview/llmeshrepository.cpp | 14 +++ indra/newview/llmeshrepository.h | 2 + indra/newview/statemachine/aidirpicker.h | 2 + indra/newview/statemachine/aifilepicker.h | 2 + 11 files changed, 233 insertions(+), 47 deletions(-) diff --git a/indra/aistatemachine/aistatemachine.cpp b/indra/aistatemachine/aistatemachine.cpp index fcdb2d9c8..fe7b4a3bd 100644 --- a/indra/aistatemachine/aistatemachine.cpp +++ b/indra/aistatemachine/aistatemachine.cpp @@ -293,7 +293,36 @@ void AIEngine::add(AIStateMachine* state_machine) } } -extern void print_statemachine_diagnostics(U64 total_clocks, U64 max_delta, AIEngine::queued_type::const_reference slowest_state_machine); +#if STATE_MACHINE_PROFILING +// Called from AIStateMachine::mainloop +void print_statemachine_diagnostics(U64 total_clocks, AIStateMachine::StateTimerBase::TimeData& slowest_timer, AIEngine::queued_type::const_reference slowest_element) +{ + AIStateMachine const& slowest_state_machine = slowest_element.statemachine(); + F64 const tfactor = 1000 / calc_clock_frequency(); + std::ostringstream msg; + + U64 max_delta = slowest_timer.GetDuration(); + + if (total_clocks > max_delta) + { + msg << "AIStateMachine::mainloop did run for " << (total_clocks * tfactor) << " ms. The slowest "; + } + else + { + msg << "AIStateMachine::mainloop: A "; + } + msg << "state machine " << "(" << slowest_state_machine.getName() << ") " << "ran for " << (max_delta * tfactor) << " ms"; + if (slowest_state_machine.getRuntime() > max_delta) + { + msg << " (" << (slowest_state_machine.getRuntime() * tfactor) << " ms in total now)"; + } + msg << ".\n"; + + AIStateMachine::StateTimerBase::DumpTimers(msg); + + llwarns << msg.str() << llendl; +} +#endif // MAIN-THREAD void AIEngine::mainloop(void) @@ -305,28 +334,33 @@ void AIEngine::mainloop(void) queued_element = engine_state_w->list.begin(); } U64 total_clocks = 0; -#ifndef LL_RELEASE_FOR_DOWNLOAD - U64 max_delta = 0; +#if STATE_MACHINE_PROFILING queued_type::value_type slowest_element(NULL); + AIStateMachine::StateTimerRoot::TimeData slowest_timer; #endif while (queued_element != end) { AIStateMachine& state_machine(queued_element->statemachine()); - U64 start = get_clock_count(); - if (!state_machine.sleep(start)) + AIStateMachine::StateTimerBase::TimeData time_data; + if (!state_machine.sleep(get_clock_count())) { - state_machine.multiplex(AIStateMachine::normal_run); + AIStateMachine::StateTimerRoot timer(state_machine.getName()); + state_machine.multiplex(AIStateMachine::normal_run); + time_data = timer.GetTimerData(); } - U64 delta = get_clock_count() - start; - state_machine.add(delta); - total_clocks += delta; -#ifndef LL_RELEASE_FOR_DOWNLOAD - if (delta > max_delta) + if (U64 delta = time_data.GetDuration()) { - max_delta = delta; - slowest_element = *queued_element; - } + state_machine.add(delta); + total_clocks += delta; +#if STATE_MACHINE_PROFILING + if (delta > slowest_timer.GetDuration()) + { + slowest_element = *queued_element; + slowest_timer = time_data; + } #endif + } + bool active = state_machine.active(this); // This locks mState shortly, so it must be called before locking mEngineState because add() locks mEngineState while holding mState. engine_state_type_wat engine_state_w(mEngineState); if (!active) @@ -340,8 +374,8 @@ void AIEngine::mainloop(void) } if (total_clocks >= sMaxCount) { -#ifndef LL_RELEASE_FOR_DOWNLOAD - print_statemachine_diagnostics(total_clocks, max_delta, slowest_element); +#if STATE_MACHINE_PROFILING + print_statemachine_diagnostics(total_clocks, slowest_timer, slowest_element); #endif Dout(dc::statemachine, "Sorting " << engine_state_w->list.size() << " state machines."); engine_state_w->list.sort(QueueElementComp()); @@ -752,6 +786,22 @@ void AIStateMachine::multiplex(event_type event) } } +#if STATE_MACHINE_PROFILING +std::vector AIStateMachine::StateTimerBase::mTimerStack; +AIStateMachine::StateTimerBase::TimeData AIStateMachine::StateTimerBase::TimeData::sRoot(""); +void AIStateMachine::StateTimer::TimeData::DumpTimer(std::ostringstream& msg, std::string prefix) +{ + F64 const tfactor = 1000 / calc_clock_frequency(); + msg << prefix << mName << " " << (mEnd - mStart)*tfactor << "ms" << std::endl; + prefix.push_back(' '); + std::vector::iterator it; + for (it = mChildren.begin(); it != mChildren.end(); ++it) + { + it->DumpTimer(msg, prefix); + } +} +#endif + AIStateMachine::state_type AIStateMachine::begin_loop(base_state_type base_state) { DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::begin_loop(" << state_str(base_state) << ") [" << (void*)this << "]"); diff --git a/indra/aistatemachine/aistatemachine.h b/indra/aistatemachine/aistatemachine.h index a9ac33d68..8c80cc01f 100644 --- a/indra/aistatemachine/aistatemachine.h +++ b/indra/aistatemachine/aistatemachine.h @@ -36,6 +36,7 @@ #include "aithreadsafe.h" #include +#include "lltimer.h" #include #include @@ -98,11 +99,140 @@ class AIEngine extern AIEngine gMainThreadEngine; extern AIEngine gStateMachineThreadEngine; +#ifndef STATE_MACHINE_PROFILING +#define STATE_MACHINE_PROFILING (LL_RELEASE_FOR_DOWNLOAD) +#endif + class AIStateMachine : public LLThreadSafeRefCount { public: typedef U32 state_type; //!< The type of run_state + // A simple timer class that will calculate time delta between ctor and GetTimerData call. + // Time data is stored as a nested TimeData object. + // If STATE_MACHINE_PROFILING is defined then a stack of all StateTimers from root is maintained for debug output. + class StateTimerBase + { + public: + class TimeData + { + friend class StateTimerBase; + public: + TimeData() : mStart(-1), mEnd(-1) {} + U64 GetDuration() { return mEnd - mStart; } + private: + U64 mStart, mEnd; + +#if !STATE_MACHINE_PROFILING + TimeData(const std::string& name) : mStart(get_clock_count()), mEnd(get_clock_count()) {} +#else + TimeData(const std::string& name) : mName(name), mStart(get_clock_count()), mEnd(get_clock_count()) {} + void DumpTimer(std::ostringstream& msg, std::string prefix); + std::vector mChildren; + std::string mName; + static TimeData sRoot; +#endif + }; + protected: +#if !STATE_MACHINE_PROFILING + StateTimerBase(const std::string& name) : mData(name) {} + ~StateTimerBase() {} + TimeData mData; + // Return a copy of the underlying timer data. + // This allows the data live beyond the scope of the state timer. + public: + const TimeData GetTimerData() + { + mData.mEnd = get_clock_count(); //set mEnd to current time, since GetTimerData() will always be called before the dtor, obv. + return mData; + } +#else + // Ctors/dtors are hidden. Only StateTimerRoot and StateTimer are permitted to access them. + StateTimerBase() : mData(NULL) {} + ~StateTimerBase() + { + // If mData is null then the timer was not registered due to being in the wrong thread or the root timer wasn't in the expected state. + if (!mData) + return; + mData->mEnd = get_clock_count(); + mTimerStack.pop_back(); + } + + // Also hide internals from everything except StateTimerRoot and StateTimer + bool AddAsRoot(const std::string& name) + { + + if (!is_main_thread()) + return true; //Ignoring this timer, but pretending it was added. + if (!mTimerStack.empty()) + return false; + TimeData::sRoot = TimeData(name); + mData = &TimeData::sRoot; + mData->mChildren.clear(); + mTimerStack.push_back(this); + return true; + } + bool AddAsChild(const std::string& name) + { + if (!is_main_thread()) + return true; //Ignoring this timer, but pretending it was added. + if (mTimerStack.empty()) + return false; + mTimerStack.back()->mData->mChildren.push_back(TimeData(name)); + mData = &mTimerStack.back()->mData->mChildren.back(); + mTimerStack.push_back(this); + return true; + } + + TimeData* mData; + static std::vector mTimerStack; + + public: + // Debug spew + static void DumpTimers(std::ostringstream& msg) + { + TimeData::sRoot.DumpTimer(msg, ""); + } + + // Return a copy of the underlying timer data. + // This allows the data live beyond the scope of the state timer. + const TimeData GetTimerData() const + { + if (mData) + { + TimeData ret = *mData; + ret.mEnd = get_clock_count(); //set mEnd to current time, since GetTimerData() will always be called before the dtor, obv. + return ret; + } + return TimeData(); + } +#endif + }; +public: +#if !STATE_MACHINE_PROFILING + typedef StateTimerBase StateTimerRoot; + typedef StateTimerBase StateTimer; +#else + class StateTimerRoot : public StateTimerBase + { //A StateTimerRoot can become a child if a root already exists. + public: + StateTimerRoot(const std::string& name) + { + if(!AddAsRoot(name)) + AddAsChild(name); + } + }; + class StateTimer : public StateTimerBase + { //A StateTimer can never become a root + public: + StateTimer(const std::string& name) + { + AddAsChild(name); + } + }; +#endif + + protected: // The type of event that causes multiplex() to be called. enum event_type { @@ -302,6 +432,9 @@ class AIStateMachine : public LLThreadSafeRefCount void add(U64 count) { mRuntime += count; } U64 getRuntime(void) const { return mRuntime; } + // For diagnostics. Every derived class must override this. + virtual const char* getName() const = 0; + protected: virtual void initialize_impl(void) = 0; virtual void multiplex_impl(state_type run_state) = 0; diff --git a/indra/aistatemachine/aistatemachinethread.h b/indra/aistatemachine/aistatemachinethread.h index d2ca65c8d..58b1e812a 100644 --- a/indra/aistatemachine/aistatemachinethread.h +++ b/indra/aistatemachine/aistatemachinethread.h @@ -232,6 +232,13 @@ class AIStateMachineThread : public AIStateMachineThreadBase { // Accessor. THREAD_IMPL& thread_impl(void) { return mThreadImpl; } + /*virtual*/ const char* getName() const + { +#define STRIZE(arg) #arg + return "AIStateMachineThread<"STRIZE(THREAD_IMPL)">"; +#undef STRIZE + } + protected: /*virtual*/ AIThreadImpl& impl(void) { return mThreadImpl; } }; diff --git a/indra/aistatemachine/aitimer.h b/indra/aistatemachine/aitimer.h index a8aeb8ca6..f3623c1d9 100644 --- a/indra/aistatemachine/aitimer.h +++ b/indra/aistatemachine/aitimer.h @@ -98,6 +98,8 @@ class AITimer : public AIStateMachine { */ F64 getInterval(void) const { return mInterval; } + /*virtual*/ const char* getName() const { return "AITimer"; } + protected: // Call finish() (or abort()), not delete. /*virtual*/ ~AITimer() { DoutEntering(dc::statemachine(mSMDebug), "~AITimer() [" << (void*)this << "]"); mFrameTimer.cancel(); } diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 5b806161b..a112277ad 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -78,7 +78,7 @@ LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, std::string cons LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, AIPerService::Approvement* approved, bool keepalive, bool is_auth, bool compression) : mAction(action), mURL(url), mKeepAlive(keepalive), mIsAuth(is_auth), mNoCompression(!compression), - mBody(body), mResponder(responder), mHeaders(headers), mResponderNameCache(responder ? responder->getName() : "") + mBody(body), mResponder(responder), mHeaders(headers), mResponderNameCache(std::string("LLURLRequest:") + std::string(responder ? responder->getName() : "")) { if (approved) { @@ -276,32 +276,4 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w) return rv; } -// Called from AIStateMachine::mainloop, but put here because we don't want to include llurlrequest.h there of course. -void print_statemachine_diagnostics(U64 total_clocks, U64 max_delta, AIEngine::queued_type::const_reference slowest_element) -{ - AIStateMachine const& slowest_state_machine = slowest_element.statemachine(); - LLURLRequest const* request = dynamic_cast(&slowest_state_machine); - F64 const tfactor = 1000 / calc_clock_frequency(); - std::ostringstream msg; - if (total_clocks > max_delta) - { - msg << "AIStateMachine::mainloop did run for " << (total_clocks * tfactor) << " ms. The slowest "; - } - else - { - msg << "AIStateMachine::mainloop: A "; - } - msg << "state machine "; - if (request) - { - msg << "(" << request->getResponderName() << ") "; - } - msg << "ran for " << (max_delta * tfactor) << " ms"; - if (slowest_state_machine.getRuntime() > max_delta) - { - msg << " (" << (slowest_state_machine.getRuntime() * tfactor) << " ms in total now)"; - } - msg << "."; - llwarns << msg.str() << llendl; -} diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index c888b7db3..697b42b46 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -72,7 +72,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine { /** * @brief Cached value of responder->getName() as passed to the constructor. */ - char const* getResponderName(void) const { return mResponderNameCache; } + /*virtual*/ const char* getName() const { return mResponderNameCache.c_str(); } protected: // Call abort(), not delete. @@ -113,7 +113,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine { U32 mBodySize; LLHTTPClient::ResponderPtr mResponder; AIHTTPHeaders mHeaders; - char const* mResponderNameCache; + std::string mResponderNameCache; protected: // Handle initializing the object. diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index e0ec85523..29b146f59 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1543,6 +1543,8 @@ class UpdateItemSM : public AIStateMachine static void add(UpdateItem const& ui); + /*virtual*/ const char* getName() const { return "UpdateItemSM"; } + private: static UpdateItemSM* sSelf; typedef std::deque updateQueue_type; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 252df6ca7..1720ac61a 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1245,16 +1245,21 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size) { + AIStateMachine::StateTimer timer("lodReceived"); LLPointer volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); std::string mesh_string((char*) data, data_size); std::istringstream stream(mesh_string); + AIStateMachine::StateTimer timer2("unpackVolumeFaces"); if (volume->unpackVolumeFaces(stream, data_size)) { + AIStateMachine::StateTimer timer("getNumFaces"); if (volume->getNumFaces() > 0) { + AIStateMachine::StateTimer timer("LoadedMesh"); LoadedMesh mesh(volume, mesh_params, lod); { + AIStateMachine::StateTimer timer("LLMutexLock"); LLMutexLock lock(mMutex); mLoadedQ.push(mesh); } @@ -1910,6 +1915,7 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, { if (is_internal_http_error_that_warrants_a_retry(status) || status == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again + AIStateMachine::StateTimer timer("loadMeshLOD"); llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; gMeshRepo.mThread->loadMeshLOD(mMeshParams, mLOD); @@ -1928,12 +1934,14 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, if (data_size > 0) { + AIStateMachine::StateTimer timer("readAfter"); data = new U8[data_size]; buffer->readAfter(channels.in(), NULL, data, data_size); } if (gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size)) { + AIStateMachine::StateTimer timer("FileOpen"); //good fetch from sim, write to VFS for caching LLVFile file(gVFS, mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLVFile::WRITE); @@ -1942,6 +1950,7 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, if (file.getSize() >= offset+size) { + AIStateMachine::StateTimer timer("WriteData"); file.seek(offset); file.write(data, size); LLMeshRepository::sCacheBytesWritten += size; @@ -2171,6 +2180,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, if (is_internal_http_error_that_warrants_a_retry(status) || status == HTTP_SERVICE_UNAVAILABLE) { //retry + AIStateMachine::StateTimer timer("Retry"); llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; LLMeshRepoThread::HeaderRequest req(mMeshParams); @@ -2191,12 +2201,14 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, if (data_size > 0) { + AIStateMachine::StateTimer timer("readAfter"); data = new U8[data_size]; buffer->readAfter(channels.in(), NULL, data, data_size); } LLMeshRepository::sBytesReceived += llmin(data_size, 4096); + AIStateMachine::StateTimer timer("headerReceived"); bool success = gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size); llassert(success); @@ -2239,11 +2251,13 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, //only allocate as much space in the VFS as is needed for the local cache data_size = llmin(data_size, bytes); + AIStateMachine::StateTimer timer("FileOpen"); LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH, LLVFile::WRITE); if (file.getMaxSize() >= bytes || file.setMaxSize(bytes)) { LLMeshRepository::sCacheBytesWritten += data_size; + AIStateMachine::StateTimer timer("WriteData"); file.write((const U8*) data, data_size); //zero out the rest of the file diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index ab9220cdc..73b56c0e9 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -450,6 +450,8 @@ public: void setWholeModelUploadURL(std::string const& whole_model_upload_url) { mWholeModelUploadURL = whole_model_upload_url; } + /*virtual*/ const char* getName() const { return "AIMeshUpload"; } + protected: // Implement AIStateMachine. /*virtual*/ const char* state_str_impl(state_type run_state) const; diff --git a/indra/newview/statemachine/aidirpicker.h b/indra/newview/statemachine/aidirpicker.h index 484a8e650..877b0571f 100644 --- a/indra/newview/statemachine/aidirpicker.h +++ b/indra/newview/statemachine/aidirpicker.h @@ -63,6 +63,8 @@ public: bool hasDirname(void) const { return hasFilename(); } std::string const& getDirname(void) const { return getFilename(); } + /*virtual*/ const char* getName() const { return "AIDirPicker"; } + public: // Basically all public members of AIStateMachine could made accessible here, // but I don't think others will ever be needed (not even these, actually). diff --git a/indra/newview/statemachine/aifilepicker.h b/indra/newview/statemachine/aifilepicker.h index 9ef02017b..08e218f71 100644 --- a/indra/newview/statemachine/aifilepicker.h +++ b/indra/newview/statemachine/aifilepicker.h @@ -188,6 +188,8 @@ public: std::string getFolder(void) const; std::vector const& getFilenames(void) const { return mFilenames; } + /*virtual*/ const char* getName() const { return "AIFilePicker"; } + // Load the sContextMap from disk. static bool loadFile(std::string const& filename); // Save the sContextMap to disk. From 47fcc70756d9cb3a51e06959c8ca0478ea8aa87f Mon Sep 17 00:00:00 2001 From: Shyotl Date: Mon, 18 Aug 2014 00:54:46 -0500 Subject: [PATCH 6/9] Write initial mesh data to file in larger chunks. Reduces file i/o stalls. --- indra/newview/llmeshrepository.cpp | 33 ++++++++++++------------------ 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 1720ac61a..2392f0120 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -2197,12 +2197,13 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, S32 data_size = buffer->countAfter(channels.in(), NULL); - U8* data = NULL; + static U8 data[16384]; + llassert_always(data_size <= sizeof(data)); + memset(data + data_size, 0, sizeof(data)-data_size); if (data_size > 0) { AIStateMachine::StateTimer timer("readAfter"); - data = new U8[data_size]; buffer->readAfter(channels.in(), NULL, data, data_size); } @@ -2219,7 +2220,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, << "Unable to parse mesh header: " << status << ": " << reason << llendl; } - else if (data && data_size > 0) + else if (data_size > 0) { //header was successfully retrieved from sim, cache in vfs LLUUID mesh_id = mMeshParams.getSculptID(); @@ -2258,28 +2259,20 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, LLMeshRepository::sCacheBytesWritten += data_size; AIStateMachine::StateTimer timer("WriteData"); - file.write((const U8*) data, data_size); - - //zero out the rest of the file - U8 block[4096]; - memset(block, 0, 4096); - - while (bytes-file.tell() > 4096) + S32 bytes_remaining = bytes; + while (bytes_remaining > 0) { - file.write(block, 4096); - } - - S32 remaining = bytes-file.tell(); - - if (remaining > 0) - { - file.write(block, remaining); + const S32 bytes_written = llmin(bytes_remaining, (S32)sizeof(data)); + file.write(data, bytes_written); + if (bytes_remaining == bytes && bytes_written < bytes_remaining) + { + memset(data, 0, data_size); + } + bytes_remaining -= llmin(bytes_remaining, bytes_written); } } } } - - delete [] data; } From d1d68721ac94dab38e7e05561e6bd8341b9667a9 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Mon, 18 Aug 2014 17:16:45 -0500 Subject: [PATCH 7/9] Pulled mesh header info parsing and VFS fetching into their own procedures to remove duplicate code. --- indra/newview/llmeshrepository.cpp | 354 +++++++++-------------------- indra/newview/llmeshrepository.h | 15 ++ 2 files changed, 125 insertions(+), 244 deletions(-) diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 2392f0120..efd6abf61 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -775,7 +775,7 @@ std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id) return http_url; } -bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) +bool LLMeshRepoThread::getMeshHeaderInfo(const LLUUID& mesh_id, const char* block_name, MeshHeaderInfo& info) { //protected by mMutex if (!mHeaderMutex) @@ -783,229 +783,141 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) return false; } - mHeaderMutex->lock(); + LLMutexLock lock(mHeaderMutex); if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) { //we have no header info for this mesh, do nothing - mHeaderMutex->unlock(); return false; } - bool ret = true ; - U32 header_size = mMeshHeaderSize[mesh_id]; - - if (header_size > 0) + if ((info.mHeaderSize = mMeshHeaderSize[mesh_id]) > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id]["skin"]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id]["skin"]["size"].asInteger(); + info.mVersion = mMeshHeader[mesh_id]["version"].asInteger(); + info.mOffset = info.mHeaderSize + mMeshHeader[mesh_id][block_name]["offset"].asInteger(); + info.mSize = mMeshHeader[mesh_id][block_name]["size"].asInteger(); + } + return true; +} - mHeaderMutex->unlock(); +bool LLMeshRepoThread::loadInfoFromVFS(const LLUUID& mesh_id, MeshHeaderInfo& info, boost::function fn) +{ + //check VFS for mesh skin info + LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= info.mOffset + info.mSize) + { + LLMeshRepository::sCacheBytesRead += info.mSize; - if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) + file.seek(info.mOffset); + U8* buffer = new U8[info.mSize]; + file.read(buffer, info.mSize); + + //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(info.mSize, S32(1024)) && zero; ++i) { - //check VFS for mesh skin info - LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); - if (file.getSize() >= offset+size) + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (fn(mesh_id, buffer, info.mSize)) { - LLMeshRepository::sCacheBytesRead += size; - file.seek(offset); - U8* buffer = new U8[size]; - file.read(buffer, size); - - //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) - bool zero = true; - for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) - { - zero = buffer[i] > 0 ? false : true; - } - - if (!zero) - { //attempt to parse - if (skinInfoReceived(mesh_id, buffer, size)) - { - delete[] buffer; - return true; - } - } - delete[] buffer; - } - - //reading from VFS failed for whatever reason, fetch from sim - AIHTTPHeaders headers("Accept", "application/octet-stream"); - - std::string http_url = constructUrl(mesh_id); - if (!http_url.empty()) - { - ret = LLHTTPClient::getByteRange(http_url, headers, offset, size, - new LLMeshSkinInfoResponder(mesh_id, offset, size)); - if (ret) - { - LLMeshRepository::sHTTPRequestCount++; - } + return true; } } + + delete[] buffer; } - else - { - mHeaderMutex->unlock(); + return false; +} + +bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) +{ + MeshHeaderInfo info; + if (!getMeshHeaderInfo(mesh_id, "skin", info)) + { + return false; + } + + if (info.mHeaderSize > 0 && info.mVersion <= MAX_MESH_VERSION && info.mOffset >= 0 && info.mSize > 0) + { + //check VFS for mesh skin info + if (loadInfoFromVFS(mesh_id, info, boost::bind(&LLMeshRepoThread::skinInfoReceived, this, _1, _2, _3 ))) + return true; + + //reading from VFS failed for whatever reason, fetch from sim + AIHTTPHeaders headers("Accept", "application/octet-stream"); + + std::string http_url = constructUrl(mesh_id); + if (!http_url.empty()) + { + if (!LLHTTPClient::getByteRange(http_url, headers, info.mOffset, info.mSize, + new LLMeshSkinInfoResponder(mesh_id, info.mOffset, info.mSize))) + return false; + LLMeshRepository::sHTTPRequestCount++; + } } //early out was not hit, effectively fetched - return ret; + return true; } bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) -{ //protected by mMutex - if (!mHeaderMutex) +{ + MeshHeaderInfo info; + if (!getMeshHeaderInfo(mesh_id, "physics_convex", info)) { return false; } - mHeaderMutex->lock(); - - if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) - { //we have no header info for this mesh, do nothing - mHeaderMutex->unlock(); - return false; - } - - U32 header_size = mMeshHeaderSize[mesh_id]; - bool ret = true ; - - if (header_size > 0) + if (info.mHeaderSize > 0 && info.mVersion <= MAX_MESH_VERSION && info.mOffset >= 0 && info.mSize > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger(); + if (loadInfoFromVFS(mesh_id, info, boost::bind(&LLMeshRepoThread::decompositionReceived, this, _1, _2, _3 ))) + return true; - mHeaderMutex->unlock(); + //reading from VFS failed for whatever reason, fetch from sim + AIHTTPHeaders headers("Accept", "application/octet-stream"); - if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) - { - //check VFS for mesh skin info - LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); - if (file.getSize() >= offset+size) - { - LLMeshRepository::sCacheBytesRead += size; - - file.seek(offset); - U8* buffer = new U8[size]; - file.read(buffer, size); - - //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) - bool zero = true; - for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) - { - zero = buffer[i] > 0 ? false : true; - } - - if (!zero) - { //attempt to parse - if (decompositionReceived(mesh_id, buffer, size)) - { - delete[] buffer; - return true; - } - } - - delete[] buffer; - } - - //reading from VFS failed for whatever reason, fetch from sim - AIHTTPHeaders headers("Accept", "application/octet-stream"); - - std::string http_url = constructUrl(mesh_id); - if (!http_url.empty()) - { - ret = LLHTTPClient::getByteRange(http_url, headers, offset, size, - new LLMeshDecompositionResponder(mesh_id, offset, size)); - if(ret) - { - LLMeshRepository::sHTTPRequestCount++; - } - } + std::string http_url = constructUrl(mesh_id); + if (!http_url.empty()) + { + if (!LLHTTPClient::getByteRange(http_url, headers, info.mOffset, info.mSize, + new LLMeshDecompositionResponder(mesh_id, info.mOffset, info.mSize))) + return false; + LLMeshRepository::sHTTPRequestCount++; } } - else - { - mHeaderMutex->unlock(); - } //early out was not hit, effectively fetched - return ret; + return true; } bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) -{ //protected by mMutex - if (!mHeaderMutex) +{ + MeshHeaderInfo info; + if (!getMeshHeaderInfo(mesh_id, "physics_mesh", info)) { return false; } - mHeaderMutex->lock(); - - if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) - { //we have no header info for this mesh, do nothing - mHeaderMutex->unlock(); - return false; - } - - U32 header_size = mMeshHeaderSize[mesh_id]; - bool ret = true ; - - if (header_size > 0) + if (info.mHeaderSize > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger(); - - mHeaderMutex->unlock(); - - if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) + if (info.mVersion <= MAX_MESH_VERSION && info.mOffset >= 0 && info.mSize > 0) { - //check VFS for mesh physics shape info - LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); - if (file.getSize() >= offset+size) - { - LLMeshRepository::sCacheBytesRead += size; - file.seek(offset); - U8* buffer = new U8[size]; - file.read(buffer, size); - - //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) - bool zero = true; - for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) - { - zero = buffer[i] > 0 ? false : true; - } - - if (!zero) - { //attempt to parse - if (physicsShapeReceived(mesh_id, buffer, size)) - { - delete[] buffer; - return true; - } - } - - delete[] buffer; - } + if (loadInfoFromVFS(mesh_id, info, boost::bind(&LLMeshRepoThread::physicsShapeReceived, this, _1, _2, _3 ))) + return true; //reading from VFS failed for whatever reason, fetch from sim AIHTTPHeaders headers("Accept", "application/octet-stream"); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) - { - ret = LLHTTPClient::getByteRange(http_url, headers, offset, size, - new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); - - if(ret) - { - LLMeshRepository::sHTTPRequestCount++; - } + { + if (!LLHTTPClient::getByteRange(http_url, headers, info.mOffset, info.mSize, + new LLMeshPhysicsShapeResponder(mesh_id, info.mOffset, info.mSize))) + return false; + LLMeshRepository::sHTTPRequestCount++; } } else @@ -1013,13 +925,9 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) physicsShapeReceived(mesh_id, NULL, 0); } } - else - { - mHeaderMutex->unlock(); - } - + //early out was not hit, effectively fetched - return ret; + return true; } //static @@ -1095,72 +1003,34 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c //return false if failed to get mesh lod. bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count) -{ //protected by mMutex - if (!mHeaderMutex) +{ + LLUUID mesh_id = mesh_params.getSculptID(); + MeshHeaderInfo info; + + if (!getMeshHeaderInfo(mesh_id, header_lod[lod].c_str(), info)) { return false; } - - mHeaderMutex->lock(); - - bool retval = true; - - LLUUID mesh_id = mesh_params.getSculptID(); - - U32 header_size = mMeshHeaderSize[mesh_id]; - - if (header_size > 0) + + if (info.mHeaderSize > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id][header_lod[lod]]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id][header_lod[lod]]["size"].asInteger(); - mHeaderMutex->unlock(); - - if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) + if(info.mVersion <= MAX_MESH_VERSION && info.mOffset >= 0 && info.mSize > 0) { - - //check VFS for mesh asset - LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); - if (file.getSize() >= offset+size) - { - LLMeshRepository::sCacheBytesRead += size; - file.seek(offset); - U8* buffer = new U8[size]; - file.read(buffer, size); - - //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) - bool zero = true; - for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) - { - zero = buffer[i] > 0 ? false : true; - } - - if (!zero) - { //attempt to parse - if (lodReceived(mesh_params, lod, buffer, size)) - { - delete[] buffer; - return true; - } - } - - delete[] buffer; - } + if (loadInfoFromVFS(mesh_id, info, boost::bind(&LLMeshRepoThread::lodReceived, this, mesh_params, lod, _2, _3 ))) + return true; //reading from VFS failed for whatever reason, fetch from sim AIHTTPHeaders headers("Accept", "application/octet-stream"); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) - { - retval = LLHTTPClient::getByteRange(constructUrl(mesh_id), headers, offset, size, - new LLMeshLODResponder(mesh_params, lod, offset, size)); - - if (retval) - { - LLMeshRepository::sHTTPRequestCount++; - } - count++; + { + count++; + if (!LLHTTPClient::getByteRange(constructUrl(mesh_id), headers, info.mOffset, info.mSize, + new LLMeshLODResponder(mesh_params, lod, info.mOffset, info.mSize))) + return false; + LLMeshRepository::sHTTPRequestCount++; + } else { @@ -1172,12 +1042,8 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, mUnavailableQ.push(LODRequest(mesh_params, lod)); } } - else - { - mHeaderMutex->unlock(); - } - - return retval; + + return true; } bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size) diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 73b56c0e9..de26a1ba0 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -40,6 +40,8 @@ #include "lluploadfloaterobservers.h" #include "aistatemachinethread.h" +#include + class LLVOVolume; class LLMeshResponder; class LLMutex; @@ -283,6 +285,16 @@ public: }; + struct MeshHeaderInfo + { + MeshHeaderInfo() + : mHeaderSize(0), mVersion(0), mOffset(-1), mSize(0) {} + U32 mHeaderSize; + U32 mVersion; + S32 mOffset; + S32 mSize; + }; + //set of requested skin info std::set mSkinRequests; @@ -332,6 +344,9 @@ public: bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size); LLSD& getMeshHeader(const LLUUID& mesh_id); + bool getMeshHeaderInfo(const LLUUID& mesh_id, const char* block_name, MeshHeaderInfo& info); + bool loadInfoFromVFS(const LLUUID& mesh_id, MeshHeaderInfo& info, boost::function fn); + void notifyLoadedMeshes(); S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); From 1b3f0f9ec0625b129f513e3775dd419eec2c7ba6 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Mon, 18 Aug 2014 23:47:37 -0500 Subject: [PATCH 8/9] Manual texture reloading now re-fetches materials-related textures. --- indra/newview/llviewermenu.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 7f73a760d..72015c651 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2204,8 +2204,17 @@ void reload_objects(LLTextureReloader& texture_list, LLViewerObject::const_child for (U8 i = 0; i < object->getNumTEs(); i++) { texture_list.addTexture(object->getTEImage(i)); + const LLTextureEntry* te = object->getTE(i); + if (LLMaterial* mat = te ? te->getMaterialParams().get() : NULL) + { + if (mat->getSpecularID().notNull()) + texture_list.addTexture(LLViewerTextureManager::getFetchedTexture(mat->getSpecularID())); + if (mat->getNormalID().notNull()) + texture_list.addTexture(LLViewerTextureManager::getFetchedTexture(mat->getNormalID())); + } } + if(recurse) { reload_objects(texture_list,object->getChildren(), true); From 1afd723c4e2785912c0dcad6dccd6751cca0ef5d Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 19 Aug 2014 01:36:24 -0500 Subject: [PATCH 9/9] Post-merge fixup. --- indra/newview/llviewerobjectlist.cpp | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 8cbd3c955..2f9317090 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -738,28 +738,28 @@ public: } } - /*virtual*/ void error(U32 statusNum, const std::string& reason) + /*virtual*/ void httpFailure(void) { llwarns << "Transport error requesting object cost " - << "HTTP status: " << statusNum << ", reason: " - << reason << "." << llendl; + << "HTTP status: " << mStatus << ", reason: " + << mReason << "." << llendl; // TODO*: Error message to user // For now just clear the request from the pending list clear_object_list_pending_requests(); } - /*virtual*/ void result(const LLSD& content) + /*virtual*/ void httpSuccess(void) { - if ( !content.isMap() || content.has("error") ) + if ( !mContent.isMap() || mContent.has("error") ) { // Improper response or the request had an error, // show an error to the user? llwarns << "Application level error when fetching object " - << "cost. Message: " << content["error"]["message"].asString() - << ", identifier: " << content["error"]["identifier"].asString() + << "cost. Message: " << mContent["error"]["message"].asString() + << ", identifier: " << mContent["error"]["identifier"].asString() << llendl; // TODO*: Adaptively adjust request size if the @@ -780,15 +780,15 @@ public: LLUUID object_id = iter->asUUID(); // Check to see if the request contains data for the object - if ( content.has(iter->asString()) ) + if ( mContent.has(iter->asString()) ) { F32 link_cost = - content[iter->asString()]["linked_set_resource_cost"].asReal(); + mContent[iter->asString()]["linked_set_resource_cost"].asReal(); F32 object_cost = - content[iter->asString()]["resource_cost"].asReal(); + mContent[iter->asString()]["resource_cost"].asReal(); - F32 physics_cost = content[iter->asString()]["physics_cost"].asReal(); - F32 link_physics_cost = content[iter->asString()]["linked_set_physics_cost"].asReal(); + F32 physics_cost = mContent[iter->asString()]["physics_cost"].asReal(); + F32 link_physics_cost = mContent[iter->asString()]["linked_set_physics_cost"].asReal(); gObjectList.updateObjectCost(object_id, object_cost, link_cost, physics_cost, link_physics_cost); } @@ -829,28 +829,28 @@ public: } } - /*virtual*/ void error(U32 statusNum, const std::string& reason) + /*virtual*/ void httpFailure(void) { llwarns << "Transport error requesting object physics flags " - << "HTTP status: " << statusNum << ", reason: " - << reason << "." << llendl; + << "HTTP status: " << mStatus << ", reason: " + << mReason << "." << llendl; // TODO*: Error message to user // For now just clear the request from the pending list clear_object_list_pending_requests(); } - /*virtual*/ void result(const LLSD& content) + /*virtual*/ void httpSuccess(void) { - if ( !content.isMap() || content.has("error") ) + if ( !mContent.isMap() || mContent.has("error") ) { // Improper response or the request had an error, // show an error to the user? llwarns << "Application level error when fetching object " - << "physics flags. Message: " << content["error"]["message"].asString() - << ", identifier: " << content["error"]["identifier"].asString() + << "physics flags. Message: " << mContent["error"]["message"].asString() + << ", identifier: " << mContent["error"]["identifier"].asString() << llendl; // TODO*: Adaptively adjust request size if the @@ -871,9 +871,9 @@ public: LLUUID object_id = iter->asUUID(); // Check to see if the request contains data for the object - if ( content.has(iter->asString()) ) + if (mContent.has(iter->asString())) { - const LLSD& data = content[iter->asString()]; + const LLSD& data = mContent[iter->asString()]; S32 shape_type = data["PhysicsShapeType"].asInteger();