diff options
Diffstat (limited to 'indra/newview/llvoavatarself.cpp')
-rwxr-xr-x | indra/newview/llvoavatarself.cpp | 377 |
1 files changed, 322 insertions, 55 deletions
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 77deb5e3bc..c069488a37 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -62,6 +62,7 @@ #include "llvovolume.h" #include "llsdutil.h" #include "llstartup.h" +#include "llsdserialize.h" #if LL_MSVC // disable boost::lexical_cast warning @@ -81,15 +82,15 @@ void selfStartPhase(const std::string& phase_name) { if (isAgentAvatarValid()) { - gAgentAvatarp->getPhases().startPhase(phase_name); + gAgentAvatarp->startPhase(phase_name); } } -void selfStopPhase(const std::string& phase_name) +void selfStopPhase(const std::string& phase_name, bool err_check) { if (isAgentAvatarValid()) { - gAgentAvatarp->getPhases().stopPhase(phase_name); + gAgentAvatarp->stopPhase(phase_name, err_check); } } @@ -97,16 +98,7 @@ void selfClearPhases() { if (isAgentAvatarValid()) { - gAgentAvatarp->getPhases().clearPhases(); - gAgentAvatarp->mLastRezzedStatus = -1; - } -} - -void selfStopAllPhases() -{ - if (isAgentAvatarValid()) - { - gAgentAvatarp->getPhases().stopAllPhases(); + gAgentAvatarp->clearPhases(); } } @@ -176,6 +168,35 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, lldebugs << "Marking avatar as self " << id << llendl; } +// Called periodically for diagnostics, return true when done. +bool output_self_av_texture_diagnostics() +{ + if (!isAgentAvatarValid()) + return true; // done checking + + gAgentAvatarp->outputRezDiagnostics(); + + return false; +} + +bool update_avatar_rez_metrics() +{ + if (!isAgentAvatarValid()) + return true; + + gAgentAvatarp->updateAvatarRezMetrics(false); + return false; +} + +bool check_for_unsupported_baked_appearance() +{ + if (!isAgentAvatarValid()) + return true; + + gAgentAvatarp->checkForUnsupportedServerBakeAppearance(); + return false; +} + void LLVOAvatarSelf::initInstance() { BOOL status = TRUE; @@ -209,6 +230,10 @@ void LLVOAvatarSelf::initInstance() llerrs << "Unable to load user's avatar" << llendl; return; } + + //doPeriodically(output_self_av_texture_diagnostics, 30.0); + doPeriodically(update_avatar_rez_metrics, 5.0); + doPeriodically(check_for_unsupported_baked_appearance, 120.0); } // virtual @@ -255,8 +280,6 @@ BOOL LLVOAvatarSelf::loadAvatarSelf() BOOL LLVOAvatarSelf::buildSkeletonSelf(const LLAvatarSkeletonInfo *info) { - LLMemType mt(LLMemType::MTYPE_AVATAR); - // add special-purpose "screen" joint mScreenp = new LLViewerJoint("mScreen", NULL); // for now, put screen at origin, as it is only used during special @@ -582,8 +605,6 @@ LLVOAvatarSelf::~LLVOAvatarSelf() // virtual BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent) { - LLMemType mt(LLMemType::MTYPE_AVATAR); - // update screen joint size if (mScreenp) { @@ -750,6 +771,15 @@ U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, { U32 retval = LLVOAvatar::processUpdateMessage(mesgsys,user_data,block_num,update_type,dp); +#if 0 + // DRANO - it's not clear this does anything useful. If we wait + // until an appearance message has been received, we already have + // the texture ids. If we don't wait, we don't yet know where to + // look for baked textures, because we haven't received the + // appearance version data from the appearance message. This looks + // like an old optimization that's incompatible with server-side + // texture baking. + // FIXME DRANO - skipping in the case of !mFirstAppearanceMessageReceived prevents us from trying to // load textures before we know where they come from (ie, from baking service or not); // unknown impact on performance. @@ -774,6 +804,7 @@ U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, mInitialBakesLoaded = true; } +#endif return retval; } @@ -959,8 +990,6 @@ void LLVOAvatarSelf::idleUpdateTractorBeam() // virtual void LLVOAvatarSelf::restoreMeshData() { - LLMemType mt(LLMemType::MTYPE_AVATAR); - //llinfos << "Restoring" << llendl; mMeshValid = TRUE; updateJointLODs(); @@ -1415,7 +1444,9 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { - if (getLocalDiscardLevel(*local_tex_iter, wearable_index) > (S32)(desired_tex_discard_level)) + S32 local_discard_level = getLocalDiscardLevel(*local_tex_iter, wearable_index); + if ((local_discard_level > (S32)(desired_tex_discard_level)) || + (local_discard_level < 0 )) { return FALSE; } @@ -1428,6 +1459,7 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset return FALSE; } + BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const { const U32 desired_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); @@ -1445,7 +1477,9 @@ BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) { - if (getLocalDiscardLevel(*local_tex_iter, wearable_index) > (S32)(desired_tex_discard_level)) + S32 local_discard_level = getLocalDiscardLevel(*local_tex_iter, wearable_index); + if ((local_discard_level > (S32)(desired_tex_discard_level)) || + (local_discard_level < 0 )) { return FALSE; } @@ -2008,6 +2042,84 @@ void LLVOAvatarSelf::debugBakedTextureUpload(EBakedTextureIndex index, BOOL fini mDebugBakedTextureTimes[index][done] = mDebugSelfLoadTimer.getElapsedTimeF32(); } +const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const +{ + std::ostringstream outbuf; + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = + LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const EBakedTextureIndex baked_index = baked_iter->first; + if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) + { + outbuf << "baked_index: " << baked_index << "\n"; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const std::string tex_name = LLAvatarAppearanceDictionary::getInstance()->getTexture(tex_index)->mName; + outbuf << " tex_index " << (S32) tex_index << " name " << tex_name << "\n"; + const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + if (wearable_count > 0) + { + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + outbuf << " " << LLWearableType::getTypeName(wearable_type) << " " << wearable_index << ":"; + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(tex_index, wearable_index); + if (local_tex_obj) + { + LLViewerFetchedTexture* image = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() ); + if (tex_index >= 0 + && local_tex_obj->getID() != IMG_DEFAULT_AVATAR + && !image->isMissingAsset()) + { + outbuf << " id: " << image->getID() + << " refs: " << image->getNumRefs() + << " glocdisc: " << getLocalDiscardLevel(tex_index, wearable_index) + << " discard: " << image->getDiscardLevel() + << " desired: " << image->getDesiredDiscardLevel() + << " decode: " << image->getDecodePriority() + << " addl: " << image->getAdditionalDecodePriority() + << " ts: " << image->getTextureState() + << " bl: " << image->getBoostLevel() + << " fl: " << image->isFullyLoaded() // this is not an accessor for mFullyLoaded - see comment there. + << " cl: " << (image->isFullyLoaded() && image->getDiscardLevel()==0) // "completely loaded" + << " mvs: " << image->getMaxVirtualSize() + << " mvsc: " << image->getMaxVirtualSizeResetCounter() + << " mem: " << image->getTextureMemory(); + } + } + outbuf << "\n"; + } + } + } + break; + } + } + return outbuf.str(); +} + +void LLVOAvatarSelf::dumpAllTextures() const +{ + std::string vd_text = "Local textures per baked index and wearable:\n"; + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + ++baked_iter) + { + const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); + if (!layerset) continue; + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); + if (!layerset_buffer) continue; + vd_text += verboseDebugDumpLocalTextureDataInfo(layerset); + } + LL_DEBUGS("Avatar") << vd_text << llendl; +} + const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const { std::string text=""; @@ -2076,20 +2188,14 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const return text; } + +#if 0 // Dump avatar metrics data. LLSD LLVOAvatarSelf::metricsData() { // runway - add region info LLSD result; result["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus()); - std::vector<S32> rez_counts; - LLVOAvatar::getNearbyRezzedStats(rez_counts); - result["nearby"] = LLSD::emptyMap(); - for (S32 i=0; i<rez_counts.size(); ++i) - { - std::string rez_status_name = LLVOAvatar::rezStatusToString(i); - result["nearby"][rez_status_name] = rez_counts[i]; - } result["timers"]["debug_existence"] = mDebugExistenceTimer.getElapsedTimeF32(); result["timers"]["ruth_debug"] = mRuthDebugTimer.getElapsedTimeF32(); result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32(); @@ -2099,6 +2205,7 @@ LLSD LLVOAvatarSelf::metricsData() return result; } +#endif class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder { @@ -2116,6 +2223,7 @@ public: const std::string& reason, const LLSD& content) { + gPendingMetricsUploads--; // if we add retry, this should be moved to the isGoodStatus case. if (isGoodStatus(status)) { LL_DEBUGS("Avatar") << "OK" << LL_ENDL; @@ -2129,11 +2237,6 @@ public: } // virtual - void error(U32 status_num, const std::string & reason) - { - } - - // virtual void result(const LLSD & content) { if (mLiveSequence == mExpectedSequence) @@ -2148,19 +2251,121 @@ private: volatile bool & mReportingStarted; }; -void LLVOAvatarSelf::sendAppearanceChangeMetrics() +bool LLVOAvatarSelf::updateAvatarRezMetrics(bool force_send) +{ + const F32 AV_METRICS_INTERVAL_QA = 30.0; + F32 send_period = 300.0; + if (gSavedSettings.getBOOL("QAModeMetrics")) + { + send_period = AV_METRICS_INTERVAL_QA; + } + + if (force_send || mTimeSinceLastRezMessage.getElapsedTimeF32() > send_period) + { + // Stats for completed phases have been getting logged as they + // complete. This will give us stats for any timers that + // haven't finished as of the metric's being sent. + + if (force_send) + { + LLVOAvatar::logPendingPhasesAllAvatars(); + } + sendViewerAppearanceChangeMetrics(); + } + + return false; +} + +void LLVOAvatarSelf::addMetricsTimerRecord(const LLSD& record) +{ + mPendingTimerRecords.push_back(record); +} + +bool operator<(const LLSD& a, const LLSD& b) +{ + std::ostringstream aout, bout; + aout << LLSDNotationStreamer(a); + bout << LLSDNotationStreamer(b); + std::string astring = aout.str(); + std::string bstring = bout.str(); + + return astring < bstring; + +} + +// Given a vector of LLSD records, return an LLSD array of bucketed stats for val_field. +LLSD summarize_by_buckets(std::vector<LLSD> in_records, + std::vector<std::string> by_fields, + std::string val_field) +{ + LLSD result = LLSD::emptyArray(); + std::map<LLSD,LLViewerStats::StatsAccumulator> accum; + for (std::vector<LLSD>::iterator in_record_iter = in_records.begin(); + in_record_iter != in_records.end(); ++in_record_iter) + { + LLSD& record = *in_record_iter; + LLSD key; + for (std::vector<std::string>::iterator field_iter = by_fields.begin(); + field_iter != by_fields.end(); ++field_iter) + { + const std::string& field = *field_iter; + key[field] = record[field]; + } + LLViewerStats::StatsAccumulator& stats = accum[key]; + F32 value = record[val_field].asReal(); + stats.push(value); + } + for (std::map<LLSD,LLViewerStats::StatsAccumulator>::iterator accum_it = accum.begin(); + accum_it != accum.end(); ++accum_it) + { + LLSD out_record = accum_it->first; + out_record["stats"] = accum_it->second.getData(); + result.append(out_record); + } + return result; +} + +void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics() { // gAgentAvatarp->stopAllPhases(); static volatile bool reporting_started(false); static volatile S32 report_sequence(0); - LLSD msg = metricsData(); + LLSD msg; // = metricsData(); msg["message"] = "ViewerAppearanceChangeMetrics"; msg["session_id"] = gAgentSessionID; msg["agent_id"] = gAgentID; msg["sequence"] = report_sequence; msg["initial"] = !reporting_started; msg["break"] = false; + msg["duration"] = mTimeSinceLastRezMessage.getElapsedTimeF32(); + + // Status of our own rezzing. + msg["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus()); + + // Status of all nearby avs including ourself. + msg["nearby"] = LLSD::emptyArray(); + std::vector<S32> rez_counts; + LLVOAvatar::getNearbyRezzedStats(rez_counts); + for (S32 rez_stat=0; rez_stat < rez_counts.size(); ++rez_stat) + { + std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat); + msg["nearby"][rez_status_name] = rez_counts[rez_stat]; + } + + // std::vector<std::string> bucket_fields("timer_name","is_self","grid_x","grid_y","is_using_server_bake"); + std::vector<std::string> by_fields; + by_fields.push_back("timer_name"); + by_fields.push_back("completed"); + by_fields.push_back("grid_x"); + by_fields.push_back("grid_y"); + by_fields.push_back("is_using_server_bakes"); + by_fields.push_back("is_self"); + by_fields.push_back("central_bake_version"); + LLSD summary = summarize_by_buckets(mPendingTimerRecords, by_fields, std::string("elapsed")); + msg["timers"] = summary; + + mPendingTimerRecords.clear(); // Update sequence number if (S32_MAX == ++report_sequence) @@ -2175,15 +2380,73 @@ void LLVOAvatarSelf::sendAppearanceChangeMetrics() } if (!caps_url.empty()) { + gPendingMetricsUploads++; LLCurlRequest::headers_t headers; LLHTTPClient::post(caps_url, msg, new ViewerAppearanceChangeMetricsResponder(report_sequence, report_sequence, reporting_started)); + mTimeSinceLastRezMessage.reset(); } } +class CheckAgentAppearanceServiceResponder: public LLHTTPClient::Responder +{ +public: + CheckAgentAppearanceServiceResponder() + { + } + + virtual ~CheckAgentAppearanceServiceResponder() + { + } + + /* virtual */ void result(const LLSD& content) + { + LL_DEBUGS("Avatar") << "status OK" << llendl; + } + + // Error + /*virtual*/ void error(U32 status, const std::string& reason) + { + if (isAgentAvatarValid()) + { + LL_DEBUGS("Avatar") << "failed, will rebake" << llendl; + forceAppearanceUpdate(); + } + } + + static void forceAppearanceUpdate() + { + // Trying to rebake immediately after crossing region boundary + // seems to be failure prone; adding a delay factor. Yes, this + // fix is ad-hoc and not guaranteed to work in all cases. + doAfterInterval(boost::bind(&LLVOAvatarSelf::forceBakeAllTextures, + gAgentAvatarp.get(), true), 5.0); + } +}; + +void LLVOAvatarSelf::checkForUnsupportedServerBakeAppearance() +{ + // Need to check only if we have a server baked appearance and are + // in a non-baking region. + if (!gAgentAvatarp->isUsingServerBakes()) + return; + if (!gAgent.getRegion() || gAgent.getRegion()->getCentralBakeVersion()!=0) + return; + + // if baked image service is unknown, need to refresh. + if (gSavedSettings.getString("AgentAppearanceServiceURL").empty()) + { + CheckAgentAppearanceServiceResponder::forceAppearanceUpdate(); + } + // query baked image service to check status. + std::string image_url = gAgentAvatarp->getImageURL(TEX_HEAD_BAKED, + getTE(TEX_HEAD_BAKED)->getID()); + LLHTTPClient::head(image_url, new CheckAgentAppearanceServiceResponder); +} + const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) const { if (canGrabBakedTexture(baked_index)) @@ -2277,30 +2540,34 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe { if (!isIndexLocalTexture(type)) return; - if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR && imagep->getDiscardLevel() != 0) + if (!covered_by_baked) { - F32 desired_pixels; - desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); - - if (isUsingLocalAppearance()) + if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR) { - imagep->setBoostLevel(getAvatarBoostLevel()); - imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; + imagep->setNoDelete(); + if (imagep->getDiscardLevel() != 0) + { + F32 desired_pixels; + desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); + + imagep->setBoostLevel(getAvatarBoostLevel()); + imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; + imagep->resetTextureStats(); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); + imagep->addTextureStats( desired_pixels / texel_area_ratio ); + imagep->forceUpdateBindStats() ; + if (imagep->getDiscardLevel() < 0) + { + mHasGrey = TRUE; // for statistics gathering + } + } } - imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); - imagep->addTextureStats( desired_pixels / texel_area_ratio ); - imagep->forceUpdateBindStats() ; - if (imagep->getDiscardLevel() < 0) + else { + // texture asset is missing mHasGrey = TRUE; // for statistics gathering } } - else - { - // texture asset is missing - mHasGrey = TRUE; // for statistics gathering - } } LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLAvatarAppearanceDefines::ETextureIndex i, U32 wearable_index) const @@ -2466,6 +2733,8 @@ void LLVOAvatarSelf::outputRezDiagnostics() const if (!layerset_buffer) continue; LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << llendl; } + + dumpAllTextures(); } void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const @@ -2780,8 +3049,6 @@ void LLVOAvatarSelf::dumpScratchTextureByteCount() llinfos << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << llendl; } -void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value); - void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile) { apr_file_t* file = outfile.getFileHandle(); |