From 4bff25310163ec58c25c462a218e2ad94d87a093 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 5 Oct 2023 01:14:30 +0300 Subject: SL-19311 Grey textures after teleport --- indra/newview/lltexturefetch.cpp | 100 ++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 16 deletions(-) (limited to 'indra/newview/lltexturefetch.cpp') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index a1beec7c1f..d1ab019a3e 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -259,6 +259,10 @@ static const S32 HTTP_NONPIPE_REQUESTS_LOW_WATER = 20; // request (e.g. 'Range: -') which seems to fix the problem. static const S32 HTTP_REQUESTS_RANGE_END_MAX = 20000000; +// stop after 720 seconds, might be overkill, but cap request can keep going forever. +static const S32 MAX_CAP_MISSING_RETRIES = 720; +static const S32 CAP_MISSING_EXPIRATION_DELAY = 1; // seconds + ////////////////////////////////////////////////////////////////////////////// namespace { @@ -554,6 +558,7 @@ private: e_state mState; void setState(e_state new_state); + LLViewerRegion* getRegion(); e_write_to_cache_state mWriteToCacheState; LLTextureFetch* mFetcher; @@ -610,6 +615,10 @@ private: LLCore::HttpStatus mGetStatus; std::string mGetReason; LLAdaptiveRetryPolicy mFetchRetryPolicy; + bool mCanUseCapability; + LLTimer mRegionRetryTimer; + S32 mRegionRetryAttempt; + LLUUID mLastRegionId; // Work Data @@ -960,7 +969,9 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mCacheReadCount(0U), mCacheWriteCount(0U), mResourceWaitCount(0U), - mFetchRetryPolicy(10.0,3600.0,2.0,10) + mFetchRetryPolicy(10.0, 3600.0,2.0,10), + mCanUseCapability(true), + mRegionRetryAttempt(0) { calcWorkPriority(); mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL; @@ -1138,6 +1149,19 @@ bool LLTextureFetchWorker::doWork(S32 param) return true; // abort } } + if (mState > CACHE_POST && !mCanUseCapability && mCanUseHTTP) + { + if (mRegionRetryAttempt > MAX_CAP_MISSING_RETRIES) + { + mCanUseHTTP = false; + } + else if (!mRegionRetryTimer.hasExpired()) + { + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + return false; + } + // else retry + } if(mState > CACHE_POST && !mCanUseHTTP) { //nowhere to get data, abort. @@ -1341,16 +1365,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // if (mHost.isInvalid()) get_url = false; if ( use_http && mCanUseHTTP && mUrl.empty())//get http url. { - LLViewerRegion* region = NULL; - if (mHost.isInvalid()) - { - region = gAgent.getRegion(); - } - else if (LLWorld::instanceExists()) - { - region = LLWorld::getInstance()->getRegion(mHost); - } - + LLViewerRegion* region = getRegion(); if (region) { std::string http_url = region->getViewerAssetUrl(); @@ -1363,19 +1378,29 @@ bool LLTextureFetchWorker::doWork(S32 param) setUrl(http_url + "/?texture_id=" + mID.asString().c_str()); LL_DEBUGS(LOG_TXT) << "Texture URL: " << mUrl << LL_ENDL; mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id. + mCanUseCapability = true; + mRegionRetryAttempt = 0; + mLastRegionId = region->getRegionID(); } else { - mCanUseHTTP = false ; - LL_WARNS(LOG_TXT) << "Texture not available via HTTP: empty URL." << LL_ENDL; + mCanUseCapability = false; + mRegionRetryAttempt++; + mRegionRetryTimer.setTimerExpirySec(CAP_MISSING_EXPIRATION_DELAY); + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + // ex: waiting for caps + LL_INFOS_ONCE(LOG_TXT) << "Texture not available via HTTP: empty URL." << LL_ENDL; } } else { + mCanUseCapability = false; + mRegionRetryAttempt++; + mRegionRetryTimer.setTimerExpirySec(CAP_MISSING_EXPIRATION_DELAY); + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // This will happen if not logged in or if a region deoes not have HTTP Texture enabled //LL_WARNS(LOG_TXT) << "Region not found for host: " << mHost << LL_ENDL; - LL_WARNS(LOG_TXT) << "Texture not available via HTTP: no region " << mUrl << LL_ENDL; - mCanUseHTTP = false; + LL_INFOS_ONCE(LOG_TXT) << "Texture not available via HTTP: no region " << mUrl << LL_ENDL; } } else if (mFTType == FTT_SERVER_BAKE) @@ -1383,7 +1408,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mWriteToCacheState = CAN_WRITE; } - if (mCanUseHTTP && !mUrl.empty()) + if (mCanUseCapability && mCanUseHTTP && !mUrl.empty()) { setState(WAIT_HTTP_RESOURCE); setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); @@ -1586,10 +1611,39 @@ bool LLTextureFetchWorker::doWork(S32 param) } return true; } + + if (mCanUseHTTP && !mUrl.empty() && cur_size <= 0) + { + LLViewerRegion* region = getRegion(); + if (!region || mLastRegionId != region->getRegionID()) + { + // cap failure? try on new region. + mUrl.clear(); + ++mRetryAttempt; + mLastRegionId.setNull(); + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + setState(INIT); + return false; + } + } } else if (http_service_unavail == mGetStatus) { LL_INFOS_ONCE(LOG_TXT) << "Texture server busy (503): " << mUrl << LL_ENDL; + if (mCanUseHTTP && !mUrl.empty() && cur_size <= 0) + { + LLViewerRegion* region = getRegion(); + if (!region || mLastRegionId != region->getRegionID()) + { + // try on new region. + mUrl.clear(); + ++mRetryAttempt; + mLastRegionId.setNull(); + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + setState(INIT); + return false; + } + } } else if (http_not_sat == mGetStatus) { @@ -3125,6 +3179,20 @@ void LLTextureFetchWorker::setState(e_state new_state) mState = new_state; } +LLViewerRegion* LLTextureFetchWorker::getRegion() +{ + LLViewerRegion* region = NULL; + if (mHost.isInvalid()) + { + region = gAgent.getRegion(); + } + else if (LLWorld::instanceExists()) + { + region = LLWorld::getInstance()->getRegion(mHost); + } + return region; +} + ////////////////////////////////////////////////////////////////////////////// // Threads: T* -- cgit v1.2.3 From da48bd943923958952ea77eed858ba8372d58d9a Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 23 Jan 2024 02:23:28 +0200 Subject: SL-18721 Shutdown fixes #2 Set DONE if decode thread is down instead of waiting for an update. Decodes can't be canceled, so fix potential situation where we get two responses --- indra/newview/lltexturefetch.cpp | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) (limited to 'indra/newview/lltexturefetch.cpp') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 38c9b3717d..40bbe2b934 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -348,13 +348,13 @@ private: } // Threads: Tid - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) + virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) { LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* worker = mFetcher->getWorker(mID); if (worker) { - worker->callbackDecoded(success, raw, aux); + worker->callbackDecoded(success, raw, aux, request_id); } } private: @@ -398,7 +398,7 @@ public: void callbackCacheWrite(bool success); // Threads: Tid - void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux); + void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id); // Threads: T* void setGetStatus(LLCore::HttpStatus status, const std::string& reason) @@ -1800,8 +1800,22 @@ bool LLTextureFetchWorker::doWork(S32 param) setState(DECODE_IMAGE_UPDATE); LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard << " All Data: " << mHaveAllData << LL_ENDL; - mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage, discard, mNeedsAux, - new DecodeResponder(mFetcher, mID, this)); + + // In case worked manages to request decode, be shut down, + // then init and request decode again with first decode + // still in progress, assign a sufficiently unique id + mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage, + discard, + mNeedsAux, + new DecodeResponder(mFetcher, mID, this)); + if (mDecodeHandle == 0) + { + // Abort, failed to put into queue. + // Happens if viewer is shutting down + setState(DONE); + LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: failed to post for decoding" << LL_ENDL; + return true; + } // fall though } @@ -2305,16 +2319,24 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success) ////////////////////////////////////////////////////////////////////////////// // Threads: Tid -void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux) +void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id) { LLMutexLock lock(&mWorkMutex); // +Mw if (mDecodeHandle == 0) { return; // aborted, ignore } + if (mDecodeHandle != decode_id) + { + // Queue doesn't support canceling old requests. + // This shouldn't normally happen, but in case it's possible that a worked + // will request decode, be aborted, reinited then start a new decode + LL_DEBUGS(LOG_TXT) << mID << " received obsolete decode's callback" << LL_ENDL; + return; // ignore + } if (mState != DECODE_IMAGE_UPDATE) { -// LL_WARNS(LOG_TXT) << "Decode callback for " << mID << " with state = " << mState << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "Decode callback for " << mID << " with state = " << mState << LL_ENDL; mDecodeHandle = 0; return; } -- cgit v1.2.3