diff options
author | Howard Stearns <howard.stearns@gmail.com> | 2022-08-30 10:20:15 -0700 |
---|---|---|
committer | Howard Stearns <howard.stearns@gmail.com> | 2022-08-30 10:20:15 -0700 |
commit | 3b70c9d49c2a963439b3811e80d24576f390552b (patch) | |
tree | 11461161da7c92d76a36d921247158230e4052f2 /indra | |
parent | 6fbc733c9779454f2f1ebade494323e315917851 (diff) | |
parent | 197ac7cc2048fe4c259858f48946cd954782dfc2 (diff) |
Merge branch 'DRTVWR-559' of bitbucket.org:lindenlab/viewer into initscapade
Diffstat (limited to 'indra')
108 files changed, 2098 insertions, 4512 deletions
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index ce5c7142d5..06b4f6c75a 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -151,7 +151,7 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther) mCachedProcessedTexture(pOther.mCachedProcessedTexture), mStaticImageTGA(pOther.mStaticImageTGA), mStaticImageRaw(pOther.mStaticImageRaw), - mNeedsCreateTexture(pOther.mNeedsCreateTexture), + mNeedsCreateTexture(pOther.mNeedsCreateTexture.load()), mStaticImageInvalid(pOther.mStaticImageInvalid), mAvgDistortionVec(pOther.mAvgDistortionVec), mCachedEffectiveWeight(pOther.mCachedEffectiveWeight) diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index e2440998b3..000f55685e 100644 --- a/indra/llappearance/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -100,7 +100,7 @@ private: LLPointer<LLGLTexture> mCachedProcessedTexture; LLPointer<LLImageTGA> mStaticImageTGA; LLPointer<LLImageRaw> mStaticImageRaw; - BOOL mNeedsCreateTexture; + std::atomic<BOOL> mNeedsCreateTexture; BOOL mStaticImageInvalid; LL_ALIGN_16(LLVector4a mAvgDistortionVec); F32 mCachedEffectiveWeight; diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 59aa731af2..62307c6e26 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -29,6 +29,7 @@ include_directories( # ${LLCOMMON_LIBRARIES}) set(llcommon_SOURCE_FILES + commoncontrol.cpp indra_constants.cpp llallocator.cpp llallocator_heap_profile.cpp @@ -130,6 +131,7 @@ set(llcommon_HEADER_FILES chrono.h classic_callback.h + commoncontrol.h ctype_workaround.h fix_macros.h indra_constants.h diff --git a/indra/llcommon/commoncontrol.cpp b/indra/llcommon/commoncontrol.cpp new file mode 100644 index 0000000000..81e66baf8c --- /dev/null +++ b/indra/llcommon/commoncontrol.cpp @@ -0,0 +1,106 @@ +/** + * @file commoncontrol.cpp + * @author Nat Goodspeed + * @date 2022-06-08 + * @brief Implementation for commoncontrol. + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Copyright (c) 2022, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "commoncontrol.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llevents.h" +#include "llsdutil.h" + +LLSD LL::CommonControl::access(const LLSD& params) +{ + // We can't actually introduce a link-time dependency on llxml, or on any + // global LLControlGroup (*koff* gSavedSettings *koff*) but we can issue a + // runtime query. If we're running as part of a viewer with + // LLViewerControlListener, we can use that to interact with any + // instantiated LLControGroup. + LLSD response; + { + LLEventStream reply("reply"); + LLTempBoundListener connection = reply.listen("listener", + [&response] (const LLSD& event) + { + response = event; + return false; + }); + LLSD rparams{ params }; + rparams["reply"] = reply.getName(); + LLEventPumps::instance().obtain("LLViewerControl").post(rparams); + } + // LLViewerControlListener responds immediately. If it's listening at all, + // it will already have set response. + if (! response.isDefined()) + { + LLTHROW(NoListener("No LLViewerControl listener instantiated")); + } + LLSD error{ response["error"] }; + if (error.isDefined()) + { + LLTHROW(ParamError(error)); + } + response.erase("error"); + response.erase("reqid"); + return response; +} + +/// set control group.key to defined default value +LLSD LL::CommonControl::set_default(const std::string& group, const std::string& key) +{ + return access(llsd::map("op", "set", + "group", group, "key", key))["value"]; +} + +/// set control group.key to specified value +LLSD LL::CommonControl::set(const std::string& group, const std::string& key, const LLSD& value) +{ + return access(llsd::map("op", "set", + "group", group, "key", key, "value", value))["value"]; +} + +/// toggle boolean control group.key +LLSD LL::CommonControl::toggle(const std::string& group, const std::string& key) +{ + return access(llsd::map("op", "toggle", + "group", group, "key", key))["value"]; +} + +/// get the definition for control group.key, (! isDefined()) if bad +/// ["name"], ["type"], ["value"], ["comment"] +LLSD LL::CommonControl::get_def(const std::string& group, const std::string& key) +{ + return access(llsd::map("op", "get", + "group", group, "key", key)); +} + +/// get the value of control group.key +LLSD LL::CommonControl::get(const std::string& group, const std::string& key) +{ + return access(llsd::map("op", "get", + "group", group, "key", key))["value"]; +} + +/// get defined groups +std::vector<std::string> LL::CommonControl::get_groups() +{ + auto groups{ access(llsd::map("op", "groups"))["groups"] }; + return { groups.beginArray(), groups.endArray() }; +} + +/// get definitions for all variables in group +LLSD LL::CommonControl::get_vars(const std::string& group) +{ + return access(llsd::map("op", "vars", "group", group))["vars"]; +} diff --git a/indra/llcommon/commoncontrol.h b/indra/llcommon/commoncontrol.h new file mode 100644 index 0000000000..07d4a45ac5 --- /dev/null +++ b/indra/llcommon/commoncontrol.h @@ -0,0 +1,75 @@ +/** + * @file commoncontrol.h + * @author Nat Goodspeed + * @date 2022-06-08 + * @brief Access LLViewerControl LLEventAPI, if process has one. + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Copyright (c) 2022, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_COMMONCONTROL_H) +#define LL_COMMONCONTROL_H + +#include <vector> +#include "llexception.h" +#include "llsd.h" + +namespace LL +{ + class CommonControl + { + public: + struct Error: public LLException + { + Error(const std::string& what): LLException(what) {} + }; + + /// Exception thrown if there's no LLViewerControl LLEventAPI + struct NoListener: public Error + { + NoListener(const std::string& what): Error(what) {} + }; + + struct ParamError: public Error + { + ParamError(const std::string& what): Error(what) {} + }; + + /// set control group.key to defined default value + static + LLSD set_default(const std::string& group, const std::string& key); + + /// set control group.key to specified value + static + LLSD set(const std::string& group, const std::string& key, const LLSD& value); + + /// toggle boolean control group.key + static + LLSD toggle(const std::string& group, const std::string& key); + + /// get the definition for control group.key, (! isDefined()) if bad + /// ["name"], ["type"], ["value"], ["comment"] + static + LLSD get_def(const std::string& group, const std::string& key); + + /// get the value of control group.key + static + LLSD get(const std::string& group, const std::string& key); + + /// get defined groups + static + std::vector<std::string> get_groups(); + + /// get definitions for all variables in group + static + LLSD get_vars(const std::string& group); + + private: + static + LLSD access(const LLSD& params); + }; +} // namespace LL + +#endif /* ! defined(LL_COMMONCONTROL_H) */ diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index db94765871..b537102510 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -526,6 +526,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) //static S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) { + LL_PROFILE_ZONE_SCOPED; //***************************************** LLAPRFilePoolScope scope(pool); apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY); @@ -570,6 +571,7 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb //static S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) { + LL_PROFILE_ZONE_SCOPED; apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; if (offset < 0) { diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp index 58af32f1af..1e9920746b 100644 --- a/indra/llcommon/llframetimer.cpp +++ b/indra/llcommon/llframetimer.cpp @@ -29,11 +29,6 @@ #include "llframetimer.h" -// We don't bother building a stand alone lib; we just need to include the one source file for Tracy support -//#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER -// #include "TracyClient.cpp" -//#endif // LL_PROFILER_CONFIGURATION - // Static members //LLTimer LLFrameTimer::sInternalTimer; U64 LLFrameTimer::sStartTotalTime = totalTime(); diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 849867586a..749b66b472 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -35,6 +35,7 @@ # include <sys/types.h> # include <mach/task.h> # include <mach/mach_init.h> +#include <mach/mach_host.h> #elif LL_LINUX # include <unistd.h> #endif @@ -109,6 +110,50 @@ void LLMemory::updateMemoryInfo() { sAvailPhysicalMemInKB = U32Kilobytes(0); } + +#elif defined(LL_DARWIN) + task_vm_info info; + mach_msg_type_number_t infoCount = TASK_VM_INFO_COUNT; + // MACH_TASK_BASIC_INFO reports the same resident_size, but does not tell us the reusable bytes or phys_footprint. + if (task_info(mach_task_self(), TASK_VM_INFO, reinterpret_cast<task_info_t>(&info), &infoCount) == KERN_SUCCESS) + { + // Our Windows definition of PagefileUsage is documented by Microsoft as "the total amount of + // memory that the memory manager has committed for a running process", which is rss. + sAllocatedPageSizeInKB = U32Bytes(info.resident_size); + + // Activity Monitor => Inspect Process => Real Memory Size appears to report resident_size + // Activity monitor => main window memory column appears to report phys_footprint, which spot checks as at least 30% less. + // I think that is because of compression, which isn't going to give us a consistent measurement. We want uncompressed totals. + // + // In between is resident_size - reusable. This is what Chrome source code uses, with source comments saying it is 'the "Real Memory" value + // reported for the app by the Memory Monitor in Instruments.' It is still about 8% bigger than phys_footprint. + // + // (On Windows, we use WorkingSetSize.) + sAllocatedMemInKB = U32Bytes(info.resident_size - info.reusable); + } + else + { + LL_WARNS() << "task_info failed" << LL_ENDL; + } + + // Total installed and available physical memory are properties of the host, not just our process. + vm_statistics64_data_t vmstat; + mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; + mach_port_t host = mach_host_self(); + vm_size_t page_size; + host_page_size(host, &page_size); + kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info_t>(&vmstat), &count); + if (result == KERN_SUCCESS) { + // This is what Chrome reports as 'the "Physical Memory Free" value reported by the Memory Monitor in Instruments.' + // Note though that inactive pages are not included here and not yet free, but could become so under memory pressure. + sAvailPhysicalMemInKB = U32Bytes(vmstat.free_count * page_size); + sMaxPhysicalMemInKB = LLMemoryInfo::getHardwareMemSize(); + } + else + { + LL_WARNS() << "task_info failed" << LL_ENDL; + } + #else //not valid for other systems for now. sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS()); diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h index bc46128d21..c0f5868db3 100644 --- a/indra/llcommon/llprofiler.h +++ b/indra/llcommon/llprofiler.h @@ -134,6 +134,10 @@ extern thread_local bool gProfilerEnabled; #define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow #define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan #define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red + //#define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size) // memory allocation tracking currently not working + //#define LL_PROFILE_FREE(ptr) TracyFree(ptr) + #define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size); + #define LL_PROFILE_FREE(ptr) (void)(ptr); #endif #else #define LL_PROFILER_FRAME_END diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 8cef4293cd..155e32ebae 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -26,20 +26,26 @@ #include "linden_common.h" #include "llqueuedthread.h" +#include <chrono> + #include "llstl.h" #include "lltimer.h" // ms_sleep() -#include "lltracethreadrecorder.h" +#include "llmutex.h" //============================================================================ // MAIN THREAD LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) : - LLThread(name), - mThreaded(threaded), - mIdleThread(TRUE), - mNextHandle(0), - mStarted(FALSE) + LLThread(name), + mIdleThread(TRUE), + mNextHandle(0), + mStarted(FALSE), + mThreaded(threaded), + mRequestQueue(name, 1024 * 1024) { + llassert(threaded); // not threaded implementation is deprecated + mMainQueue = LL::WorkQueue::getInstance("mainloop"); + if (mThreaded) { if(should_pause) @@ -69,6 +75,11 @@ void LLQueuedThread::shutdown() unpause(); // MAIN THREAD if (mThreaded) { + if (mRequestQueue.size() == 0) + { + mRequestQueue.close(); + } + S32 timeout = 100; for ( ; timeout>0; timeout--) { @@ -104,6 +115,8 @@ void LLQueuedThread::shutdown() { LL_WARNS() << "~LLQueuedThread() called with active requests: " << active_count << LL_ENDL; } + + mRequestQueue.close(); } //---------------------------------------------------------------------------- @@ -112,6 +125,7 @@ void LLQueuedThread::shutdown() // virtual S32 LLQueuedThread::update(F32 max_time_ms) { + LL_PROFILE_ZONE_SCOPED; if (!mStarted) { if (!mThreaded) @@ -125,29 +139,34 @@ S32 LLQueuedThread::update(F32 max_time_ms) S32 LLQueuedThread::updateQueue(F32 max_time_ms) { - F64 max_time = (F64)max_time_ms * .001; - LLTimer timer; - S32 pending = 1; - + LL_PROFILE_ZONE_SCOPED; // Frame Update if (mThreaded) { - pending = getPending(); - if(pending > 0) + // schedule a call to threadedUpdate for every call to updateQueue + if (!isQuitting()) + { + mRequestQueue.post([=]() + { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qt - update"); + mIdleThread = FALSE; + threadedUpdate(); + mIdleThread = TRUE; + } + ); + } + + if(getPending() > 0) { - unpause(); - } + unpause(); + } } else { - while (pending > 0) - { - pending = processNextRequest(); - if (max_time && timer.getElapsedTimeF64() > max_time) - break; - } + mRequestQueue.runFor(std::chrono::microseconds((int) (max_time_ms*1000.f))); + threadedUpdate(); } - return pending; + return getPending(); } void LLQueuedThread::incQueue() @@ -166,11 +185,7 @@ void LLQueuedThread::incQueue() // May be called from any thread S32 LLQueuedThread::getPending() { - S32 res; - lockData(); - res = mRequestQueue.size(); - unlockData(); - return res; + return mRequestQueue.size(); } // MAIN thread @@ -195,35 +210,28 @@ void LLQueuedThread::waitOnPending() // MAIN thread void LLQueuedThread::printQueueStats() { - lockData(); - if (!mRequestQueue.empty()) + U32 size = mRequestQueue.size(); + if (size > 0) { - QueuedRequest *req = *mRequestQueue.begin(); - LL_INFOS() << llformat("Pending Requests:%d Current status:%d", mRequestQueue.size(), req->getStatus()) << LL_ENDL; + LL_INFOS() << llformat("Pending Requests:%d ", mRequestQueue.size()) << LL_ENDL; } else { LL_INFOS() << "Queued Thread Idle" << LL_ENDL; } - unlockData(); } // MAIN thread LLQueuedThread::handle_t LLQueuedThread::generateHandle() { - lockData(); - while ((mNextHandle == nullHandle()) || (mRequestHash.find(mNextHandle))) - { - mNextHandle++; - } - const LLQueuedThread::handle_t res = mNextHandle++; - unlockData(); + U32 res = ++mNextHandle; return res; } // MAIN thread bool LLQueuedThread::addRequest(QueuedRequest* req) { + LL_PROFILE_ZONE_SCOPED; if (mStatus == QUITTING) { return false; @@ -231,14 +239,14 @@ bool LLQueuedThread::addRequest(QueuedRequest* req) lockData(); req->setStatus(STATUS_QUEUED); - mRequestQueue.insert(req); - mRequestHash.insert(req); + mRequestHash.insert(req); #if _DEBUG // LL_INFOS() << llformat("LLQueuedThread::Added req [%08d]",handle) << LL_ENDL; #endif unlockData(); - incQueue(); + llassert(!mDataLock->isSelfLocked()); + mRequestQueue.post([this, req]() { processRequest(req); }); return true; } @@ -246,6 +254,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req) // MAIN thread bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_complete) { + LL_PROFILE_ZONE_SCOPED; llassert (handle != nullHandle()); bool res = false; bool waspaused = isPaused(); @@ -312,6 +321,7 @@ LLQueuedThread::status_t LLQueuedThread::getRequestStatus(handle_t handle) void LLQueuedThread::abortRequest(handle_t handle, bool autocomplete) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; lockData(); QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); if (req) @@ -333,30 +343,9 @@ void LLQueuedThread::setFlags(handle_t handle, U32 flags) unlockData(); } -void LLQueuedThread::setPriority(handle_t handle, U32 priority) -{ - lockData(); - QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); - if (req) - { - if(req->getStatus() == STATUS_INPROGRESS) - { - // not in list - req->setPriority(priority); - } - else if(req->getStatus() == STATUS_QUEUED) - { - // remove from list then re-insert - llverify(mRequestQueue.erase(req) == 1); - req->setPriority(priority); - mRequestQueue.insert(req); - } - } - unlockData(); -} - bool LLQueuedThread::completeRequest(handle_t handle) { + LL_PROFILE_ZONE_SCOPED; bool res = false; lockData(); QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle); @@ -399,89 +388,115 @@ bool LLQueuedThread::check() //============================================================================ // Runs on its OWN thread -S32 LLQueuedThread::processNextRequest() +void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req) { - QueuedRequest *req; + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + + mIdleThread = FALSE; + //threadedUpdate(); + // Get next request from pool lockData(); - while(1) + if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING)) { - req = NULL; - if (mRequestQueue.empty()) + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - abort"); + req->setStatus(STATUS_ABORTED); + req->finishRequest(false); + if (req->getFlags() & FLAG_AUTO_COMPLETE) { - break; - } - req = *mRequestQueue.begin(); - mRequestQueue.erase(mRequestQueue.begin()); - if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING)) - { - req->setStatus(STATUS_ABORTED); - req->finishRequest(false); - if (req->getFlags() & FLAG_AUTO_COMPLETE) - { - mRequestHash.erase(req); - req->deleteRequest(); -// check(); - } - continue; - } - llassert_always(req->getStatus() == STATUS_QUEUED); - break; - } - U32 start_priority = 0 ; - if (req) - { - req->setStatus(STATUS_INPROGRESS); - start_priority = req->getPriority(); - } - unlockData(); - - // This is the only place we will call req->setStatus() after - // it has initially been seet to STATUS_QUEUED, so it is - // safe to access req. - if (req) - { - // process request - bool complete = req->processRequest(); - - if (complete) - { - lockData(); - req->setStatus(STATUS_COMPLETE); - req->finishRequest(true); - if (req->getFlags() & FLAG_AUTO_COMPLETE) - { - mRequestHash.erase(req); - req->deleteRequest(); + mRequestHash.erase(req); + req->deleteRequest(); // check(); - } - unlockData(); } - else - { - lockData(); - req->setStatus(STATUS_QUEUED); - mRequestQueue.insert(req); - unlockData(); - if (mThreaded && start_priority < PRIORITY_NORMAL) - { - ms_sleep(1); // sleep the thread a little - } - } - - LLTrace::get_thread_recorder()->pushToParent(); + unlockData(); } + else + { + llassert_always(req->getStatus() == STATUS_QUEUED); + + if (req) + { + req->setStatus(STATUS_INPROGRESS); + } + unlockData(); + + // This is the only place we will call req->setStatus() after + // it has initially been seet to STATUS_QUEUED, so it is + // safe to access req. + if (req) + { + // process request + bool complete = req->processRequest(); + + if (complete) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - complete"); + lockData(); + req->setStatus(STATUS_COMPLETE); + req->finishRequest(true); + if (req->getFlags() & FLAG_AUTO_COMPLETE) + { + mRequestHash.erase(req); + req->deleteRequest(); + // check(); + } + unlockData(); + } + else + { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - retry"); + //put back on queue and try again in 0.1ms + lockData(); + req->setStatus(STATUS_QUEUED); + + unlockData(); + + llassert(!mDataLock->isSelfLocked()); + +#if 0 + // try again on next frame + // NOTE: tried using "post" with a time in the future, but this + // would invariably cause this thread to wait for a long time (10+ ms) + // while work is pending + bool ret = LL::WorkQueue::postMaybe( + mMainQueue, + [=]() + { + LL_PROFILE_ZONE_NAMED("processRequest - retry"); + mRequestQueue.post([=]() + { + LL_PROFILE_ZONE_NAMED("processRequest - retry"); // <-- not redundant, track retry on both queues + processRequest(req); + }); + }); + llassert(ret); +#else + using namespace std::chrono_literals; + auto retry_time = LL::WorkQueue::TimePoint::clock::now() + 16ms; + mRequestQueue.post([=] + { + LL_PROFILE_ZONE_NAMED("processRequest - retry"); + while (LL::WorkQueue::TimePoint::clock::now() < retry_time) + { + std::this_thread::yield(); //note: don't use LLThread::yield here to avoid + } + processRequest(req); + }); +#endif + + } + } + } - S32 pending = getPending(); - return pending; + mIdleThread = TRUE; } // virtual bool LLQueuedThread::runCondition() { // mRunCondition must be locked here - if (mRequestQueue.empty() && mIdleThread) + if (mRequestQueue.size() == 0 && mIdleThread) return false; else return true; @@ -495,18 +510,13 @@ void LLQueuedThread::run() startThread(); mStarted = TRUE; - while (1) + + /*while (1) { + LL_PROFILE_ZONE_SCOPED; // this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state. checkPause(); - if (isQuitting()) - { - LLTrace::get_thread_recorder()->pushToParent(); - endThread(); - break; - } - mIdleThread = FALSE; threadedUpdate(); @@ -515,12 +525,18 @@ void LLQueuedThread::run() if (pending_work == 0) { + //LL_PROFILE_ZONE_NAMED("LLQueuedThread - sleep"); mIdleThread = TRUE; - ms_sleep(1); + //ms_sleep(1); } //LLThread::yield(); // thread should yield after each request - } + }*/ + mRequestQueue.runUntilClose(); + + endThread(); LL_INFOS() << "LLQueuedThread " << mName << " EXITING." << LL_ENDL; + + } // virtual @@ -540,10 +556,9 @@ void LLQueuedThread::threadedUpdate() //============================================================================ -LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U32 priority, U32 flags) : +LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U32 flags) : LLSimpleHashEntry<LLQueuedThread::handle_t>(handle), mStatus(STATUS_UNKNOWN), - mPriority(priority), mFlags(flags) { } diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index 5d3f873646..6b82ccc434 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -36,6 +36,7 @@ #include "llthread.h" #include "llsimplehash.h" +#include "workqueue.h" //============================================================================ // Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small @@ -45,15 +46,6 @@ class LL_COMMON_API LLQueuedThread : public LLThread { //------------------------------------------------------------------------ public: - enum priority_t { - PRIORITY_IMMEDIATE = 0x7FFFFFFF, - PRIORITY_URGENT = 0x40000000, - PRIORITY_HIGH = 0x30000000, - PRIORITY_NORMAL = 0x20000000, - PRIORITY_LOW = 0x10000000, - PRIORITY_LOWBITS = 0x0FFFFFFF, - PRIORITY_HIGHBITS = 0x70000000 - }; enum status_t { STATUS_EXPIRED = -1, STATUS_UNKNOWN = 0, @@ -82,28 +74,17 @@ public: virtual ~QueuedRequest(); // use deleteRequest() public: - QueuedRequest(handle_t handle, U32 priority, U32 flags = 0); + QueuedRequest(handle_t handle, U32 flags = 0); status_t getStatus() { return mStatus; } - U32 getPriority() const - { - return mPriority; - } U32 getFlags() const { return mFlags; } - bool higherPriority(const QueuedRequest& second) const - { - if ( mPriority == second.mPriority) - return mHashKey < second.mHashKey; - else - return mPriority > second.mPriority; - } - + protected: status_t setStatus(status_t newstatus) { @@ -121,28 +102,11 @@ public: virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted virtual void deleteRequest(); // Only method to delete a request - void setPriority(U32 pri) - { - // Only do this on a request that is not in a queued list! - mPriority = pri; - }; - protected: LLAtomicBase<status_t> mStatus; - U32 mPriority; U32 mFlags; }; -protected: - struct queued_request_less - { - bool operator()(const QueuedRequest* lhs, const QueuedRequest* rhs) const - { - return lhs->higherPriority(*rhs); // higher priority in front of queue (set) - } - }; - - //------------------------------------------------------------------------ public: @@ -167,7 +131,7 @@ private: protected: handle_t generateHandle(); bool addRequest(QueuedRequest* req); - S32 processNextRequest(void); + void processRequest(QueuedRequest* req); void incQueue(); public: @@ -186,7 +150,6 @@ public: status_t getRequestStatus(handle_t handle); void abortRequest(handle_t handle, bool autocomplete); void setFlags(handle_t handle, U32 flags); - void setPriority(handle_t handle, U32 priority); bool completeRequest(handle_t handle); // This is public for support classes like LLWorkerThread, // but generally the methods above should be used. @@ -200,8 +163,10 @@ protected: BOOL mStarted; // required when mThreaded is false to call startThread() from update() LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle - typedef std::set<QueuedRequest*, queued_request_less> request_queue_t; - request_queue_t mRequestQueue; + //typedef std::set<QueuedRequest*, queued_request_less> request_queue_t; + //request_queue_t mRequestQueue; + LL::WorkQueue mRequestQueue; + LL::WorkQueue::weak_t mMainQueue; enum { REQUEST_HASH_SIZE = 512 }; // must be power of 2 typedef LLSimpleHash<handle_t, REQUEST_HASH_SIZE> request_hash_t; diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 9b6bb3826c..45417bfa37 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -710,20 +710,28 @@ static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB) } #endif +#if LL_DARWIN +// static +U32Kilobytes LLMemoryInfo::getHardwareMemSize() +{ + // This might work on Linux as well. Someone check... + uint64_t phys = 0; + int mib[2] = { CTL_HW, HW_MEMSIZE }; + + size_t len = sizeof(phys); + sysctl(mib, 2, &phys, &len, NULL, 0); + + return U64Bytes(phys); +} +#endif + U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const { #if LL_WINDOWS return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger())); #elif LL_DARWIN - // This might work on Linux as well. Someone check... - uint64_t phys = 0; - int mib[2] = { CTL_HW, HW_MEMSIZE }; - - size_t len = sizeof(phys); - sysctl(mib, 2, &phys, &len, NULL, 0); - - return U64Bytes(phys); + return getHardwareMemSize(); #elif LL_LINUX U64 phys = 0; diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index cb92cb0ac6..538e61c521 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -117,7 +117,10 @@ public: LLMemoryInfo(); ///< Default constructor void stream(std::ostream& s) const; ///< output text info to s - U32Kilobytes getPhysicalMemoryKB() const; + U32Kilobytes getPhysicalMemoryKB() const; +#if LL_DARWIN + static U32Kilobytes getHardwareMemSize(); // Because some Mac linkers won't let us reference extern gSysMemory from a different lib. +#endif //get the available memory infomation in KiloBytes. static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb); diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index aaa6df325c..39dfee3755 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -30,6 +30,9 @@ #include "u64.h" +#include <chrono> +#include <thread> + #if LL_WINDOWS # include "llwin32headerslean.h" #elif LL_LINUX || LL_DARWIN @@ -64,7 +67,13 @@ LLTimer* LLTimer::sTimer = NULL; #if LL_WINDOWS void ms_sleep(U32 ms) { - Sleep(ms); + LL_PROFILE_ZONE_SCOPED; + using TimePoint = std::chrono::steady_clock::time_point; + auto resume_time = TimePoint::clock::now() + std::chrono::milliseconds(ms); + while (TimePoint::clock::now() < resume_time) + { + std::this_thread::yield(); //note: don't use LLThread::yield here to avoid yielding for too long + } } U32 micro_sleep(U64 us, U32 max_yields) diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 4b91b2caca..02ce4823b8 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -133,11 +133,11 @@ S32 LLWorkerThread::update(F32 max_time_ms) //---------------------------------------------------------------------------- -LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority) +LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param) { handle_t handle = generateHandle(); - WorkRequest* req = new WorkRequest(handle, priority, workerclass, param); + WorkRequest* req = new WorkRequest(handle, workerclass, param); bool res = addRequest(req); if (!res) @@ -160,8 +160,8 @@ void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass) //============================================================================ // Runs on its OWN thread -LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param) : - LLQueuedThread::QueuedRequest(handle, priority), +LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param) : + LLQueuedThread::QueuedRequest(handle), mWorkerClass(workerclass), mParam(param) { @@ -180,6 +180,7 @@ void LLWorkerThread::WorkRequest::deleteRequest() // virtual bool LLWorkerThread::WorkRequest::processRequest() { + LL_PROFILE_ZONE_SCOPED; LLWorkerClass* workerclass = getWorkerClass(); workerclass->setWorking(true); bool complete = workerclass->doWork(getParam()); @@ -190,6 +191,7 @@ bool LLWorkerThread::WorkRequest::processRequest() // virtual void LLWorkerThread::WorkRequest::finishRequest(bool completed) { + LL_PROFILE_ZONE_SCOPED; LLWorkerClass* workerclass = getWorkerClass(); workerclass->finishWork(getParam(), completed); U32 flags = LLWorkerClass::WCF_WORK_FINISHED | (completed ? 0 : LLWorkerClass::WCF_WORK_ABORTED); @@ -203,7 +205,6 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na : mWorkerThread(workerthread), mWorkerClassName(name), mRequestHandle(LLWorkerThread::nullHandle()), - mRequestPriority(LLWorkerThread::PRIORITY_NORMAL), mMutex(), mWorkFlags(0) { @@ -292,7 +293,7 @@ bool LLWorkerClass::yield() //---------------------------------------------------------------------------- // calls startWork, adds doWork() to queue -void LLWorkerClass::addWork(S32 param, U32 priority) +void LLWorkerClass::addWork(S32 param) { mMutex.lock(); llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK))); @@ -306,7 +307,7 @@ void LLWorkerClass::addWork(S32 param, U32 priority) startWork(param); clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED); setFlags(WCF_HAVE_WORK); - mRequestHandle = mWorkerThread->addWorkRequest(this, param, priority); + mRequestHandle = mWorkerThread->addWorkRequest(this, param); mMutex.unlock(); } @@ -321,7 +322,6 @@ void LLWorkerClass::abortWork(bool autocomplete) if (mRequestHandle != LLWorkerThread::nullHandle()) { mWorkerThread->abortRequest(mRequestHandle, autocomplete); - mWorkerThread->setPriority(mRequestHandle, LLQueuedThread::PRIORITY_IMMEDIATE); setFlags(WCF_ABORT_REQUESTED); } mMutex.unlock(); @@ -395,16 +395,5 @@ void LLWorkerClass::scheduleDelete() } } -void LLWorkerClass::setPriority(U32 priority) -{ - mMutex.lock(); - if (mRequestHandle != LLWorkerThread::nullHandle() && mRequestPriority != priority) - { - mRequestPriority = priority; - mWorkerThread->setPriority(mRequestHandle, priority); - } - mMutex.unlock(); -} - //============================================================================ diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index 0387e75c65..06bbb7369e 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -56,7 +56,7 @@ public: virtual ~WorkRequest(); // use deleteRequest() public: - WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param); + WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param); S32 getParam() { @@ -90,7 +90,7 @@ public: /*virtual*/ S32 update(F32 max_time_ms); - handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL); + handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param); S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug @@ -151,10 +151,6 @@ public: bool isWorking() { return getFlags(WCF_WORKING); } bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); } - // setPriority(): changes the priority of a request - void setPriority(U32 priority); - U32 getPriority() { return mRequestPriority; } - const std::string& getName() const { return mWorkerClassName; } protected: @@ -169,7 +165,7 @@ protected: void setWorkerThread(LLWorkerThread* workerthread); // addWork(): calls startWork, adds doWork() to queue - void addWork(S32 param, U32 priority = LLWorkerThread::PRIORITY_NORMAL); + void addWork(S32 param); // abortWork(): requests that work be aborted void abortWork(bool autocomplete); @@ -193,7 +189,6 @@ protected: LLWorkerThread* mWorkerThread; std::string mWorkerClassName; handle_t mRequestHandle; - U32 mRequestPriority; // last priority set private: LLMutex mMutex; diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index ba914035e2..f49dd40a8b 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -17,14 +17,17 @@ // std headers // external library headers // other Linden headers +#include "commoncontrol.h" #include "llerror.h" #include "llevents.h" +#include "llsd.h" #include "stringize.h" LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity): + super(name), mQueue(name, capacity), mName("ThreadPool:" + name), - mThreadCount(threads) + mThreadCount(getConfiguredWidth(name, threads)) {} void LL::ThreadPool::start() @@ -86,3 +89,58 @@ void LL::ThreadPool::run() { mQueue.runUntilClose(); } + +//static +size_t LL::ThreadPool::getConfiguredWidth(const std::string& name, size_t dft) +{ + LLSD poolSizes; + try + { + poolSizes = LL::CommonControl::get("Global", "ThreadPoolSizes"); + // "ThreadPoolSizes" is actually a map containing the sizes of + // interest -- or should be, if this process has an + // LLViewerControlListener instance and its settings include + // "ThreadPoolSizes". If we failed to retrieve it, perhaps we're in a + // program that doesn't define that, or perhaps there's no such + // setting, or perhaps we're asking too early, before the LLEventAPI + // itself has been instantiated. In any of those cases, it seems worth + // warning. + if (! poolSizes.isDefined()) + { + // Note: we don't warn about absence of an override key for a + // particular ThreadPool name, that's fine. This warning is about + // complete absence of a ThreadPoolSizes setting, which we expect + // in a normal viewer session. + LL_WARNS("ThreadPool") << "No 'ThreadPoolSizes' setting for ThreadPool '" + << name << "'" << LL_ENDL; + } + } + catch (const LL::CommonControl::Error& exc) + { + // We don't want ThreadPool to *require* LLViewerControlListener. + // Just log it and carry on. + LL_WARNS("ThreadPool") << "Can't check 'ThreadPoolSizes': " << exc.what() << LL_ENDL; + } + + LL_DEBUGS("ThreadPool") << "ThreadPoolSizes = " << poolSizes << LL_ENDL; + // LLSD treats an undefined value as an empty map when asked to retrieve a + // key, so we don't need this to be conditional. + LLSD sizeSpec{ poolSizes[name] }; + // We retrieve sizeSpec as LLSD, rather than immediately as LLSD::Integer, + // so we can distinguish the case when it's undefined. + return sizeSpec.isInteger() ? sizeSpec.asInteger() : dft; +} + +//static +size_t LL::ThreadPool::getWidth(const std::string& name, size_t dft) +{ + auto instance{ getInstance(name) }; + if (instance) + { + return instance->getWidth(); + } + else + { + return getConfiguredWidth(name, dft); + } +} diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index b79c9b9090..b49d511257 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -22,14 +22,25 @@ namespace LL { - class ThreadPool + class ThreadPool: public LLInstanceTracker<ThreadPool, std::string> { + private: + using super = LLInstanceTracker<ThreadPool, std::string>; public: /** * Pass ThreadPool a string name. This can be used to look up the * relevant WorkQueue. + * + * The number of threads you pass sets the compile-time default. But + * if the user has overridden the LLSD map in the "ThreadPoolSizes" + * setting with a key matching this ThreadPool name, that setting + * overrides this parameter. + * + * Pass an explicit capacity to limit the size of the queue. + * Constraining the queue can cause a submitter to block. Do not + * constrain any ThreadPool accepting work from the main thread. */ - ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024); + ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024*1024); virtual ~ThreadPool(); /** @@ -57,6 +68,25 @@ namespace LL */ virtual void run(); + /** + * getConfiguredWidth() returns the setting, if any, for the specified + * ThreadPool name. Returns dft if the "ThreadPoolSizes" map does not + * contain the specified name. + */ + static + size_t getConfiguredWidth(const std::string& name, size_t dft=0); + + /** + * This getWidth() returns the width of the instantiated ThreadPool + * with the specified name, if any. If no instance exists, returns its + * getConfiguredWidth() if any. If there's no instance and no relevant + * override, return dft. Presumably dft should match the threads + * parameter passed to the ThreadPool constructor call that will + * eventually instantiate the ThreadPool with that name. + */ + static + size_t getWidth(const std::string& name, size_t dft); + private: void run(const std::string& name); diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 96574a18b9..784327f929 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -162,9 +162,15 @@ namespace LL CALLABLE&& callable); template <typename CALLABLE> + bool tryPost(const TimePoint& time, CALLABLE&& callable) + { + return mQueue.tryPush(TimedWork(time, std::move(callable))); + } + + template <typename CALLABLE> bool tryPost(CALLABLE&& callable) { - return mQueue.tryPush(TimedWork(TimePoint::clock::now(), std::move(callable))); + return mQueue.tryPush(TimePoint::clock::now(), std::move(callable)); } /*------------------------- handshake API --------------------------*/ diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp index 975ce8a4d5..bd0ac740db 100644 --- a/indra/llcorehttp/_httplibcurl.cpp +++ b/indra/llcorehttp/_httplibcurl.cpp @@ -113,6 +113,7 @@ void HttpLibcurl::shutdown() void HttpLibcurl::start(int policy_count) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; llassert_always(policy_count <= HTTP_POLICY_CLASS_LIMIT); llassert_always(! mMultiHandles); // One-time call only @@ -143,6 +144,7 @@ void HttpLibcurl::start(int policy_count) // sleep otherwise ask for a normal polling interval. HttpService::ELoopSpeed HttpLibcurl::processTransport() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpService::ELoopSpeed ret(HttpService::REQUEST_SLEEP); // Give libcurl some cycles to do I/O & callbacks @@ -168,6 +170,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport() CURLMcode status(CURLM_CALL_MULTI_PERFORM); do { + LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("httppt - curl_multi_perform"); running = 0; status = curl_multi_perform(mMultiHandles[policy_class], &running); } @@ -176,31 +179,34 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport() // Run completion on anything done CURLMsg * msg(NULL); int msgs_in_queue(0); - while ((msg = curl_multi_info_read(mMultiHandles[policy_class], &msgs_in_queue))) - { - if (CURLMSG_DONE == msg->msg) - { - CURL * handle(msg->easy_handle); - CURLcode result(msg->data.result); + { + LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("httppt - curl_multi_info_read"); + while ((msg = curl_multi_info_read(mMultiHandles[policy_class], &msgs_in_queue))) + { + if (CURLMSG_DONE == msg->msg) + { + CURL* handle(msg->easy_handle); + CURLcode result(msg->data.result); - completeRequest(mMultiHandles[policy_class], handle, result); - handle = NULL; // No longer valid on return - ret = HttpService::NORMAL; // If anything completes, we may have a free slot. - // Turning around quickly reduces connection gap by 7-10mS. - } - else if (CURLMSG_NONE == msg->msg) - { - // Ignore this... it shouldn't mean anything. - ; - } - else - { - LL_WARNS_ONCE(LOG_CORE) << "Unexpected message from libcurl. Msg code: " - << msg->msg - << LL_ENDL; - } - msgs_in_queue = 0; - } + completeRequest(mMultiHandles[policy_class], handle, result); + handle = NULL; // No longer valid on return + ret = HttpService::NORMAL; // If anything completes, we may have a free slot. + // Turning around quickly reduces connection gap by 7-10mS. + } + else if (CURLMSG_NONE == msg->msg) + { + // Ignore this... it shouldn't mean anything. + ; + } + else + { + LL_WARNS_ONCE(LOG_CORE) << "Unexpected message from libcurl. Msg code: " + << msg->msg + << LL_ENDL; + } + msgs_in_queue = 0; + } + } } if (! mActiveOps.empty()) @@ -214,6 +220,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport() // Caller has provided us with a ref count on op. void HttpLibcurl::addOp(const HttpOpRequest::ptr_t &op) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; llassert_always(op->mReqPolicy < mPolicyCount); llassert_always(mMultiHandles[op->mReqPolicy] != NULL); @@ -257,6 +264,7 @@ void HttpLibcurl::addOp(const HttpOpRequest::ptr_t &op) // method to kill the request. bool HttpLibcurl::cancel(HttpHandle handle) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpOpRequest::ptr_t op = HttpOpRequest::fromHandle<HttpOpRequest>(handle); active_set_t::iterator it(mActiveOps.find(op)); if (mActiveOps.end() == it) @@ -282,6 +290,7 @@ bool HttpLibcurl::cancel(HttpHandle handle) // op to the reply queue with refcount intact. void HttpLibcurl::cancelRequest(const HttpOpRequest::ptr_t &op) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; // Deactivate request op->mCurlActive = false; @@ -308,6 +317,7 @@ void HttpLibcurl::cancelRequest(const HttpOpRequest::ptr_t &op) // Keep them synchronized as necessary. bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode status) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpHandle ophandle(NULL); CURLcode ccode(CURLE_OK); @@ -445,6 +455,7 @@ int HttpLibcurl::getActiveCountInClass(int policy_class) const void HttpLibcurl::policyUpdated(int policy_class) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; if (policy_class < 0 || policy_class >= mPolicyCount || ! mMultiHandles) { return; diff --git a/indra/llcorehttp/_httpoperation.cpp b/indra/llcorehttp/_httpoperation.cpp index 3fc4e28910..3b64018132 100644 --- a/indra/llcorehttp/_httpoperation.cpp +++ b/indra/llcorehttp/_httpoperation.cpp @@ -62,7 +62,6 @@ HttpOperation::HttpOperation(): mReplyQueue(), mUserHandler(), mReqPolicy(HttpRequest::DEFAULT_POLICY_ID), - mReqPriority(0U), mTracing(HTTP_TRACE_OFF), mMyHandle(LLCORE_HTTP_HANDLE_INVALID) { diff --git a/indra/llcorehttp/_httpoperation.h b/indra/llcorehttp/_httpoperation.h index 1a75921c09..8c1364bab4 100644 --- a/indra/llcorehttp/_httpoperation.h +++ b/indra/llcorehttp/_httpoperation.h @@ -181,7 +181,6 @@ protected: public: // Request Data HttpRequest::policy_t mReqPolicy; - HttpRequest::priority_t mReqPriority; // Reply Data HttpStatus mStatus; diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index ba31290c24..d60eb6c95f 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -200,6 +200,7 @@ HttpOpRequest::~HttpOpRequest() void HttpOpRequest::stageFromRequest(HttpService * service) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpOpRequest::ptr_t self(boost::dynamic_pointer_cast<HttpOpRequest>(shared_from_this())); service->getPolicy().addOp(self); // transfers refcount } @@ -207,6 +208,7 @@ void HttpOpRequest::stageFromRequest(HttpService * service) void HttpOpRequest::stageFromReady(HttpService * service) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpOpRequest::ptr_t self(boost::dynamic_pointer_cast<HttpOpRequest>(shared_from_this())); service->getTransport().addOp(self); // transfers refcount } @@ -214,6 +216,7 @@ void HttpOpRequest::stageFromReady(HttpService * service) void HttpOpRequest::stageFromActive(HttpService * service) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; if (mReplyLength) { // If non-zero, we received and processed a Content-Range @@ -250,6 +253,7 @@ void HttpOpRequest::stageFromActive(HttpService * service) void HttpOpRequest::visitNotifier(HttpRequest * request) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; if (mUserHandler) { HttpResponse * response = new HttpResponse(); @@ -292,6 +296,7 @@ void HttpOpRequest::visitNotifier(HttpRequest * request) HttpStatus HttpOpRequest::cancel() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; mStatus = HttpStatus(HttpStatus::LLCORE, HE_OP_CANCELED); addAsReply(); @@ -301,12 +306,12 @@ HttpStatus HttpOpRequest::cancel() HttpStatus HttpOpRequest::setupGet(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers) { - setupCommon(policy_id, priority, url, NULL, options, headers); + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + setupCommon(policy_id, url, NULL, options, headers); mReqMethod = HOR_GET; return HttpStatus(); @@ -314,14 +319,14 @@ HttpStatus HttpOpRequest::setupGet(HttpRequest::policy_t policy_id, HttpStatus HttpOpRequest::setupGetByteRange(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, size_t offset, size_t len, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers) { - setupCommon(policy_id, priority, url, NULL, options, headers); + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + setupCommon(policy_id, url, NULL, options, headers); mReqMethod = HOR_GET; mReqOffset = offset; mReqLength = len; @@ -335,13 +340,13 @@ HttpStatus HttpOpRequest::setupGetByteRange(HttpRequest::policy_t policy_id, HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers) { - setupCommon(policy_id, priority, url, body, options, headers); + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + setupCommon(policy_id, url, body, options, headers); mReqMethod = HOR_POST; return HttpStatus(); @@ -349,13 +354,13 @@ HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id, HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers) { - setupCommon(policy_id, priority, url, body, options, headers); + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + setupCommon(policy_id, url, body, options, headers); mReqMethod = HOR_PUT; return HttpStatus(); @@ -363,12 +368,12 @@ HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id, HttpStatus HttpOpRequest::setupDelete(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers) { - setupCommon(policy_id, priority, url, NULL, options, headers); + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + setupCommon(policy_id, url, NULL, options, headers); mReqMethod = HOR_DELETE; return HttpStatus(); @@ -376,13 +381,13 @@ HttpStatus HttpOpRequest::setupDelete(HttpRequest::policy_t policy_id, HttpStatus HttpOpRequest::setupPatch(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers) { - setupCommon(policy_id, priority, url, body, options, headers); + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + setupCommon(policy_id, url, body, options, headers); mReqMethod = HOR_PATCH; return HttpStatus(); @@ -390,12 +395,12 @@ HttpStatus HttpOpRequest::setupPatch(HttpRequest::policy_t policy_id, HttpStatus HttpOpRequest::setupCopy(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t &headers) { - setupCommon(policy_id, priority, url, NULL, options, headers); + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + setupCommon(policy_id, url, NULL, options, headers); mReqMethod = HOR_COPY; return HttpStatus(); @@ -403,12 +408,12 @@ HttpStatus HttpOpRequest::setupCopy(HttpRequest::policy_t policy_id, HttpStatus HttpOpRequest::setupMove(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t &headers) { - setupCommon(policy_id, priority, url, NULL, options, headers); + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + setupCommon(policy_id, url, NULL, options, headers); mReqMethod = HOR_MOVE; return HttpStatus(); @@ -416,15 +421,14 @@ HttpStatus HttpOpRequest::setupMove(HttpRequest::policy_t policy_id, void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; mProcFlags = 0U; mReqPolicy = policy_id; - mReqPriority = priority; mReqURL = url; if (body) { @@ -465,6 +469,7 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id, // *TODO: Move this to _httplibcurl where it belongs. HttpStatus HttpOpRequest::prepareRequest(HttpService * service) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; // Scrub transport and result data for retried op case mCurlActive = false; mCurlHandle = NULL; @@ -773,6 +778,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void * userdata) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata)); if (! op->mReplyBody) @@ -788,6 +794,7 @@ size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void * userdata) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata)); if (! op->mReqBody) @@ -819,6 +826,7 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void int HttpOpRequest::seekCallback(void *userdata, curl_off_t offset, int origin) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata)); if (!op->mReqBody) @@ -850,6 +858,7 @@ int HttpOpRequest::seekCallback(void *userdata, curl_off_t offset, int origin) size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, void * userdata) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; static const char status_line[] = "HTTP/"; static const size_t status_line_len = sizeof(status_line) - 1; static const char con_ran_line[] = "content-range"; @@ -999,6 +1008,7 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userdata) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata)); if (op->mCallbackSSLVerify) @@ -1025,6 +1035,7 @@ CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userd int HttpOpRequest::sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(param)); if (op->mCallbackSSLVerify) @@ -1037,6 +1048,7 @@ int HttpOpRequest::sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param) int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffer, size_t len, void * userdata) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata)); std::string safe_line; diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h index cdbe350785..ec84822cf4 100644 --- a/indra/llcorehttp/_httpoprequest.h +++ b/indra/llcorehttp/_httpoprequest.h @@ -105,13 +105,11 @@ public: /// Threading: called by application thread /// HttpStatus setupGet(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupGetByteRange(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, size_t offset, size_t len, @@ -119,40 +117,34 @@ public: const HttpHeaders::ptr_t & headers); HttpStatus setupPost(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupPut(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupDelete(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupPatch(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupCopy(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupMove(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); @@ -172,7 +164,6 @@ protected: // Threading: called by application thread // void setupCommon(HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, @@ -239,19 +230,6 @@ public: -/// HttpOpRequestCompare isn't an operation but a uniform comparison -/// functor for STL containers that order by priority. Mainly -/// used for the ready queue container but defined here. -class HttpOpRequestCompare -{ -public: - bool operator()(const HttpOpRequest * lhs, const HttpOpRequest * rhs) - { - return lhs->mReqPriority > rhs->mReqPriority; - } -}; // end class HttpOpRequestCompare - - // --------------------------------------- // Free functions // --------------------------------------- diff --git a/indra/llcorehttp/_httpopsetpriority.cpp b/indra/llcorehttp/_httpopsetpriority.cpp index d48c7a0b7d..b99b4e9e4a 100644 --- a/indra/llcorehttp/_httpopsetpriority.cpp +++ b/indra/llcorehttp/_httpopsetpriority.cpp @@ -24,6 +24,7 @@ * $/LicenseInfo$ */ +#if 0 // DEPRECATED #include "_httpopsetpriority.h" #include "httpresponse.h" @@ -61,3 +62,5 @@ void HttpOpSetPriority::stageFromRequest(HttpService * service) } // end namespace LLCore + +#endif diff --git a/indra/llcorehttp/_httpopsetpriority.h b/indra/llcorehttp/_httpopsetpriority.h index 43e2aa081b..fd543f37cc 100644 --- a/indra/llcorehttp/_httpopsetpriority.h +++ b/indra/llcorehttp/_httpopsetpriority.h @@ -27,7 +27,7 @@ #ifndef _LLCORE_HTTP_SETPRIORITY_H_ #define _LLCORE_HTTP_SETPRIORITY_H_ - +#if 0 // DEPRECATED #include "httpcommon.h" #include "httprequest.h" #include "_httpoperation.h" @@ -49,7 +49,7 @@ namespace LLCore class HttpOpSetPriority : public HttpOperation { public: - HttpOpSetPriority(HttpHandle handle, HttpRequest::priority_t priority); + HttpOpSetPriority(HttpHandle handle); virtual ~HttpOpSetPriority(); @@ -63,10 +63,10 @@ public: protected: // Request Data HttpHandle mHandle; - HttpRequest::priority_t mPriority; }; // end class HttpOpSetPriority } // end namespace LLCore +#endif #endif // _LLCORE_HTTP_SETPRIORITY_H_ diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp index 885f0ed61d..29f50c1693 100644 --- a/indra/llcorehttp/_httppolicy.cpp +++ b/indra/llcorehttp/_httppolicy.cpp @@ -330,37 +330,6 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue() return result; } - -bool HttpPolicy::changePriority(HttpHandle handle, HttpRequest::priority_t priority) -{ - for (int policy_class(0); policy_class < mClasses.size(); ++policy_class) - { - ClassState & state(*mClasses[policy_class]); - // We don't scan retry queue because a priority change there - // is meaningless. The request will be issued based on retry - // intervals not priority value, which is now moot. - - // Scan ready queue for requests that match policy - HttpReadyQueue::container_type & c(state.mReadyQueue.get_container()); - for (HttpReadyQueue::container_type::iterator iter(c.begin()); c.end() != iter;) - { - HttpReadyQueue::container_type::iterator cur(iter++); - - if ((*cur)->getHandle() == handle) - { - HttpOpRequest::ptr_t op(*cur); - c.erase(cur); // All iterators are now invalidated - op->mReqPriority = priority; - state.mReadyQueue.push(op); // Re-insert using adapter class - return true; - } - } - } - - return false; -} - - bool HttpPolicy::cancel(HttpHandle handle) { for (int policy_class(0); policy_class < mClasses.size(); ++policy_class) diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h index 3c4126e14b..0b8806a3e2 100644 --- a/indra/llcorehttp/_httppolicy.h +++ b/indra/llcorehttp/_httppolicy.h @@ -110,12 +110,6 @@ public: /// Threading: called by worker thread void retryOp(const opReqPtr_t &); - /// Attempt to change the priority of an earlier request. - /// Request that Shadows HttpService's method - /// - /// Threading: called by worker thread - bool changePriority(HttpHandle handle, HttpRequest::priority_t priority); - /// Attempt to cancel a previous request. /// Shadows HttpService's method as well /// diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index 56f52f1b09..294acd7f63 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -80,6 +80,7 @@ HttpService::HttpService() HttpService::~HttpService() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; mExitRequested = 1U; if (RUNNING == sState) { @@ -131,6 +132,7 @@ HttpService::~HttpService() void HttpService::init(HttpRequestQueue * queue) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; llassert_always(! sInstance); llassert_always(NOT_INITIALIZED == sState); sInstance = new HttpService(); @@ -145,6 +147,7 @@ void HttpService::init(HttpRequestQueue * queue) void HttpService::term() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; if (sInstance) { if (RUNNING == sState && sInstance->mThread) @@ -196,6 +199,7 @@ bool HttpService::isStopped() /// Threading: callable by consumer thread *once*. void HttpService::startThread() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; llassert_always(! mThread || STOPPED == sState); llassert_always(INITIALIZED == sState || STOPPED == sState); @@ -220,22 +224,6 @@ void HttpService::stopRequested() } -/// Threading: callable by worker thread. -bool HttpService::changePriority(HttpHandle handle, HttpRequest::priority_t priority) -{ - bool found(false); - - // Skip the request queue as we currently don't leave earlier - // requests sitting there. Start with the ready queue... - found = mPolicy->changePriority(handle, priority); - - // If not there, we could try the transport/active queue but priority - // doesn't really have much effect there so we don't waste cycles. - - return found; -} - - /// Try to find the given request handle on any of the request /// queues and cancel the operation. /// @@ -244,6 +232,7 @@ bool HttpService::changePriority(HttpHandle handle, HttpRequest::priority_t prio /// Threading: callable by worker thread. bool HttpService::cancel(HttpHandle handle) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; bool canceled(false); // Request can't be on request queue so skip that. @@ -264,6 +253,7 @@ bool HttpService::cancel(HttpHandle handle) /// Threading: callable by worker thread. void HttpService::shutdown() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; // Disallow future enqueue of requests mRequestQueue->stopQueue(); @@ -293,6 +283,8 @@ void HttpService::shutdown() // requested to stop. void HttpService::threadRun(LLCoreInt::HttpThread * thread) { + LL_PROFILER_SET_THREAD_NAME("HttpService"); + boost::this_thread::disable_interruption di; LLThread::registerThreadID(); @@ -300,6 +292,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread) ELoopSpeed loop(REQUEST_SLEEP); while (! mExitRequested) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; try { loop = processRequestQueue(loop); @@ -344,6 +337,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread) HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpRequestQueue::OpContainer ops; const bool wait_for_req(REQUEST_SLEEP == loop); @@ -384,6 +378,7 @@ HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop) HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass, long * ret_value) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range || opt >= HttpRequest::PO_LAST // ditto || (! sOptionDesc[opt].mIsLong) // datatype is long @@ -416,6 +411,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass, std::string * ret_value) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG); if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range @@ -443,6 +439,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass, HttpRequest::policyCallback_t * ret_value) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG); if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range @@ -472,6 +469,7 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass, long value, long * ret_value) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG); if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range @@ -517,6 +515,7 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass, const std::string & value, std::string * ret_value) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG); if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range @@ -548,6 +547,7 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass, HttpRequest::policyCallback_t value, HttpRequest::policyCallback_t * ret_value) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG); if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h index d0c37ac195..551a718f20 100644 --- a/indra/llcorehttp/_httpservice.h +++ b/indra/llcorehttp/_httpservice.h @@ -147,15 +147,6 @@ public: void shutdown(); /// Try to find the given request handle on any of the request - /// queues and reset the priority (and queue position) of the - /// request if found. - /// - /// @return True if the request was found somewhere. - /// - /// Threading: callable by worker thread. - bool changePriority(HttpHandle handle, HttpRequest::priority_t priority); - - /// Try to find the given request handle on any of the request /// queues and cancel the operation. /// /// @return True if the request was found and canceled. diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp index c7376042b3..cc53b20add 100644 --- a/indra/llcorehttp/examples/http_texture_load.cpp +++ b/indra/llcorehttp/examples/http_texture_load.cpp @@ -469,11 +469,11 @@ bool WorkingSet::reload(LLCore::HttpRequest * hr, LLCore::HttpOptions::ptr_t & o LLCore::HttpHandle handle; if (offset || length) { - handle = hr->requestGetByteRange(0, 0, buffer, offset, length, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor)); + handle = hr->requestGetByteRange(0, buffer, offset, length, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor)); } else { - handle = hr->requestGet(0, 0, buffer, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor)); + handle = hr->requestGet(0, buffer, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor)); } if (! handle) { diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp index 2687f77217..de3854a101 100644 --- a/indra/llcorehttp/httprequest.cpp +++ b/indra/llcorehttp/httprequest.cpp @@ -32,7 +32,6 @@ #include "_httppolicy.h" #include "_httpoperation.h" #include "_httpoprequest.h" -#include "_httpopsetpriority.h" #include "_httpopcancel.h" #include "_httpopsetget.h" @@ -183,16 +182,16 @@ HttpStatus HttpRequest::getStatus() const HttpHandle HttpRequest::requestGet(policy_t policy_id, - priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers, HttpHandler::ptr_t user_handler) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpStatus status; HttpOpRequest::ptr_t op(new HttpOpRequest()); - if (! (status = op->setupGet(policy_id, priority, url, options, headers))) + if (! (status = op->setupGet(policy_id, url, options, headers))) { mLastReqStatus = status; return LLCORE_HTTP_HANDLE_INVALID; @@ -210,7 +209,6 @@ HttpHandle HttpRequest::requestGet(policy_t policy_id, HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id, - priority_t priority, const std::string & url, size_t offset, size_t len, @@ -218,10 +216,11 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id, const HttpHeaders::ptr_t & headers, HttpHandler::ptr_t user_handler) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; HttpStatus status; HttpOpRequest::ptr_t op(new HttpOpRequest()); - if (! (status = op->setupGetByteRange(policy_id, priority, url, offset, len, options, headers))) + if (! (status = op->setupGetByteRange(policy_id, url, offset, len, options, headers))) { mLastReqStatus = status; return LLCORE_HTTP_HANDLE_INVALID; @@ -239,7 +238,6 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id, HttpHandle HttpRequest::requestPost(policy_t policy_id, - priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, @@ -249,7 +247,7 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id, HttpStatus status; HttpOpRequest::ptr_t op(new HttpOpRequest()); - if (! (status = op->setupPost(policy_id, priority, url, body, options, headers))) + if (! (status = op->setupPost(policy_id, url, body, options, headers))) { mLastReqStatus = status; return LLCORE_HTTP_HANDLE_INVALID; @@ -267,7 +265,6 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id, HttpHandle HttpRequest::requestPut(policy_t policy_id, - priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, @@ -277,7 +274,7 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id, HttpStatus status; HttpOpRequest::ptr_t op (new HttpOpRequest()); - if (! (status = op->setupPut(policy_id, priority, url, body, options, headers))) + if (! (status = op->setupPut(policy_id, url, body, options, headers))) { mLastReqStatus = status; return LLCORE_HTTP_HANDLE_INVALID; @@ -294,7 +291,6 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id, } HttpHandle HttpRequest::requestDelete(policy_t policy_id, - priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers, @@ -303,7 +299,7 @@ HttpHandle HttpRequest::requestDelete(policy_t policy_id, HttpStatus status; HttpOpRequest::ptr_t op(new HttpOpRequest()); - if (!(status = op->setupDelete(policy_id, priority, url, options, headers))) + if (!(status = op->setupDelete(policy_id, url, options, headers))) { mLastReqStatus = status; return LLCORE_HTTP_HANDLE_INVALID; @@ -320,7 +316,6 @@ HttpHandle HttpRequest::requestDelete(policy_t policy_id, } HttpHandle HttpRequest::requestPatch(policy_t policy_id, - priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, @@ -330,7 +325,7 @@ HttpHandle HttpRequest::requestPatch(policy_t policy_id, HttpStatus status; HttpOpRequest::ptr_t op (new HttpOpRequest()); - if (!(status = op->setupPatch(policy_id, priority, url, body, options, headers))) + if (!(status = op->setupPatch(policy_id, url, body, options, headers))) { mLastReqStatus = status; return LLCORE_HTTP_HANDLE_INVALID; @@ -347,7 +342,6 @@ HttpHandle HttpRequest::requestPatch(policy_t policy_id, } HttpHandle HttpRequest::requestCopy(policy_t policy_id, - priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers, @@ -356,7 +350,7 @@ HttpHandle HttpRequest::requestCopy(policy_t policy_id, HttpStatus status; HttpOpRequest::ptr_t op(new HttpOpRequest()); - if (!(status = op->setupCopy(policy_id, priority, url, options, headers))) + if (!(status = op->setupCopy(policy_id, url, options, headers))) { mLastReqStatus = status; return LLCORE_HTTP_HANDLE_INVALID; @@ -374,7 +368,6 @@ HttpHandle HttpRequest::requestCopy(policy_t policy_id, } HttpHandle HttpRequest::requestMove(policy_t policy_id, - priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers, @@ -383,7 +376,7 @@ HttpHandle HttpRequest::requestMove(policy_t policy_id, HttpStatus status; HttpOpRequest::ptr_t op (new HttpOpRequest()); - if (!(status = op->setupMove(policy_id, priority, url, options, headers))) + if (!(status = op->setupMove(policy_id, url, options, headers))) { mLastReqStatus = status; return LLCORE_HTTP_HANDLE_INVALID; @@ -483,24 +476,6 @@ HttpHandle HttpRequest::requestCancel(HttpHandle request, HttpHandler::ptr_t use } -HttpHandle HttpRequest::requestSetPriority(HttpHandle request, priority_t priority, - HttpHandler::ptr_t handler) -{ - HttpStatus status; - - HttpOperation::ptr_t op (new HttpOpSetPriority(request, priority)); - op->setReplyPath(mReplyQueue, handler); - if (! (status = mRequestQueue->addOp(op))) // transfers refcount - { - mLastReqStatus = status; - return LLCORE_HTTP_HANDLE_INVALID; - } - - mLastReqStatus = status; - return op->getHandle(); -} - - // ==================================== // Utility Methods // ==================================== diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h index a418eb6a7a..ca4b9e92bc 100644 --- a/indra/llcorehttp/httprequest.h +++ b/indra/llcorehttp/httprequest.h @@ -95,7 +95,6 @@ private: public: typedef unsigned int policy_t; - typedef unsigned int priority_t; typedef boost::shared_ptr<HttpRequest> ptr_t; typedef boost::weak_ptr<HttpRequest> wptr_t; @@ -316,8 +315,6 @@ public: /// /// @param policy_id Default or user-defined policy class under /// which this request is to be serviced. - /// @param priority Standard priority scheme inherited from - /// Indra code base (U32-type scheme). /// @param url URL with any encoded query parameters to /// be accessed. /// @param options Optional instance of an HttpOptions object @@ -346,7 +343,6 @@ public: /// case, @see getStatus() will return more info. /// HttpHandle requestGet(policy_t policy_id, - priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers, @@ -377,7 +373,6 @@ public: /// - Referer: /// /// @param policy_id @see requestGet() - /// @param priority " /// @param url " /// @param offset Offset of first byte into resource to be returned. /// @param len Count of bytes to be returned @@ -387,7 +382,6 @@ public: /// @return " /// HttpHandle requestGetByteRange(policy_t policy_id, - priority_t priority, const std::string & url, size_t offset, size_t len, @@ -418,7 +412,6 @@ public: /// - Expect: /// /// @param policy_id @see requestGet() - /// @param priority " /// @param url " /// @param body Byte stream to be sent as the body. No /// further encoding or escaping will be done @@ -429,7 +422,6 @@ public: /// @return " /// HttpHandle requestPost(policy_t policy_id, - priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, @@ -459,7 +451,6 @@ public: /// - Content-Type: /// /// @param policy_id @see requestGet() - /// @param priority " /// @param url " /// @param body Byte stream to be sent as the body. No /// further encoding or escaping will be done @@ -470,7 +461,6 @@ public: /// @return " /// HttpHandle requestPut(policy_t policy_id, - priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, @@ -483,7 +473,6 @@ public: /// encoding and communicating the content types. /// /// @param policy_id @see requestGet() - /// @param priority " /// @param url " /// @param options @see requestGet()K(optional) /// @param headers " @@ -491,7 +480,6 @@ public: /// @return " /// HttpHandle requestDelete(policy_t policy_id, - priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers, @@ -502,7 +490,6 @@ public: /// encoding and communicating the content types. /// /// @param policy_id @see requestGet() - /// @param priority " /// @param url " /// @param body Byte stream to be sent as the body. No /// further encoding or escaping will be done @@ -513,7 +500,6 @@ public: /// @return " /// HttpHandle requestPatch(policy_t policy_id, - priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, @@ -525,7 +511,6 @@ public: /// encoding and communicating the content types. /// /// @param policy_id @see requestGet() - /// @param priority " /// @param url " /// @param options @see requestGet()K(optional) /// @param headers " @@ -533,7 +518,6 @@ public: /// @return " /// HttpHandle requestCopy(policy_t policy_id, - priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers, @@ -544,7 +528,6 @@ public: /// encoding and communicating the content types. /// /// @param policy_id @see requestGet() - /// @param priority " /// @param url " /// @param options @see requestGet()K(optional) /// @param headers " @@ -552,7 +535,6 @@ public: /// @return " /// HttpHandle requestMove(policy_t policy_id, - priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers, @@ -593,18 +575,6 @@ public: HttpHandle requestCancel(HttpHandle request, HttpHandler::ptr_t); - /// Request that a previously-issued request be reprioritized. - /// The status of whether the change itself succeeded arrives - /// via notification. - /// - /// @param request Handle of previously-issued request to - /// be changed. - /// @param priority New priority value. - /// @param handler @see requestGet() - /// @return " - /// - HttpHandle requestSetPriority(HttpHandle request, priority_t priority, HttpHandler::ptr_t handler); - /// @} /// @name UtilityMethods diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp index 154f6b12e9..3eaac10aeb 100644 --- a/indra/llcorehttp/tests/test_httprequest.hpp +++ b/indra/llcorehttp/tests/test_httprequest.hpp @@ -614,7 +614,6 @@ void HttpRequestTestObjectType::test<7>() // Issue a GET that can't connect mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT); HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, - 0U, "http://127.0.0.1:2/nothing/here", 0, 0, @@ -716,7 +715,6 @@ void HttpRequestTestObjectType::test<8>() // Issue a GET that *can* connect mStatus = HttpStatus(200); HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base, HttpOptions::ptr_t(), HttpHeaders::ptr_t(), @@ -812,7 +810,6 @@ void HttpRequestTestObjectType::test<9>() // Issue a GET that *can* connect mStatus = HttpStatus(200); HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base, 0, 0, @@ -913,7 +910,6 @@ void HttpRequestTestObjectType::test<10>() body->append(body_text, strlen(body_text)); mStatus = HttpStatus(200); HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base, body, HttpOptions::ptr_t(), @@ -1020,7 +1016,6 @@ void HttpRequestTestObjectType::test<11>() body->append(body_text, strlen(body_text)); mStatus = HttpStatus(200); HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base, body, HttpOptions::ptr_t(), @@ -1127,7 +1122,6 @@ void HttpRequestTestObjectType::test<12>() // Issue a GET that *can* connect mStatus = HttpStatus(200); HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base, 0, 0, @@ -1240,7 +1234,6 @@ void HttpRequestTestObjectType::test<13>() regex_container_t::value_type(boost::regex("X-LL-Special", boost::regex::icase), boost::regex(".*", boost::regex::icase))); HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base, 0, 0, @@ -1346,7 +1339,6 @@ void HttpRequestTestObjectType::test<14>() // Issue a GET that sleeps mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT); HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base, 0, 0, @@ -1454,7 +1446,6 @@ void HttpRequestTestObjectType::test<15>() mStatus = HttpStatus(200); handler.mCheckContentType = "application/llsd+xml"; HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base, HttpOptions::ptr_t(), HttpHeaders::ptr_t(), @@ -1609,7 +1600,6 @@ void HttpRequestTestObjectType::test<16>() boost::regex("X-Reflect-content-encoding", boost::regex::icase), boost::regex(".*", boost::regex::icase))); HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base + "reflect/", options, HttpHeaders::ptr_t(), @@ -1684,7 +1674,6 @@ void HttpRequestTestObjectType::test<16>() boost::regex("X-Reflect-content-encoding", boost::regex::icase), boost::regex(".*", boost::regex::icase))); handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base + "reflect/", 0, 47, @@ -1863,7 +1852,6 @@ void HttpRequestTestObjectType::test<17>() boost::regex("X-Reflect-transfer_encoding", boost::regex::icase), boost::regex(".*chunked.*", boost::regex::icase))); HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base + "reflect/", ba, options, @@ -2049,7 +2037,6 @@ void HttpRequestTestObjectType::test<18>() boost::regex(".*", boost::regex::icase))); HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base + "reflect/", ba, options, @@ -2249,7 +2236,6 @@ void HttpRequestTestObjectType::test<19>() boost::regex("X-Reflect-content-encoding", boost::regex::icase), boost::regex(".*", boost::regex::icase))); HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base + "reflect/", options, headers, @@ -2457,7 +2443,6 @@ void HttpRequestTestObjectType::test<20>() boost::regex(".*", boost::regex::icase))); HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base + "reflect/", ba, options, @@ -2666,7 +2651,6 @@ void HttpRequestTestObjectType::test<21>() boost::regex("X-Reflect-content-type", boost::regex::icase), boost::regex("text/html", boost::regex::icase))); HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base + "reflect/", ba, options, @@ -2797,7 +2781,6 @@ void HttpRequestTestObjectType::test<22>() char buffer[128]; sprintf(buffer, "/bug2295/%d/", i); HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base + buffer, 0, 25, @@ -2829,7 +2812,6 @@ void HttpRequestTestObjectType::test<22>() char buffer[128]; sprintf(buffer, "/bug2295/00000012/%d/", i); HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base + buffer, 0, 25, @@ -2861,7 +2843,6 @@ void HttpRequestTestObjectType::test<22>() char buffer[128]; sprintf(buffer, "/bug2295/inv_cont_range/%d/", i); HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, - 0U, url_base + buffer, 0, 25, @@ -2984,7 +2965,6 @@ void HttpRequestTestObjectType::test<23>() std::ostringstream url; url << url_base << i << "/"; HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, - 0U, url.str(), 0, 0, diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 0d8fb4863b..bb603d3d7f 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -418,7 +418,7 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg updateApplication(llformat("%s, try %d...", msg.c_str(), i+1)); LL_INFOS("CRASHREPORT") << "POST crash data to " << host << LL_ENDL; - LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(httpRequest.get(), LLCore::HttpRequest::DEFAULT_POLICY_ID, 0, + LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(httpRequest.get(), LLCore::HttpRequest::DEFAULT_POLICY_ID, host, data, httpOpts, LLCore::HttpHeaders::ptr_t(), LLCore::HttpHandler::ptr_t(new LLCrashLoggerHandler)); if (handle == LLCORE_HTTP_HANDLE_INVALID) diff --git a/indra/llfilesystem/lllfsthread.cpp b/indra/llfilesystem/lllfsthread.cpp index be8e83a56f..dbb69cd605 100644 --- a/indra/llfilesystem/lllfsthread.cpp +++ b/indra/llfilesystem/lllfsthread.cpp @@ -45,8 +45,7 @@ void LLLFSThread::initClass(bool local_is_threaded) //static S32 LLLFSThread::updateClass(U32 ms_elapsed) { - sLocal->update((F32)ms_elapsed); - return sLocal->getPending(); + return sLocal->update((F32)ms_elapsed); } //static @@ -58,6 +57,7 @@ void LLLFSThread::cleanupClass() { sLocal->update(0); } + sLocal->shutdown(); delete sLocal; sLocal = NULL; } @@ -65,8 +65,7 @@ void LLLFSThread::cleanupClass() //---------------------------------------------------------------------------- LLLFSThread::LLLFSThread(bool threaded) : - LLQueuedThread("LFS", threaded), - mPriorityCounter(PRIORITY_LOWBITS) + LLQueuedThread("LFS", threaded) { if(!mLocalAPRFilePoolp) { @@ -84,14 +83,12 @@ LLLFSThread::~LLLFSThread() LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfinder: ignore */ U8* buffer, S32 offset, S32 numbytes, - Responder* responder, U32 priority) + Responder* responder) { + LL_PROFILE_ZONE_SCOPED; handle_t handle = generateHandle(); - if (priority == 0) priority = PRIORITY_NORMAL | priorityCounter(); - else if (priority < PRIORITY_LOW) priority |= PRIORITY_LOW; // All reads are at least PRIORITY_LOW - - Request* req = new Request(this, handle, priority, + Request* req = new Request(this, handle, FILE_READ, filename, buffer, offset, numbytes, responder); @@ -107,13 +104,12 @@ LLLFSThread::handle_t LLLFSThread::read(const std::string& filename, /* Flawfind LLLFSThread::handle_t LLLFSThread::write(const std::string& filename, U8* buffer, S32 offset, S32 numbytes, - Responder* responder, U32 priority) + Responder* responder) { + LL_PROFILE_ZONE_SCOPED; handle_t handle = generateHandle(); - if (priority == 0) priority = PRIORITY_LOW | priorityCounter(); - - Request* req = new Request(this, handle, priority, + Request* req = new Request(this, handle, FILE_WRITE, filename, buffer, offset, numbytes, responder); @@ -130,11 +126,11 @@ LLLFSThread::handle_t LLLFSThread::write(const std::string& filename, //============================================================================ LLLFSThread::Request::Request(LLLFSThread* thread, - handle_t handle, U32 priority, + handle_t handle, operation_t op, const std::string& filename, U8* buffer, S32 offset, S32 numbytes, Responder* responder) : - QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE), + QueuedRequest(handle, FLAG_AUTO_COMPLETE), mThread(thread), mOperation(op), mFileName(filename), @@ -157,6 +153,7 @@ LLLFSThread::Request::~Request() // virtual, called from own thread void LLLFSThread::Request::finishRequest(bool completed) { + LL_PROFILE_ZONE_SCOPED; if (mResponder.notNull()) { mResponder->completed(completed ? mBytesRead : 0); @@ -166,6 +163,7 @@ void LLLFSThread::Request::finishRequest(bool completed) void LLLFSThread::Request::deleteRequest() { + LL_PROFILE_ZONE_SCOPED; if (getStatus() == STATUS_QUEUED) { LL_ERRS() << "Attempt to delete a queued LLLFSThread::Request!" << LL_ENDL; @@ -180,6 +178,7 @@ void LLLFSThread::Request::deleteRequest() bool LLLFSThread::Request::processRequest() { + LL_PROFILE_ZONE_SCOPED; bool complete = false; if (mOperation == FILE_READ) { diff --git a/indra/llfilesystem/lllfsthread.h b/indra/llfilesystem/lllfsthread.h index 58f658f7ba..f2693a1172 100644 --- a/indra/llfilesystem/lllfsthread.h +++ b/indra/llfilesystem/lllfsthread.h @@ -68,7 +68,7 @@ public: public: Request(LLLFSThread* thread, - handle_t handle, U32 priority, + handle_t handle, operation_t op, const std::string& filename, U8* buffer, S32 offset, S32 numbytes, Responder* responder); @@ -120,22 +120,15 @@ public: // Return a Request handle handle_t read(const std::string& filename, /* Flawfinder: ignore */ U8* buffer, S32 offset, S32 numbytes, - Responder* responder, U32 pri=0); + Responder* responder); handle_t write(const std::string& filename, U8* buffer, S32 offset, S32 numbytes, - Responder* responder, U32 pri=0); - - // Misc - U32 priorityCounter() { return mPriorityCounter-- & PRIORITY_LOWBITS; } // Use to order IO operations + Responder* responder); // static initializers static void initClass(bool local_is_threaded = TRUE); // Setup sLocal static S32 updateClass(U32 ms_elapsed); static void cleanupClass(); // Delete sLocal - - -private: - U32 mPriorityCounter; public: static LLLFSThread* sLocal; // Default local file thread diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index ad7124b5aa..186b01d60c 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -798,7 +798,6 @@ U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 si // LLImageRaw //--------------------------------------------------------------------------- -S32 LLImageRaw::sGlobalRawMemory = 0; S32 LLImageRaw::sRawImageCount = 0; LLImageRaw::LLImageRaw() @@ -856,16 +855,13 @@ LLImageRaw::~LLImageRaw() U8* LLImageRaw::allocateData(S32 size) { U8* res = LLImageBase::allocateData(size); - sGlobalRawMemory += getDataSize(); return res; } // virtual U8* LLImageRaw::reallocateData(S32 size) { - sGlobalRawMemory -= getDataSize(); U8* res = LLImageBase::reallocateData(size); - sGlobalRawMemory += getDataSize(); return res; } @@ -878,7 +874,6 @@ void LLImageRaw::releaseData() // virtual void LLImageRaw::deleteData() { - sGlobalRawMemory -= getDataSize(); LLImageBase::deleteData(); } diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 59c192d9f8..9e50fd502b 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -276,7 +276,6 @@ protected: void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; public: - static S32 sGlobalRawMemory; static S32 sRawImageCount; private: diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index e1809dbe59..8dba1641a6 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -146,6 +146,7 @@ bool LLImageJ2C::initEncode(LLImageRaw &raw_image, int blocks_size, int precinct bool LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; return decodeChannels(raw_imagep, decode_time, 0, 4); } @@ -153,6 +154,7 @@ bool LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time) // Returns true to mean done, whether successful or not. bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count ) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LLTimer elapsed; bool res = true; diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index 0dbb744bcf..0093958e6d 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -28,64 +28,88 @@ #include "llimageworker.h" #include "llimagedxt.h" +#include "threadpool.h" + +/*--------------------------------------------------------------------------*/ +class ImageRequest +{ +public: + ImageRequest(const LLPointer<LLImageFormatted>& image, + S32 discard, BOOL needs_aux, + const LLPointer<LLImageDecodeThread::Responder>& responder); + virtual ~ImageRequest(); + + /*virtual*/ bool processRequest(); + /*virtual*/ void finishRequest(bool completed); + +private: + // LLPointers stored in ImageRequest MUST be LLPointer instances rather + // than references: we need to increment the refcount when storing these. + // input + LLPointer<LLImageFormatted> mFormattedImage; + S32 mDiscardLevel; + BOOL mNeedsAux; + // output + LLPointer<LLImageRaw> mDecodedImageRaw; + LLPointer<LLImageRaw> mDecodedImageAux; + BOOL mDecodedRaw; + BOOL mDecodedAux; + LLPointer<LLImageDecodeThread::Responder> mResponder; +}; + //---------------------------------------------------------------------------- // MAIN THREAD -LLImageDecodeThread::LLImageDecodeThread(bool threaded) - : LLQueuedThread("imagedecode", threaded) +LLImageDecodeThread::LLImageDecodeThread(bool /*threaded*/) { - mCreationMutex = new LLMutex(); + mThreadPool.reset(new LL::ThreadPool("ImageDecode", 8)); + mThreadPool->start(); } //virtual LLImageDecodeThread::~LLImageDecodeThread() -{ - delete mCreationMutex ; -} +{} // MAIN THREAD // virtual S32 LLImageDecodeThread::update(F32 max_time_ms) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - LLMutexLock lock(mCreationMutex); - for (creation_list_t::iterator iter = mCreationList.begin(); - iter != mCreationList.end(); ++iter) - { - creation_info& info = *iter; - ImageRequest* req = new ImageRequest(info.handle, info.image, - info.priority, info.discard, info.needs_aux, - info.responder); + return getPending(); +} - bool res = addRequest(req); - if (!res) - { - LL_ERRS() << "request added after LLLFSThread::cleanupClass()" << LL_ENDL; - } - } - mCreationList.clear(); - S32 res = LLQueuedThread::update(max_time_ms); - return res; +S32 LLImageDecodeThread::getPending() +{ + return mThreadPool->getQueue().size(); } -LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image, - U32 priority, S32 discard, BOOL needs_aux, Responder* responder) +LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage( + const LLPointer<LLImageFormatted>& image, + S32 discard, + BOOL needs_aux, + const LLPointer<LLImageDecodeThread::Responder>& responder) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - LLMutexLock lock(mCreationMutex); - handle_t handle = generateHandle(); - mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder)); - return handle; + + // Instantiate the ImageRequest right in the lambda, why not? + mThreadPool->getQueue().post( + [req = ImageRequest(image, discard, needs_aux, responder)] + () mutable + { + auto done = req.processRequest(); + req.finishRequest(done); + }); + + // It's important to our consumer (LLTextureFetchWorker) that we return a + // nonzero handle. It is NOT important that the nonzero handle be unique: + // nothing is ever done with it except to compare it to zero, or zero it. + return 17; } -// Used by unit test only -// Returns the size of the mutex guarded list as an indication of sanity -S32 LLImageDecodeThread::tut_size() +void LLImageDecodeThread::shutdown() { - LLMutexLock lock(mCreationMutex); - S32 res = mCreationList.size(); - return res; + mThreadPool->close(); } LLImageDecodeThread::Responder::~Responder() @@ -94,11 +118,10 @@ LLImageDecodeThread::Responder::~Responder() //---------------------------------------------------------------------------- -LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatted* image, - U32 priority, S32 discard, BOOL needs_aux, - LLImageDecodeThread::Responder* responder) - : LLQueuedThread::QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE), - mFormattedImage(image), +ImageRequest::ImageRequest(const LLPointer<LLImageFormatted>& image, + S32 discard, BOOL needs_aux, + const LLPointer<LLImageDecodeThread::Responder>& responder) + : mFormattedImage(image), mDiscardLevel(discard), mNeedsAux(needs_aux), mDecodedRaw(FALSE), @@ -107,7 +130,7 @@ LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatte { } -LLImageDecodeThread::ImageRequest::~ImageRequest() +ImageRequest::~ImageRequest() { mDecodedImageRaw = NULL; mDecodedImageAux = NULL; @@ -118,10 +141,10 @@ LLImageDecodeThread::ImageRequest::~ImageRequest() // Returns true when done, whether or not decode was successful. -bool LLImageDecodeThread::ImageRequest::processRequest() +bool ImageRequest::processRequest() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - const F32 decode_time_slice = .1f; + const F32 decode_time_slice = 0.f; //disable time slicing bool done = true; if (!mDecodedRaw && mFormattedImage.notNull()) { @@ -145,7 +168,7 @@ bool LLImageDecodeThread::ImageRequest::processRequest() mFormattedImage->getHeight(), mFormattedImage->getComponents()); } - done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // 1ms + done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // some decoders are removing data when task is complete and there were errors mDecodedRaw = done && mDecodedImageRaw->getData(); } @@ -158,14 +181,14 @@ bool LLImageDecodeThread::ImageRequest::processRequest() mFormattedImage->getHeight(), 1); } - done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); // 1ms + done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); mDecodedAux = done && mDecodedImageAux->getData(); } return done; } -void LLImageDecodeThread::ImageRequest::finishRequest(bool completed) +void ImageRequest::finishRequest(bool completed) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (mResponder.notNull()) @@ -175,10 +198,3 @@ void LLImageDecodeThread::ImageRequest::finishRequest(bool completed) } // Will automatically be deleted } - -// Used by unit test only -// Checks that a responder exists for this instance so that something can happen when completion is reached -bool LLImageDecodeThread::ImageRequest::tut_isOK() -{ - return mResponder.notNull(); -} diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index 1bfb0ddfd3..18398d9ae2 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -29,9 +29,13 @@ #include "llimage.h" #include "llpointer.h" -#include "llworkerthread.h" -class LLImageDecodeThread : public LLQueuedThread +namespace LL +{ + class ThreadPool; +} // namespace LL + +class LLImageDecodeThread { public: class Responder : public LLThreadSafeRefCount @@ -42,63 +46,24 @@ public: virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0; }; - class ImageRequest : public LLQueuedThread::QueuedRequest - { - protected: - virtual ~ImageRequest(); // use deleteRequest() - - public: - ImageRequest(handle_t handle, LLImageFormatted* image, - U32 priority, S32 discard, BOOL needs_aux, - LLImageDecodeThread::Responder* responder); - - /*virtual*/ bool processRequest(); - /*virtual*/ void finishRequest(bool completed); - - // Used by unit tests to check the consitency of the request instance - bool tut_isOK(); - - private: - // input - LLPointer<LLImageFormatted> mFormattedImage; - S32 mDiscardLevel; - BOOL mNeedsAux; - // output - LLPointer<LLImageRaw> mDecodedImageRaw; - LLPointer<LLImageRaw> mDecodedImageAux; - BOOL mDecodedRaw; - BOOL mDecodedAux; - LLPointer<LLImageDecodeThread::Responder> mResponder; - }; - public: LLImageDecodeThread(bool threaded = true); virtual ~LLImageDecodeThread(); - handle_t decodeImage(LLImageFormatted* image, - U32 priority, S32 discard, BOOL needs_aux, - Responder* responder); + // meant to resemble LLQueuedThread::handle_t + typedef U32 handle_t; + handle_t decodeImage(const LLPointer<LLImageFormatted>& image, + S32 discard, BOOL needs_aux, + const LLPointer<Responder>& responder); + S32 getPending(); S32 update(F32 max_time_ms); + void shutdown(); - // Used by unit tests to check the consistency of the thread instance - S32 tut_size(); - private: - struct creation_info - { - handle_t handle; - LLPointer<LLImageFormatted> image; - U32 priority; - S32 discard; - BOOL needs_aux; - LLPointer<Responder> responder; - creation_info(handle_t h, LLImageFormatted* i, U32 p, S32 d, BOOL aux, Responder* r) - : handle(h), image(i), priority(p), discard(d), needs_aux(aux), responder(r) - {} - }; - typedef std::list<creation_info> creation_list_t; - creation_list_t mCreationList; - LLMutex* mCreationMutex; + // As of SL-17483, LLImageDecodeThread is no longer itself an + // LLQueuedThread - instead this is the API by which we submit work to the + // "ImageDecode" ThreadPool. + std::unique_ptr<LL::ThreadPool> mThreadPool; }; #endif diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp index 9011ac615c..0a97b739b0 100644 --- a/indra/llimage/tests/llimageworker_test.cpp +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -125,42 +125,11 @@ namespace tut } }; - // Test wrapper declaration : image worker - // Note: this class is not meant to be instantiated outside an LLImageDecodeThread instance - // but it's not a bad idea to get its public API a good shake as part of a thorough unit test set. - // Some gotcha with the destructor though (see below). - struct imagerequest_test - { - // Instance to be tested - LLImageDecodeThread::ImageRequest* mRequest; - bool done; - - // Constructor and destructor of the test wrapper - imagerequest_test() - { - done = false; - - mRequest = new LLImageDecodeThread::ImageRequest(0, 0, - LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, - new responder_test(&done)); - } - ~imagerequest_test() - { - // We should delete the object *but*, because its destructor is protected, that cannot be - // done from outside an LLImageDecodeThread instance... So we leak memory here... It's fine... - //delete mRequest; - } - }; - // Tut templating thingamagic: test group, object and test instance typedef test_group<imagedecodethread_test> imagedecodethread_t; typedef imagedecodethread_t::object imagedecodethread_object_t; tut::imagedecodethread_t tut_imagedecodethread("LLImageDecodeThread"); - typedef test_group<imagerequest_test> imagerequest_t; - typedef imagerequest_t::object imagerequest_object_t; - tut::imagerequest_t tut_imagerequest("LLImageRequest"); - // --------------------------------------------------------------------------------------- // Test functions // Notes: @@ -172,64 +141,18 @@ namespace tut // --------------------------------------------------------------------------------------- // Test the LLImageDecodeThread interface // --------------------------------------------------------------------------------------- - // - // Note on Unit Testing Queued Thread Classes - // - // Since methods on such a class are called on a separate loop and that we can't insert tut - // ensure() calls in there, we exercise the class with 2 sets of tests: - // - 1: Test as a single threaded instance: We declare the class but ask for no thread - // to be spawned (easy with LLThreads since there's a boolean argument on the constructor - // just for that). We can then unit test each public method like we do on a normal class. - // - 2: Test as a threaded instance: We let the thread launch and check that its external - // behavior is as expected (i.e. it runs, can accept a work order and processes - // it). Typically though there's no guarantee that this exercises all the methods of the - // class which is why we also need the previous "non threaded" set of unit tests for - // complete coverage. - // - // --------------------------------------------------------------------------------------- template<> template<> void imagedecodethread_object_t::test<1>() { - // Test a *non threaded* instance of the class - mThread = new LLImageDecodeThread(false); - ensure("LLImageDecodeThread: non threaded constructor failed", mThread != NULL); - // Test that we start with an empty list right at creation - ensure("LLImageDecodeThread: non threaded init state incorrect", mThread->tut_size() == 0); - // Insert something in the queue - bool done = false; - LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done)); - // Verifies we got a valid handle - ensure("LLImageDecodeThread: non threaded decodeImage(), returned handle is null", decodeHandle != 0); - // Verifies that we do now have something in the queued list - ensure("LLImageDecodeThread: non threaded decodeImage() insertion in threaded list failed", mThread->tut_size() == 1); - // Trigger queue handling "manually" (on a threaded instance, this is done on the thread loop) - S32 res = mThread->update(0); - // Verifies that we successfully handled the list - ensure("LLImageDecodeThread: non threaded update() list handling test failed", res == 0); - // Verifies that the list is now empty - ensure("LLImageDecodeThread: non threaded update() list emptying test failed", mThread->tut_size() == 0); - } - - template<> template<> - void imagedecodethread_object_t::test<2>() - { // Test a *threaded* instance of the class mThread = new LLImageDecodeThread(true); ensure("LLImageDecodeThread: threaded constructor failed", mThread != NULL); - // Test that we start with an empty list right at creation - ensure("LLImageDecodeThread: threaded init state incorrect", mThread->tut_size() == 0); // Insert something in the queue bool done = false; - LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done)); + LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, 0, FALSE, new responder_test(&done)); // Verifies we get back a valid handle ensure("LLImageDecodeThread: threaded decodeImage(), returned handle is null", decodeHandle != 0); - // Wait a little so to simulate the main thread doing something on its main loop... - ms_sleep(500); // 500 milliseconds - // Verifies that the responder has *not* been called yet in the meantime - ensure("LLImageDecodeThread: responder creation failed", done == false); - // Ask the thread to update: that means tells the queue to check itself and creates work requests - mThread->update(1); // Wait till the thread has time to handle the work order (though it doesn't do much per work order...) const U32 INCREMENT_TIME = 500; // 500 milliseconds const U32 MAX_TIME = 20 * INCREMENT_TIME; // Do the loop 20 times max, i.e. wait 10 seconds but no more @@ -242,24 +165,4 @@ namespace tut // Verifies that the responder has now been called ensure("LLImageDecodeThread: threaded work unit not processed", done == true); } - - // --------------------------------------------------------------------------------------- - // Test the LLImageDecodeThread::ImageRequest interface - // --------------------------------------------------------------------------------------- - - template<> template<> - void imagerequest_object_t::test<1>() - { - // Test that we start with a correct request at creation - ensure("LLImageDecodeThread::ImageRequest::ImageRequest() constructor test failed", mRequest->tut_isOK()); - bool res = mRequest->processRequest(); - // Verifies that we processed the request successfully - ensure("LLImageDecodeThread::ImageRequest::processRequest() processing request test failed", res == true); - // Check that we can call the finishing call safely - try { - mRequest->finishRequest(false); - } catch (...) { - fail("LLImageDecodeThread::ImageRequest::finishRequest() test failed"); - } - } } diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index 925da5674b..8a641617fa 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -118,6 +118,7 @@ bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int block bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; // // FIXME: Get the comment field out of the texture // diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index dac5349f57..2ad42d6b87 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -379,6 +379,7 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod void LLImageJ2CKDU::cleanupCodeStream() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; mInputp.reset(); mDecodeState.reset(); mCodeStreamp.reset(); @@ -426,6 +427,7 @@ bool LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc // decodeImpl() usage matters for production. bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; base.resetLastError(); // *FIX: kdu calls our callback function if there's an error, and then bombs. @@ -509,6 +511,7 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco // Returns true to mean done, whether successful or not. bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; ECodeStreamMode mode = MODE_FAST; LLTimer decode_timer; @@ -1332,6 +1335,7 @@ the `buf' pointer may actually point into a larger buffer representing multiple tiles. For this reason, `row_gap' is needed to identify the separation between consecutive rows in the real buffer. */ { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; S32 c; // Now walk through the lines of the buffer, recovering them from the // relevant tile-component processing engines. @@ -1339,18 +1343,27 @@ separation between consecutive rows in the real buffer. */ LLTimer decode_timer; while (mDims.size.y--) { - for (c = 0; c < mNumComponents; c++) - { - mEngines[c].pull(mLines[c]); - } + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("kduptc - pull"); + for (c = 0; c < mNumComponents; c++) + { + mEngines[c].pull(mLines[c]); + } + } + if ((mNumComponents >= 3) && mUseYCC) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("kduptc - convert"); kdu_convert_ycc_to_rgb(mLines[0],mLines[1],mLines[2]); } - for (c = 0; c < mNumComponents; c++) - { - transfer_bytes(mBuf+c,mLines[c],mNumComponents,mBitDepths[c]); - } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("kduptc - transfer"); + for (c = 0; c < mNumComponents; c++) + { + transfer_bytes(mBuf + c, mLines[c], mNumComponents, mBitDepths[c]); + } + } mBuf += mRowGap; if (mDims.size.y % 10) { diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index c67f59bc0c..ae066112c1 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -64,7 +64,6 @@ LLCore::HttpRequest::ptr_t sHttpRequest; LLCore::HttpHeaders::ptr_t sHttpHeaders; LLCore::HttpOptions::ptr_t sHttpOptions; LLCore::HttpRequest::policy_t sHttpPolicy; -LLCore::HttpRequest::priority_t sHttpPriority; /* Sample response: <?xml version="1.0"?> @@ -121,7 +120,6 @@ LLAvatarNameCache::LLAvatarNameCache() sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()); sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()); sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID; - sHttpPriority = 0; } LLAvatarNameCache::~LLAvatarNameCache() diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 7031f1aa8c..96af8bacee 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -131,7 +131,6 @@ bool responseToLLSD(HttpResponse * response, bool log, LLSD & out_llsd) HttpHandle requestPostWithLLSD(HttpRequest * request, HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const HttpOptions::ptr_t &options, @@ -145,7 +144,6 @@ HttpHandle requestPostWithLLSD(HttpRequest * request, LLSDSerialize::toXML(body, bas); handle = request->requestPost(policy_id, - priority, url, ba, options, @@ -158,7 +156,6 @@ HttpHandle requestPostWithLLSD(HttpRequest * request, HttpHandle requestPutWithLLSD(HttpRequest * request, HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const HttpOptions::ptr_t &options, @@ -172,7 +169,6 @@ HttpHandle requestPutWithLLSD(HttpRequest * request, LLSDSerialize::toXML(body, bas); handle = request->requestPut(policy_id, - priority, url, ba, options, @@ -184,7 +180,6 @@ HttpHandle requestPutWithLLSD(HttpRequest * request, HttpHandle requestPatchWithLLSD(HttpRequest * request, HttpRequest::policy_t policy_id, - HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const HttpOptions::ptr_t &options, @@ -198,7 +193,6 @@ HttpHandle requestPatchWithLLSD(HttpRequest * request, LLSDSerialize::toXML(body, bas); handle = request->requestPatch(policy_id, - priority, url, ba, options, @@ -672,10 +666,9 @@ const std::string HttpCoroutineAdapter::HTTP_RESULTS_CONTENT("content"); const std::string HttpCoroutineAdapter::HTTP_RESULTS_RAW("raw"); HttpCoroutineAdapter::HttpCoroutineAdapter(const std::string &name, - LLCore::HttpRequest::policy_t policyId, LLCore::HttpRequest::priority_t priority) : + LLCore::HttpRequest::policy_t policyId) : mAdapterName(name), mPolicyId(policyId), - mPriority(priority), mYieldingHandle(LLCORE_HTTP_HANDLE_INVALID), mWeakRequest(), mWeakHandler() @@ -709,7 +702,7 @@ LLSD HttpCoroutineAdapter::postAndSuspend_(LLCore::HttpRequest::ptr_t &request, // The HTTPCoroHandler does not self delete, so retrieval of a the contained // pointer from the smart pointer is safe in this case. LLCore::HttpHandle hhandle = requestPostWithLLSD(request, - mPolicyId, mPriority, url, body, options, headers, + mPolicyId, url, body, options, headers, handler); if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -832,7 +825,7 @@ LLSD HttpCoroutineAdapter::postAndSuspend_(LLCore::HttpRequest::ptr_t &request, // The HTTPCoroHandler does not self delete, so retrieval of a the contained // pointer from the smart pointer is safe in this case. - LLCore::HttpHandle hhandle = request->requestPost(mPolicyId, mPriority, url, rawbody.get(), + LLCore::HttpHandle hhandle = request->requestPost(mPolicyId, url, rawbody.get(), options, headers, handler); if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -890,7 +883,7 @@ LLSD HttpCoroutineAdapter::putAndSuspend_(LLCore::HttpRequest::ptr_t &request, // The HTTPCoroHandler does not self delete, so retrieval of a the contained // pointer from the smart pointer is safe in this case. LLCore::HttpHandle hhandle = requestPutWithLLSD(request, - mPolicyId, mPriority, url, body, options, headers, + mPolicyId, url, body, options, headers, handler); if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -916,7 +909,7 @@ LLSD HttpCoroutineAdapter::putAndSuspend_(LLCore::HttpRequest::ptr_t &request, // The HTTPCoroHandler does not self delete, so retrieval of a the contained // pointer from the smart pointer is safe in this case. - LLCore::HttpHandle hhandle = request->requestPut(mPolicyId, mPriority, + LLCore::HttpHandle hhandle = request->requestPut(mPolicyId, url, rawbody.get(), options, headers, handler); if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -972,7 +965,7 @@ LLSD HttpCoroutineAdapter::getAndSuspend_(LLCore::HttpRequest::ptr_t &request, // The HTTPCoroHandler does not self delete, so retrieval of a the contained // pointer from the smart pointer is safe in this case. - LLCore::HttpHandle hhandle = request->requestGet(mPolicyId, mPriority, + LLCore::HttpHandle hhandle = request->requestGet(mPolicyId, url, options, headers, handler); if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -1018,7 +1011,7 @@ LLSD HttpCoroutineAdapter::deleteAndSuspend_(LLCore::HttpRequest::ptr_t &request checkDefaultHeaders(headers); // The HTTPCoroHandler does not self delete, so retrieval of a the contained // pointer from the smart pointer is safe in this case. - LLCore::HttpHandle hhandle = request->requestDelete(mPolicyId, mPriority, + LLCore::HttpHandle hhandle = request->requestDelete(mPolicyId, url, options, headers, handler); if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -1056,7 +1049,7 @@ LLSD HttpCoroutineAdapter::patchAndSuspend_(LLCore::HttpRequest::ptr_t &request, // The HTTPCoroHandler does not self delete, so retrieval of a the contained // pointer from the smart pointer is safe in this case. LLCore::HttpHandle hhandle = requestPatchWithLLSD(request, - mPolicyId, mPriority, url, body, options, headers, + mPolicyId, url, body, options, headers, handler); if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -1098,7 +1091,7 @@ LLSD HttpCoroutineAdapter::copyAndSuspend_(LLCore::HttpRequest::ptr_t &request, // The HTTPCoroHandler does not self delete, so retrieval of a the contained // pointer from the smart pointer is safe in this case. // - LLCore::HttpHandle hhandle = request->requestCopy(mPolicyId, mPriority, url, + LLCore::HttpHandle hhandle = request->requestCopy(mPolicyId, url, options, headers, handler); if (hhandle == LLCORE_HTTP_HANDLE_INVALID) @@ -1140,7 +1133,7 @@ LLSD HttpCoroutineAdapter::moveAndSuspend_(LLCore::HttpRequest::ptr_t &request, // The HTTPCoroHandler does not self delete, so retrieval of a the contained // pointer from the smart pointer is safe in this case. // - LLCore::HttpHandle hhandle = request->requestMove(mPolicyId, mPriority, url, + LLCore::HttpHandle hhandle = request->requestMove(mPolicyId, url, options, headers, handler); if (hhandle == LLCORE_HTTP_HANDLE_INVALID) diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h index 6f0b865f83..430dc417ac 100644 --- a/indra/llmessage/llcorehttputil.h +++ b/indra/llmessage/llcorehttputil.h @@ -116,7 +116,6 @@ std::string responseToString(LLCore::HttpResponse * response); /// LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request, LLCore::HttpRequest::policy_t policy_id, - LLCore::HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const LLCore::HttpOptions::ptr_t &options, @@ -125,20 +124,18 @@ LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request, inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request, LLCore::HttpRequest::policy_t policy_id, - LLCore::HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const LLCore::HttpOptions::ptr_t & options, const LLCore::HttpHeaders::ptr_t & headers, const LLCore::HttpHandler::ptr_t & handler) { - return requestPostWithLLSD(request.get(), policy_id, priority, + return requestPostWithLLSD(request.get(), policy_id, url, body, options, headers, handler); } inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request, LLCore::HttpRequest::policy_t policy_id, - LLCore::HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const LLCore::HttpHandler::ptr_t &handler) @@ -146,7 +143,7 @@ inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & reque LLCore::HttpOptions::ptr_t options; LLCore::HttpHeaders::ptr_t headers; - return requestPostWithLLSD(request.get(), policy_id, priority, + return requestPostWithLLSD(request.get(), policy_id, url, body, options, headers, handler); } @@ -169,7 +166,6 @@ inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & reque /// LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest * request, LLCore::HttpRequest::policy_t policy_id, - LLCore::HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const LLCore::HttpOptions::ptr_t &options, @@ -178,20 +174,18 @@ LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest * request, inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request, LLCore::HttpRequest::policy_t policy_id, - LLCore::HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const LLCore::HttpOptions::ptr_t & options, const LLCore::HttpHeaders::ptr_t & headers, LLCore::HttpHandler::ptr_t handler) { - return requestPutWithLLSD(request.get(), policy_id, priority, + return requestPutWithLLSD(request.get(), policy_id, url, body, options, headers, handler); } inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request, LLCore::HttpRequest::policy_t policy_id, - LLCore::HttpRequest::priority_t priority, const std::string & url, const LLSD & body, LLCore::HttpHandler::ptr_t handler) @@ -199,7 +193,7 @@ inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & reques LLCore::HttpOptions::ptr_t options; LLCore::HttpHeaders::ptr_t headers; - return requestPutWithLLSD(request.get(), policy_id, priority, + return requestPutWithLLSD(request.get(), policy_id, url, body, options, headers, handler); } @@ -221,7 +215,6 @@ inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & reques /// LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest * request, LLCore::HttpRequest::policy_t policy_id, - LLCore::HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const LLCore::HttpOptions::ptr_t &options, @@ -230,20 +223,18 @@ LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest * request, inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request, LLCore::HttpRequest::policy_t policy_id, - LLCore::HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const LLCore::HttpOptions::ptr_t & options, const LLCore::HttpHeaders::ptr_t & headers, const LLCore::HttpHandler::ptr_t & handler) { - return requestPatchWithLLSD(request.get(), policy_id, priority, + return requestPatchWithLLSD(request.get(), policy_id, url, body, options, headers, handler); } inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request, LLCore::HttpRequest::policy_t policy_id, - LLCore::HttpRequest::priority_t priority, const std::string & url, const LLSD & body, const LLCore::HttpHandler::ptr_t &handler) @@ -251,7 +242,7 @@ inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & requ LLCore::HttpOptions::ptr_t options; LLCore::HttpHeaders::ptr_t headers; - return requestPatchWithLLSD(request.get(), policy_id, priority, + return requestPatchWithLLSD(request.get(), policy_id, url, body, options, headers, handler); } @@ -329,8 +320,7 @@ public: typedef boost::shared_ptr<HttpCoroutineAdapter> ptr_t; typedef boost::weak_ptr<HttpCoroutineAdapter> wptr_t; - HttpCoroutineAdapter(const std::string &name, LLCore::HttpRequest::policy_t policyId, - LLCore::HttpRequest::priority_t priority = 0L); + HttpCoroutineAdapter(const std::string &name, LLCore::HttpRequest::policy_t policyId); ~HttpCoroutineAdapter(); /// Execute a Post transaction on the supplied URL and yield execution of @@ -673,7 +663,6 @@ private: void checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers); std::string mAdapterName; - LLCore::HttpRequest::priority_t mPriority; LLCore::HttpRequest::policy_t mPolicyId; LLCore::HttpHandle mYieldingHandle; diff --git a/indra/llmessage/tests/llcoproceduremanager_test.cpp b/indra/llmessage/tests/llcoproceduremanager_test.cpp index 6424117ef3..78424a28c8 100644 --- a/indra/llmessage/tests/llcoproceduremanager_test.cpp +++ b/indra/llmessage/tests/llcoproceduremanager_test.cpp @@ -48,7 +48,7 @@ #pragma warning(disable: 4702) #endif -LLCoreHttpUtil::HttpCoroutineAdapter::HttpCoroutineAdapter(std::string const&, unsigned int, unsigned int) +LLCoreHttpUtil::HttpCoroutineAdapter::HttpCoroutineAdapter(std::string const&, unsigned int) { } diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 89dd68da76..6215727de0 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -53,13 +53,75 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f; //assumes i is a power of 2 > 0 U32 wpo2(U32 i); + +// texture memory accounting (for OS X) +static LLMutex sTexMemMutex; +static std::unordered_map<U32, U32> sTextureAllocs; +static U64 sTextureBytes = 0; + +// track a texture alloc on the currently bound texture. +// asserts that no currently tracked alloc exists +static void alloc_tex_image(U32 width, U32 height, U32 pixformat) +{ + U32 texUnit = gGL.getCurrentTexUnitIndex(); + U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture(); + S32 size = LLImageGL::dataFormatBytes(pixformat, width, height); + + llassert(size >= 0); + + sTexMemMutex.lock(); + llassert(sTextureAllocs.find(texName) == sTextureAllocs.end()); + + sTextureAllocs[texName] = size; + sTextureBytes += size; + + sTexMemMutex.unlock(); +} + +// track texture free on given texName +static void free_tex_image(U32 texName) +{ + sTexMemMutex.lock(); + auto iter = sTextureAllocs.find(texName); + if (iter != sTextureAllocs.end()) + { + llassert(iter->second <= sTextureBytes); // sTextureBytes MUST NOT go below zero + + sTextureBytes -= iter->second; + + sTextureAllocs.erase(iter); + } + + sTexMemMutex.unlock(); +} + +// track texture free on given texNames +static void free_tex_images(U32 count, const U32* texNames) +{ + for (int i = 0; i < count; ++i) + { + free_tex_image(texNames[i]); + } +} + +// track texture free on currently bound texture +static void free_cur_tex_image() +{ + U32 texUnit = gGL.getCurrentTexUnitIndex(); + U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture(); + free_tex_image(texName); +} + +// static +U64 LLImageGL::getTextureBytesAllocated() +{ + return sTextureBytes; +} + //statics U32 LLImageGL::sUniqueCount = 0; U32 LLImageGL::sBindCount = 0; -S32Bytes LLImageGL::sGlobalTextureMemory(0); -S32Bytes LLImageGL::sBoundTextureMemory(0); -S32Bytes LLImageGL::sCurBoundTextureMemory(0); S32 LLImageGL::sCount = 0; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; @@ -220,6 +282,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_RGBA: return 32; case GL_SRGB_ALPHA: return 32; case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac + case GL_DEPTH_COMPONENT: return 24; default: LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL; return 0; @@ -282,15 +345,6 @@ void LLImageGL::updateStats(F32 current_time) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; sLastFrameTime = current_time; - sBoundTextureMemory = sCurBoundTextureMemory; - sCurBoundTextureMemory = S32Bytes(0); -} - -//static -S32 LLImageGL::updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) -{ - LLImageGL::sCurBoundTextureMemory += mem ; - return LLImageGL::sCurBoundTextureMemory.value(); } //---------------------------------------------------------------------------- @@ -623,7 +677,7 @@ void LLImageGL::forceUpdateBindStats(void) const mLastBindTime = sLastFrameTime; } -BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const +BOOL LLImageGL::updateBindStats() const { if (mTexName != 0) { @@ -635,7 +689,6 @@ BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const { // we haven't accounted for this texture yet this frame sUniqueCount++; - updateBoundTexMem(tex_mem, mComponents, mCategory); mLastBindTime = sLastFrameTime; return TRUE ; @@ -1232,6 +1285,7 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures) { if (gGLManager.mInited) { + free_tex_images(numTextures, textures); glDeleteTextures(numTextures, textures); } } @@ -1354,7 +1408,10 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt stop_glerror(); { LL_PROFILE_ZONE_NAMED("glTexImage2D"); + + free_cur_tex_image(); glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); + alloc_tex_image(width, height, pixformat); } stop_glerror(); @@ -1601,11 +1658,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ // things will break if we don't unbind after creation gGL.getTexUnit(0)->unbind(mBindTarget); - if (old_texname != 0) - { - sGlobalTextureMemory -= mTextureMemory; - } - //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread if (!defer_copy) { @@ -1626,7 +1678,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel); - sGlobalTextureMemory += mTextureMemory; mTexelsInGLTexture = getWidth() * getHeight(); // mark this as bound at this point, so we don't throw it out immediately @@ -1636,51 +1687,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ return TRUE; } -void LLImageGLThread::updateClass() -{ - LL_PROFILE_ZONE_SCOPED; - - // update available vram one per second - static LLFrameTimer sTimer; - - if (sTimer.getElapsedSeconds() < 1.f) - { - return; - } - - sTimer.reset(); - - auto func = []() - { - if (gGLManager.mHasATIMemInfo) - { - S32 meminfo[4]; - glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); - LLImageGLThread::sFreeVRAMMegabytes = meminfo[0]; - - } - else if (gGLManager.mHasNVXMemInfo) - { - S32 free_memory; - glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); - LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024; - } - }; - - - // post update to background thread if available, otherwise execute immediately - auto queue = LL::WorkQueue::getInstance("LLImageGL"); - if (sEnabled) - { - queue->post(func); - } - else - { - llassert(queue == nullptr); - func(); - } -} - void LLImageGL::syncToMainThread(LLGLuint new_tex_name) { LL_PROFILE_ZONE_SCOPED; @@ -1874,7 +1880,6 @@ void LLImageGL::destroyGLTexture() { if(mTextureMemory != S32Bytes(0)) { - sGlobalTextureMemory -= mTextureMemory; mTextureMemory = (S32Bytes)0; } @@ -2426,13 +2431,9 @@ void LLImageGL::checkActiveThread() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips); */ -std::atomic<S32> LLImageGLThread::sFreeVRAMMegabytes(4096); //if free vram is unknown, default to 4GB - LLImageGLThread::LLImageGLThread(LLWindow* window) - // We want exactly one thread, but a very large capacity: we never want - // anyone, especially inner-loop render code, to have to block on post() - // because we're full. - : ThreadPool("LLImageGL", 1, 1024*1024) + // We want exactly one thread. + : ThreadPool("LLImageGL", 1) , mWindow(window) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -2455,8 +2456,3 @@ void LLImageGLThread::run() mWindow->destroySharedContext(mContext); } -S32 LLImageGLThread::getFreeVRAMMegabytes() -{ - return sFreeVRAMMegabytes; -} - diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index b419c9fab5..b4618fd35c 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -52,6 +52,13 @@ class LLImageGL : public LLRefCount { friend class LLTexUnit; public: + + // Get an estimate of how many bytes have been allocated in vram for textures. + // Does not include mipmaps. + // NOTE: multiplying this number by two gives a good estimate for total + // video memory usage based on testing in lagland against an NVIDIA GPU. + static U64 getTextureBytesAllocated(); + // These 2 functions replace glGenTextures() and glDeleteTextures() static void generateTextures(S32 numTextures, U32 *textures); static void deleteTextures(S32 numTextures, const U32 *textures); @@ -61,7 +68,7 @@ public: static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height); static S32 dataFormatComponents(S32 dataformat); - BOOL updateBindStats(S32Bytes tex_mem) const ; + BOOL updateBindStats() const ; F32 getTimePassedSinceLastBound(); void forceUpdateBindStats(void) const; @@ -73,9 +80,6 @@ public: static void restoreGL(); static void dirtyTexOptions(); - // Sometimes called externally for textures not using LLImageGL (should go away...) - static S32 updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) ; - static bool checkSize(S32 width, S32 height); //for server side use only. @@ -165,7 +169,7 @@ public: void updatePickMask(S32 width, S32 height, const U8* data_in); BOOL getMask(const LLVector2 &tc); - void checkTexSize(bool forced = false) const ; + void checkTexSize(bool forced = false) const ; // Sets the addressing mode used to sample the texture // (such as wrapping, mirrored wrapping, and clamp) @@ -265,9 +269,6 @@ public: static F32 sLastFrameTime; // Global memory statistics - static S32Bytes sGlobalTextureMemory; // Tracks main memory texmem - static S32Bytes sBoundTextureMemory; // Tracks bound texmem for last completed frame - static S32Bytes sCurBoundTextureMemory; // Tracks bound texmem for current frame static U32 sBindCount; // Tracks number of texture binds for current frame static U32 sUniqueCount; // Tracks number of unique texture binds for current frame static BOOL sGlobalUseAnisotropic; @@ -327,12 +328,6 @@ public: // follows gSavedSettings "RenderGLMultiThreaded" static bool sEnabled; - // app should call this function periodically - static void updateClass(); - - // free video memory in megabytes - static std::atomic<S32> sFreeVRAMMegabytes; - LLImageGLThread(LLWindow* window); // post a function to be executed on the LLImageGL background thread @@ -344,8 +339,6 @@ public: void run() override; - static S32 getFreeVRAMMegabytes(); - private: LLWindow* mWindow; void* mContext = nullptr; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 3adb47f493..e5bd19e91c 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -224,7 +224,7 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) enable(gl_tex->getTarget()); mCurrTexture = gl_tex->getTexName(); glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); - if(gl_tex->updateBindStats(gl_tex->mTextureMemory)) + if(gl_tex->updateBindStats()) { texture->setActive() ; texture->updateBindStatsForTester() ; @@ -303,7 +303,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32 mCurrTexture = texname; glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); stop_glerror(); - texture->updateBindStats(texture->mTextureMemory); + texture->updateBindStats(); mHasMipMaps = texture->mHasMipMaps; if (texture->mTexOptionsDirty) { @@ -342,7 +342,7 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap) mCurrTexture = cubeMap->mImages[0]->getTexName(); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture); mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps; - cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory); + cubeMap->mImages[0]->updateBindStats(); if (cubeMap->mImages[0]->mTexOptionsDirty) { cubeMap->mImages[0]->mTexOptionsDirty = false; diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 70eb99c86c..32f0fa14c4 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -145,6 +145,8 @@ if (WINDOWS) list(APPEND llwindow_LINK_LIBRARIES comdlg32 # Common Dialogs for ChooseColor ole32 + dxgi + d3d9 ) endif (WINDOWS) diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index f6d90f3479..c4cdb45677 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -141,7 +141,12 @@ attributedStringInfo getSegments(NSAttributedString *str) CGLError the_err = CGLQueryRendererInfo (CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers); if(0 == the_err) { - CGLDescribeRenderer (info, 0, kCGLRPTextureMemoryMegabytes, &vram_megabytes); + // The name, uses, and other platform definitions of gGLManager.mVRAM suggest that this is supposed to be total vram in MB, + // rather than, say, just the texture memory. The two exceptions are: + // 1. LLAppViewer::getViewerInfo() puts the value in a field labeled "TEXTURE_MEMORY" + // 2. For years, this present function used kCGLRPTextureMemoryMegabytes + // Now we use kCGLRPVideoMemoryMegabytes to bring it in line with everything else (except thatone label). + CGLDescribeRenderer (info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes); CGLDestroyRendererInfo (info); } else diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 0edf39f6ef..2c538a60c9 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -162,7 +162,10 @@ public: virtual F32 getNativeAspectRatio() = 0; virtual F32 getPixelAspectRatio() = 0; virtual void setNativeAspectRatio(F32 aspect) = 0; - + + // query VRAM usage + virtual U32 getAvailableVRAMMegabytes() = 0; + virtual void beforeDialog() {}; // prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode) virtual void afterDialog() {}; // undo whatever was done in beforeDialog() diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index 410da79623..2f2c0de5bd 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -32,72 +32,79 @@ class LLWindowHeadless : public LLWindow { public: - /*virtual*/ void show() {}; - /*virtual*/ void hide() {}; - /*virtual*/ void close() {}; - /*virtual*/ BOOL getVisible() {return FALSE;}; - /*virtual*/ BOOL getMinimized() {return FALSE;}; - /*virtual*/ BOOL getMaximized() {return FALSE;}; - /*virtual*/ BOOL maximize() {return FALSE;}; - /*virtual*/ void minimize() {}; - /*virtual*/ void restore() {}; - /*virtual*/ BOOL getFullscreen() {return FALSE;}; - /*virtual*/ BOOL getPosition(LLCoordScreen *position) {return FALSE;}; - /*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;}; - /*virtual*/ BOOL getSize(LLCoordWindow *size) {return FALSE;}; - /*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;}; - /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;}; - /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;}; - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;}; - void* createSharedContext() { return nullptr; } - void makeContextCurrent(void*) {} - void destroySharedContext(void*) {} - /*virtual*/ void toggleVSync(bool enable_vsync) { } - /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;}; - /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;}; + /*virtual*/ void show() override {} + /*virtual*/ void hide() override {} + /*virtual*/ void close() override {} + /*virtual*/ BOOL getVisible() override {return FALSE;} + /*virtual*/ BOOL getMinimized() override {return FALSE;} + /*virtual*/ BOOL getMaximized() override {return FALSE;} + /*virtual*/ BOOL maximize() override {return FALSE;} + /*virtual*/ void minimize() override {} + /*virtual*/ void restore() override {} + // TODO: LLWindow::getFullscreen() is (intentionally?) NOT virtual. + // Apparently the coder of LLWindowHeadless didn't realize that. Is it a + // mistake to shadow the base-class method with an LLWindowHeadless + // override when called on the subclass, yet call the base-class method + // when indirecting through a polymorphic pointer or reference? + BOOL getFullscreen() {return FALSE;} + /*virtual*/ BOOL getPosition(LLCoordScreen *position) override {return FALSE;} + /*virtual*/ BOOL getSize(LLCoordScreen *size) override {return FALSE;} + /*virtual*/ BOOL getSize(LLCoordWindow *size) override {return FALSE;} + /*virtual*/ BOOL setPosition(LLCoordScreen position) override {return FALSE;} + /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) override {return FALSE;} + /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) override {return FALSE;} + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) override {return FALSE;} + void* createSharedContext() override { return nullptr; } + void makeContextCurrent(void*) override {} + void destroySharedContext(void*) override {} + /*virtual*/ void toggleVSync(bool enable_vsync) override { } + /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) override {return FALSE;} + /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) override {return FALSE;} #if LL_WINDOWS - /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) { return FALSE; } + /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) override { return FALSE; } #endif - /*virtual*/ void showCursor() {}; - /*virtual*/ void hideCursor() {}; - /*virtual*/ void showCursorFromMouseMove() {}; - /*virtual*/ void hideCursorUntilMouseMove() {}; - /*virtual*/ BOOL isCursorHidden() {return FALSE;}; - /*virtual*/ void updateCursor() {}; - //virtual ECursorType getCursor() { return mCurrentCursor; }; - /*virtual*/ void captureMouse() {}; - /*virtual*/ void releaseMouse() {}; - /*virtual*/ void setMouseClipping( BOOL b ) {}; - /*virtual*/ BOOL isClipboardTextAvailable() {return FALSE; }; - /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst) {return FALSE; }; - /*virtual*/ BOOL copyTextToClipboard(const LLWString &src) {return FALSE; }; - /*virtual*/ void flashIcon(F32 seconds) {}; - /*virtual*/ F32 getGamma() {return 1.0f; }; - /*virtual*/ BOOL setGamma(const F32 gamma) {return FALSE; }; // Set the gamma - /*virtual*/ void setFSAASamples(const U32 fsaa_samples) { } - /*virtual*/ U32 getFSAASamples() { return 0; } - /*virtual*/ BOOL restoreGamma() {return FALSE; }; // Restore original gamma table (before updating gamma) - //virtual ESwapMethod getSwapMethod() { return mSwapMethod; } - /*virtual*/ void gatherInput() {}; - /*virtual*/ void delayInputProcessing() {}; - /*virtual*/ void swapBuffers(); + /*virtual*/ void showCursor() override {} + /*virtual*/ void hideCursor() override {} + /*virtual*/ void showCursorFromMouseMove() override {} + /*virtual*/ void hideCursorUntilMouseMove() override {} + /*virtual*/ BOOL isCursorHidden() override {return FALSE;} + /*virtual*/ void updateCursor() override {} + //virtual ECursorType getCursor() override { return mCurrentCursor; } + /*virtual*/ void captureMouse() override {} + /*virtual*/ void releaseMouse() override {} + /*virtual*/ void setMouseClipping( BOOL b ) override {} + /*virtual*/ BOOL isClipboardTextAvailable() override {return FALSE; } + /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst) override {return FALSE; } + /*virtual*/ BOOL copyTextToClipboard(const LLWString &src) override {return FALSE; } + /*virtual*/ void flashIcon(F32 seconds) override {} + /*virtual*/ F32 getGamma() override {return 1.0f; } + /*virtual*/ BOOL setGamma(const F32 gamma) override {return FALSE; } // Set the gamma + /*virtual*/ void setFSAASamples(const U32 fsaa_samples) override { } + /*virtual*/ U32 getFSAASamples() override { return 0; } + /*virtual*/ BOOL restoreGamma() override {return FALSE; } // Restore original gamma table (before updating gamma) + //virtual ESwapMethod getSwapMethod() override { return mSwapMethod; } + /*virtual*/ void gatherInput() override {} + /*virtual*/ void delayInputProcessing() override {} + /*virtual*/ void swapBuffers() override; // handy coordinate space conversion routines - /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) { return FALSE; }; - /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) { return FALSE; }; - /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) { return FALSE; }; - /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) { return FALSE; }; - /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) { return FALSE; }; - /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) { return FALSE; }; + /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) override { return FALSE; } + /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) override { return FALSE; } + /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) override { return FALSE; } + /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) override { return FALSE; } + /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) override { return FALSE; } + /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) override { return FALSE; } - /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) { return NULL; }; - /*virtual*/ F32 getNativeAspectRatio() { return 1.0f; }; - /*virtual*/ F32 getPixelAspectRatio() { return 1.0f; }; - /*virtual*/ void setNativeAspectRatio(F32 ratio) {} + /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override { return NULL; } + /*virtual*/ F32 getNativeAspectRatio() override { return 1.0f; } + /*virtual*/ F32 getPixelAspectRatio() override { return 1.0f; } + /*virtual*/ void setNativeAspectRatio(F32 ratio) override {} - /*virtual*/ void *getPlatformWindow() { return 0; }; - /*virtual*/ void bringToFront() {}; + U32 getAvailableVRAMMegabytes() override { return 4096; } + + /*virtual*/ void *getPlatformWindow() override { return 0; } + /*virtual*/ void bringToFront() override {} LLWindowHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, @@ -113,12 +120,12 @@ private: class LLSplashScreenHeadless : public LLSplashScreen { public: - LLSplashScreenHeadless() {}; - virtual ~LLSplashScreenHeadless() {}; + LLSplashScreenHeadless() {} + virtual ~LLSplashScreenHeadless() {} - /*virtual*/ void showImpl() {}; - /*virtual*/ void updateImpl(const std::string& mesg) {}; - /*virtual*/ void hideImpl() {}; + /*virtual*/ void showImpl() override {} + /*virtual*/ void updateImpl(const std::string& mesg) override {} + /*virtual*/ void hideImpl() override {} }; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index bc4f07941b..4bcb9b3aef 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1222,6 +1222,16 @@ F32 LLWindowMacOSX::getPixelAspectRatio() return 1.f; } +U32 LLWindowMacOSX::getAvailableVRAMMegabytes() { + // MTL (and MoltenVK) has some additional gpu data, such as recommendedMaxWorkingSetSize and currentAllocatedSize. + // But these are not available for OpenGL and/or our current mimimum OS version. + // So we will estimate. + static const U32 mb = 1024*1024; + // We're asked for total available gpu memory, but we only have allocation info on texture usage. So estimate by doubling that. + static const U32 total_factor = 2; // estimated total/textures + return gGLManager.mVRAM - (LLImageGL::getTextureBytesAllocated() * total_factor/mb); +} + //static SInt32 oldWindowLevel; // MBW -- XXX -- There's got to be a better way than this. Find it, please... diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index b0f339e1db..0f316f1ddf 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -100,6 +100,9 @@ public: F32 getPixelAspectRatio() override; void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; } + // query VRAM usage + /*virtual*/ U32 getAvailableVRAMMegabytes() override; + void beforeDialog() override; void afterDialog() override; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 1f23040260..553507bc0c 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -47,6 +47,9 @@ #include "llglslshader.h" #include "llthreadsafequeue.h" #include "stringize.h" +#include "llframetimer.h" +#include "commoncontrol.h" // TODO: Remove after testing +#include "llsd.h" // TODO: Remove after testing // System includes #include <commdlg.h> @@ -61,6 +64,9 @@ #include <sstream> #include <utility> // std::pair +#include <d3d9.h> +#include <dxgi1_4.h> + // Require DirectInput version 8 #define DIRECTINPUT_VERSION 0x0800 @@ -347,6 +353,20 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool void run() override; + // initialzie DXGI adapter (for querying available VRAM) + void initDX(); + + // initialize D3D (if DXGI cannot be used) + void initD3D(); + + // call periodically to update available VRAM + void updateVRAMUsage(); + + U32 getAvailableVRAMMegabytes() + { + return mAvailableVRAM; + } + /// called by main thread to post work to this window thread template <typename CALLABLE> void post(CALLABLE&& func) @@ -395,6 +415,15 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool void gatherInput(); HWND mWindowHandle = NULL; HDC mhDC = 0; + + // best guess at available video memory in MB + std::atomic<U32> mAvailableVRAM; + + bool mTryUseDXGIAdapter; // TODO: Remove after testing + IDXGIAdapter3* mDXGIAdapter = nullptr; + bool mTryUseD3DDevice; // TODO: Remove after testing + LPDIRECT3D9 mD3D = nullptr; + LPDIRECT3DDEVICE9 mD3DDevice = nullptr; }; @@ -4531,12 +4560,24 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList() return std::vector<std::string>(); } +U32 LLWindowWin32::getAvailableVRAMMegabytes() +{ + return mWindowThread ? mWindowThread->getAvailableVRAMMegabytes() : 0; +} #endif // LL_WINDOWS inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE) { + const LLSD skipDXGI{ LL::CommonControl::get("Global", "DisablePrimaryGraphicsMemoryAccounting") }; // TODO: Remove after testing + LL_WARNS() << "DisablePrimaryGraphicsMemoryAccounting: " << skipDXGI << ", as boolean: " << skipDXGI.asBoolean() << LL_ENDL; + mTryUseDXGIAdapter = !skipDXGI.asBoolean(); + LL_WARNS() << "mTryUseDXGIAdapter: " << mTryUseDXGIAdapter << LL_ENDL; + const LLSD skipD3D{ LL::CommonControl::get("Global", "DisableSecondaryGraphicsMemoryAccounting") }; // TODO: Remove after testing + LL_WARNS() << "DisableSecondaryGraphicsMemoryAccounting: " << skipD3D << ", as boolean: " << skipD3D.asBoolean() << LL_ENDL; + mTryUseD3DDevice = !skipD3D.asBoolean(); + LL_WARNS() << "mTryUseD3DDevice: " << mTryUseD3DDevice << LL_ENDL; ThreadPool::start(); } @@ -4586,17 +4627,216 @@ private: std::string mPrev; }; +// Print hardware debug info about available graphics adapters in ordinal order +void debugEnumerateGraphicsAdapters() +{ + LL_INFOS("Window") << "Enumerating graphics adapters..." << LL_ENDL; + + IDXGIFactory1* factory; + HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory); + if (FAILED(res) || !factory) + { + LL_WARNS() << "CreateDXGIFactory1 failed: 0x" << std::hex << res << LL_ENDL; + } + else + { + UINT graphics_adapter_index = 0; + IDXGIAdapter3* dxgi_adapter; + while (true) + { + res = factory->EnumAdapters(graphics_adapter_index, reinterpret_cast<IDXGIAdapter**>(&dxgi_adapter)); + if (FAILED(res)) + { + if (graphics_adapter_index == 0) + { + LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL; + } + else + { + LL_INFOS("Window") << "Done enumerating graphics adapters" << LL_ENDL; + } + } + else + { + DXGI_ADAPTER_DESC desc; + dxgi_adapter->GetDesc(&desc); + std::wstring description_w((wchar_t*)desc.Description); + std::string description(description_w.begin(), description_w.end()); + LL_INFOS("Window") << "Graphics adapter index: " << graphics_adapter_index << ", " + << "Description: " << description << ", " + << "DeviceId: " << desc.DeviceId << ", " + << "SubSysId: " << desc.SubSysId << ", " + << "AdapterLuid: " << desc.AdapterLuid.HighPart << "_" << desc.AdapterLuid.LowPart << ", " + << "DedicatedVideoMemory: " << desc.DedicatedVideoMemory / 1024 / 1024 << ", " + << "DedicatedSystemMemory: " << desc.DedicatedSystemMemory / 1024 / 1024 << ", " + << "SharedSystemMemory: " << desc.SharedSystemMemory / 1024 / 1024 << LL_ENDL; + } + + if (dxgi_adapter) + { + dxgi_adapter->Release(); + dxgi_adapter = NULL; + } + else + { + break; + } + + graphics_adapter_index++; + } + } + + if (factory) + { + factory->Release(); + } +} + +void LLWindowWin32::LLWindowWin32Thread::initDX() +{ + if (mDXGIAdapter == NULL && mTryUseDXGIAdapter) + { + debugEnumerateGraphicsAdapters(); + + IDXGIFactory4* pFactory = nullptr; + + HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&pFactory); + + if (FAILED(res)) + { + LL_WARNS() << "CreateDXGIFactory1 failed: 0x" << std::hex << res << LL_ENDL; + } + else + { + res = pFactory->EnumAdapters(0, reinterpret_cast<IDXGIAdapter**>(&mDXGIAdapter)); + if (FAILED(res)) + { + LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL; + } + else + { + LL_INFOS() << "EnumAdapters success" << LL_ENDL; + } + } + + if (pFactory) + { + pFactory->Release(); + } + } +} + +void LLWindowWin32::LLWindowWin32Thread::initD3D() +{ + if (mDXGIAdapter == NULL && mD3DDevice == NULL && mTryUseD3DDevice && mWindowHandle != 0) + { + mD3D = Direct3DCreate9(D3D_SDK_VERSION); + + D3DPRESENT_PARAMETERS d3dpp; + + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.Windowed = TRUE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + HRESULT res = mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice); + + if (FAILED(res)) + { + LL_WARNS() << "(fallback) CreateDevice failed: 0x" << std::hex << res << LL_ENDL; + } + else + { + LL_INFOS() << "(fallback) CreateDevice success" << LL_ENDL; + } + } +} + +void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage() +{ + LL_PROFILE_ZONE_SCOPED; + if (mDXGIAdapter != nullptr) + { + // NOTE: what lies below is hand wavy math based on compatibility testing and observation against a variety of hardware + // It doesn't make sense, but please don't refactor it to make sense. -- davep + + DXGI_QUERY_VIDEO_MEMORY_INFO info; + mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info); + +#if 0 // debug 0 budget and 0 CU + info.Budget = 0; + info.CurrentUsage = 0; +#endif + + U32 budget_mb = info.Budget / 1024 / 1024; + U32 afr_mb = info.AvailableForReservation / 1024 / 1024; + // correct for systems that misreport budget + if (budget_mb == 0) + { + // fall back to available for reservation clamped between 512MB and 2GB + budget_mb = llclamp(afr_mb, (U32) 512, (U32) 2048); + } + + U32 cu_mb = info.CurrentUsage / 1024 / 1024; + + // get an estimated usage based on texture bytes allocated + U32 eu_mb = LLImageGL::getTextureBytesAllocated() * 2 / 1024 / 1024; + + if (cu_mb == 0) + { // current usage is sometimes unreliable on Intel GPUs, fall back to estimated usage + cu_mb = llmax((U32)1, eu_mb); + } + F32 eu_error = (F32)((S32)eu_mb - (S32)cu_mb) / (F32)cu_mb; + + U32 target_mb = info.Budget / 1024 / 1024; + + if (target_mb > 4096) // if 4GB are installed, try to leave 2GB free + { + target_mb -= 2048; + } + else // if less than 4GB are installed, try not to use more than half of it + { + target_mb /= 2; + } + + mAvailableVRAM = cu_mb < target_mb ? target_mb - cu_mb : 0; + + LL_INFOS("Window") << "\nLocal\nAFR: " << info.AvailableForReservation / 1024 / 1024 + << "\nBudget: " << info.Budget / 1024 / 1024 + << "\nCR: " << info.CurrentReservation / 1024 / 1024 + << "\nCU: " << info.CurrentUsage / 1024 / 1024 + << "\nEU: " << eu_mb << llformat(" (%.2f)", eu_error) + << "\nTU: " << target_mb + << "\nAM: " << mAvailableVRAM << LL_ENDL; + + /*mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &info); + LL_INFOS("Window") << "\nNon-Local\nAFR: " << info.AvailableForReservation / 1024 / 1024 + << "\nBudget: " << info.Budget / 1024 / 1024 + << "\nCR: " << info.CurrentReservation / 1024 / 1024 + << "\nCU: " << info.CurrentUsage / 1024 / 1024 << LL_ENDL;*/ + } + else if (mD3DDevice != NULL) + { // fallback to D3D9 + mAvailableVRAM = mD3DDevice->GetAvailableTextureMem() / 1024 / 1024; + } +} + void LLWindowWin32::LLWindowWin32Thread::run() { sWindowThreadId = std::this_thread::get_id(); LogChange logger("Window"); + initDX(); + while (! getQueue().done()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; if (mWindowHandle != 0) { + // lazily call initD3D inside this loop to catch when mWindowHandle has been set + // *TODO: Shutdown if this fails when mWindowHandle exists + initD3D(); + MSG msg; BOOL status; if (mhDC == 0) @@ -4629,6 +4869,13 @@ void LLWindowWin32::LLWindowWin32Thread::run() getQueue().runPending(); } + // update available vram once every 3 seconds + static LLFrameTimer vramTimer; + if (vramTimer.getElapsedTimeF32() > 3.f) + { + updateVRAMUsage(); + vramTimer.reset(); + } #if 0 { LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Sleep"); @@ -4637,6 +4884,26 @@ void LLWindowWin32::LLWindowWin32Thread::run() } #endif } + + //clean up DXGI/D3D resources + if (mDXGIAdapter) + { + mDXGIAdapter->Release(); + mDXGIAdapter = nullptr; + } + + if (mD3DDevice) + { + mD3DDevice->Release(); + mD3DDevice = nullptr; + } + + if (mD3D) + { + mD3D->Release(); + mD3D = nullptr; + } + } void LLWindowWin32::post(const std::function<void()>& func) diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index b391acc12d..bd53b3e92a 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -108,7 +108,9 @@ public: /*virtual*/ F32 getPixelAspectRatio(); /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; } - /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b ); + U32 getAvailableVRAMMegabytes() override; + + /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b ); /*virtual*/ void *getPlatformWindow(); /*virtual*/ void bringToFront(); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 950697a72a..213b34b4a6 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -321,7 +321,6 @@ set(viewer_SOURCE_FILES llfloatertelehub.cpp llfloatertestinspectors.cpp llfloatertestlistview.cpp - llfloatertexturefetchdebugger.cpp llfloatertools.cpp llfloatertopobjects.cpp llfloatertos.cpp @@ -967,7 +966,6 @@ set(viewer_HEADER_FILES llfloatertelehub.h llfloatertestinspectors.h llfloatertestlistview.h - llfloatertexturefetchdebugger.h llfloatertools.h llfloatertopobjects.h llfloatertos.h @@ -2519,6 +2517,19 @@ if (LL_TESTS) "${test_libs}" ) + set(llviewercontrollistener_test_sources + llviewercontrollistener.cpp + ../llxml/llcontrol.cpp + ../llxml/llxmltree.cpp + ../llxml/llxmlparser.cpp + ../llcommon/commoncontrol.cpp + ) + + LL_ADD_INTEGRATION_TEST(llviewercontrollistener + "${llviewercontrollistener_test_sources}" + "${test_libs}" + ) + LL_ADD_INTEGRATION_TEST(llviewernetwork llviewernetwork.cpp "${test_libs}" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8a86faa18d..cd33690075 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3398,6 +3398,29 @@ <key>Value</key> <integer>0</integer> </map> + <!-- TODO: Remove settings keys DisablePrimaryGraphicsMemoryAccounting and DisableSecondaryGraphicsMemoryAccounting after testing, and code that references them --> + <key>DisablePrimaryGraphicsMemoryAccounting</key> + <map> + <key>Comment</key> + <string>Disable the first method used to detect GPU memory use</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>DisableSecondaryGraphicsMemoryAccounting</key> + <map> + <key>Comment</key> + <string>Disable the second method used to detect GPU memory use, used as a fallback when the first method fails</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>DisableTextHyperlinkActions</key> <map> <key>Comment</key> @@ -3924,7 +3947,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>0.1</real> + <real>1.0</real> </map> <key>QueueInventoryFetchTimeout</key> <map> @@ -10313,6 +10336,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderReflectionProbeCount</key> + <map> + <key>Comment</key> + <string>Number of reflection probes (maximum is 256, requires restart)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>256</integer> + </map> <key>RenderReflectionProbeDrawDistance</key> <map> @@ -10447,17 +10481,6 @@ <key>Value</key> <real>12.0</real> </map> - <key>RenderTextureMemoryMultiple</key> - <map> - <key>Comment</key> - <string>Multiple of texture memory value to use (should fit: 0 < value <= 1.0)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1.0</real> - </map> <key>RenderTrackerBeacon</key> <map> <key>Comment</key> @@ -12537,17 +12560,6 @@ <key>Value</key> <real>20.0</real> </map> - <key>TexelPixelRatio</key> - <map> - <key>Comment</key> - <string>texel pixel ratio = texel / pixel</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1.0</real> - </map> <key>TextureCameraMotionThreshold</key> <map> <key>Comment</key> @@ -12647,17 +12659,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>TextureFetchDebuggerEnabled</key> - <map> - <key>Comment</key> - <string>Enable the texture fetching debugger if set</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>TextureFetchMinTimeToLog</key> <map> <key>Comment</key> @@ -12680,21 +12681,10 @@ <key>Value</key> <real>0.0</real> </map> - <key>TextureFetchSource</key> - <map> - <key>Comment</key> - <string>Debug use: Source to fetch textures</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>TextureFetchUpdateHighPriority</key> + <key>TextureFetchUpdateMinCount</key> <map> <key>Comment</key> - <string>Number of high priority textures to update per frame</string> + <string>Minimum number of textures to update per frame</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -12702,91 +12692,14 @@ <key>Value</key> <integer>32</integer> </map> - <key>TextureFetchUpdateMaxMediumPriority</key> - <map> - <key>Comment</key> - <string>Maximum number of medium priority textures to update per frame</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>256</integer> - </map> - <key>TextureFetchUpdateMinMediumPriority</key> - <map> - <key>Comment</key> - <string>Minimum number of medium priority textures to update per frame</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>32</integer> - </map> - <key>TextureFetchUpdatePriorityThreshold</key> - <map> - <key>Comment</key> - <string>Threshold under which textures will be considered too low priority and skipped for update</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.0</real> - </map> - <key>TextureFetchUpdateSkipLowPriority</key> - <map> - <key>Comment</key> - <string>Flag indicating if we want to skip textures with too low of a priority</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>TextureFetchUpdatePriorities</key> - <map> - <key>Comment</key> - <string>Number of priority texture to update per frame</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>32</integer> - </map> - <key>TextureListFetchingThreshold</key> - <map> - <key>Comment</key> - <string>If the ratio between fetched and all textures in the list is greater than this threshold, which we assume that almost all textures are fetched</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.97</real> - </map> <key>TextureLoadFullRes</key> <map> <key>Comment</key> <string>If TRUE, always load textures at full resolution (discard = 0)</string> <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>TextureMemory</key> - <map> - <key>Comment</key> - <string>Amount of memory to use for textures in MB (0 = autodetect)</string> - <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>S32</string> + <string>Boolean</string> <key>Value</key> <integer>0</integer> </map> @@ -12856,7 +12769,9 @@ <key>Value</key> <map> <key>General</key> - <integer>4</integer> + <integer>1</integer> + <key>ImageDecode</key> + <integer>9</integer> </map> </map> <key>ThrottleBandwidthKBPS</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index 87c1ff5517..b5c38bba04 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -104,15 +104,16 @@ void main() tnorm = normalize(tnorm.xyz); norm.xyz = normalize(tnorm.xyz); + // RGB = Occlusion, Roughness, Metal - // default values - // occlusion ? - // roughness 1.0 - // metal 1.0 + // default values, see LLViewerTexture::sDefaultPBRORMImagep + // occlusion 1.0 + // roughness 0.0 + // metal 0.0 #ifdef HAS_SPECULAR_MAP vec3 spec = texture2D(specularMap, vary_texcoord2.xy).rgb; #else - vec3 spec = vec3(1,1,1); + vec3 spec = vec3(1,0,0); #endif spec.g *= roughnessFactor; diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index ec8605aa5c..6b4ab1be17 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 35 +version 36 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended @@ -60,10 +60,10 @@ WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 -RenderTextureMemoryMultiple 1 1.0 RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderPBR 1 1 +RenderReflectionProbeCount 1 256 RenderDeferred 1 1 RenderDeferredSSAO 1 1 RenderUseAdvancedAtmospherics 1 0 @@ -291,8 +291,11 @@ RenderGLContextCoreProfile 1 0 // AMD cards generally perform better when not using VBOs for streaming data // AMD cards also prefer an OpenGL Compatibility Profile Context +// HACK: Current AMD drivers have bugged cubemap arrays, limit number of reflection probes to 16 list AMD RenderUseStreamVBO 1 0 RenderGLContextCoreProfile 1 0 +RenderReflectionProbeCount 1 16 + diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 7bad9b56f1..311b669d7f 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -60,7 +60,6 @@ WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 -RenderTextureMemoryMultiple 1 1.0 RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 225a14dee0..0e2828332e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -103,7 +103,6 @@ #include "lldiskcache.h" #include "llvopartgroup.h" #include "llweb.h" -#include "llfloatertexturefetchdebugger.h" #include "llspellcheck.h" #include "llscenemonitor.h" #include "llavatarrenderinfoaccountant.h" @@ -1551,7 +1550,6 @@ bool LLAppViewer::doFrame() { S32 non_interactive_ms_sleep_time = 100; LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getImageDecodeThread()->pause(); ms_sleep(non_interactive_ms_sleep_time); } @@ -1571,7 +1569,6 @@ bool LLAppViewer::doFrame() ms_sleep(milliseconds_to_sleep); // also pause worker threads during this wait period LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getImageDecodeThread()->pause(); } } @@ -1620,7 +1617,6 @@ bool LLAppViewer::doFrame() { LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df getTextureCache" ) LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getImageDecodeThread()->pause(); LLAppViewer::getTextureFetch()->pause(); } if(!total_io_pending) //pause file threads if nothing to process. @@ -1629,21 +1625,9 @@ bool LLAppViewer::doFrame() LLLFSThread::sLocal->pause(); } - //texture fetching debugger - if(LLTextureFetchDebugger::isEnabled()) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df tex_fetch_debugger_instance" ) - LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = - LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger"); - if(tex_fetch_debugger_instance) - { - tex_fetch_debugger_instance->idle() ; - } - } - { LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" ) - resumeMainloopTimeout(); + resumeMainloopTimeout(); } pingMainloopTimeout("Main:End"); } @@ -1695,16 +1679,20 @@ S32 LLAppViewer::updateTextureThreads(F32 max_time) void LLAppViewer::flushLFSIO() { - while (1) - { - S32 pending = LLLFSThread::updateClass(0); - if (!pending) - { - break; - } - LL_INFOS() << "Waiting for pending IO to finish: " << pending << LL_ENDL; - ms_sleep(100); - } + S32 pending = LLLFSThread::updateClass(0); + if (pending > 0) + { + LL_INFOS() << "Waiting for pending IO to finish: " << pending << LL_ENDL; + while (1) + { + pending = LLLFSThread::updateClass(0); + if (!pending) + { + break; + } + ms_sleep(100); + } + } } bool LLAppViewer::cleanup() @@ -1861,8 +1849,6 @@ bool LLAppViewer::cleanup() LL_INFOS() << "Cache files removed" << LL_ENDL; - // Wait for any pending LFS IO - flushLFSIO(); LL_INFOS() << "Shutting down Views" << LL_ENDL; // Destroy the UI @@ -2062,13 +2048,13 @@ bool LLAppViewer::cleanup() sTextureCache->shutdown(); sImageDecodeThread->shutdown(); sPurgeDiskCacheThread->shutdown(); - if (mGeneralThreadPool) - { - mGeneralThreadPool->close(); - } + if (mGeneralThreadPool) + { + mGeneralThreadPool->close(); + } sTextureFetch->shutDownTextureCacheThread() ; - sTextureFetch->shutDownImageDecodeThread() ; + LLLFSThread::sLocal->shutdown(); LL_INFOS() << "Shutting down message system" << LL_ENDL; end_messaging_system(); @@ -2185,14 +2171,7 @@ void LLAppViewer::initGeneralThread() return; } - LLSD poolSizes{ gSavedSettings.getLLSD("ThreadPoolSizes") }; - LLSD sizeSpec{ poolSizes["General"] }; - LLSD::Integer poolSize{ sizeSpec.isInteger() ? sizeSpec.asInteger() : 3 }; - LL_DEBUGS("ThreadPool") << "Instantiating General pool with " - << poolSize << " threads" << LL_ENDL; - // We don't want anyone, especially the main thread, to have to block - // due to this ThreadPool being full. - mGeneralThreadPool = new LL::ThreadPool("General", poolSize, 1024 * 1024); + mGeneralThreadPool = new LL::ThreadPool("General", 3); mGeneralThreadPool->start(); } @@ -2202,13 +2181,12 @@ bool LLAppViewer::initThreads() LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); - LLLFSThread::initClass(enable_threads && false); + LLLFSThread::initClass(enable_threads && true); // TODO: fix crashes associated with this shutdo // Image decoding LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true); LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true); LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), - sImageDecodeThread, enable_threads && true, app_metrics_qa_mode); LLAppViewer::sPurgeDiskCacheThread = new LLPurgeDiskCacheThread(); @@ -3279,7 +3257,7 @@ LLSD LLAppViewer::getViewerInfo() const info["LOD_FACTOR"] = gSavedSettings.getF32("RenderVolumeLODFactor"); info["RENDER_QUALITY"] = (F32)gSavedSettings.getU32("RenderQualityPerformance"); info["GPU_SHADERS"] = gSavedSettings.getBOOL("RenderDeferred") ? "Enabled" : "Disabled"; - info["TEXTURE_MEMORY"] = gSavedSettings.getS32("TextureMemory"); + info["TEXTURE_MEMORY"] = gGLManager.mVRAM; #if LL_DARWIN info["HIDPI"] = gHiDPISupport; @@ -4711,10 +4689,6 @@ void LLAppViewer::idle() // // Special case idle if still starting up // - if (LLStartUp::getStartupState() >= STATE_WORLD_INIT) - { - update_texture_time(); - } if (LLStartUp::getStartupState() < STATE_STARTED) { // Skip rest if idle startup returns false (essentially, no world yet) diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index cc5cb667f0..be33e1b30a 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -148,7 +148,7 @@ void LLDrawPoolTerrain::boostTerrainDetailTextures() for (S32 i = 0; i < 4; i++) { compp->mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); - compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area + gPipeline.touchTexture(compp->mDetailTextures[i], 1024.f * 1024.f); } } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 499d8d161d..52aacb607c 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2321,6 +2321,7 @@ void LLFace::resetVirtualSize() F32 LLFace::getTextureVirtualSize() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; F32 radius; F32 cos_angle_to_view_dir; BOOL in_frustum = calcPixelArea(cos_angle_to_view_dir, radius); diff --git a/indra/newview/llfloaterlagmeter.cpp b/indra/newview/llfloaterlagmeter.cpp index f72f2631a1..db00f69f03 100644 --- a/indra/newview/llfloaterlagmeter.cpp +++ b/indra/newview/llfloaterlagmeter.cpp @@ -179,7 +179,7 @@ void LLFloaterLagMeter::determineClient() { mClientCause->setText( getString("client_texture_loading_cause_msg", mStringArgs) ); } - else if(LLViewerTexture::sBoundTextureMemory > LLViewerTexture::sMaxBoundTextureMemory) + else if(LLViewerTexture::isMemoryForTextureLow()) { mClientCause->setText( getString("client_texture_memory_cause_msg", mStringArgs) ); } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index f1db12ddb0..34596d165b 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1225,12 +1225,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() shadow_text->setEnabled(enabled); // Hardware settings - F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); - S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting(); - S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier); - getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem.value()); - getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem.value()); - + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") || !gGLManager.mHasVertexBufferObject) { diff --git a/indra/newview/llfloatertexturefetchdebugger.cpp b/indra/newview/llfloatertexturefetchdebugger.cpp deleted file mode 100644 index cda4dc8bcc..0000000000 --- a/indra/newview/llfloatertexturefetchdebugger.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/** - * @file llfloatertexturefetchdebugger.cpp - * @brief LLFloaterTextureFetchDebugger class definition - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloatertexturefetchdebugger.h" - -#include "lluictrlfactory.h" -#include "llbutton.h" -#include "llspinctrl.h" -#include "llresmgr.h" - -#include "llmath.h" -#include "llviewerwindow.h" -#include "llappviewer.h" -#include "lltexturefetch.h" -#include "llviewercontrol.h" -#include "llviewerassetstats.h" //gTextureTimer - -LLFloaterTextureFetchDebugger::LLFloaterTextureFetchDebugger(const LLSD& key) - : LLFloater(key), - mDebugger(NULL) -{ - setTitle("Texture Fetching Debugger Floater"); - - mCommitCallbackRegistrar.add("TexFetchDebugger.ChangeTexelPixelRatio", boost::bind(&LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio, this)); - - mCommitCallbackRegistrar.add("TexFetchDebugger.Start", boost::bind(&LLFloaterTextureFetchDebugger::onClickStart, this)); - mCommitCallbackRegistrar.add("TexFetchDebugger.Clear", boost::bind(&LLFloaterTextureFetchDebugger::onClickClear, this)); - mCommitCallbackRegistrar.add("TexFetchDebugger.Close", boost::bind(&LLFloaterTextureFetchDebugger::onClickClose, this)); - mCommitCallbackRegistrar.add("TexFetchDebugger.ResetFetchTime", boost::bind(&LLFloaterTextureFetchDebugger::onClickResetFetchTime, this)); - - mCommitCallbackRegistrar.add("TexFetchDebugger.CacheRead", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheRead, this)); - mCommitCallbackRegistrar.add("TexFetchDebugger.CacheWrite", boost::bind(&LLFloaterTextureFetchDebugger::onClickCacheWrite, this)); - mCommitCallbackRegistrar.add("TexFetchDebugger.HTTPLoad", boost::bind(&LLFloaterTextureFetchDebugger::onClickHTTPLoad, this)); - mCommitCallbackRegistrar.add("TexFetchDebugger.Decode", boost::bind(&LLFloaterTextureFetchDebugger::onClickDecode, this)); - mCommitCallbackRegistrar.add("TexFetchDebugger.GLTexture", boost::bind(&LLFloaterTextureFetchDebugger::onClickGLTexture, this)); - - mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisCache", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisCache, this)); - mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchVisHTTP", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP, this)); - mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchAllCache", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchAllCache, this)); - mCommitCallbackRegistrar.add("TexFetchDebugger.RefetchAllHTTP", boost::bind(&LLFloaterTextureFetchDebugger::onClickRefetchAllHTTP, this)); -} -//---------------------------------------------- - -BOOL LLFloaterTextureFetchDebugger::postBuild(void) -{ - mDebugger = LLAppViewer::getTextureFetch()->getFetchDebugger(); - mStartStatus = (S32)LLTextureFetchDebugger::IDLE; - - //set states for buttons - mButtonStateMap["start_btn"] = true; - mButtonStateMap["close_btn"] = true; - mButtonStateMap["clear_btn"] = true; - mButtonStateMap["cacheread_btn"] = false; - mButtonStateMap["cachewrite_btn"] = false; - mButtonStateMap["http_btn"] = false; - mButtonStateMap["decode_btn"] = false; - mButtonStateMap["gl_btn"] = false; - - mButtonStateMap["refetchviscache_btn"] = false; - mButtonStateMap["refetchvishttp_btn"] = false; - mButtonStateMap["refetchallcache_btn"] = false; - mButtonStateMap["refetchallhttp_btn"] = false; - - updateButtons(); - - getChild<LLUICtrl>("texel_pixel_ratio")->setValue(gSavedSettings.getF32("TexelPixelRatio")); - - return TRUE ; -} - -LLFloaterTextureFetchDebugger::~LLFloaterTextureFetchDebugger() -{ - //stop everything - mDebugger->setStopDebug(); -} - -void LLFloaterTextureFetchDebugger::updateButtons() -{ - for(std::map<std::string, bool>::iterator iter = mButtonStateMap.begin(); iter != mButtonStateMap.end(); ++iter) - { - if(iter->second) - { - childEnable(iter->first.c_str()); - } - else - { - childDisable(iter->first.c_str()); - } - } -} - -void LLFloaterTextureFetchDebugger::disableButtons() -{ - childDisable("start_btn"); - childDisable("clear_btn"); - childDisable("cacheread_btn"); - childDisable("cachewrite_btn"); - childDisable("http_btn"); - childDisable("decode_btn"); - childDisable("gl_btn"); - childDisable("refetchviscache_btn"); - childDisable("refetchvishttp_btn"); - childDisable("refetchallcache_btn"); - childDisable("refetchallhttp_btn"); -} -void LLFloaterTextureFetchDebugger::setStartStatus(S32 status) -{ - llassert_always(LLTextureFetchDebugger::IDLE == (LLTextureFetchDebugger::e_debug_state)mStartStatus) ; - mStartStatus = status; -} - -bool LLFloaterTextureFetchDebugger::idleStart() -{ - if(mStartStatus != (S32)LLTextureFetchDebugger::IDLE) - { - mDebugger->startWork((LLTextureFetchDebugger::e_debug_state)mStartStatus); - mStartStatus = (S32)LLTextureFetchDebugger::IDLE; - return true; - } - - return false; -} - -void LLFloaterTextureFetchDebugger::idle() -{ - if(idleStart()) - { - return; - } - - const F32 max_time = 0.005f; //5ms - LLTextureFetchDebugger::e_debug_state state = mDebugger->getState(); - if(mDebugger->update(max_time)) - { - switch(state) - { - case LLTextureFetchDebugger::IDLE: - break; - case LLTextureFetchDebugger::START_DEBUG: - mButtonStateMap["cacheread_btn"] = true; - mButtonStateMap["http_btn"] = true; - mButtonStateMap["refetchviscache_btn"] = true; - mButtonStateMap["refetchvishttp_btn"] = true; - mButtonStateMap["refetchallcache_btn"] = true; - mButtonStateMap["refetchallhttp_btn"] = true; - break; - case LLTextureFetchDebugger::READ_CACHE: - mButtonStateMap["decode_btn"] = true; - break; - case LLTextureFetchDebugger::WRITE_CACHE: - break; - case LLTextureFetchDebugger::DECODING: - mButtonStateMap["gl_btn"] = true; - break; - case LLTextureFetchDebugger::HTTP_FETCHING: - mButtonStateMap["cacheread_btn"] = true; - mButtonStateMap["cachewrite_btn"] = true; - mButtonStateMap["decode_btn"] = true; - break; - case LLTextureFetchDebugger::GL_TEX: - break; - case LLTextureFetchDebugger::REFETCH_VIS_CACHE: - break; - case LLTextureFetchDebugger::REFETCH_VIS_HTTP: - break; - case LLTextureFetchDebugger::REFETCH_ALL_CACHE: - break; - case LLTextureFetchDebugger::REFETCH_ALL_HTTP: - break; - default: - break; - } - - if(state != LLTextureFetchDebugger::IDLE) - { - updateButtons(); - } - } -} - -//---------------------- -void LLFloaterTextureFetchDebugger::onChangeTexelPixelRatio() -{ - gSavedSettings.setF32("TexelPixelRatio", getChild<LLUICtrl>("texel_pixel_ratio")->getValue().asReal()); -} - -void LLFloaterTextureFetchDebugger::onClickStart() -{ - disableButtons(); - - setStartStatus((S32)LLTextureFetchDebugger::START_DEBUG); - - mButtonStateMap["start_btn"] = false; - - updateButtons(); -} - -void LLFloaterTextureFetchDebugger::onClickClose() -{ - setVisible(FALSE); - - //stop everything - mDebugger->setStopDebug(); - - delete this; -} - -void LLFloaterTextureFetchDebugger::onClickResetFetchTime() -{ - gTextureTimer.start(); - gTextureTimer.pause(); -} - -void LLFloaterTextureFetchDebugger::onClickClear() -{ - mButtonStateMap["start_btn"] = true; - mButtonStateMap["close_btn"] = true; - mButtonStateMap["clear_btn"] = true; - mButtonStateMap["cacheread_btn"] = false; - mButtonStateMap["cachewrite_btn"] = false; - mButtonStateMap["http_btn"] = false; - mButtonStateMap["decode_btn"] = false; - mButtonStateMap["gl_btn"] = false; - mButtonStateMap["refetchviscache_btn"] = true; - mButtonStateMap["refetchvishttp_btn"] = true; - updateButtons(); - - //stop everything - mDebugger->setStopDebug(); - mDebugger->clearHistory(); -} - -void LLFloaterTextureFetchDebugger::onClickCacheRead() -{ - disableButtons(); - - setStartStatus((S32)LLTextureFetchDebugger::READ_CACHE); -} - -void LLFloaterTextureFetchDebugger::onClickCacheWrite() -{ - disableButtons(); - - setStartStatus((S32)LLTextureFetchDebugger::WRITE_CACHE); -} - -void LLFloaterTextureFetchDebugger::onClickHTTPLoad() -{ - disableButtons(); - - setStartStatus((S32)LLTextureFetchDebugger::HTTP_FETCHING); -} - -void LLFloaterTextureFetchDebugger::onClickDecode() -{ - disableButtons(); - - setStartStatus((S32)LLTextureFetchDebugger::DECODING); -} - -void LLFloaterTextureFetchDebugger::onClickGLTexture() -{ - disableButtons(); - - setStartStatus((S32)LLTextureFetchDebugger::GL_TEX); -} - -void LLFloaterTextureFetchDebugger::onClickRefetchVisCache() -{ - disableButtons(); - - setStartStatus((S32)LLTextureFetchDebugger::REFETCH_VIS_CACHE); -} - -void LLFloaterTextureFetchDebugger::onClickRefetchVisHTTP() -{ - disableButtons(); - - setStartStatus((S32)LLTextureFetchDebugger::REFETCH_VIS_HTTP); -} - -void LLFloaterTextureFetchDebugger::onClickRefetchAllCache() -{ - disableButtons(); - - setStartStatus((S32)LLTextureFetchDebugger::REFETCH_ALL_CACHE); -} - -void LLFloaterTextureFetchDebugger::onClickRefetchAllHTTP() -{ - disableButtons(); - - setStartStatus((S32)LLTextureFetchDebugger::REFETCH_ALL_HTTP); -} - -void LLFloaterTextureFetchDebugger::draw() -{ - //total number of fetched textures - { - getChild<LLUICtrl>("total_num_fetched_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchedTextures())); - } - - //total number of fetching requests - { - getChild<LLUICtrl>("total_num_fetching_requests_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumFetchingRequests())); - } - - //total number of cache hits - { - getChild<LLUICtrl>("total_num_cache_hits_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumCacheHits())); - } - - //total number of visible textures - { - getChild<LLUICtrl>("total_num_visible_tex_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchedTextures())); - } - - //total number of visible texture fetching requests - { - getChild<LLUICtrl>("total_num_visible_tex_fetch_req_label")->setTextArg("[NUM]", llformat("%d", mDebugger->getNumVisibleFetchingRequests())); - } - - //total number of fetched data - { - getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getFetchedData() >> 10)); - getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getDecodedData() >> 10)); - getChild<LLUICtrl>("total_fetched_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getFetchedPixels() / 1000000.f)); - } - - //total number of visible fetched data - { - getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getVisibleFetchedData() >> 10)); - getChild<LLUICtrl>("total_fetched_vis_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getVisibleDecodedData() >> 10)); - } - - //total number of rendered fetched data - { - getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE1]", llformat("%d", mDebugger->getRenderedData() >> 10)); - getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[SIZE2]", llformat("%d", mDebugger->getRenderedDecodedData() >> 10)); - getChild<LLUICtrl>("total_fetched_rendered_data_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRenderedPixels() / 1000000.f)); - } - - //total time on cache readings - if(mDebugger->getCacheReadTime() < 0.f) - { - getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", std::string("----")); - } - else - { - getChild<LLUICtrl>("total_time_cache_read_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheReadTime())); - } - - //total time on cache writings - if(mDebugger->getCacheWriteTime() < 0.f) - { - getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", std::string("----")); - } - else - { - getChild<LLUICtrl>("total_time_cache_write_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getCacheWriteTime())); - } - - //total time on decoding - if(mDebugger->getDecodeTime() < 0.f) - { - getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", std::string("----")); - } - else - { - getChild<LLUICtrl>("total_time_decode_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getDecodeTime())); - } - - //total time on gl texture creation - if(mDebugger->getGLCreationTime() < 0.f) - { - getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", std::string("----")); - } - else - { - getChild<LLUICtrl>("total_time_gl_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getGLCreationTime())); - } - - //total time on HTTP fetching - if(mDebugger->getHTTPTime() < 0.f) - { - getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", std::string("----")); - } - else - { - getChild<LLUICtrl>("total_time_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getHTTPTime())); - } - - //total time on entire fetching - { - getChild<LLUICtrl>("total_time_fetch_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getTotalFetchingTime())); - } - - //total time on refetching visible textures from cache - if(mDebugger->getRefetchVisCacheTime() < 0.f) - { - getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", std::string("----")); - getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", std::string("----")); - getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", std::string("----")); - } - else - { - getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisCacheTime())); - getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedVisData() >> 10)); - getChild<LLUICtrl>("total_time_refetch_vis_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedVisPixels() / 1000000.f)); - } - - //total time on refetching all textures from cache - if(mDebugger->getRefetchAllCacheTime() < 0.f) - { - getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[TIME]", std::string("----")); - getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[SIZE]", std::string("----")); - getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[PIXEL]", std::string("----")); - } - else - { - getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchAllCacheTime())); - getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedAllData() >> 10)); - getChild<LLUICtrl>("total_time_refetch_all_cache_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedAllPixels() / 1000000.f)); - } - - //total time on refetching visible textures from http - if(mDebugger->getRefetchVisHTTPTime() < 0.f) - { - getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", std::string("----")); - getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", std::string("----")); - getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", std::string("----")); - } - else - { - getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchVisHTTPTime())); - getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedVisData() >> 10)); - getChild<LLUICtrl>("total_time_refetch_vis_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedVisPixels() / 1000000.f)); - } - - //total time on refetching all textures from http - if(mDebugger->getRefetchAllHTTPTime() < 0.f) - { - getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[TIME]", std::string("----")); - getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[SIZE]", std::string("----")); - getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[PIXEL]", std::string("----")); - } - else - { - getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[TIME]", llformat("%.3f", mDebugger->getRefetchAllHTTPTime())); - getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[SIZE]", llformat("%d", mDebugger->getRefetchedAllData() >> 10)); - getChild<LLUICtrl>("total_time_refetch_all_http_label")->setTextArg("[PIXEL]", llformat("%.3f", mDebugger->getRefetchedAllPixels() / 1000000.f)); - } - - LLFloater::draw(); -} diff --git a/indra/newview/llfloatertexturefetchdebugger.h b/indra/newview/llfloatertexturefetchdebugger.h deleted file mode 100644 index 637f3b03e5..0000000000 --- a/indra/newview/llfloatertexturefetchdebugger.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @file llfloatertexturefetchdebugger.h - * @brief texture fetching debugger window, debug use only - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H -#define LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H - -#include "llfloater.h" -class LLTextureFetchDebugger; - -class LLFloaterTextureFetchDebugger : public LLFloater -{ - friend class LLFloaterReg; -public: - /// initialize all the callbacks for the menu - - virtual BOOL postBuild() ; - virtual void draw() ; - - void onChangeTexelPixelRatio(); - - void onClickStart(); - void onClickClear(); - void onClickClose(); - void onClickResetFetchTime(); - - void onClickCacheRead(); - void onClickCacheWrite(); - void onClickHTTPLoad(); - void onClickDecode(); - void onClickGLTexture(); - - void onClickRefetchVisCache(); - void onClickRefetchVisHTTP(); - void onClickRefetchAllCache(); - void onClickRefetchAllHTTP(); -public: - void idle() ; - -private: - LLFloaterTextureFetchDebugger(const LLSD& key); - virtual ~LLFloaterTextureFetchDebugger(); - - void updateButtons(); - void disableButtons(); - - void setStartStatus(S32 status); - bool idleStart(); -private: - LLTextureFetchDebugger* mDebugger; - std::map<std::string, bool> mButtonStateMap; - S32 mStartStatus; -}; - -#endif // LL_FLOATER_TEXTURE_FETCH_DEBUGGER__H diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 37500176ea..c101033a5d 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -222,8 +222,6 @@ LLInventoryModel::LLInventoryModel() mHttpOptions(), mHttpHeaders(), mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), - mHttpPriorityFG(0), - mHttpPriorityBG(0), mCategoryLock(), mItemLock(), mValidationInfo(new LLInventoryValidationInfo) @@ -2799,7 +2797,6 @@ LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground, handle = LLCoreHttpUtil::requestPostWithLLSD(request, mHttpPolicyClass, - (foreground ? mHttpPriorityFG : mHttpPriorityBG), url, body, mHttpOptions, diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index eeec89bfb0..85343cf95c 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -617,8 +617,6 @@ private: LLCore::HttpOptions::ptr_t mHttpOptions; LLCore::HttpHeaders::ptr_t mHttpHeaders; LLCore::HttpRequest::policy_t mHttpPolicyClass; - LLCore::HttpRequest::priority_t mHttpPriorityFG; - LLCore::HttpRequest::priority_t mHttpPriorityBG; /** HTTP Transport ** ** diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index 11aa607393..27a9758ec3 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -133,8 +133,7 @@ LLMaterialMgr::LLMaterialMgr(): mHttpRequest(), mHttpHeaders(), mHttpOptions(), - mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID), - mHttpPriority(0) + mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) { LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); @@ -699,7 +698,7 @@ void LLMaterialMgr::processGetQueue() << "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL; LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, - mHttpPolicy, mHttpPriority, capURL, + mHttpPolicy, capURL, postData, mHttpOptions, mHttpHeaders, handler); if (handle == LLCORE_HTTP_HANDLE_INVALID) @@ -985,7 +984,7 @@ void LLMaterialMgr::processPutQueue() )); LLCore::HttpHandle handle = LLCoreHttpUtil::requestPutWithLLSD( - mHttpRequest, mHttpPolicy, mHttpPriority, capURL, + mHttpRequest, mHttpPolicy, capURL, putData, mHttpOptions, mHttpHeaders, handler); if (handle == LLCORE_HTTP_HANDLE_INVALID) diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index 843dc66fbc..f76cc27db1 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -141,7 +141,6 @@ private: LLCore::HttpHeaders::ptr_t mHttpHeaders; LLCore::HttpOptions::ptr_t mHttpOptions; LLCore::HttpRequest::policy_t mHttpPolicy; - LLCore::HttpRequest::priority_t mHttpPriority; U32 getMaxEntries(const LLViewerRegion* regionp); }; diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index bc45eb6d3a..142977e939 100644 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -355,7 +355,7 @@ void LLMediaDataClient::serviceQueue() // and make the post LLCore::HttpHandler::ptr_t handler = request->createHandler(); - LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy, 0, + LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy, url, sd_payload, mHttpOpts, mHttpHeaders, handler); if (handle == LLCORE_HTTP_HANDLE_INVALID) diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index d28e929b48..6fa71e130e 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -823,8 +823,7 @@ LLMeshRepoThread::LLMeshRepoThread() mHttpLargeOptions(), mHttpHeaders(), mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), - mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), - mHttpPriority(0) + mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID) { LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); @@ -1268,7 +1267,6 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, if (len < LARGE_MESH_FETCH_THRESHOLD) { handle = mHttpRequest->requestGetByteRange( mHttpPolicyClass, - mHttpPriority, url, (disable_range_req ? size_t(0) : offset), (disable_range_req ? size_t(0) : len), @@ -1283,7 +1281,6 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, else { handle = mHttpRequest->requestGetByteRange(mHttpLargePolicyClass, - mHttpPriority, url, (disable_range_req ? size_t(0) : offset), (disable_range_req ? size_t(0) : len), @@ -2130,7 +2127,6 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders); mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML); mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_UPLOADS); - mHttpPriority = 0; } LLMeshUploadThread::~LLMeshUploadThread() @@ -2649,7 +2645,6 @@ void LLMeshUploadThread::doWholeModelUpload() LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicyClass, - mHttpPriority, mWholeModelUploadURL, body, mHttpOptions, @@ -2700,7 +2695,6 @@ void LLMeshUploadThread::requestWholeModelFee() dump_llsd_to_file(mModelData, make_dump_name("whole_model_fee_request_", dump_num)); LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicyClass, - mHttpPriority, mWholeModelFeeCapability, mModelData, mHttpOptions, diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 1989350303..5459bbb4af 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -321,7 +321,6 @@ public: LLCore::HttpHeaders::ptr_t mHttpHeaders; LLCore::HttpRequest::policy_t mHttpPolicyClass; LLCore::HttpRequest::policy_t mHttpLargePolicyClass; - LLCore::HttpRequest::priority_t mHttpPriority; typedef std::set<LLCore::HttpHandler::ptr_t> http_request_set; http_request_set mHttpRequestSet; // Outstanding HTTP requests @@ -489,7 +488,6 @@ private: LLCore::HttpOptions::ptr_t mHttpOptions; LLCore::HttpHeaders::ptr_t mHttpHeaders; LLCore::HttpRequest::policy_t mHttpPolicyClass; - LLCore::HttpRequest::priority_t mHttpPriority; }; // Params related to streaming cost, render cost, and scene complexity tracking. diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 583c6de77b..b285cc531e 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -40,7 +40,7 @@ extern BOOL gTeleportDisplay; LLReflectionMapManager::LLReflectionMapManager() { - for (int i = 0; i < LL_REFLECTION_PROBE_COUNT; ++i) + for (int i = 0; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i) { mCubeFree[i] = true; } @@ -76,16 +76,7 @@ void LLReflectionMapManager::update() } // =============== TODO -- move to an init function ================= - - if (mTexture.isNull()) - { - mTexture = new LLCubeMapArray(); - // store LL_REFLECTION_PROBE_COUNT+2 cube maps, final two cube maps are used for render target and radiance map generation source) - mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT+2); - - mIrradianceMaps = new LLCubeMapArray(); - mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT); - } + initReflectionMaps(); if (!mRenderTarget.isComplete()) { @@ -167,7 +158,7 @@ void LLReflectionMapManager::update() LLVector4a d; if (!did_update && - i < LL_REFLECTION_PROBE_COUNT && + i < mReflectionProbeCount && (oldestProbe == nullptr || probe->mLastUpdateTime < oldestProbe->mLastUpdateTime)) { oldestProbe = probe; @@ -317,7 +308,7 @@ LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vo S32 LLReflectionMapManager::allocateCubeIndex() { - for (int i = 0; i < LL_REFLECTION_PROBE_COUNT; ++i) + for (int i = 0; i < mReflectionProbeCount; ++i) { if (mCubeFree[i]) { @@ -327,7 +318,7 @@ S32 LLReflectionMapManager::allocateCubeIndex() } // no cubemaps free, steal one from the back of the probe list - for (int i = mProbes.size() - 1; i >= LL_REFLECTION_PROBE_COUNT; --i) + for (int i = mProbes.size() - 1; i >= mReflectionProbeCount; --i) { if (mProbes[i]->mCubeIndex != -1) { @@ -392,7 +383,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gPipeline.mRT = &gPipeline.mMainRT; mRenderTarget.flush(); - S32 targetIdx = LL_REFLECTION_PROBE_COUNT; + S32 targetIdx = mReflectionProbeCount; if (probe != mUpdatingProbe) { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel @@ -625,15 +616,15 @@ void LLReflectionMapManager::updateUniforms() // see class3/deferred/reflectionProbeF.glsl struct ReflectionProbeData { - LLMatrix4 refBox[LL_REFLECTION_PROBE_COUNT]; // object bounding box as needed - LLVector4 refSphere[LL_REFLECTION_PROBE_COUNT]; //origin and radius of refmaps in clip space - LLVector4 refParams[LL_REFLECTION_PROBE_COUNT]; //extra parameters (currently only ambiance) - GLint refIndex[LL_REFLECTION_PROBE_COUNT][4]; + LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; // object bounding box as needed + LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; //origin and radius of refmaps in clip space + LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT]; //extra parameters (currently only ambiance) + GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4]; GLint refNeighbor[4096]; GLint refmapCount; }; - mReflectionMaps.resize(LL_REFLECTION_PROBE_COUNT); + mReflectionMaps.resize(mReflectionProbeCount); getReflectionMaps(mReflectionMaps); ReflectionProbeData rpd; @@ -830,3 +821,19 @@ void LLReflectionMapManager::renderDebug() gDebugProgram.unbind(); } + +void LLReflectionMapManager::initReflectionMaps() +{ + if (mTexture.isNull()) + { + mReflectionProbeCount = llclamp(gSavedSettings.getS32("RenderReflectionProbeCount"), 1, LL_MAX_REFLECTION_PROBE_COUNT); + + mTexture = new LLCubeMapArray(); + + // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) + mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 3, mReflectionProbeCount + 2); + + mIrradianceMaps = new LLCubeMapArray(); + mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount); + } +} diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 5f0b11ec17..29a9ece2f8 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -35,7 +35,7 @@ class LLSpatialGroup; class LLViewerObject; // number of reflection probes to keep in vram -#define LL_REFLECTION_PROBE_COUNT 256 +#define LL_MAX_REFLECTION_PROBE_COUNT 256 // reflection probe resolution #define LL_REFLECTION_PROBE_RESOLUTION 256 @@ -88,6 +88,9 @@ public: // probe debug display is active void renderDebug(); + // call once at startup to allocate cubemap arrays + void initReflectionMaps(); + private: friend class LLPipeline; @@ -120,7 +123,7 @@ private: LLPointer<LLCubeMapArray> mIrradianceMaps; // array indicating if a particular cubemap is free - bool mCubeFree[LL_REFLECTION_PROBE_COUNT]; + bool mCubeFree[LL_MAX_REFLECTION_PROBE_COUNT]; // start tracking the given spatial group void trackGroup(LLSpatialGroup* group); @@ -148,5 +151,8 @@ private: LLReflectionMap* mUpdatingProbe = nullptr; U32 mUpdatingFace = 0; + + // number of reflection probes to use for rendering (based on saved setting RenderReflectionProbeCount) + U32 mReflectionProbeCount; }; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index f445bc98eb..10b3683cc8 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3367,10 +3367,10 @@ public: } } - if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + /*if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { renderTexturePriority(drawable); - } + }*/ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS)) { @@ -3697,7 +3697,7 @@ void LLSpatialPartition::renderDebug() LLPipeline::RENDER_DEBUG_BBOXES | LLPipeline::RENDER_DEBUG_NORMALS | LLPipeline::RENDER_DEBUG_POINTS | - LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | + //LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | LLPipeline::RENDER_DEBUG_RAYCAST | LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index d4fc6f3de2..8f4eb9438b 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -95,14 +95,13 @@ private: }; public: - LLTextureCacheWorker(LLTextureCache* cache, U32 priority, const LLUUID& id, + LLTextureCacheWorker(LLTextureCache* cache, const LLUUID& id, U8* data, S32 datasize, S32 offset, S32 imagesize, // for writes LLTextureCache::Responder* responder) : LLWorkerClass(cache, "LLTextureCacheWorker"), mID(id), mCache(cache), - mPriority(priority), mReadData(NULL), mWriteData(data), mDataSize(datasize), @@ -115,7 +114,6 @@ public: mBytesToRead(0), mBytesRead(0) { - mPriority &= LLWorkerThread::PRIORITY_LOWBITS; } ~LLTextureCacheWorker() { @@ -129,13 +127,12 @@ public: virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest() - handle_t read() { addWork(0, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; } - handle_t write() { addWork(1, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; } + handle_t read() { addWork(0); return mRequestHandle; } + handle_t write() { addWork(1); return mRequestHandle; } bool complete() { return checkWork(); } void ioComplete(S32 bytes) { mBytesRead = bytes; - setPriority(LLWorkerThread::PRIORITY_HIGH | mPriority); } private: @@ -145,7 +142,6 @@ private: protected: LLTextureCache* mCache; - U32 mPriority; LLUUID mID; U8* mReadData; @@ -164,11 +160,11 @@ protected: class LLTextureCacheLocalFileWorker : public LLTextureCacheWorker { public: - LLTextureCacheLocalFileWorker(LLTextureCache* cache, U32 priority, const std::string& filename, const LLUUID& id, + LLTextureCacheLocalFileWorker(LLTextureCache* cache, const std::string& filename, const LLUUID& id, U8* data, S32 datasize, S32 offset, S32 imagesize, // for writes LLTextureCache::Responder* responder) - : LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder), + : LLTextureCacheWorker(cache, id, data, datasize, offset, imagesize, responder), mFileName(filename) { @@ -183,6 +179,7 @@ private: bool LLTextureCacheLocalFileWorker::doRead() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; S32 local_size = LLAPRFile::size(mFileName, mCache->getLocalAPRFilePool()); if (local_size > 0 && mFileName.size() > 4) @@ -207,50 +204,6 @@ bool LLTextureCacheLocalFileWorker::doRead() return true; } -#if USE_LFS_READ - if (mFileHandle == LLLFSThread::nullHandle()) - { - mImageLocal = TRUE; - mImageSize = local_size; - if (!mDataSize || mDataSize + mOffset > local_size) - { - mDataSize = local_size - mOffset; - } - if (mDataSize <= 0) - { - // no more data to read - mDataSize = 0; - return true; - } - mReadData = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), mDataSize); - mBytesRead = -1; - mBytesToRead = mDataSize; - setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); - mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize, - new ReadResponder(mCache, mRequestHandle)); - return false; - } - else - { - if (mBytesRead >= 0) - { - if (mBytesRead != mBytesToRead) - { -// LL_WARNS() << "Error reading file from local cache: " << local_filename -// << " Bytes: " << mDataSize << " Offset: " << mOffset -// << " / " << mDataSize << LL_ENDL; - mDataSize = 0; // failed - ll_aligned_free_16(mReadData); - mReadData = NULL; - } - return true; - } - else - { - return false; - } - } -#else if (!mDataSize || mDataSize > local_size) { mDataSize = local_size; @@ -274,7 +227,6 @@ bool LLTextureCacheLocalFileWorker::doRead() mImageLocal = TRUE; } return true; -#endif } bool LLTextureCacheLocalFileWorker::doWrite() @@ -286,12 +238,12 @@ bool LLTextureCacheLocalFileWorker::doWrite() class LLTextureCacheRemoteWorker : public LLTextureCacheWorker { public: - LLTextureCacheRemoteWorker(LLTextureCache* cache, U32 priority, const LLUUID& id, + LLTextureCacheRemoteWorker(LLTextureCache* cache, const LLUUID& id, U8* data, S32 datasize, S32 offset, S32 imagesize, // for writes LLPointer<LLImageRaw> raw, S32 discardlevel, LLTextureCache::Responder* responder) - : LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder), + : LLTextureCacheWorker(cache, id, data, datasize, offset, imagesize, responder), mState(INIT), mRawImage(raw), mRawDiscardLevel(discardlevel) @@ -329,6 +281,7 @@ void LLTextureCacheWorker::startWork(S32 param) // - the code supports offset reading but this is actually never exercised in the viewer bool LLTextureCacheRemoteWorker::doRead() { + LL_PROFILE_ZONE_SCOPED; bool done = false; S32 idx = -1; @@ -580,6 +533,7 @@ bool LLTextureCacheRemoteWorker::doRead() // - the code *does not* support offset writing so there are no difference between buffer addresses and start of data bool LLTextureCacheRemoteWorker::doWrite() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; bool done = false; S32 idx = -1; @@ -756,6 +710,7 @@ bool LLTextureCacheRemoteWorker::doWrite() //virtual bool LLTextureCacheWorker::doWork(S32 param) { + LL_PROFILE_ZONE_SCOPED; bool res = false; if (param == 0) // read { @@ -775,11 +730,13 @@ bool LLTextureCacheWorker::doWork(S32 param) //virtual (WORKER THREAD) void LLTextureCacheWorker::finishWork(S32 param, bool completed) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (mResponder.notNull()) { bool success = (completed && mDataSize > 0); if (param == 0) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("tcwfw - read"); // read if (success) { @@ -789,12 +746,14 @@ void LLTextureCacheWorker::finishWork(S32 param, bool completed) } else { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("tcwfw - read fail"); ll_aligned_free_16(mReadData); mReadData = NULL; } } else { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("tcwfw - write"); // write mWriteData = NULL; // we never owned data mDataSize = 0; @@ -806,6 +765,7 @@ void LLTextureCacheWorker::finishWork(S32 param, bool completed) //virtual (MAIN THREAD) void LLTextureCacheWorker::endWork(S32 param, bool aborted) { + LL_PROFILE_ZONE_SCOPED; if (aborted) { // Let the destructor handle any cleanup @@ -861,6 +821,7 @@ LLTextureCache::~LLTextureCache() //virtual S32 LLTextureCache::update(F32 max_time_ms) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static LLFrameTimer timer ; static const F32 MAX_TIME_INTERVAL = 300.f ; //seconds. @@ -874,22 +835,6 @@ S32 LLTextureCache::update(F32 max_time_ms) mCompletedList.clear(); mListMutex.unlock(); - lockWorkers(); - - for (handle_list_t::iterator iter1 = priorty_list.begin(); - iter1 != priorty_list.end(); ++iter1) - { - handle_t handle = *iter1; - handle_map_t::iterator iter2 = mWriters.find(handle); - if(iter2 != mWriters.end()) - { - LLTextureCacheWorker* worker = iter2->second; - worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mPriority); - } - } - - unlockWorkers(); - // call 'completed' with workers list unlocked (may call readComplete() or writeComplete() for (responder_list_t::iterator iter1 = completed_list.begin(); iter1 != completed_list.end(); ++iter1) @@ -1323,6 +1268,7 @@ void LLTextureCache::updateEntryTimeStamp(S32 idx, Entry& entry) //update an existing entry, write to header file immediately. bool LLTextureCache::updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32 new_data_size) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; S32 new_body_size = llmax(0, new_data_size - TEXTURE_CACHE_ENTRY_SIZE) ; if(new_image_size == entry.mImageSize && new_body_size == entry.mBodySize) @@ -1872,6 +1818,7 @@ void LLTextureCache::purgeTextures(bool validate) // call lockWorkers() first! LLTextureCacheWorker* LLTextureCache::getReader(handle_t handle) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LLTextureCacheWorker* res = NULL; handle_map_t::iterator iter = mReaders.find(handle); if (iter != mReaders.end()) @@ -1883,6 +1830,7 @@ LLTextureCacheWorker* LLTextureCache::getReader(handle_t handle) LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LLTextureCacheWorker* res = NULL; handle_map_t::iterator iter = mWriters.find(handle); if (iter != mWriters.end()) @@ -1898,6 +1846,7 @@ LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle) // Reads imagesize from the header, updates timestamp S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, Entry& entry) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LLMutexLock lock(&mHeaderMutex); S32 idx = openAndReadEntry(id, entry, false); if (idx >= 0) @@ -1910,6 +1859,7 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, Entry& entry) // Writes imagesize to the header, updates timestamp S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imagesize, S32 datasize) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; mHeaderMutex.lock(); S32 idx = openAndReadEntry(id, entry, true); // read or create mHeaderMutex.unlock(); @@ -1942,13 +1892,14 @@ S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imag // Calls from texture pipeline thread (i.e. LLTextureFetch) -LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filename, const LLUUID& id, U32 priority, +LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filename, const LLUUID& id, S32 offset, S32 size, ReadResponder* responder) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; // Note: checking to see if an entry exists can cause a stall, // so let the thread handle it LLMutexLock lock(&mWorkersMutex); - LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, priority, filename, id, + LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, filename, id, NULL, size, offset, 0, responder); handle_t handle = worker->read(); @@ -1956,13 +1907,14 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filena return handle; } -LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 priority, +LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, S32 offset, S32 size, ReadResponder* responder) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; // Note: checking to see if an entry exists can cause a stall, // so let the thread handle it LLMutexLock lock(&mWorkersMutex); - LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, + LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, id, NULL, size, offset, 0, NULL, 0, responder); handle_t handle = worker->read(); @@ -1973,6 +1925,7 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri bool LLTextureCache::readComplete(handle_t handle, bool abort) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; lockWorkers(); handle_map_t::iterator iter = mReaders.find(handle); LLTextureCacheWorker* worker = NULL; @@ -2000,7 +1953,7 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort) return (complete || abort); } -LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority, +LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel, WriteResponder* responder) @@ -2018,7 +1971,7 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio mDoPurge = !mPurgeEntryList.empty(); } LLMutexLock lock(&mWorkersMutex); - LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, + LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, id, data, datasize, 0, imagesize, rawimage, discardlevel, responder); handle_t handle = worker->write(); @@ -2086,6 +2039,7 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d //return the fast cache location bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointer<LLImageRaw> raw, S32 discardlevel) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; //rescale image if needed if (raw.isNull() || raw->isBufferInvalid() || !raw->getData()) { diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index e1c752b58e..f2a5978a7c 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -119,13 +119,13 @@ public: void setReadOnly(BOOL read_only) ; S64 initCache(ELLPath location, S64 maxsize, BOOL texture_cache_mismatch); - handle_t readFromCache(const std::string& local_filename, const LLUUID& id, U32 priority, S32 offset, S32 size, + handle_t readFromCache(const std::string& local_filename, const LLUUID& id, S32 offset, S32 size, ReadResponder* responder); - handle_t readFromCache(const LLUUID& id, U32 priority, S32 offset, S32 size, + handle_t readFromCache(const LLUUID& id, S32 offset, S32 size, ReadResponder* responder); bool readComplete(handle_t handle, bool abort); - handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel, + handle_t writeToCache(const LLUUID& id, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel, WriteResponder* responder); LLPointer<LLImageRaw> readFromFastCache(const LLUUID& id, S32& discardlevel); bool writeComplete(handle_t handle, bool abort = false); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 35e4bb03ac..dc10e42446 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -62,8 +62,6 @@ #include "llcorehttputil.h" #include "llhttpretrypolicy.h" -bool LLTextureFetchDebugger::sDebuggerEnabled = false ; - LLTrace::CountStatHandle<F64> LLTextureFetch::sCacheHit("texture_cache_hit"); LLTrace::CountStatHandle<F64> LLTextureFetch::sCacheAttempt("texture_cache_attempt"); LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > LLTextureFetch::sCacheHitRate("texture_cache_hits"); @@ -213,35 +211,17 @@ const std::string sTesterName("TextureFetchTester"); // // Worker State Machine // -// (ASCII art needed) -// -// -// Priority Scheme -// -// [PRIORITY_LOW, PRIORITY_NORMAL) - for WAIT_HTTP_RESOURCE state -// and other wait states -// [PRIORITY_HIGH, PRIORITY_URGENT) - External event delivered, -// rapidly transitioning through states, -// no waiting allowed -// -// By itself, the above work queue model would fail the concurrency -// and liveness requirements of the interface. A high priority -// request could find itself on the head and stalled for external -// reasons (see VWR-28996). So a few additional constraints are -// required to keep things running: -// * Anything that can make forward progress must be kept at a -// higher priority than anything that can't. -// * On completion of external events, the associated request -// needs to be elevated beyond the normal range to handle -// any data delivery and release any external resource. -// -// This effort is made to keep higher-priority entities moving -// forward in their state machines at every possible step of -// processing. It's not entirely proven that this produces the -// experiencial benefits promised. +// "doWork" will be executed for a given worker on its respective +// LLQueuedThread. If doWork returns true, the worker is treated +// as completed. If doWork returns false, the worker will be +// put on the back of the work queue at the start of the next iteration +// of the mainloop. If a worker is waiting on a resource, it should +// return false as soon as possible and not block to avoid starving +// other workers of cpu cycles. // + ////////////////////////////////////////////////////////////////////////////// // Tuning/Parameterization Constants @@ -262,8 +242,8 @@ static const S32 HTTP_REQUESTS_RANGE_END_MAX = 20000000; ////////////////////////////////////////////////////////////////////////////// namespace { - // The NoOpDeletor is used when passing certain objects (the LLTextureFetchWorker and - // the LLTextureFetchDebugger) in a smart pointer below for passage into + // The NoOpDeletor is used when passing certain objects (the LLTextureFetchWorker) + // in a smart pointer below for passage into // the LLCore::Http libararies. When the smart pointer is destroyed, no // action will be taken since we do not in these cases want the object to // be destroyed at the end of the call. @@ -301,7 +281,6 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler { friend class LLTextureFetch; - friend class LLTextureFetchDebugger; private: class CacheReadResponder : public LLTextureCache::ReadResponder @@ -386,14 +365,7 @@ private: bool operator()(const LLTextureFetchWorker* lhs, const LLTextureFetchWorker* rhs) const { // greater priority is "less" - const F32 lpriority = lhs->mImagePriority; - const F32 rpriority = rhs->mImagePriority; - if (lpriority > rpriority) // higher priority - return true; - else if (lpriority < rpriority) - return false; - else - return lhs < rhs; + return lhs->mImagePriority > rhs->mImagePriority; } }; @@ -484,6 +456,9 @@ private: // Locks: Mw void resetFormattedData(); + // get the relative priority of this worker (should map to max virtual size) + F32 getImagePriority() const; + // Locks: Mw void setImagePriority(F32 priority); @@ -500,9 +475,6 @@ private: // Locks: Mw void setupPacketData(); - // Locks: Mw (ctor invokes without lock) - U32 calcWorkPriority(); - // Locks: Mw void removeFromCache(); @@ -573,16 +545,13 @@ private: LLHost mHost; std::string mUrl; U8 mType; - F32 mImagePriority; - U32 mWorkPriority; + F32 mImagePriority; // should map to max virtual size F32 mRequestedPriority; S32 mDesiredDiscard; S32 mSimRequestedDiscard; S32 mRequestedDiscard; S32 mLoadedDiscard; S32 mDecodedDiscard; - S32 mFullWidth; - S32 mFullHeight; LLFrameTimer mRequestedDeltaTimer; LLFrameTimer mFetchDeltaTimer; LLTimer mCacheReadTimer; @@ -923,7 +892,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mHost(host), mUrl(url), mImagePriority(priority), - mWorkPriority(0), mRequestedPriority(0.f), mDesiredDiscard(-1), mSimRequestedDiscard(-1), @@ -970,17 +938,15 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mCacheReadCount(0U), mCacheWriteCount(0U), mResourceWaitCount(0U), - mFetchRetryPolicy(10.0,3600.0,2.0,10) + mFetchRetryPolicy(10.f,3600.f,2.f,10) { mCanUseNET = mUrl.empty() ; - calcWorkPriority(); mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL; // LL_INFOS(LOG_TXT) << "Create: " << mID << " mHost:" << host << " Discard=" << discard << LL_ENDL; if (!mFetcher->mDebugPause) { - U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; - addWork(0, work_priority ); + addWork(0); } setDesiredDiscard(discard, size); } @@ -1071,16 +1037,6 @@ void LLTextureFetchWorker::setupPacketData() } // Locks: Mw (ctor invokes without lock) -U32 LLTextureFetchWorker::calcWorkPriority() -{ - //llassert_always(mImagePriority >= 0 && mImagePriority <= LLViewerFetchedTexture::maxDecodePriority()); - static const F32 PRIORITY_SCALE = (F32)LLWorkerThread::PRIORITY_LOWBITS / LLViewerFetchedTexture::maxDecodePriority(); - - mWorkPriority = llmin((U32)LLWorkerThread::PRIORITY_LOWBITS, (U32)(mImagePriority * PRIORITY_SCALE)); - return mWorkPriority; -} - -// Locks: Mw (ctor invokes without lock) void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size) { bool prioritize = false; @@ -1088,11 +1044,9 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size) { if (!haveWork()) { - calcWorkPriority(); if (!mFetcher->mDebugPause) { - U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; - addWork(0, work_priority); + addWork(0); } } else if (mDesiredDiscard < discard) @@ -1111,23 +1065,13 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size) if ((prioritize && mState == INIT) || mState == DONE) { setState(INIT); - U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; - setPriority(work_priority); } } // Locks: Mw void LLTextureFetchWorker::setImagePriority(F32 priority) { -// llassert_always(priority >= 0 && priority <= LLViewerTexture::maxDecodePriority()); - F32 delta = fabs(priority - mImagePriority); - if (delta > (mImagePriority * .05f) || mState == DONE) - { - mImagePriority = priority; - calcWorkPriority(); - U32 work_priority = mWorkPriority | (getPriority() & LLWorkerThread::PRIORITY_HIGHBITS); - setPriority(work_priority); - } + mImagePriority = priority; //should map to max virtual size, abort if zero } // Locks: Mw @@ -1147,6 +1091,11 @@ void LLTextureFetchWorker::resetFormattedData() mHaveAllData = FALSE; } +F32 LLTextureFetchWorker::getImagePriority() const +{ + return mImagePriority; +} + // Threads: Tmain void LLTextureFetchWorker::startWork(S32 param) { @@ -1156,7 +1105,7 @@ void LLTextureFetchWorker::startWork(S32 param) // Threads: Ttf bool LLTextureFetchWorker::doWork(S32 param) { - LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; if (gNonInteractive) { return true; @@ -1171,20 +1120,23 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (mState < DECODE_IMAGE) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - state < decode"); return true; // abort } } - if(mImagePriority < F_ALMOST_ZERO) + if (mImagePriority < F_ALMOST_ZERO) { if (mState == INIT || mState == LOAD_FROM_NETWORK || mState == LOAD_FROM_SIMULATOR) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - priority < 0"); LL_DEBUGS(LOG_TXT) << mID << " abort: mImagePriority < F_ALMOST_ZERO" << LL_ENDL; return true; // abort } } if(mState > CACHE_POST && !mCanUseNET && !mCanUseHTTP) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - state > cache_post"); //nowhere to get data, abort. LL_WARNS(LOG_TXT) << mID << " abort, nowhere to get data" << LL_ENDL; return true ; @@ -1206,6 +1158,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == INIT) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - INIT"); mStateTimer.reset(); mFetchTimer.reset(); for(auto i : LOGGED_STATES) @@ -1247,15 +1200,16 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == LOAD_FROM_TEXTURE_CACHE) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - LOAD_FROM_TEXTURE_CACHE"); if (mCacheReadHandle == LLTextureCache::nullHandle()) { - U32 cache_priority = mWorkPriority; S32 offset = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0; S32 size = mDesiredSize - offset; if (size <= 0) { setState(CACHE_POST); - return false; + return doWork(param); + // return false; } mFileSize = 0; mLoaded = FALSE; @@ -1264,35 +1218,28 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mUrl.compare(0, 7, "file://") == 0) { - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it - // read file from local disk ++mCacheReadCount; std::string filename = mUrl.substr(7, std::string::npos); CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); mCacheReadTimer.reset(); - mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority, - offset, size, responder); + mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, offset, size, responder); } else if ((mUrl.empty() || mFTType==FTT_SERVER_BAKE) && mFetcher->canLoadFromCache()) { - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it - ++mCacheReadCount; CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); mCacheReadTimer.reset(); - mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, + mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, offset, size, responder);; } else if(!mUrl.empty() && mCanUseHTTP) { - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); setState(WAIT_HTTP_RESOURCE); } else { - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); setState(LOAD_FROM_NETWORK); } } @@ -1325,6 +1272,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == CACHE_POST) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - CACHE_POST"); mCachedSize = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0; // Successfully loaded if ((mCachedSize >= mDesiredSize) || mHaveAllData) @@ -1366,6 +1314,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == LOAD_FROM_NETWORK) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - LOAD_FROM_NETWORK"); // Check for retries to previous server failures. F32 wait_seconds; if (mFetchRetryPolicy.shouldRetry(wait_seconds)) @@ -1399,7 +1348,7 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (mFTType != FTT_DEFAULT) { - LL_WARNS(LOG_TXT) << "trying to seek a non-default texture on the sim. Bad!" << LL_ENDL; + LL_WARNS(LOG_TXT) << "Trying to fetch a texture of non-default type by UUID. This probably won't work!" << LL_ENDL; } setUrl(http_url + "/?texture_id=" + mID.asString().c_str()); LL_DEBUGS(LOG_TXT) << "Texture URL: " << mUrl << LL_ENDL; @@ -1427,7 +1376,6 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mCanUseHTTP && !mUrl.empty()) { setState(WAIT_HTTP_RESOURCE); - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if(mWriteToCacheState != NOT_WRITE) { mWriteToCacheState = CAN_WRITE ; @@ -1444,25 +1392,19 @@ bool LLTextureFetchWorker::doWork(S32 param) mSentRequest = QUEUED; mFetcher->addToNetworkQueue(this); recordTextureStart(false); - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - return false; } else { // Shouldn't need to do anything here - //llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end()); - // Make certain this is in the network queue - //mFetcher->addToNetworkQueue(this); - //recordTextureStart(false); - //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - + //llassert(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end()); return false; } } if (mState == LOAD_FROM_SIMULATOR) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - LOAD_FROM_SIMULATOR"); if (mFormattedImage.isNull()) { mFormattedImage = new LLImageJ2C; @@ -1492,7 +1434,7 @@ bool LLTextureFetchWorker::doWork(S32 param) LL_WARNS(LOG_TXT) << mID << " processSimulatorPackets() failed to load buffer" << LL_ENDL; return true; // failed } - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + if (mLoadedDiscard < 0) { LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard @@ -1506,7 +1448,6 @@ bool LLTextureFetchWorker::doWork(S32 param) else { mFetcher->addToNetworkQueue(this); // failsafe - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); recordTextureStart(false); } return false; @@ -1514,6 +1455,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == WAIT_HTTP_RESOURCE) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_HTTP_RESOURCE"); // NOTE: // control the number of the http requests issued for: // 1, not openning too many file descriptors at the same time; @@ -1524,7 +1466,6 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mFetcher->getHttpWaitersCount() || ! acquireHttpSemaphore()) { setState(WAIT_HTTP_RESOURCE2); - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); mFetcher->addHttpWaiter(this->mID); ++mResourceWaitCount; return false; @@ -1538,12 +1479,14 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == WAIT_HTTP_RESOURCE2) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_HTTP_RESOURCE2"); // Just idle it if we make it to the head... return false; } if (mState == SEND_HTTP_REQ) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - SEND_HTTP_REQ"); // Also used in llmeshrepository static LLCachedControl<bool> disable_range_req(gSavedSettings, "HttpRangeRequestsDisable", false); @@ -1566,7 +1509,6 @@ bool LLTextureFetchWorker::doWork(S32 param) { // We already have all the data, just decode it mLoadedDiscard = mFormattedImage->getDiscardLevel(); - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if (mLoadedDiscard < 0) { LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard @@ -1574,7 +1516,8 @@ bool LLTextureFetchWorker::doWork(S32 param) } setState(DECODE_IMAGE); releaseHttpSemaphore(); - return false; + //return false; + return doWork(param); } else { @@ -1635,7 +1578,6 @@ bool LLTextureFetchWorker::doWork(S32 param) // by people with questionable ISPs or networking gear that // doesn't handle these well. mHttpHandle = mFetcher->mHttpRequest->requestGet(mHttpPolicyClass, - mWorkPriority, mUrl, options, mFetcher->mHttpHeaders, @@ -1644,7 +1586,6 @@ bool LLTextureFetchWorker::doWork(S32 param) else { mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass, - mWorkPriority, mUrl, mRequestedOffset, (mRequestedOffset + mRequestedSize) > HTTP_REQUESTS_RANGE_END_MAX @@ -1669,7 +1610,6 @@ bool LLTextureFetchWorker::doWork(S32 param) mHttpActive = true; mFetcher->addToHTTPQueue(mID); recordTextureStart(true); - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); setState(WAIT_HTTP_REQ); // fall through @@ -1677,6 +1617,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == WAIT_HTTP_REQ) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_HTTP_REQ"); // *NOTE: As stated above, all transitions out of this state should // call releaseHttpSemaphore(). if (mLoaded) @@ -1708,9 +1649,9 @@ bool LLTextureFetchWorker::doWork(S32 param) setState(INIT); mCanUseHTTP = false; mUrl.clear(); - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); releaseHttpSemaphore(); - return false; + //return false; + return doWork(param); } } else if (http_service_unavail == mGetStatus) @@ -1730,7 +1671,7 @@ bool LLTextureFetchWorker::doWork(S32 param) << LL_ENDL; } - if (mFTType != FTT_SERVER_BAKE) + if (mFTType != FTT_SERVER_BAKE && mFTType != FTT_MAP_TILE) { mUrl.clear(); } @@ -1738,7 +1679,6 @@ bool LLTextureFetchWorker::doWork(S32 param) { // Use available data mLoadedDiscard = mFormattedImage->getDiscardLevel(); - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if (mLoadedDiscard < 0) { LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard @@ -1746,7 +1686,8 @@ bool LLTextureFetchWorker::doWork(S32 param) } setState(DECODE_IMAGE); releaseHttpSemaphore(); - return false; + //return false; + return doWork(param); } // Fail harder @@ -1863,9 +1804,9 @@ bool LLTextureFetchWorker::doWork(S32 param) { mWriteToCacheState = SHOULD_WRITE ; } - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); releaseHttpSemaphore(); - return false; + //return false; + return doWork(param); } else { @@ -1875,17 +1816,16 @@ bool LLTextureFetchWorker::doWork(S32 param) // an enormous amount of time to load textures. We'll revisit the // various possible timeout components (total request time, connection // time, I/O time, with and without retries, etc.) in the future. - - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + return false; } } if (mState == DECODE_IMAGE) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - DECODE_IMAGE"); static LLCachedControl<bool> textures_decode_disabled(gSavedSettings, "TextureDecodeDisabled", false); - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it if (textures_decode_disabled) { // for debug use, don't decode @@ -1924,25 +1864,20 @@ bool LLTextureFetchWorker::doWork(S32 param) mAuxImage = NULL; llassert_always(mFormattedImage.notNull()); S32 discard = mHaveAllData ? 0 : mLoadedDiscard; - U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority; mDecoded = FALSE; setState(DECODE_IMAGE_UPDATE); LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard << " All Data: " << mHaveAllData << LL_ENDL; - mDecodeHandle = mFetcher->mImageDecodeThread->decodeImage(mFormattedImage, image_priority, discard, mNeedsAux, + mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage, discard, mNeedsAux, new DecodeResponder(mFetcher, mID, this)); // fall though } if (mState == DECODE_IMAGE_UPDATE) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - DECODE_IMAGE_UPDATE"); if (mDecoded) { - if(mFetcher->getFetchDebugger() && !mInLocalCache) - { - mFetcher->getFetchDebugger()->addHistoryEntry(this); - } - mDecodeTime = mDecodeTimer.getElapsedTimeF32(); if (mDecodedDiscard < 0) @@ -1954,9 +1889,9 @@ bool LLTextureFetchWorker::doWork(S32 param) llassert_always(mDecodeHandle == 0); mFormattedImage = NULL; ++mRetryAttempt; - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); setState(INIT); - return false; + //return false; + return doWork(param); } else { @@ -1969,7 +1904,6 @@ bool LLTextureFetchWorker::doWork(S32 param) llassert_always(mRawImage.notNull()); LL_DEBUGS(LOG_TXT) << mID << ": Decoded. Discard: " << mDecodedDiscard << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL; - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); setState(WRITE_TO_CACHE); } // fall through @@ -1982,12 +1916,14 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == WRITE_TO_CACHE) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WRITE_TO_CACHE"); if (mWriteToCacheState != SHOULD_WRITE || mFormattedImage.isNull()) { // If we're in a local cache or we didn't actually receive any new data, // or we failed to load anything, skip setState(DONE); - return false; + //return false; + return doWork(param); } S32 datasize = mFormattedImage->getDataSize(); if(mFileSize < datasize)//This could happen when http fetching and sim fetching mixed. @@ -2002,8 +1938,6 @@ bool LLTextureFetchWorker::doWork(S32 param) } } llassert_always(datasize); - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it - U32 cache_priority = mWorkPriority; mWritten = FALSE; setState(WAIT_ON_WRITE); ++mCacheWriteCount; @@ -2014,7 +1948,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // So make sure users of getRequestFinished() does not attempt to modify image while // fetcher is working mCacheWriteTimer.reset(); - mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority, + mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, mFormattedImage->getData(), datasize, mFileSize, mRawImage, mDecodedDiscard, responder); // fall through @@ -2022,6 +1956,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == WAIT_ON_WRITE) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - WAIT_ON_WRITE"); if (writeToCacheComplete()) { mCacheWriteTime = mCacheWriteTimer.getElapsedTimeF32(); @@ -2043,6 +1978,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == DONE) { + LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("tfwdw - DONE"); if (mDecodedDiscard >= 0 && mDesiredDiscard < mDecodedDiscard) { // More data was requested, return to INIT @@ -2050,12 +1986,11 @@ bool LLTextureFetchWorker::doWork(S32 param) LL_DEBUGS(LOG_TXT) << mID << " more data requested, returning to INIT: " << " mDecodedDiscard " << mDecodedDiscard << ">= 0 && mDesiredDiscard " << mDesiredDiscard << "<" << " mDecodedDiscard " << mDecodedDiscard << LL_ENDL; - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - return false; + // return false; + return doWork(param); } else { - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); mFetchTime = mFetchTimer.getElapsedTimeF32(); return true; } @@ -2068,6 +2003,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // virtual void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) { + LL_PROFILE_ZONE_SCOPED; static LLCachedControl<bool> log_to_viewer_log(gSavedSettings, "LogTextureDownloadsToViewerLog", false); static LLCachedControl<bool> log_to_sim(gSavedSettings, "LogTextureDownloadsToSimulator", false); static LLCachedControl<bool> log_texture_traffic(gSavedSettings, "LogTextureNetworkTraffic", false) ; @@ -2177,9 +2113,10 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe // Threads: Tmain void LLTextureFetchWorker::endWork(S32 param, bool aborted) { + LL_PROFILE_ZONE_SCOPED; if (mDecodeHandle != 0) { - mFetcher->mImageDecodeThread->abortRequest(mDecodeHandle, false); + // LL::ThreadPool has no operation to cancel a particular work item mDecodeHandle = 0; } mFormattedImage = NULL; @@ -2192,6 +2129,7 @@ void LLTextureFetchWorker::endWork(S32 param, bool aborted) // virtual void LLTextureFetchWorker::finishWork(S32 param, bool completed) { + LL_PROFILE_ZONE_SCOPED; // The following are required in case the work was aborted if (mCacheReadHandle != LLTextureCache::nullHandle()) { @@ -2445,7 +2383,6 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response, } mLoaded = TRUE; - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if (LLViewerStatsRecorder::instanceExists()) { @@ -2461,6 +2398,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response, void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* image, S32 imagesize, BOOL islocal) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LLMutexLock lock(&mWorkMutex); // +Mw if (mState != LOAD_FROM_TEXTURE_CACHE) { @@ -2480,7 +2418,6 @@ void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* ima } } mLoaded = TRUE; - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); } // -Mw // Threads: Ttc @@ -2493,7 +2430,6 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success) return; } mWritten = TRUE; - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); } // -Mw ////////////////////////////////////////////////////////////////////////////// @@ -2532,7 +2468,6 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag } mDecoded = TRUE; // LL_INFOS(LOG_TXT) << mID << " : DECODE COMPLETE " << LL_ENDL; - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); } // -Mw ////////////////////////////////////////////////////////////////////////////// @@ -2595,7 +2530,17 @@ void LLTextureFetchWorker::recordTextureDone(bool is_http, F64 byte_count) ////////////////////////////////////////////////////////////////////////////// // public -LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded, bool qa_mode) +std::string LLTextureFetch::getStateString(S32 state) +{ + if (state < 0 || state > sizeof(e_state_name) / sizeof(char*)) + { + return llformat("%d", state); + } + + return e_state_name[state]; +} + +LLTextureFetch::LLTextureFetch(LLTextureCache* cache, bool threaded, bool qa_mode) : LLWorkerThread("TextureFetch", threaded, true), mDebugCount(0), mDebugPause(FALSE), @@ -2604,7 +2549,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mQueueMutex(), mNetworkQueueMutex(), mTextureCache(cache), - mImageDecodeThread(imagedecodethread), mTextureBandwidth(0), mHTTPTextureBits(0), mTotalHTTPRequests(0), @@ -2619,10 +2563,8 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mTotalCacheReadCount(0U), mTotalCacheWriteCount(0U), mTotalResourceWaitCount(0U), - mFetchDebugger(NULL), mFetchSource(LLTextureFetch::FROM_ALL), mOriginFetchSource(LLTextureFetch::FROM_ALL), - mFetcherLocked(FALSE), mTextureInfoMainThread(false) { mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); @@ -2643,21 +2585,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHttpLowWater = HTTP_NONPIPE_REQUESTS_LOW_WATER; mHttpSemaphore = 0; - // Conditionally construct debugger object after 'this' is - // fully initialized. - LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"); - if(LLTextureFetchDebugger::isEnabled()) - { - mFetchDebugger = new LLTextureFetchDebugger(this, cache, imagedecodethread) ; - mFetchSource = (e_tex_source)gSavedSettings.getS32("TextureFetchSource"); - if(mFetchSource < 0 && mFetchSource >= INVALID_SOURCE) - { - mFetchSource = LLTextureFetch::FROM_ALL; - gSavedSettings.setS32("TextureFetchSource", 0); - } - mOriginFetchSource = mFetchSource; - } - // If that test log has ben requested but not yet created, create it if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) { @@ -2686,19 +2613,13 @@ LLTextureFetch::~LLTextureFetch() delete mHttpRequest; mHttpRequest = NULL; - delete mFetchDebugger; - mFetchDebugger = NULL; - // ~LLQueuedThread() called here } bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http) { - if(mFetcherLocked) - { - return false; - } + LL_PROFILE_ZONE_SCOPED; if (mDebugPause) { return false; @@ -2773,6 +2694,11 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const return false; // need to wait for previous aborted request to complete } worker->lockWorkMutex(); // +Mw + if (worker->mState == LLTextureFetchWorker::DONE && worker->mDesiredSize == llmax(desired_size, TEXTURE_CACHE_ENTRY_SIZE) && worker->mDesiredDiscard == desired_discard) { + worker->unlockWorkMutex(); // -Mw + + return false; // similar request has failed or is in a transitional state + } worker->mActiveCount++; worker->mNeedsAux = needs_aux; worker->setImagePriority(priority); @@ -2786,7 +2712,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const worker->setState(LLTextureFetchWorker::INIT); worker->unlockWorkMutex(); // -Mw - worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); + worker->addWork(0); } else { @@ -2818,6 +2744,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const // protected void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) { + LL_PROFILE_ZONE_SCOPED; lockQueue(); // +Mfq bool in_request_map = (mRequestMap.find(worker->mID) != mRequestMap.end()) ; unlockQueue(); // -Mfq @@ -2839,6 +2766,7 @@ void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) // Threads: T* void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel) { + LL_PROFILE_ZONE_SCOPED; LLMutexLock lock(&mNetworkQueueMutex); // +Mfnq size_t erased = mNetworkQueue.erase(worker->mID); if (cancel && erased > 0) @@ -2852,6 +2780,7 @@ void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool c // protected void LLTextureFetch::addToHTTPQueue(const LLUUID& id) { + LL_PROFILE_ZONE_SCOPED; LLMutexLock lock(&mNetworkQueueMutex); // +Mfnq mHTTPTextureQueue.insert(id); mTotalHTTPRequests++; @@ -2860,6 +2789,7 @@ void LLTextureFetch::addToHTTPQueue(const LLUUID& id) // Threads: T* void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32Bytes received_size) { + LL_PROFILE_ZONE_SCOPED; LLMutexLock lock(&mNetworkQueueMutex); // +Mfnq mHTTPTextureQueue.erase(id); mHTTPTextureBits += received_size; // Approximate - does not include header bits @@ -2872,6 +2802,7 @@ void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32Bytes received_siz // Threads: T* void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) { + LL_PROFILE_ZONE_SCOPED; lockQueue(); // +Mfq LLTextureFetchWorker* worker = getWorkerAfterLock(id); if (worker) @@ -2898,6 +2829,7 @@ void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) // Threads: T* void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel) { + LL_PROFILE_ZONE_SCOPED; if(!worker) { return; @@ -2967,6 +2899,7 @@ U32 LLTextureFetch::getTotalNumHTTPRequests() // Locks: Mfq LLTextureFetchWorker* LLTextureFetch::getWorkerAfterLock(const LLUUID& id) { + LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* res = NULL; map_t::iterator iter = mRequestMap.find(id); if (iter != mRequestMap.end()) @@ -2990,6 +2923,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux, LLCore::HttpStatus& last_http_get_status) { + LL_PROFILE_ZONE_SCOPED; bool res = false; LLTextureFetchWorker* worker = getWorker(id); if (worker) @@ -3004,7 +2938,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, if (!mDebugPause) { // LL_WARNS(LOG_TXT) << "Adding work for inactive worker: " << id << LL_ENDL; - worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); + worker->addWork(0); } } else if (worker->checkWork()) @@ -3080,16 +3014,19 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, // Threads: T* bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) { - bool res = false; - LLTextureFetchWorker* worker = getWorker(id); - if (worker) - { - worker->lockWorkMutex(); // +Mw - worker->setImagePriority(priority); - worker->unlockWorkMutex(); // -Mw - res = true; - } - return res; + LL_PROFILE_ZONE_SCOPED; + mRequestQueue.tryPost([=]() + { + LLTextureFetchWorker* worker = getWorker(id); + if (worker) + { + worker->lockWorkMutex(); // +Mw + worker->setImagePriority(priority); + worker->unlockWorkMutex(); // -Mw + } + }); + + return true; } // Replicates and expands upon the base class's @@ -3106,6 +3043,7 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) //virtual S32 LLTextureFetch::getPending() { + LL_PROFILE_ZONE_SCOPED; S32 res; lockData(); // +Ct { @@ -3139,7 +3077,7 @@ bool LLTextureFetch::runCondition() } // -Mfq return ! (have_no_commands - && (mRequestQueue.empty() && mIdleThread)); // From base class + && (mRequestQueue.size() == 0 && mIdleThread)); // From base class } ////////////////////////////////////////////////////////////////////////////// @@ -3147,6 +3085,7 @@ bool LLTextureFetch::runCondition() // Threads: Ttf void LLTextureFetch::commonUpdate() { + LL_PROFILE_ZONE_SCOPED; // Update low/high water levels based on pipelining. We pick // up setting eventually, so the semaphore/request level can // fall outside the [0..HIGH_WATER] range. Expect that. @@ -3183,6 +3122,7 @@ void LLTextureFetch::commonUpdate() //virtual S32 LLTextureFetch::update(F32 max_time_ms) { + LL_PROFILE_ZONE_SCOPED; static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS", 3000.0); { @@ -3213,11 +3153,6 @@ S32 LLTextureFetch::update(F32 max_time_ms) commonUpdate(); } - if (mFetchDebugger) - { - mFetchDebugger->tryToStopDebug(); //check if need to stop debugger. - } - return res; } @@ -3233,18 +3168,6 @@ void LLTextureFetch::shutDownTextureCacheThread() } } -// called in the MAIN thread after the ImageDecodeThread shuts down. -// -// Threads: Tmain -void LLTextureFetch::shutDownImageDecodeThread() -{ - if(mImageDecodeThread) - { - llassert_always(mImageDecodeThread->isQuitting() || mImageDecodeThread->isStopped()) ; - mImageDecodeThread = NULL ; - } -} - // Threads: Ttf void LLTextureFetch::startThread() { @@ -3266,6 +3189,7 @@ void LLTextureFetch::endThread() // Threads: Ttf void LLTextureFetch::threadedUpdate() { + LL_PROFILE_ZONE_SCOPED; llassert_always(mHttpRequest); #if 0 @@ -3301,6 +3225,7 @@ void LLTextureFetch::threadedUpdate() // Threads: Tmain void LLTextureFetch::sendRequestListToSimulators() { + LL_PROFILE_ZONE_SCOPED; // All requests const F32 REQUEST_DELTA_TIME = 0.10f; // 10 fps @@ -3351,7 +3276,6 @@ void LLTextureFetch::sendRequestListToSimulators() req->mLastPacket >= req->mTotalPackets-1) { // We have all the packets... make sure this is high priority -// req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority); continue; } F32 elapsed = req->mRequestedDeltaTimer.getElapsedTimeF32(); @@ -3499,6 +3423,7 @@ void LLTextureFetch::sendRequestListToSimulators() // Locks: Mw bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) { + LL_PROFILE_ZONE_SCOPED; mRequestedDeltaTimer.reset(); if (index >= mTotalPackets) { @@ -3531,6 +3456,7 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) void LLTextureFetchWorker::setState(e_state new_state) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (mFTType == FTT_SERVER_BAKE) { // NOTE: turning on these log statements is a reliable way to get @@ -3552,7 +3478,7 @@ void LLTextureFetchWorker::setState(e_state new_state) mSkippedStatesTime += d_time; } } - + mStateTimer.reset(); mState = new_state; } @@ -3561,6 +3487,7 @@ void LLTextureFetchWorker::setState(e_state new_state) bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data) { + LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* worker = getWorker(id); bool res = true; @@ -3612,7 +3539,6 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 llassert_always(totalbytes > 0); llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize); res = worker->insertPacket(0, data, data_size); - worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); worker->setState(LLTextureFetchWorker::LOAD_FROM_SIMULATOR); worker->unlockWorkMutex(); // -Mw return res; @@ -3622,6 +3548,7 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 // Threads: T* bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data) { + LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* worker = getWorker(id); bool res = true; @@ -3662,7 +3589,6 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 if ((worker->mState == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) || (worker->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK)) { - worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); worker->setState(LLTextureFetchWorker::LOAD_FROM_SIMULATOR); } else @@ -3707,10 +3633,23 @@ BOOL LLTextureFetch::isFromLocalCache(const LLUUID& id) return from_cache ; } +S32 LLTextureFetch::getFetchState(const LLUUID& id) +{ + S32 state = LLTextureFetchWorker::INVALID; + LLTextureFetchWorker* worker = getWorker(id); + if (worker && worker->haveWork()) + { + state = worker->mState; + } + + return state; +} + // Threads: T* S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& requested_priority_p, U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http) { + LL_PROFILE_ZONE_SCOPED; S32 state = LLTextureFetchWorker::INVALID; F32 data_progress = 0.0f; F32 requested_priority = 0.0f; @@ -3746,7 +3685,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r { requested_priority = worker->mImagePriority; } - fetch_priority = worker->getPriority(); + fetch_priority = worker->getImagePriority(); can_use_http = worker->getCanUseHTTP() ; worker->unlockWorkMutex(); // -Mw } @@ -3760,19 +3699,6 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r void LLTextureFetch::dump() { - LL_INFOS(LOG_TXT) << "LLTextureFetch REQUESTS:" << LL_ENDL; - for (request_queue_t::iterator iter = mRequestQueue.begin(); - iter != mRequestQueue.end(); ++iter) - { - LLQueuedThread::QueuedRequest* qreq = *iter; - LLWorkerThread::WorkRequest* wreq = (LLWorkerThread::WorkRequest*)qreq; - LLTextureFetchWorker* worker = (LLTextureFetchWorker*)wreq->getWorkerClass(); - LL_INFOS(LOG_TXT) << " ID: " << worker->mID - << " PRI: " << llformat("0x%08x",wreq->getPriority()) - << " STATE: " << sStateDescs[worker->mState] - << LL_ENDL; - } - LL_INFOS(LOG_TXT) << "LLTextureFetch ACTIVE_HTTP:" << LL_ENDL; for (queue_t::const_iterator iter(mHTTPTextureQueue.begin()); mHTTPTextureQueue.end() != iter; @@ -3839,6 +3765,7 @@ bool LLTextureFetch::isHttpWaiter(const LLUUID & tid) // Locks: -Mw (must not hold any worker when called) void LLTextureFetch::releaseHttpWaiters() { + LL_PROFILE_ZONE_SCOPED; // Use mHttpSemaphore rather than mHTTPTextureQueue.size() // to avoid a lock. if (mHttpSemaphore >= mHttpLowWater) @@ -3935,7 +3862,6 @@ void LLTextureFetch::releaseHttpWaiters() } worker->setState(LLTextureFetchWorker::SEND_HTTP_REQ); - worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); worker->unlockWorkMutex(); // -Mw removeHttpWaiter(worker->mID); @@ -4025,6 +3951,7 @@ void LLTextureFetch::commandDataBreak() // Threads: T* void LLTextureFetch::cmdEnqueue(TFRequest * req) { + LL_PROFILE_ZONE_SCOPED; lockQueue(); // +Mfq mCommands.push_back(req); unlockQueue(); // -Mfq @@ -4035,6 +3962,7 @@ void LLTextureFetch::cmdEnqueue(TFRequest * req) // Threads: T* LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue() { + LL_PROFILE_ZONE_SCOPED; TFRequest * ret = 0; lockQueue(); // +Mfq @@ -4051,6 +3979,7 @@ LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue() // Threads: Ttf void LLTextureFetch::cmdDoWork() { + LL_PROFILE_ZONE_SCOPED; if (mDebugPause) { return; // debug: don't do any work @@ -4141,7 +4070,7 @@ TFReqSendMetrics::~TFReqSendMetrics() bool TFReqSendMetrics::doWork(LLTextureFetch * fetcher) { - static const U32 report_priority(1); + LL_PROFILE_ZONE_SCOPED; //if (! gViewerAssetStatsThread1) // return true; @@ -4184,7 +4113,6 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) // Don't care about handle, this is a fire-and-forget operation. LLCoreHttpUtil::requestPostWithLLSD(&fetcher->getHttpRequest(), fetcher->getMetricsPolicyClass(), - report_priority, mCapsURL, mStatsSD, LLCore::HttpOptions::ptr_t(), @@ -4246,971 +4174,6 @@ truncate_viewer_metrics(int max_regions, LLSD & metrics) } // end of anonymous namespace - -/////////////////////////////////////////////////////////////////////////////////////////// -//Start LLTextureFetchDebugger -/////////////////////////////////////////////////////////////////////////////////////////// -//--------------------- -class LLDebuggerCacheReadResponder : public LLTextureCache::ReadResponder -{ -public: - LLDebuggerCacheReadResponder(LLTextureFetchDebugger* debugger, S32 id, LLImageFormatted* image) - : mDebugger(debugger), mID(id) - { - setImage(image); - } - virtual void completed(bool success) - { - mDebugger->callbackCacheRead(mID, success, mFormattedImage, mImageSize, mImageLocal); - } -private: - LLTextureFetchDebugger* mDebugger; - S32 mID; -}; - -class LLDebuggerCacheWriteResponder : public LLTextureCache::WriteResponder -{ -public: - LLDebuggerCacheWriteResponder(LLTextureFetchDebugger* debugger, S32 id) - : mDebugger(debugger), mID(id) - { - } - virtual void completed(bool success) - { - mDebugger->callbackCacheWrite(mID, success); - } -private: - LLTextureFetchDebugger* mDebugger; - S32 mID; -}; - -class LLDebuggerDecodeResponder : public LLImageDecodeThread::Responder -{ -public: - LLDebuggerDecodeResponder(LLTextureFetchDebugger* debugger, S32 id) - : mDebugger(debugger), mID(id) - { - } - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) - { - mDebugger->callbackDecoded(mID, success, raw, aux); - } -private: - LLTextureFetchDebugger* mDebugger; - S32 mID; -}; - - -LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) : - LLCore::HttpHandler(), - mFetcher(fetcher), - mTextureCache(cache), - mImageDecodeThread(imagedecodethread), - mHttpHeaders(), - mHttpPolicyClass(fetcher->getPolicyClass()), - mNbCurlCompleted(0), - mTempIndex(0), - mHistoryListIndex(0) -{ - init(); -} - -LLTextureFetchDebugger::~LLTextureFetchDebugger() -{ - mFetchingHistory.clear(); - mStopDebug = TRUE; - tryToStopDebug(); -} - -void LLTextureFetchDebugger::init() -{ - setDebuggerState(IDLE); - - mCacheReadTime = -1.f; - mCacheWriteTime = -1.f; - mDecodingTime = -1.f; - mHTTPTime = -1.f; - mGLCreationTime = -1.f; - - mTotalFetchingTime = 0.f; - mRefetchVisCacheTime = -1.f; - mRefetchVisHTTPTime = -1.f; - mRefetchAllCacheTime = -1.f; - mRefetchAllHTTPTime = -1.f; - - mNumFetchedTextures = 0; - mNumCacheHits = 0; - mNumVisibleFetchedTextures = 0; - mNumVisibleFetchingRequests = 0; - mFetchedData = 0; - mDecodedData = 0; - mVisibleFetchedData = 0; - mVisibleDecodedData = 0; - mRenderedData = 0; - mRenderedDecodedData = 0; - mFetchedPixels = 0; - mRenderedPixels = 0; - mRefetchedVisData = 0; - mRefetchedVisPixels = 0; - mRefetchedAllData = 0; - mRefetchedAllPixels = 0; - - mFreezeHistory = FALSE; - mStopDebug = FALSE; - mClearHistory = FALSE; - mRefetchNonVis = FALSE; - - mNbCurlRequests = 0; - - if (! mHttpHeaders) - { - mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders); - mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C); - } -} - -void LLTextureFetchDebugger::startWork(e_debug_state state) -{ - switch(state) - { - case IDLE: - break; - case START_DEBUG: - startDebug(); - break; - case READ_CACHE: - debugCacheRead(); - break; - case WRITE_CACHE: - debugCacheWrite(); - break; - case DECODING: - debugDecoder(); - break; - case HTTP_FETCHING: - debugHTTP(); - break; - case GL_TEX: - debugGLTextureCreation(); - break; - case REFETCH_VIS_CACHE: - debugRefetchVisibleFromCache(); - break; - case REFETCH_VIS_HTTP: - debugRefetchVisibleFromHTTP(); - break; - case REFETCH_ALL_CACHE: - debugRefetchAllFromCache(); - break; - case REFETCH_ALL_HTTP: - debugRefetchAllFromHTTP(); - break; - default: - break; - } - return; -} - -void LLTextureFetchDebugger::startDebug() -{ - //lock the fetcher - mFetcher->lockFetcher(true); - mFreezeHistory = TRUE; - mFetcher->resetLoadSource(); - - //clear the current fetching queue - gTextureList.clearFetchingRequests(); - - setDebuggerState(START_DEBUG); -} - -bool LLTextureFetchDebugger::processStartDebug(F32 max_time) -{ - mTimer.reset(); - - //wait for all works to be done - while(1) - { - S32 pending = 0; - pending += LLAppViewer::getTextureCache()->update(1); - pending += LLAppViewer::getImageDecodeThread()->update(1); - // pending += LLAppViewer::getTextureFetch()->update(1); // This causes infinite recursion in some cases - pending += mNbCurlRequests; - if(!pending) - { - break; - } - - if(mTimer.getElapsedTimeF32() > max_time) - { - return false; - } - } - - //collect statistics - mTotalFetchingTime = gTextureTimer.getElapsedTimeF32() - mTotalFetchingTime; - - std::set<LLUUID> fetched_textures; - S32 size = mFetchingHistory.size(); - for(S32 i = 0 ; i < size; i++) - { - bool in_list = true; - if(fetched_textures.find(mFetchingHistory[i].mID) == fetched_textures.end()) - { - fetched_textures.insert(mFetchingHistory[i].mID); - in_list = false; - } - - std::vector<LLViewerFetchedTexture*> textures; - LLViewerTextureManager::findFetchedTextures(mFetchingHistory[i].mID, textures); - std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin(); - while (iter != textures.end()) - { - LLViewerFetchedTexture* tex = *iter++; - // fetched data will be counted for both ui and regular elements - if (tex && tex->isJustBound()) //visible - { - if (!in_list) - { - mNumVisibleFetchedTextures++; - } - mNumVisibleFetchingRequests++; - - mVisibleFetchedData += mFetchingHistory[i].mFetchedSize; - mVisibleDecodedData += mFetchingHistory[i].mDecodedSize; - - if (tex->getDiscardLevel() >= mFetchingHistory[i].mDecodedLevel) - { - mRenderedData += mFetchingHistory[i].mFetchedSize; - mRenderedDecodedData += mFetchingHistory[i].mDecodedSize; - mRenderedPixels += tex->getWidth() * tex->getHeight(); - } - } - } - } - - mNumFetchedTextures = fetched_textures.size(); - - return true; -} - -void LLTextureFetchDebugger::tryToStopDebug() -{ - if(!mStopDebug) - { - return; - } - - //clear the current debug work - S32 size = mFetchingHistory.size(); - switch(mDebuggerState) - { - case READ_CACHE: - for(S32 i = 0 ; i < size; i++) - { - if (mFetchingHistory[i]. mCacheHandle != LLTextureCache::nullHandle()) - { - mTextureCache->readComplete(mFetchingHistory[i].mCacheHandle, true); - } - } - break; - case WRITE_CACHE: - for(S32 i = 0 ; i < size; i++) - { - if (mFetchingHistory[i].mCacheHandle != LLTextureCache::nullHandle()) - { - mTextureCache->writeComplete(mFetchingHistory[i].mCacheHandle, true); - } - } - break; - case DECODING: - break; - case HTTP_FETCHING: - break; - case GL_TEX: - break; - case REFETCH_VIS_CACHE: - break; - case REFETCH_VIS_HTTP: - break; - case REFETCH_ALL_CACHE: - mRefetchList.clear(); - break; - case REFETCH_ALL_HTTP: - mRefetchList.clear(); - break; - default: - break; - } - - if(update(0.005f)) - { - //unlock the fetcher - mFetcher->lockFetcher(false); - mFetcher->resetLoadSource(); - mFreezeHistory = FALSE; - mStopDebug = FALSE; - - if(mClearHistory) - { - mFetchingHistory.clear(); - mHandleToFetchIndex.clear(); - init(); - mTotalFetchingTime = gTextureTimer.getElapsedTimeF32(); //reset - } - } -} - -//called in the main thread and when the fetching queue is empty -void LLTextureFetchDebugger::clearHistory() -{ - mClearHistory = TRUE; -} - -void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker) -{ - if(worker->mRawImage.isNull() || worker->mFormattedImage.isNull()) - { - return; - } - - if(mFreezeHistory) - { - if(mDebuggerState == REFETCH_VIS_CACHE || mDebuggerState == REFETCH_VIS_HTTP) - { - mRefetchedVisPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); - mRefetchedVisData += worker->mFormattedImage->getDataSize(); - } - else - { - mRefetchedAllPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); - mRefetchedAllData += worker->mFormattedImage->getDataSize(); - - // refetch list only requests/creates normal images, so requesting ui='false' - LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(worker->mID, TEX_LIST_STANDARD); - if(tex && mRefetchList[tex].begin() != mRefetchList[tex].end()) - { - if(worker->mDecodedDiscard == mFetchingHistory[mRefetchList[tex][0]].mDecodedLevel) - { - mRefetchList[tex].erase(mRefetchList[tex].begin()); - } - } - } - return; - } - - if(worker->mInCache) - { - mNumCacheHits++; - } - mFetchedData += worker->mFormattedImage->getDataSize(); - mDecodedData += worker->mRawImage->getDataSize(); - mFetchedPixels += worker->mRawImage->getWidth() * worker->mRawImage->getHeight(); - - mFetchingHistory.push_back(FetchEntry(worker->mID, worker->mDesiredSize, worker->mDecodedDiscard, - worker->mFormattedImage->getDataSize(), worker->mRawImage->getDataSize())); -} - -void LLTextureFetchDebugger::lockCache() -{ -} - -void LLTextureFetchDebugger::unlockCache() -{ -} - -void LLTextureFetchDebugger::debugCacheRead() -{ - lockCache(); - llassert_always(mDebuggerState == IDLE); - mTimer.reset(); - setDebuggerState(READ_CACHE); - mCacheReadTime = -1.f; - - S32 size = mFetchingHistory.size(); - for(S32 i = 0 ; i < size ; i++) - { - mFetchingHistory[i].mFormattedImage = NULL; - mFetchingHistory[i].mCacheHandle = mTextureCache->readFromCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, 0, mFetchingHistory[i].mFetchedSize, - new LLDebuggerCacheReadResponder(this, i, mFetchingHistory[i].mFormattedImage)); - } -} - -void LLTextureFetchDebugger::clearCache() -{ - S32 size = mFetchingHistory.size(); - { - std::set<LLUUID> deleted_list; - for(S32 i = 0 ; i < size ; i++) - { - if(deleted_list.find(mFetchingHistory[i].mID) == deleted_list.end()) - { - deleted_list.insert(mFetchingHistory[i].mID); - mTextureCache->removeFromCache(mFetchingHistory[i].mID); - } - } - } -} - -void LLTextureFetchDebugger::debugCacheWrite() -{ - //remove from cache - clearCache(); - - lockCache(); - llassert_always(mDebuggerState == IDLE); - mTimer.reset(); - setDebuggerState(WRITE_CACHE); - mCacheWriteTime = -1.f; - - S32 size = mFetchingHistory.size(); - for(S32 i = 0 ; i < size ; i++) - { - if(mFetchingHistory[i].mFormattedImage.notNull()) - { - mFetchingHistory[i].mCacheHandle = mTextureCache->writeToCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL, - mFetchingHistory[i].mFormattedImage->getData(), mFetchingHistory[i].mFetchedSize, - mFetchingHistory[i].mDecodedLevel == 0 ? mFetchingHistory[i].mFetchedSize : mFetchingHistory[i].mFetchedSize + 1, - NULL, 0, new LLDebuggerCacheWriteResponder(this, i)); - } - } -} - -void LLTextureFetchDebugger::lockDecoder() -{ -} - -void LLTextureFetchDebugger::unlockDecoder() -{ -} - -void LLTextureFetchDebugger::debugDecoder() -{ - lockDecoder(); - llassert_always(mDebuggerState == IDLE); - mTimer.reset(); - setDebuggerState(DECODING); - mDecodingTime = -1.f; - - S32 size = mFetchingHistory.size(); - for(S32 i = 0 ; i < size ; i++) - { - if(mFetchingHistory[i].mFormattedImage.isNull()) - { - continue; - } - - mImageDecodeThread->decodeImage(mFetchingHistory[i].mFormattedImage, LLWorkerThread::PRIORITY_NORMAL, - mFetchingHistory[i].mDecodedLevel, mFetchingHistory[i].mNeedsAux, - new LLDebuggerDecodeResponder(this, i)); - } -} - -void LLTextureFetchDebugger::debugHTTP() -{ - llassert_always(mDebuggerState == IDLE); - - LLViewerRegion* region = gAgent.getRegion(); - if (!region) - { - LL_INFOS(LOG_TXT) << "Fetch Debugger : Current region undefined. Cannot fetch textures through HTTP." << LL_ENDL; - return; - } - - mHTTPUrl = region->getViewerAssetUrl(); - if (mHTTPUrl.empty()) - { - LL_INFOS(LOG_TXT) << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << LL_ENDL; - return; - } - - mTimer.reset(); - setDebuggerState(HTTP_FETCHING); - mHTTPTime = -1.f; - - S32 size = mFetchingHistory.size(); - for (S32 i = 0 ; i < size ; i++) - { - mFetchingHistory[i].mCurlState = FetchEntry::CURL_NOT_DONE; - mFetchingHistory[i].mCurlReceivedSize = 0; - mFetchingHistory[i].mFormattedImage = NULL; - } - mNbCurlRequests = 0; - mNbCurlCompleted = 0; - - fillCurlQueue(); -} - -S32 LLTextureFetchDebugger::fillCurlQueue() -{ - if(mStopDebug) //stop - { - mNbCurlCompleted = mFetchingHistory.size(); - return 0; - } - if (mNbCurlRequests > HTTP_NONPIPE_REQUESTS_LOW_WATER) - { - return mNbCurlRequests; - } - - S32 size = mFetchingHistory.size(); - for (S32 i = 0 ; i < size ; i++) - { - if (mFetchingHistory[i].mCurlState != FetchEntry::CURL_NOT_DONE) - { - continue; - } - std::string texture_url = mHTTPUrl + "/?texture_id=" + mFetchingHistory[i].mID.asString().c_str(); - S32 requestedSize = mFetchingHistory[i].mRequestedSize; - // We request the whole file if the size was not set. - requestedSize = llmax(0,requestedSize); - // We request the whole file if the size was set to an absurdly high value (meaning all file) - requestedSize = (requestedSize == 33554432 ? 0 : requestedSize); - - LLCore::HttpHandle handle = mFetcher->getHttpRequest().requestGetByteRange(mHttpPolicyClass, - LLWorkerThread::PRIORITY_LOWBITS, - texture_url, - 0, - requestedSize, - LLCore::HttpOptions::ptr_t(), - mHttpHeaders, - LLCore::HttpHandler::ptr_t(this, &NoOpDeletor)); - if (LLCORE_HTTP_HANDLE_INVALID != handle) - { - mHandleToFetchIndex[handle] = i; - mFetchingHistory[i].mHttpHandle = handle; - mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS; - mNbCurlRequests++; - if (mNbCurlRequests >= HTTP_NONPIPE_REQUESTS_HIGH_WATER) // emulate normal pipeline - { - break; - } - } - else - { - // Failed to queue request, log it and mark it done. - LLCore::HttpStatus status(mFetcher->getHttpRequest().getStatus()); - - LL_WARNS(LOG_TXT) << "Couldn't issue HTTP request in debugger for texture " - << mFetchingHistory[i].mID - << ", status: " << status.toTerseString() - << " reason: " << status.toString() - << LL_ENDL; - mFetchingHistory[i].mCurlState = FetchEntry::CURL_DONE; - } - } - //LL_INFOS(LOG_TXT) << "Fetch Debugger : Having " << mNbCurlRequests << " requests through the curl thread." << LL_ENDL; - return mNbCurlRequests; -} - -void LLTextureFetchDebugger::debugGLTextureCreation() -{ - llassert_always(mDebuggerState == IDLE); - setDebuggerState(GL_TEX); - mTempTexList.clear(); - - S32 size = mFetchingHistory.size(); - for(S32 i = 0 ; i < size ; i++) - { - if(mFetchingHistory[i].mRawImage.notNull()) - { - std::vector<LLViewerFetchedTexture*> textures; - gTextureList.findTexturesByID(mFetchingHistory[i].mID, textures); - std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin(); - while (iter != textures.end()) - { - LLViewerFetchedTexture* tex = *iter++; - if (tex && !tex->isForSculptOnly()) - { - tex->destroyGLTexture(); - mTempTexList.push_back(tex); - } - } - } - } - - mGLCreationTime = -1.f; - mTempIndex = 0; - mHistoryListIndex = 0; - - return; -} - -bool LLTextureFetchDebugger::processGLCreation(F32 max_time) -{ - mTimer.reset(); - - bool done = true; - S32 size = mFetchingHistory.size(); - S32 size1 = mTempTexList.size(); - for(; mHistoryListIndex < size && mTempIndex < size1; mHistoryListIndex++) - { - if(mFetchingHistory[mHistoryListIndex].mRawImage.notNull()) - { - if(mFetchingHistory[mHistoryListIndex].mID == mTempTexList[mTempIndex]->getID()) - { - mTempTexList[mTempIndex]->createGLTexture(mFetchingHistory[mHistoryListIndex].mDecodedLevel, - mFetchingHistory[mHistoryListIndex].mRawImage, 0, TRUE, mTempTexList[mTempIndex]->getBoostLevel()); - mTempIndex++; - } - } - - if(mTimer.getElapsedTimeF32() > max_time) - { - done = false; - break; - } - } - - if(mGLCreationTime < 0.f) - { - mGLCreationTime = mTimer.getElapsedTimeF32() ; - } - else - { - mGLCreationTime += mTimer.getElapsedTimeF32() ; - } - - return done; -} - -//clear fetching results of all textures. -void LLTextureFetchDebugger::clearTextures() -{ - S32 size = mFetchingHistory.size(); - for(S32 i = 0 ; i < size ; i++) - { - std::vector<LLViewerFetchedTexture*> textures; - gTextureList.findTexturesByID(mFetchingHistory[i].mID, textures); - std::vector<LLViewerFetchedTexture*>::iterator iter = textures.begin(); - while (iter != textures.end()) - { - LLViewerFetchedTexture* tex = *iter++; - if (tex) - { - tex->clearFetchedResults(); - } - } - } -} - -void LLTextureFetchDebugger::makeRefetchList() -{ - mRefetchList.clear(); - S32 size = mFetchingHistory.size(); - for(S32 i = 0 ; i < size; i++) - { - LLViewerFetchedTexture* tex = LLViewerTextureManager::getFetchedTexture(mFetchingHistory[i].mID); - if(tex && tex->isJustBound()) //visible - { - continue; //the texture fetch pipeline will take care of visible textures. - } - - // todo: Will attempt to refetch icons and ui elements as normal images (boost_none) - // thus will create unnecessary LLViewerFetchedTexture, consider supporting separate UI textures - mRefetchList[tex].push_back(i); - } -} - -void LLTextureFetchDebugger::scanRefetchList() -{ - if(mStopDebug) - { - return; - } - if(!mRefetchNonVis) - { - return; - } - - for(std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> >::iterator iter = mRefetchList.begin(); - iter != mRefetchList.end(); ) - { - if(iter->second.empty()) - { - gTextureList.setDebugFetching(iter->first, -1); - mRefetchList.erase(iter++); // This is the correct method to "erase and move on" in an std::map - } - else - { - gTextureList.setDebugFetching(iter->first, mFetchingHistory[iter->second[0]].mDecodedLevel); - ++iter; - } - } -} - -void LLTextureFetchDebugger::debugRefetchVisibleFromCache() -{ - llassert_always(mDebuggerState == IDLE); - setDebuggerState(REFETCH_VIS_CACHE); - - clearTextures(); - mFetcher->setLoadSource(LLTextureFetch::FROM_ALL); - - mTimer.reset(); - mFetcher->lockFetcher(false); - mRefetchVisCacheTime = -1.f; - mRefetchedVisData = 0; - mRefetchedVisPixels = 0; -} - -void LLTextureFetchDebugger::debugRefetchVisibleFromHTTP() -{ - llassert_always(mDebuggerState == IDLE); - setDebuggerState(REFETCH_VIS_HTTP); - - clearTextures(); - mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY); - - mTimer.reset(); - mFetcher->lockFetcher(false); - mRefetchVisHTTPTime = -1.f; - mRefetchedVisData = 0; - mRefetchedVisPixels = 0; -} - -void LLTextureFetchDebugger::debugRefetchAllFromCache() -{ - llassert_always(mDebuggerState == IDLE); - setDebuggerState(REFETCH_ALL_CACHE); - - clearTextures(); - makeRefetchList(); - mFetcher->setLoadSource(LLTextureFetch::FROM_ALL); - - mTimer.reset(); - mFetcher->lockFetcher(false); - mRefetchAllCacheTime = -1.f; - mRefetchedAllData = 0; - mRefetchedAllPixels = 0; - mRefetchNonVis = FALSE; -} - -void LLTextureFetchDebugger::debugRefetchAllFromHTTP() -{ - llassert_always(mDebuggerState == IDLE); - setDebuggerState(REFETCH_ALL_HTTP); - - clearTextures(); - makeRefetchList(); - mFetcher->setLoadSource(LLTextureFetch::FROM_HTTP_ONLY); - - mTimer.reset(); - mFetcher->lockFetcher(false); - mRefetchAllHTTPTime = -1.f; - mRefetchedAllData = 0; - mRefetchedAllPixels = 0; - mRefetchNonVis = TRUE; -} - -bool LLTextureFetchDebugger::update(F32 max_time) -{ - switch(mDebuggerState) - { - case START_DEBUG: - if(processStartDebug(max_time)) - { - setDebuggerState(IDLE); - } - break; - case READ_CACHE: - if(!mTextureCache->update(1)) - { - mCacheReadTime = mTimer.getElapsedTimeF32() ; - setDebuggerState(IDLE); - unlockCache(); - } - break; - case WRITE_CACHE: - if(!mTextureCache->update(1)) - { - mCacheWriteTime = mTimer.getElapsedTimeF32() ; - setDebuggerState(IDLE); - unlockCache(); - } - break; - case DECODING: - if(!mImageDecodeThread->update(1)) - { - mDecodingTime = mTimer.getElapsedTimeF32() ; - setDebuggerState(IDLE); - unlockDecoder(); - } - break; - case HTTP_FETCHING: - // Do some notifications... - mFetcher->getHttpRequest().update(10); - if (!fillCurlQueue() && mNbCurlCompleted == mFetchingHistory.size()) - { - mHTTPTime = mTimer.getElapsedTimeF32() ; - setDebuggerState(IDLE); - } - break; - case GL_TEX: - if(processGLCreation(max_time)) - { - setDebuggerState(IDLE); - mTempTexList.clear(); - } - break; - case REFETCH_VIS_CACHE: - if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) - { - mRefetchVisCacheTime = mTimer.getElapsedTimeF32() ; - setDebuggerState(IDLE); - mFetcher->lockFetcher(true); - mFetcher->resetLoadSource(); - } - break; - case REFETCH_VIS_HTTP: - if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) - { - mRefetchVisHTTPTime = mTimer.getElapsedTimeF32() ; - setDebuggerState(IDLE); - mFetcher->lockFetcher(true); - mFetcher->resetLoadSource(); - } - break; - case REFETCH_ALL_CACHE: - scanRefetchList(); - if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) - { - if(!mRefetchNonVis) - { - mRefetchNonVis = TRUE; //start to fetch non-vis - scanRefetchList(); - break; - } - - mRefetchAllCacheTime = mTimer.getElapsedTimeF32() ; - setDebuggerState(IDLE); - mFetcher->lockFetcher(true); - mFetcher->resetLoadSource(); - mRefetchList.clear(); - mRefetchNonVis = FALSE; - } - break; - case REFETCH_ALL_HTTP: - scanRefetchList(); - if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) - { - mRefetchAllHTTPTime = mTimer.getElapsedTimeF32() ; - setDebuggerState(IDLE); - mFetcher->lockFetcher(true); - mFetcher->resetLoadSource(); - mRefetchList.clear(); - mRefetchNonVis = FALSE; - } - break; - default: - setDebuggerState(IDLE); - break; - } - - return mDebuggerState == IDLE; -} - -void LLTextureFetchDebugger::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) -{ - handle_fetch_map_t::iterator iter(mHandleToFetchIndex.find(handle)); - if (mHandleToFetchIndex.end() == iter) - { - LL_INFOS(LOG_TXT) << "Fetch Debugger : Couldn't find handle " << handle << " in fetch list." << LL_ENDL; - return; - } - - S32 fetch_ind(iter->second); - mHandleToFetchIndex.erase(iter); - if (fetch_ind >= mFetchingHistory.size() || mFetchingHistory[fetch_ind].mHttpHandle != handle) - { - LL_INFOS(LOG_TXT) << "Fetch Debugger : Handle and fetch object in disagreement. Punting." << LL_ENDL; - } - else - { - callbackHTTP(mFetchingHistory[fetch_ind], response); - mFetchingHistory[fetch_ind].mHttpHandle = LLCORE_HTTP_HANDLE_INVALID; // Not valid after notification - } -} - -void LLTextureFetchDebugger::callbackCacheRead(S32 id, bool success, LLImageFormatted* image, - S32 imagesize, BOOL islocal) -{ - if (success) - { - mFetchingHistory[id].mFormattedImage = image; - } - mTextureCache->readComplete(mFetchingHistory[id].mCacheHandle, false); - mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle(); -} - -void LLTextureFetchDebugger::callbackCacheWrite(S32 id, bool success) -{ - mTextureCache->writeComplete(mFetchingHistory[id].mCacheHandle); - mFetchingHistory[id].mCacheHandle = LLTextureCache::nullHandle(); -} - -void LLTextureFetchDebugger::callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux) -{ - if (success) - { - llassert_always(raw); - mFetchingHistory[id].mRawImage = raw; - } -} - -void LLTextureFetchDebugger::callbackHTTP(FetchEntry & fetch, LLCore::HttpResponse * response) -{ - static const LLCore::HttpStatus par_status(HTTP_PARTIAL_CONTENT); - - LLCore::HttpStatus status(response->getStatus()); - mNbCurlRequests--; - mNbCurlCompleted++; - fetch.mCurlState = FetchEntry::CURL_DONE; - if (status) - { - const bool partial(par_status == status); - LLCore::BufferArray * ba(response->getBody()); // *Not* holding reference to body - - S32 data_size = ba ? ba->size() : 0; - fetch.mCurlReceivedSize += data_size; - //LL_INFOS(LOG_TXT) << "Fetch Debugger : got results for " << fetch.mID << ", data_size = " << data_size << ", received = " << fetch.mCurlReceivedSize << ", requested = " << fetch.mRequestedSize << ", partial = " << partial << LL_ENDL; - if ((fetch.mCurlReceivedSize >= fetch.mRequestedSize) || !partial || (fetch.mRequestedSize == 600)) - { - U8* d_buffer = (U8*)ll_aligned_malloc_16(data_size); - if (ba) - { - ba->read(0, d_buffer, data_size); - } - - llassert_always(fetch.mFormattedImage.isNull()); - { - // For now, create formatted image based on extension - std::string texture_url = mHTTPUrl + "/?texture_id=" + fetch.mID.asString().c_str(); - std::string extension = gDirUtilp->getExtension(texture_url); - fetch.mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension)); - if (fetch.mFormattedImage.isNull()) - { - fetch.mFormattedImage = new LLImageJ2C; // default - } - } - - fetch.mFormattedImage->setData(d_buffer, data_size); - } - } - else //failed - { - LL_INFOS(LOG_TXT) << "Fetch Debugger : CURL GET FAILED, ID = " << fetch.mID - << ", status: " << status.toTerseString() - << " reason: " << status.toString() << LL_ENDL; - } -} - - -//--------------------- -/////////////////////////////////////////////////////////////////////////////////////////// -//End LLTextureFetchDebugger -/////////////////////////////////////////////////////////////////////////////////////////// - LLTextureFetchTester::LLTextureFetchTester() : LLMetricPerformanceTesterBasic(sTesterName) { mTextureFetchTime = 0; diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index bf6732963f..3ca88422a2 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -48,7 +48,6 @@ class LLTextureFetchWorker; class LLImageDecodeThread; class LLHost; class LLViewerAssetStats; -class LLTextureFetchDebugger; class LLTextureCache; class LLTextureFetchTester; @@ -59,7 +58,9 @@ class LLTextureFetch : public LLWorkerThread friend class LLTextureFetchWorker; public: - LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded, bool qa_mode); + static std::string getStateString(S32 state); + + LLTextureFetch(LLTextureCache* cache, bool threaded, bool qa_mode); ~LLTextureFetch(); class TFRequest; @@ -116,10 +117,11 @@ public: // Threads: T* BOOL isFromLocalCache(const LLUUID& id); - // @return Magic number giving the internal state of the - // request. We should make these codes public if we're - // going to return them as a status value. - // + // get the current fetch state, if any, from the given UUID + S32 getFetchState(const LLUUID& id); + + // @return Fetch state of given image and associates statistics + // See also getStateString // Threads: T* S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p, U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http); @@ -322,7 +324,6 @@ private: LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue. LLTextureCache* mTextureCache; - LLImageDecodeThread* mImageDecodeThread; // Map of all requests by UUID typedef std::map<LLUUID,LLTextureFetchWorker*> map_t; @@ -409,10 +410,6 @@ public: static LLTextureFetchTester* sTesterp; private: - //debug use - LLTextureFetchDebugger* mFetchDebugger; - bool mFetcherLocked; - e_tex_source mFetchSource; e_tex_source mOriginFetchSource; @@ -420,10 +417,6 @@ private: //LLAdaptiveRetryPolicy mFetchRetryPolicy; public: - //debug use - LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;} - void lockFetcher(bool lock) { mFetcherLocked = lock;} - void setLoadSource(e_tex_source source) {mFetchSource = source;} void resetLoadSource() {mFetchSource = mOriginFetchSource;} bool canLoadFromCache() { return mFetchSource != FROM_HTTP_ONLY;} @@ -431,216 +424,6 @@ public: //debug use class LLViewerFetchedTexture; -class LLTextureFetchDebugger : public LLCore::HttpHandler -{ - friend class LLTextureFetch; -public: - LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextureCache* cache, LLImageDecodeThread* imagedecodethread) ; - ~LLTextureFetchDebugger(); - -public: - enum e_debug_state - { - IDLE = 0, - START_DEBUG, - READ_CACHE, - WRITE_CACHE, - DECODING, - HTTP_FETCHING, - GL_TEX, - REFETCH_VIS_CACHE, - REFETCH_VIS_HTTP, - REFETCH_ALL_CACHE, - REFETCH_ALL_HTTP, - INVALID - }; - -private: - struct FetchEntry - { - enum e_curl_state - { - CURL_NOT_DONE = 0, - CURL_IN_PROGRESS, - CURL_DONE - }; - LLUUID mID; - S32 mRequestedSize; - S32 mDecodedLevel; - S32 mFetchedSize; - S32 mDecodedSize; - BOOL mNeedsAux; - U32 mCacheHandle; - LLPointer<LLImageFormatted> mFormattedImage; - LLPointer<LLImageRaw> mRawImage; - e_curl_state mCurlState; - S32 mCurlReceivedSize; - LLCore::HttpHandle mHttpHandle; - - FetchEntry() : - mDecodedLevel(-1), - mFetchedSize(0), - mDecodedSize(0), - mHttpHandle(LLCORE_HTTP_HANDLE_INVALID) - {} - FetchEntry(LLUUID& id, S32 r_size, /*S32 f_discard, S32 c,*/ S32 level, S32 f_size, S32 d_size) : - mID(id), - mRequestedSize(r_size), - mDecodedLevel(level), - mFetchedSize(f_size), - mDecodedSize(d_size), - mNeedsAux(false), - mHttpHandle(LLCORE_HTTP_HANDLE_INVALID) - {} - }; - typedef std::vector<FetchEntry> fetch_list_t; - fetch_list_t mFetchingHistory; - - typedef std::map<LLCore::HttpHandle, S32> handle_fetch_map_t; - handle_fetch_map_t mHandleToFetchIndex; - - void setDebuggerState(e_debug_state new_state) { mDebuggerState = new_state; } - e_debug_state mDebuggerState; - - F32 mCacheReadTime; - F32 mCacheWriteTime; - F32 mDecodingTime; - F32 mHTTPTime; - F32 mGLCreationTime; - - F32 mTotalFetchingTime; - F32 mRefetchVisCacheTime; - F32 mRefetchVisHTTPTime; - F32 mRefetchAllCacheTime; - F32 mRefetchAllHTTPTime; - - LLTimer mTimer; - - LLTextureFetch* mFetcher; - LLTextureCache* mTextureCache; - LLImageDecodeThread* mImageDecodeThread; - LLCore::HttpHeaders::ptr_t mHttpHeaders; - LLCore::HttpRequest::policy_t mHttpPolicyClass; - - S32 mNumFetchedTextures; - S32 mNumCacheHits; - S32 mNumVisibleFetchedTextures; - S32 mNumVisibleFetchingRequests; - U32 mFetchedData; - U32 mDecodedData; - U32 mVisibleFetchedData; - U32 mVisibleDecodedData; - U32 mRenderedData; - U32 mRenderedDecodedData; - U32 mFetchedPixels; - U32 mRenderedPixels; - U32 mRefetchedVisData; - U32 mRefetchedVisPixels; - U32 mRefetchedAllData; - U32 mRefetchedAllPixels; - - BOOL mFreezeHistory; - BOOL mStopDebug; - BOOL mClearHistory; - BOOL mRefetchNonVis; - - std::string mHTTPUrl; - S32 mNbCurlRequests; - S32 mNbCurlCompleted; - - std::map< LLPointer<LLViewerFetchedTexture>, std::vector<S32> > mRefetchList; // treats UI textures as normal textures - std::vector< LLPointer<LLViewerFetchedTexture> > mTempTexList; - S32 mTempIndex; - S32 mHistoryListIndex; - -public: - bool update(F32 max_time); //called in the main thread once per frame - - //fetching history - void clearHistory(); - void addHistoryEntry(LLTextureFetchWorker* worker); - - // Inherited from LLCore::HttpHandler - // Threads: Ttf - virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); - - void startWork(e_debug_state state); - void setStopDebug() {mStopDebug = TRUE;} - void tryToStopDebug(); //stop everything - void callbackCacheRead(S32 id, bool success, LLImageFormatted* image, - S32 imagesize, BOOL islocal); - void callbackCacheWrite(S32 id, bool success); - void callbackDecoded(S32 id, bool success, LLImageRaw* raw, LLImageRaw* aux); - void callbackHTTP(FetchEntry & fetch, LLCore::HttpResponse * response); - - e_debug_state getState() {return mDebuggerState;} - S32 getNumFetchedTextures() {return mNumFetchedTextures;} - S32 getNumFetchingRequests() {return mFetchingHistory.size();} - S32 getNumCacheHits() {return mNumCacheHits;} - S32 getNumVisibleFetchedTextures() {return mNumVisibleFetchedTextures;} - S32 getNumVisibleFetchingRequests() {return mNumVisibleFetchingRequests;} - U32 getFetchedData() {return mFetchedData;} - U32 getDecodedData() {return mDecodedData;} - U32 getVisibleFetchedData() {return mVisibleFetchedData;} - U32 getVisibleDecodedData() {return mVisibleDecodedData;} - U32 getRenderedData() {return mRenderedData;} - U32 getRenderedDecodedData() {return mRenderedDecodedData;} - U32 getFetchedPixels() {return mFetchedPixels;} - U32 getRenderedPixels() {return mRenderedPixels;} - U32 getRefetchedVisData() {return mRefetchedVisData;} - U32 getRefetchedVisPixels() {return mRefetchedVisPixels;} - U32 getRefetchedAllData() {return mRefetchedAllData;} - U32 getRefetchedAllPixels() {return mRefetchedAllPixels;} - - F32 getCacheReadTime() {return mCacheReadTime;} - F32 getCacheWriteTime() {return mCacheWriteTime;} - F32 getDecodeTime() {return mDecodingTime;} - F32 getGLCreationTime() {return mGLCreationTime;} - F32 getHTTPTime() {return mHTTPTime;} - F32 getTotalFetchingTime() {return mTotalFetchingTime;} - F32 getRefetchVisCacheTime() {return mRefetchVisCacheTime;} - F32 getRefetchVisHTTPTime() {return mRefetchVisHTTPTime;} - F32 getRefetchAllCacheTime() {return mRefetchAllCacheTime;} - F32 getRefetchAllHTTPTime() {return mRefetchAllHTTPTime;} - -private: - void init(); - void clearTextures();//clear fetching results of all textures. - void clearCache(); - void makeRefetchList(); - void scanRefetchList(); - - void lockFetcher(); - void unlockFetcher(); - - void lockCache(); - void unlockCache(); - - void lockDecoder(); - void unlockDecoder(); - - S32 fillCurlQueue(); - - void startDebug(); - void debugCacheRead(); - void debugCacheWrite(); - void debugHTTP(); - void debugDecoder(); - void debugGLTextureCreation(); - void debugRefetchVisibleFromCache(); - void debugRefetchVisibleFromHTTP(); - void debugRefetchAllFromCache(); - void debugRefetchAllFromHTTP(); - - bool processStartDebug(F32 max_time); - bool processGLCreation(F32 max_time); - -private: - static bool sDebuggerEnabled; -public: - static bool isEnabled() {return sDebuggerEnabled;} -}; - class LLTextureFetchTester : public LLMetricPerformanceTesterBasic { diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index b74577315e..f0e9cee101 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -49,6 +49,8 @@ #include "llviewerobjectlist.h" #include "llviewertexture.h" #include "llviewertexturelist.h" +#include "llviewerwindow.h" +#include "llwindow.h" #include "llvovolume.h" #include "llviewerstats.h" #include "llworld.h" @@ -117,8 +119,8 @@ public: LLTextureBar* bar2p = (LLTextureBar*)i2; LLViewerFetchedTexture *i1p = bar1p->mImagep; LLViewerFetchedTexture *i2p = bar2p->mImagep; - F32 pri1 = i1p->getDecodePriority(); // i1p->mRequestedDownloadPriority - F32 pri2 = i2p->getDecodePriority(); // i2p->mRequestedDownloadPriority + F32 pri1 = i1p->getMaxVirtualSize(); + F32 pri2 = i2p->getMaxVirtualSize(); if (pri1 > pri2) return true; else if (pri2 > pri1) @@ -177,7 +179,7 @@ void LLTextureBar::draw() { color = LLColor4::magenta; // except none and alm } - else if (mImagep->getDecodePriority() <= 0.0f) + else if (mImagep->getMaxVirtualSize() <= 0.0f) { color = LLColor4::grey; color[VALPHA] = .7f; } @@ -202,26 +204,13 @@ void LLTextureBar::draw() std::string uuid_str; mImagep->mID.toString(uuid_str); uuid_str = uuid_str.substr(0,7); - if (mTextureView->mOrderFetch) - { - tex_str = llformat("%s %7.0f %d(%d) 0x%08x(%8.0f)", - uuid_str.c_str(), - mImagep->mMaxVirtualSize, - mImagep->mDesiredDiscardLevel, - mImagep->mRequestedDiscardLevel, - mImagep->mFetchPriority, - mImagep->getDecodePriority()); - } - else - { - tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x)", - uuid_str.c_str(), - mImagep->mMaxVirtualSize, - mImagep->mDesiredDiscardLevel, - mImagep->mRequestedDiscardLevel, - mImagep->getDecodePriority(), - mImagep->mFetchPriority); - } + + tex_str = llformat("%s %7.0f %d(%d)", + uuid_str.c_str(), + mImagep->mMaxVirtualSize, + mImagep->mDesiredDiscardLevel, + mImagep->mRequestedDiscardLevel); + LLFontGL::getFontMonospace()->renderUTF8(tex_str, 0, title_x1, getRect().getHeight(), color, LLFontGL::LEFT, LLFontGL::TOP); @@ -500,10 +489,6 @@ private: void LLGLTexMemBar::draw() { - S32Megabytes bound_mem = LLViewerTexture::sBoundTextureMemory; - S32Megabytes max_bound_mem = LLViewerTexture::sMaxBoundTextureMemory; - S32Megabytes total_mem = LLViewerTexture::sTotalTextureMemory; - S32Megabytes max_total_mem = LLViewerTexture::sMaxTotalTextureMem; F32 discard_bias = LLViewerTexture::sDesiredDiscardBias; F32 cache_usage = LLAppViewer::getTextureCache()->getUsage().valueInUnits<LLUnits::Megabytes>(); F32 cache_max_usage = LLAppViewer::getTextureCache()->getMaxUsage().valueInUnits<LLUnits::Megabytes>(); @@ -549,15 +534,10 @@ void LLGLTexMemBar::draw() U32 texFetchLatMed = U32(recording.getMean(LLTextureFetch::sTexFetchLatency).value() * 1000.0f); U32 texFetchLatMax = U32(recording.getMax(LLTextureFetch::sTexFetchLatency).value() * 1000.0f); - text = llformat("GL Tot: %d/%d MB GL Free: %d Sys Free: %d MB Bound: %4d/%4d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB", - total_mem.value(), - max_total_mem.value(), - LLImageGLThread::getFreeVRAMMegabytes(), + text = llformat("GL Free: %d MB Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB", + gViewerWindow->getWindow()->getAvailableVRAMMegabytes(), LLMemory::getAvailableMemKB()/1024, - bound_mem.value(), - max_bound_mem.value(), LLRenderTarget::sBytesAllocated/(1024*1024), - LLImageRaw::sGlobalRawMemory >> 20, discard_bias, cache_usage, cache_max_usage); @@ -837,7 +817,7 @@ void LLTextureView::draw() LL_INFOS() << imagep->getID() << "\t" << tex_mem << "\t" << imagep->getBoostLevel() - << "\t" << imagep->getDecodePriority() + << "\t" << imagep->getMaxVirtualSize() << "\t" << imagep->getWidth() << "\t" << imagep->getHeight() << "\t" << cur_discard @@ -857,7 +837,7 @@ void LLTextureView::draw() } else { - pri = imagep->getDecodePriority(); + pri = imagep->getMaxVirtualSize(); } pri = llclamp(pri, 0.0f, HIGH_PRIORITY-1.f); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index d5f842d925..9682945208 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -341,12 +341,6 @@ static bool handleMaxPartCountChanged(const LLSD& newvalue) return true; } -static bool handleVideoMemoryChanged(const LLSD& newvalue) -{ - gTextureList.updateMaxResidentTexMem(S32Megabytes(newvalue.asInteger())); - return true; -} - static bool handleChatFontSizeChanged(const LLSD& newvalue) { if(gConsole) @@ -706,7 +700,6 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2)); - gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _2)); gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _2)); gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _2)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 6d98d9b10e..77b84c6789 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -797,8 +797,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLViewerTexture::updateClass(); } - LLImageGLThread::updateClass(); - { LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_BUMP); gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first. diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 97cb8e2000..2daa919f5c 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -132,7 +132,6 @@ #include "llfloatertelehub.h" #include "llfloatertestinspectors.h" #include "llfloatertestlistview.h" -#include "llfloatertexturefetchdebugger.h" #include "llfloatertools.h" #include "llfloatertopobjects.h" #include "llfloatertos.h" @@ -284,10 +283,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>); - if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled")) - { - LLFloaterReg::add("tex_fetch_debugger", "floater_texture_fetch_debugger.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTextureFetchDebugger>); - } LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>); LLFloaterReg::add("marketplace_listings", "floater_marketplace_listings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceListings>); LLFloaterReg::add("marketplace_validation", "floater_marketplace_validation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceValidation>); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 6aa1c5fece..6d61193a56 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2515,14 +2515,6 @@ class LLDevelopSetLoggingLevel : public view_listener_t } }; -class LLDevelopTextureFetchDebugger : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - return gSavedSettings.getBOOL("TextureFetchDebuggerEnabled"); - } -}; - ////////////////// // ADMIN MENU // ////////////////// @@ -9471,8 +9463,6 @@ void initialize_menus() view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel"); view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel"); - //Develop (Texture Fetch Debug Console) - view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger"); //Develop (clear cache immediately) commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) ); //Develop (override environment map) diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 3385d317e6..796ff04a41 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -155,10 +155,7 @@ LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > static LLTrace::SampleStatHandle<bool> CHAT_BUBBLES("chatbubbles", "Chat Bubbles Enabled"); -LLTrace::SampleStatHandle<F64Megabytes > GL_TEX_MEM("gltexmemstat"), - GL_BOUND_MEM("glboundmemstat"), - RAW_MEM("rawmemstat"), - FORMATTED_MEM("formattedmemstat"); +LLTrace::SampleStatHandle<F64Megabytes > FORMATTED_MEM("formattedmemstat"); LLTrace::SampleStatHandle<F64Kilobytes > DELTA_BANDWIDTH("deltabandwidth", "Increase/Decrease in bandwidth based on packet loss"), MAX_BANDWIDTH("maxbandwidth", "Max bandwidth setting"); @@ -319,8 +316,6 @@ U32Bytes gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGOR extern U32 gVisCompared; extern U32 gVisTested; -LLFrameTimer gTextureTimer; - void update_statistics() { gTotalWorldData += gVLManager.getTotalBytes(); @@ -416,19 +411,6 @@ void update_statistics() } } -void update_texture_time() -{ - if (gTextureList.isPrioRequestsFetched()) - { - gTextureTimer.pause(); - } - else - { - gTextureTimer.unpause(); - } - - record(LLStatViewer::TEXTURE_FETCH_TIME, gTextureTimer.getElapsedTimeF32()); -} /* * The sim-side LLSD is in newsim/llagentinfo.cpp:forwardViewerStats. * diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 017c79b2e3..c21c06256e 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -191,10 +191,8 @@ extern LLTrace::SampleStatHandle<> FPS_SAMPLE, extern LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > PACKETS_LOST_PERCENT; -extern LLTrace::SampleStatHandle<F64Megabytes > GL_TEX_MEM, - GL_BOUND_MEM, - RAW_MEM, - FORMATTED_MEM; +extern LLTrace::SampleStatHandle<F64Megabytes > FORMATTED_MEM; + extern LLTrace::SampleStatHandle<F64Kilobytes > DELTA_BANDWIDTH, MAX_BANDWIDTH; extern SimMeasurement<F64Milliseconds > SIM_FRAME_TIME, @@ -296,7 +294,6 @@ void update_statistics(); void send_viewer_stats(bool include_preferences); void update_texture_time(); -extern LLFrameTimer gTextureTimer; extern U32Bytes gTotalTextureData; extern U32Bytes gTotalObjectData; extern U32Bytes gTotalTextureBytesPerBoostLevel[] ; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index c389d2122e..0c23214b52 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -58,6 +58,8 @@ #include "llvovolume.h" #include "llviewermedia.h" #include "lltexturecache.h" +#include "llviewerwindow.h" +#include "llwindow.h" /////////////////////////////////////////////////////////////////////////////// // extern @@ -76,6 +78,8 @@ LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sFlatNormalImagep = NULL; LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap; LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL; +F32 LLViewerFetchedTexture::sMaxVirtualSize = F32_MAX/2.f; + const std::string sTesterName("TextureTester"); S32 LLViewerTexture::sImageCount = 0; @@ -84,11 +88,6 @@ S32 LLViewerTexture::sAuxCount = 0; LLFrameTimer LLViewerTexture::sEvaluationTimer; F32 LLViewerTexture::sDesiredDiscardBias = 0.f; F32 LLViewerTexture::sDesiredDiscardScale = 1.1f; -S32Bytes LLViewerTexture::sBoundTextureMemory; -S32Bytes LLViewerTexture::sTotalTextureMemory; -S32Megabytes LLViewerTexture::sMaxBoundTextureMemory; -S32Megabytes LLViewerTexture::sMaxTotalTextureMem; -S32Bytes LLViewerTexture::sMaxDesiredTextureMem; S8 LLViewerTexture::sCameraMovingDiscardBias = 0; F32 LLViewerTexture::sCameraMovingBias = 0.0f; S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size @@ -471,11 +470,6 @@ void LLViewerTextureManager::cleanup() void LLViewerTexture::initClass() { LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture(); - - if(gSavedSettings.getBOOL("TextureFetchDebuggerEnabled")) - { - sTexelPixelRatio = gSavedSettings.getF32("TexelPixelRatio"); - } } // tuning params @@ -500,7 +494,7 @@ bool LLViewerTexture::isMemoryForTextureLow() S32Megabytes physical; getGPUMemoryForTextures(gpu, physical); - return (gpu < MIN_FREE_TEXTURE_MEMORY) || (physical < MIN_FREE_MAIN_MEMORY); + return (gpu < MIN_FREE_TEXTURE_MEMORY); // || (physical < MIN_FREE_MAIN_MEMORY); } //static @@ -514,7 +508,7 @@ bool LLViewerTexture::isMemoryForTextureSuficientlyFree() S32Megabytes physical; getGPUMemoryForTextures(gpu, physical); - return (gpu > DESIRED_FREE_TEXTURE_MEMORY) && (physical > DESIRED_FREE_MAIN_MEMORY); + return (gpu > DESIRED_FREE_TEXTURE_MEMORY); // && (physical > DESIRED_FREE_MAIN_MEMORY); } //static @@ -535,9 +529,9 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p timer.reset(); { - gpu_res = (S32Megabytes) LLImageGLThread::getFreeVRAMMegabytes(); + gpu_res = (S32Megabytes)gViewerWindow->getWindow()->getAvailableVRAMMegabytes(); - //check main memory, only works for windows. + //check main memory, only works for windows and macos. LLMemory::updateMemoryInfo(); physical_res = LLMemory::getAvailableMemKB(); @@ -560,27 +554,7 @@ void LLViewerTexture::updateClass() LLViewerMediaTexture::updateClass(); - sBoundTextureMemory = LLImageGL::sBoundTextureMemory; - sTotalTextureMemory = LLImageGL::sGlobalTextureMemory; - sMaxBoundTextureMemory = gTextureList.getMaxResidentTexMem(); - sMaxTotalTextureMem = gTextureList.getMaxTotalTextureMem(); - sMaxDesiredTextureMem = sMaxTotalTextureMem; //in Bytes, by default and when total used texture memory is small. - - if (sBoundTextureMemory >= sMaxBoundTextureMemory || - sTotalTextureMemory >= sMaxTotalTextureMem) - { - //when texture memory overflows, lower down the threshold to release the textures more aggressively. - sMaxDesiredTextureMem = llmin(sMaxDesiredTextureMem * 0.75f, F32Bytes(gMaxVideoRam)); - - // If we are using more texture memory than we should, - // scale up the desired discard level - if (sEvaluationTimer.getElapsedTimeF32() > discard_delta_time) - { - sDesiredDiscardBias += discard_bias_delta; - sEvaluationTimer.reset(); - } - } - else if(isMemoryForTextureLow()) + if(isMemoryForTextureLow()) { // Note: isMemoryForTextureLow() uses 1s delay, make sure we waited enough for it to recheck if (sEvaluationTimer.getElapsedTimeF32() > GPU_MEMORY_CHECK_WAIT_TIME) @@ -590,8 +564,6 @@ void LLViewerTexture::updateClass() } } else if (sDesiredDiscardBias > 0.0f - && sBoundTextureMemory < sMaxBoundTextureMemory * texmem_lower_bound_scale - && sTotalTextureMemory < sMaxTotalTextureMem * texmem_lower_bound_scale && isMemoryForTextureSuficientlyFree()) { // If we are using less texture memory than we should, @@ -661,7 +633,6 @@ void LLViewerTexture::init(bool firstinit) mMaxVirtualSize = 0.f; mMaxVirtualSizeResetInterval = 1; mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval; - mAdditionalDecodePriority = 0.f; mParcelMedia = NULL; memset(&mNumVolumes, 0, sizeof(U32)* LLRender::NUM_VOLUME_TEXTURE_CHANNELS); @@ -689,6 +660,11 @@ void LLViewerTexture::cleanup() { notifyAboutMissingAsset(); + if (LLAppViewer::getTextureFetch()) + { + LLAppViewer::getTextureFetch()->updateRequestPriority(mID, 0.f); + } + mFaceList[LLRender::DIFFUSE_MAP].clear(); mFaceList[LLRender::NORMAL_MAP].clear(); mFaceList[LLRender::SPECULAR_MAP].clear(); @@ -745,6 +721,12 @@ void LLViewerTexture::setBoostLevel(S32 level) } } + // strongly encourage anything boosted to load at full res + if (mBoostLevel >= LLViewerTexture::BOOST_HIGH) + { + mMaxVirtualSize = 2048.f * 2048.f; + } + if (mBoostLevel == LLViewerTexture::BOOST_SELECTED) { mSelectedTime = gFrameTimeSeconds; @@ -828,15 +810,8 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co } virtual_size *= sTexelPixelRatio; - if(!mMaxVirtualSizeResetCounter) - { - //flag to reset the values because the old values are used. - resetMaxVirtualSizeResetCounter(); - mMaxVirtualSize = virtual_size; - mAdditionalDecodePriority = 0.f; - mNeedsGLTexture = needs_gltexture; - } - else if (virtual_size > mMaxVirtualSize) + + if (virtual_size > mMaxVirtualSize) { mMaxVirtualSize = virtual_size; } @@ -845,7 +820,6 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co void LLViewerTexture::resetTextureStats() { mMaxVirtualSize = 0.0f; - mAdditionalDecodePriority = 0.f; mMaxVirtualSizeResetCounter = 0; } @@ -1114,7 +1088,6 @@ void LLViewerFetchedTexture::init(bool firstinit) if (firstinit) { - mDecodePriority = 0.f; mInImageList = 0; } @@ -1163,6 +1136,7 @@ void LLViewerFetchedTexture::init(bool firstinit) LLViewerFetchedTexture::~LLViewerFetchedTexture() { + assert_main_thread(); //*NOTE getTextureFetch can return NULL when Viewer is shutting down. // This is due to LLWearableList is singleton and is destroyed after // LLAppViewer::cleanup() was called. (see ticket EXT-177) @@ -1359,10 +1333,7 @@ void LLViewerFetchedTexture::dump() void LLViewerFetchedTexture::destroyTexture() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if(LLImageGL::sGlobalTextureMemory < sMaxDesiredTextureMem * 0.95f)//not ready to release unused memory. - { - return ; - } + if (mNeedsCreateTexture)//return if in the process of generating a new texture. { return; @@ -1598,6 +1569,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) void LLViewerFetchedTexture::postCreateTexture() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (!mNeedsCreateTexture) { return; @@ -1621,6 +1593,8 @@ void LLViewerFetchedTexture::postCreateTexture() void LLViewerFetchedTexture::scheduleCreateTexture() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + if (!mNeedsCreateTexture) { mNeedsCreateTexture = TRUE; @@ -1697,6 +1671,7 @@ void LLViewerFetchedTexture::scheduleCreateTexture() //virtual void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if(mKnownDrawWidth < width || mKnownDrawHeight < height) { mKnownDrawWidth = llmax(mKnownDrawWidth, width); @@ -1708,9 +1683,31 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height) addTextureStats((F32)(mKnownDrawWidth * mKnownDrawHeight)); } +void LLViewerFetchedTexture::setDebugText(const std::string& text) +{ + for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) + { + llassert(mNumFaces[ch] <= mFaceList[ch].size()); + + for (U32 i = 0; i < mNumFaces[ch]; i++) + { + LLFace* facep = mFaceList[ch][i]; + if (facep) + { + LLDrawable* drawable = facep->getDrawable(); + if (drawable) + { + drawable->getVObj()->setDebugText(text); + } + } + } + } +} + //virtual void LLViewerFetchedTexture::processTextureStats() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if(mFullyLoaded) { if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more @@ -1718,6 +1715,7 @@ void LLViewerFetchedTexture::processTextureStats() mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel); mFullyLoaded = FALSE; } + //setDebugText("fully loaded"); } else { @@ -1730,7 +1728,7 @@ void LLViewerFetchedTexture::processTextureStats() mDesiredDiscardLevel = 0; } else if (!LLPipeline::sRenderDeferred && mBoostLevel == LLGLTexture::BOOST_ALM) - { + { // ??? don't load spec and normal maps when alm is disabled ??? mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; } else if (mDontDiscard && mBoostLevel == LLGLTexture::BOOST_ICON) @@ -1788,198 +1786,8 @@ void LLViewerFetchedTexture::processTextureStats() } } -const F32 MAX_PRIORITY_PIXEL = 999.f; //pixel area -const F32 PRIORITY_BOOST_LEVEL_FACTOR = 1000.f; //boost level -const F32 PRIORITY_DELTA_DISCARD_LEVEL_FACTOR = 100000.f; //delta discard -const S32 MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY = 4; -const F32 PRIORITY_ADDITIONAL_FACTOR = 1000000.f; //additional -const S32 MAX_ADDITIONAL_LEVEL_FOR_PRIORITY = 8; -const F32 PRIORITY_BOOST_HIGH_FACTOR = 10000000.f;//boost high -F32 LLViewerFetchedTexture::calcDecodePriority() -{ -#ifndef LL_RELEASE_FOR_DOWNLOAD - if (mID == LLAppViewer::getTextureFetch()->mDebugID) - { - LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints - } -#endif - - if (mNeedsCreateTexture) - { - return mDecodePriority; // no change while waiting to create - } - if(mFullyLoaded && !mForceToSaveRawImage)//already loaded for static texture - { - return -1.0f; //alreay fetched - } - - S32 cur_discard = getCurrentDiscardLevelForFetching(); - bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); - F32 pixel_priority = (F32) sqrt(mMaxVirtualSize); - - F32 priority = 0.f; - - if (mIsMissingAsset) - { - priority = 0.0f; - } - else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1) - { - priority = -2.0f; - } - else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel) - { - priority = -3.0f; - } - else if (mDesiredDiscardLevel > getMaxDiscardLevel()) - { - // Don't decode anything we don't need - priority = -4.0f; - } - else if ((mBoostLevel == LLGLTexture::BOOST_UI || mBoostLevel == LLGLTexture::BOOST_ICON) && !have_all_data) - { - priority = 1.f; - } - else if (pixel_priority < 0.001f && !have_all_data) - { - // Not on screen but we might want some data - if (mBoostLevel > BOOST_SELECTED) - { - // Always want high boosted images - priority = 1.f; - } - else - { - priority = -5.f; //stop fetching - } - } - else if (cur_discard < 0) - { - //texture does not have any data, so we don't know the size of the image, treat it like 32 * 32. - // priority range = 100,000 - 500,000 - static const F64 log_2 = log(2.0); - F32 desired = (F32)(log(32.0/pixel_priority) / log_2); - S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired; - ddiscard = llclamp(ddiscard, 0, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY); - priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR; - setAdditionalDecodePriority(0.1f);//boost the textures without any data so far. - } - else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel)) - { - // larger mips are corrupted - priority = -6.0f; - } - else - { - // priority range = 100,000 - 500,000 - S32 desired_discard = mDesiredDiscardLevel; - if (!isJustBound() && mCachedRawImageReady) - { - if(mBoostLevel < BOOST_HIGH) - { - // We haven't rendered this in a while, de-prioritize it - desired_discard += 2; - } - else - { - // We haven't rendered this in the last half second, and we have a cached raw image, leave the desired discard as-is - desired_discard = cur_discard; - } - } - - S32 ddiscard = cur_discard - desired_discard; - ddiscard = llclamp(ddiscard, -1, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY); - priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR; - } - - // Priority Formula: - // BOOST_HIGH + ADDITIONAL PRI + DELTA DISCARD + BOOST LEVEL + PIXELS - // [10,000,000] + [1,000,000-9,000,000] + [100,000-500,000] + [1-20,000] + [0-999] - if (priority > 0.0f) - { - bool large_enough = mCachedRawImageReady && ((S32)mTexelsPerImage > sMinLargeImageSize); - if(large_enough) - { - //Note: - //to give small, low-priority textures some chance to be fetched, - //cut the priority in half if the texture size is larger than 256 * 256 and has a 64*64 ready. - priority *= 0.5f; - } - - pixel_priority = llclamp(pixel_priority, 0.0f, MAX_PRIORITY_PIXEL); - - priority += pixel_priority + PRIORITY_BOOST_LEVEL_FACTOR * mBoostLevel; - - if ( mBoostLevel > BOOST_HIGH) - { - if(mBoostLevel > BOOST_SUPER_HIGH) - { - //for very important textures, always grant the highest priority. - priority += PRIORITY_BOOST_HIGH_FACTOR; - } - else if(mCachedRawImageReady) - { - //Note: - //to give small, low-priority textures some chance to be fetched, - //if high priority texture has a 64*64 ready, lower its fetching priority. - setAdditionalDecodePriority(0.5f); - } - else - { - priority += PRIORITY_BOOST_HIGH_FACTOR; - } - } - - if(mAdditionalDecodePriority > 0.0f) - { - // priority range += 1,000,000.f-9,000,000.f - F32 additional = PRIORITY_ADDITIONAL_FACTOR * (1.0 + mAdditionalDecodePriority * MAX_ADDITIONAL_LEVEL_FOR_PRIORITY); - if(large_enough) - { - //Note: - //to give small, low-priority textures some chance to be fetched, - //cut the additional priority to a quarter if the texture size is larger than 256 * 256 and has a 64*64 ready. - additional *= 0.25f; - } - priority += additional; - } - } - return priority; -} - -//static -F32 LLViewerFetchedTexture::maxDecodePriority() -{ - static const F32 max_priority = PRIORITY_BOOST_HIGH_FACTOR + //boost_high - PRIORITY_ADDITIONAL_FACTOR * (MAX_ADDITIONAL_LEVEL_FOR_PRIORITY + 1) + //additional (view dependent factors) - PRIORITY_DELTA_DISCARD_LEVEL_FACTOR * (MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY + 1) + //delta discard - PRIORITY_BOOST_LEVEL_FACTOR * (BOOST_MAX_LEVEL - 1) + //boost level - MAX_PRIORITY_PIXEL + 1.0f; //pixel area. - - return max_priority; -} - //============================================================================ -void LLViewerFetchedTexture::setDecodePriority(F32 priority) -{ - mDecodePriority = priority; - - if(mDecodePriority < F_ALMOST_ZERO) - { - mStopFetchingTimer.reset(); - } -} - -void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority) -{ - priority = llclamp(priority, 0.f, 1.f); - if(mAdditionalDecodePriority < priority) - { - mAdditionalDecodePriority = priority; - } -} - void LLViewerFetchedTexture::updateVirtualSize() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -1988,6 +1796,18 @@ void LLViewerFetchedTexture::updateVirtualSize() addTextureStats(0.f, FALSE);//reset } + if (getBoostLevel() >= LLViewerTexture::BOOST_HIGH) + { //always load boosted textures at highest priority full res + addTextureStats(sMaxVirtualSize); + return; + } + + if (sDesiredDiscardBias > 0.f) + { + // running out of video memory, don't hold onto high res textures in the background + mMaxVirtualSize = 0.f; + } + for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) { llassert(mNumFaces[ch] <= mFaceList[ch].size()); @@ -2009,8 +1829,12 @@ void LLViewerFetchedTexture::updateVirtualSize() setBoostLevel(LLViewerTexture::BOOST_SELECTED); } addTextureStats(facep->getVirtualSize()); - setAdditionalDecodePriority(facep->getImportanceToCamera()); + //drawable->getVObj()->setDebugText(llformat("%d:%d", (S32)sqrtf(facep->getVirtualSize()), (S32)sqrtf(getMaxVirtualSize()))); } + else + { + //drawable->getVObj()->setDebugText(""); + } } } } @@ -2072,6 +1896,16 @@ bool LLViewerFetchedTexture::isActiveFetching() return mFetchState > 7 && mFetchState < 10 && monitor_enabled; //in state of WAIT_HTTP_REQ or DECODE_IMAGE. } +void LLViewerFetchedTexture::setBoostLevel(S32 level) +{ + LLViewerTexture::setBoostLevel(level); + + if (level >= LLViewerTexture::BOOST_HIGH) + { + mDesiredDiscardLevel = 0; + } +} + bool LLViewerFetchedTexture::updateFetch() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -2098,31 +1932,40 @@ bool LLViewerFetchedTexture::updateFetch() if (mNeedsCreateTexture) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - needs create"); // We may be fetching still (e.g. waiting on write) // but don't check until we've processed the raw data we have return false; } if (mIsMissingAsset) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - missing asset"); llassert_always(!mHasFetcher); return false; // skip } if (!mLoadedCallbackList.empty() && mRawImage.notNull()) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - callback pending"); return false; // process any raw image data in callbacks before replacing } if(mInFastCacheList) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - in fast cache"); return false; } + if (mGLTexturep.isNull()) + { // fix for crash inside getCurrentDiscardLevelForFetching (shouldn't happen but appears to be happening) + llassert(false); + return false; + } S32 current_discard = getCurrentDiscardLevelForFetching(); S32 desired_discard = getDesiredDiscardLevel(); - F32 decode_priority = getDecodePriority(); - decode_priority = llclamp(decode_priority, 0.0f, maxDecodePriority()); + F32 decode_priority = mMaxVirtualSize; if (mIsFetching) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - is fetching"); // Sets mRawDiscardLevel, mRawImage, mAuxRawImage S32 fetch_discard = current_discard; @@ -2140,17 +1983,25 @@ bool LLViewerFetchedTexture::updateFetch() if (finished) { mIsFetching = FALSE; + mLastFetchState = -1; + setDebugText(""); mLastPacketTimer.reset(); } else { mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP); + /*if (mFetchState != mLastFetchState) + { + setDebugText(LLTextureFetch::getStateString(mFetchState)); + mLastFetchState = mFetchState; + }*/ } // We may have data ready regardless of whether or not we are finished (e.g. waiting on write) if (mRawImage.notNull()) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - has raw image"); LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { @@ -2161,6 +2012,7 @@ bool LLViewerFetchedTexture::updateFetch() if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && (current_discard < 0 || mRawDiscardLevel < current_discard)) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data good"); mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; setTexelsPerImage(); @@ -2197,6 +2049,7 @@ bool LLViewerFetchedTexture::updateFetch() } else { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data not needed"); // Data is ready but we don't need it // (received it already while fetcher was writing to disk) destroyRawImage(); @@ -2206,7 +2059,7 @@ bool LLViewerFetchedTexture::updateFetch() if (!mIsFetching) { - if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL)) + if ((decode_priority > 0) && (mRawDiscardLevel < 0)) { // We finished but received no data if (getDiscardLevel() < 0) @@ -2229,13 +2082,13 @@ bool LLViewerFetchedTexture::updateFetch() if(current_discard >= 0) { mMinDiscardLevel = current_discard; - desired_discard = current_discard; + //desired_discard = current_discard; } else { S32 dis_level = getDiscardLevel(); mMinDiscardLevel = dis_level; - desired_discard = dis_level; + //desired_discard = dis_level; } } destroyRawImage(); @@ -2249,12 +2102,6 @@ bool LLViewerFetchedTexture::updateFetch() } else { -// // Useful debugging code for undesired deprioritization of textures. -// if (decode_priority <= 0.0f && desired_discard >= 0 && desired_discard < current_discard) -// { -// LL_INFOS() << "Calling updateRequestPriority() with decode_priority = 0.0f" << LL_ENDL; -// calcDecodePriority(); -// } static const F32 MAX_HOLD_TIME = 5.0f; //seconds to wait before canceling fecthing if decode_priority is 0.f. if(decode_priority > 0.0f || mStopFetchingTimer.getElapsedTimeF32() > MAX_HOLD_TIME) { @@ -2264,21 +2111,27 @@ bool LLViewerFetchedTexture::updateFetch() } } + desired_discard = llmin(desired_discard, getMaxDiscardLevel()); + bool make_request = true; - if (decode_priority <= 0) + /*if (decode_priority <= 0) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - priority <= 0"); make_request = false; } else if(mDesiredDiscardLevel > getMaxDiscardLevel()) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - desired > max"); make_request = false; } - else if (mNeedsCreateTexture || mIsMissingAsset) + else */ if (mNeedsCreateTexture || mIsMissingAsset) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - create or missing"); make_request = false; } else if (current_discard >= 0 && current_discard <= mMinDiscardLevel) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current < min"); make_request = false; } else if(mCachedRawImage.notNull() // can be empty @@ -2295,6 +2148,7 @@ bool LLViewerFetchedTexture::updateFetch() if (make_request) { +#if 0 // Load the texture progressively: we try not to rush to the desired discard too fast. // If the camera is not moving, we do not tweak the discard level notch by notch but go to the desired discard with larger boosted steps // This mitigates the "textures stay blurry" problem when loading while not killing the texture memory while moving around @@ -2311,18 +2165,23 @@ bool LLViewerFetchedTexture::updateFetch() { desired_discard = llmax(desired_discard, current_discard - delta_level); } +#endif if (mIsFetching) { + // already requested a higher resolution mip if (mRequestedDiscardLevel <= desired_discard) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - requested < desired"); make_request = false; } } else { + // already at a higher resolution mip, don't discard if (current_discard >= 0 && current_discard <= desired_discard) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current <= desired"); make_request = false; } } @@ -2330,6 +2189,7 @@ bool LLViewerFetchedTexture::updateFetch() if (make_request) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - make request"); S32 w=0, h=0, c=0; if (getDiscardLevel() >= 0) { @@ -2351,6 +2211,7 @@ bool LLViewerFetchedTexture::updateFetch() if (fetch_request_created) { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - request created"); mHasFetcher = TRUE; mIsFetching = TRUE; mRequestedDiscardLevel = desired_discard; @@ -2358,15 +2219,18 @@ bool LLViewerFetchedTexture::updateFetch() mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP); } - // if createRequest() failed, we're finishing up a request for this UUID, - // wait for it to complete + // If createRequest() failed, that means one of two things: + // 1. We're finishing up a request for this UUID, so we + // should wait for it to complete + // 2. We've failed a request for this UUID, so there is + // no need to create another request } else if (mHasFetcher && !mIsFetching) { // Only delete requests that haven't received any network data // for a while. Note - this is the normal mechanism for // deleting requests, not just a place to handle timeouts. - const F32 FETCH_IDLE_TIME = 5.f; + const F32 FETCH_IDLE_TIME = 0.1f; if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME) { LL_DEBUGS("Texture") << "exceeded idle time " << FETCH_IDLE_TIME << ", deleting request: " << getID() << LL_ENDL; @@ -2676,7 +2540,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() LL_INFOS() << "baked texture: " << mID << "clears all call backs due to inactivity." << LL_ENDL; LL_INFOS() << mUrl << LL_ENDL; LL_INFOS() << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() << - " Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << getDecodePriority() << LL_ENDL; + " Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << mMaxVirtualSize << LL_ENDL; } clearCallbackEntryList() ; //remove all callbacks. @@ -2907,7 +2771,7 @@ void LLViewerFetchedTexture::forceImmediateUpdate() return; } //if already called forceImmediateUpdate() - if(mInImageList && mDecodePriority == LLViewerFetchedTexture::maxDecodePriority()) + if(mInImageList && mMaxVirtualSize == LLViewerFetchedTexture::sMaxVirtualSize) { return; } @@ -2976,6 +2840,7 @@ bool LLViewerFetchedTexture::needsToSaveRawImage() void LLViewerFetchedTexture::destroyRawImage() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (mAuxRawImage.notNull() && !needsToSaveRawImage()) { sAuxCount--; @@ -3059,6 +2924,7 @@ void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* im void LLViewerFetchedTexture::setCachedRawImage() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if(mRawImage == mCachedRawImage) { return; @@ -3134,6 +3000,7 @@ void LLViewerFetchedTexture::checkCachedRawSculptImage() void LLViewerFetchedTexture::saveRawImage() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if(mRawImage.isNull() || mRawImage == mSavedRawImage || (mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= mRawDiscardLevel)) { return; @@ -3349,25 +3216,10 @@ void LLViewerLODTexture::processTextureStats() } else { - if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 0.3f) - { - //if is a big image and not being used recently, nor close to the view point, do not load hi-res data. - mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerTexture::sMinLargeImageSize); - } - - if ((mCalculatedDiscardLevel >= 0.f) && - (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f)) - { - // < 20% change in virtual size = no change in desired discard - discard_level = mCalculatedDiscardLevel; - } - else - { - // Calculate the required scale factor of the image using pixels per texel - discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4); - mDiscardVirtualSize = mMaxVirtualSize; - mCalculatedDiscardLevel = discard_level; - } + // Calculate the required scale factor of the image using pixels per texel + discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4); + mDiscardVirtualSize = mMaxVirtualSize; + mCalculatedDiscardLevel = discard_level; } if (mBoostLevel < LLGLTexture::BOOST_SCULPTED) { @@ -3407,18 +3259,6 @@ void LLViewerLODTexture::processTextureStats() //needs to release texture memory urgently scaleDown(); } - // Limit the amount of GL memory bound each frame - else if ( sBoundTextureMemory > sMaxBoundTextureMemory * texmem_middle_bound_scale && - (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) - { - scaleDown(); - } - // Only allow GL to have 2x the video card memory - else if ( sTotalTextureMemory > sMaxTotalTextureMem * texmem_middle_bound_scale && - (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) - { - scaleDown(); - } } if (isUpdateFrozen() // we are out of memory and nearing max allowed bias @@ -4199,7 +4039,6 @@ void LLTexturePipelineTester::compareTestSessions(llofstream* os) *os << llformat("%s\n", getTesterName().c_str()); *os << llformat("AggregateResults\n"); - compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime); compareTestResults(os, "TotalGrayTime", base_sessionp->mTotalGrayTime, current_sessionp->mTotalGrayTime); compareTestResults(os, "TotalStablizingTime", base_sessionp->mTotalStablizingTime, current_sessionp->mTotalStablizingTime); compareTestResults(os, "StartTimeLoadingSculpties", base_sessionp->mStartTimeLoadingSculpties, current_sessionp->mStartTimeLoadingSculpties); @@ -4259,7 +4098,6 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo return NULL; } - F32 total_fetching_time = 0.f; F32 total_gray_time = 0.f; F32 total_stablizing_time = 0.f; F32 total_loading_sculpties_time = 0.f; @@ -4294,7 +4132,6 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo F32 cur_time = (*log)[label]["Time"].asReal(); if(start_time - start_fetching_time > F_ALMOST_ZERO) //fetching has paused for a while { - sessionp->mTotalFetchingTime += total_fetching_time; sessionp->mTotalGrayTime += total_gray_time; sessionp->mTotalStablizingTime += total_stablizing_time; @@ -4302,14 +4139,12 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time; start_fetching_time = start_time; - total_fetching_time = 0.0f; total_gray_time = 0.f; total_stablizing_time = 0.f; total_loading_sculpties_time = 0.f; } else { - total_fetching_time = cur_time - start_time; total_gray_time = (*log)[label]["TotalGrayTime"].asReal(); total_stablizing_time = (*log)[label]["TotalStablizingTime"].asReal(); @@ -4355,7 +4190,6 @@ LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::lo in_log = (*log).has(currentLabel); } - sessionp->mTotalFetchingTime += total_fetching_time; sessionp->mTotalGrayTime += total_gray_time; sessionp->mTotalStablizingTime += total_stablizing_time; @@ -4377,8 +4211,6 @@ LLTexturePipelineTester::LLTextureTestSession::~LLTextureTestSession() } void LLTexturePipelineTester::LLTextureTestSession::reset() { - mTotalFetchingTime = 0.0f; - mTotalGrayTime = 0.0f; mTotalStablizingTime = 0.0f; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 53cf911102..5893f549d0 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -134,7 +134,7 @@ public: /*virtual*/ bool isActiveFetching(); /*virtual*/ const LLUUID& getID() const { return mID; } - void setBoostLevel(S32 level); + virtual void setBoostLevel(S32 level); S32 getBoostLevel() { return mBoostLevel; } void setTextureListType(S32 tex_type) { mTextureListType = tex_type; } S32 getTextureListType() { return mTextureListType; } @@ -188,19 +188,20 @@ private: virtual void switchToCachedImage(); - static bool isMemoryForTextureLow() ; static bool isMemoryForTextureSuficientlyFree(); static void getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &physical); +public: + static bool isMemoryForTextureLow(); protected: + friend class LLViewerTextureList; LLUUID mID; S32 mTextureListType; // along with mID identifies where to search for this texture in TextureList F32 mSelectedTime; // time texture was last selected - mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? - mutable S32 mMaxVirtualSizeResetCounter ; + mutable F32 mMaxVirtualSize = 0.f; // The largest virtual size of the image, in pixels - how much data to we need? + mutable S32 mMaxVirtualSizeResetCounter; mutable S32 mMaxVirtualSizeResetInterval; - mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority. LLFrameTimer mLastReferencedTimer; ll_face_list_t mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture @@ -226,11 +227,6 @@ public: static LLFrameTimer sEvaluationTimer; static F32 sDesiredDiscardBias; static F32 sDesiredDiscardScale; - static S32Bytes sBoundTextureMemory; - static S32Bytes sTotalTextureMemory; - static S32Megabytes sMaxBoundTextureMemory; - static S32Megabytes sMaxTotalTextureMem; - static S32Bytes sMaxDesiredTextureMem ; static S8 sCameraMovingDiscardBias; static F32 sCameraMovingBias; static S32 sMaxSculptRez ; @@ -285,7 +281,6 @@ public: LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); public: - static F32 maxDecodePriority(); struct Compare { @@ -294,9 +289,10 @@ public: { const LLViewerFetchedTexture* lhsp = (const LLViewerFetchedTexture*)lhs; const LLViewerFetchedTexture* rhsp = (const LLViewerFetchedTexture*)rhs; + // greater priority is "less" - const F32 lpriority = lhsp->getDecodePriority(); - const F32 rpriority = rhsp->getDecodePriority(); + const F32 lpriority = lhsp->mMaxVirtualSize; + const F32 rpriority = rhsp->mMaxVirtualSize; if (lpriority > rpriority) // higher priority return true; if (lpriority < rpriority) @@ -306,10 +302,10 @@ public: }; public: - /*virtual*/ S8 getType() const ; + /*virtual*/ S8 getType() const override; FTType getFTType() const; - /*virtual*/ void forceImmediateUpdate() ; - /*virtual*/ void dump() ; + /*virtual*/ void forceImmediateUpdate() override; + /*virtual*/ void dump() override; // Set callbacks to get called when the image gets updated with higher // resolution versions. @@ -335,7 +331,6 @@ public: void destroyTexture() ; virtual void processTextureStats() ; - F32 calcDecodePriority() ; BOOL needsAux() const { return mNeedsAux; } @@ -343,20 +338,12 @@ public: void setTargetHost(LLHost host) { mTargetHost = host; } LLHost getTargetHost() const { return mTargetHost; } - // Set the decode priority for this image... - // DON'T CALL THIS UNLESS YOU KNOW WHAT YOU'RE DOING, it can mess up - // the priority list, and cause horrible things to happen. - void setDecodePriority(F32 priority = -1.0f); - F32 getDecodePriority() const { return mDecodePriority; }; - F32 getAdditionalDecodePriority() const { return mAdditionalDecodePriority; }; - - void setAdditionalDecodePriority(F32 priority) ; - void updateVirtualSize() ; S32 getDesiredDiscardLevel() { return mDesiredDiscardLevel; } void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } + void setBoostLevel(S32 level) override; bool updateFetch(); bool setDebugFetching(S32 debug_level); bool isInDebug() const { return mInDebug; } @@ -369,10 +356,14 @@ public: // Override the computation of discard levels if we know the exact output // size of the image. Used for UI textures to not decode, even if we have // more data. - /*virtual*/ void setKnownDrawSize(S32 width, S32 height); + /*virtual*/ void setKnownDrawSize(S32 width, S32 height) override; + + // Set the debug text of all Viewer Objects associated with this texture + // to the specified text + void setDebugText(const std::string& text); void setIsMissingAsset(BOOL is_missing = true); - /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } + /*virtual*/ BOOL isMissingAsset() const override { return mIsMissingAsset; } // returns dimensions of original image for local files (before power of two scaling) // and returns 0 for all asset system images @@ -415,7 +406,7 @@ public: BOOL isRawImageValid()const { return mIsRawImageValid ; } void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ; void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f); - /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; + /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) override; void destroySavedRawImage() ; LLImageRaw* getSavedRawImage() ; BOOL hasSavedRawImage() const ; @@ -431,10 +422,10 @@ public: void setInFastCacheList(bool in_list) { mInFastCacheList = in_list; } bool isInFastCacheList() { return mInFastCacheList; } - /*virtual*/bool isActiveFetching(); //is actively in fetching by the fetching pipeline. + /*virtual*/bool isActiveFetching() override; //is actively in fetching by the fetching pipeline. protected: - /*virtual*/ void switchToCachedImage(); + /*virtual*/ void switchToCachedImage() override; S32 getCurrentDiscardLevelForFetching() ; private: @@ -472,11 +463,11 @@ protected: S32 mRequestedDiscardLevel; F32 mRequestedDownloadPriority; S32 mFetchState; + S32 mLastFetchState = -1; // DEBUG U32 mFetchPriority; F32 mDownloadProgress; F32 mFetchDeltaTime; F32 mRequestDeltaTime; - F32 mDecodePriority; // The priority for decoding this image. S32 mMinDiscardLevel; S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have @@ -500,7 +491,7 @@ protected: F32 mLastCallBackActiveTime; LLPointer<LLImageRaw> mRawImage; - S32 mRawDiscardLevel; + S32 mRawDiscardLevel = -1; // Used ONLY for cloth meshes right now. Make SURE you know what you're // doing if you use it for anything else! - djs @@ -534,6 +525,7 @@ protected: BOOL mIsFetched ; //is loaded from remote or from cache, not generated locally. public: + static F32 sMaxVirtualSize; //maximum possible value of mMaxVirtualSize static LLPointer<LLViewerFetchedTexture> sMissingAssetImagep; // Texture to show for an image asset that is not in the database static LLPointer<LLViewerFetchedTexture> sWhiteImagep; // Texture to show NOTHING (whiteness) static LLPointer<LLViewerFetchedTexture> sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local. @@ -774,7 +766,6 @@ private: void reset() ; - F32 mTotalFetchingTime ; F32 mTotalGrayTime ; F32 mTotalStablizingTime ; F32 mStartTimeLoadingSculpties ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index bbbf9ea7a3..1a766dd404 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -89,8 +89,6 @@ LLTextureKey::LLTextureKey(LLUUID id, ETexListType tex_type) LLViewerTextureList::LLViewerTextureList() : mForceResetTextureStats(FALSE), - mMaxResidentTexMemInMegaBytes(0), - mMaxTotalTextureMemInMegaBytes(0), mInitialized(FALSE) { } @@ -99,12 +97,6 @@ void LLViewerTextureList::init() { mInitialized = TRUE ; sNumImages = 0; - mMaxResidentTexMemInMegaBytes = (U32Bytes)0; - mMaxTotalTextureMemInMegaBytes = (U32Bytes)0; - - // Update how much texture RAM we're allowed to use. - updateMaxResidentTexMem(S32Megabytes(0)); // 0 = use current - doPreloadImages(); } @@ -204,10 +196,8 @@ static std::string get_texture_list_name() void LLViewerTextureList::doPrefetchImages() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - gTextureTimer.start(); - gTextureTimer.pause(); - if (LLAppViewer::instance()->getPurgeCache()) + if (LLAppViewer::instance()->getPurgeCache()) { // cache was purged, no point return; @@ -342,7 +332,7 @@ void LLViewerTextureList::dump() { LLViewerFetchedTexture* image = *it; - LL_INFOS() << "priority " << image->getDecodePriority() + LL_INFOS() << "priority " << image->getMaxVirtualSize() << " boost " << image->getBoostLevel() << " size " << image->getWidth() << "x" << image->getHeight() << " discard " << image->getDiscardLevel() @@ -667,13 +657,14 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image) assert_main_thread(); llassert_always(mInitialized) ; llassert(image); + image->validateRefCount(); S32 count = 0; if (image->isInImageList()) { count = mImageList.erase(image) ; if(count != 1) - { + { LL_INFOS() << "Image " << image->getID() << " had mInImageList set but mImageList.erase() returned " << count << LL_ENDL; @@ -699,6 +690,7 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image) LL_INFOS() << "Image " << image->getID() << " was in mUUIDMap with same pointer" << LL_ENDL ; } count = mImageList.erase(image) ; + llassert(count != 0); if(count != 0) { // it was in the list already? LL_WARNS() << "Image " << image->getID() @@ -784,17 +776,12 @@ void LLViewerTextureList::updateImages(F32 max_time) using namespace LLStatViewer; sample(NUM_IMAGES, sNumImages); sample(NUM_RAW_IMAGES, LLImageRaw::sRawImageCount); - sample(GL_TEX_MEM, LLImageGL::sGlobalTextureMemory); - sample(GL_BOUND_MEM, LLImageGL::sBoundTextureMemory); - sample(RAW_MEM, F64Bytes(LLImageRaw::sGlobalRawMemory)); sample(FORMATTED_MEM, F64Bytes(LLImageFormatted::sGlobalFormattedMemory)); } //loading from fast cache max_time -= updateImagesLoadingFastCache(max_time); - updateImagesDecodePriorities(); - F32 total_max_time = max_time; max_time -= updateImagesFetchTextures(max_time); @@ -825,7 +812,6 @@ void LLViewerTextureList::updateImages(F32 max_time) didone = image->doLoadedCallbacks(); } } - updateImagesUpdateStats(); } @@ -848,120 +834,78 @@ void LLViewerTextureList::clearFetchingRequests() } } -void LLViewerTextureList::updateImagesDecodePriorities() +void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imagep) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - // Update the decode priority for N images each frame - { - F32 lazy_flush_timeout = 30.f; // stop decoding - F32 max_inactive_time = 20.f; // actually delete - S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference - - //reset imagep->getLastReferencedTimer() when screen is showing the progress view to avoid removing pre-fetched textures too soon. - bool reset_timer = gViewerWindow->getProgressView()->getVisible(); - - static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities"); // default: 32 - const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES); - S32 update_counter = llmin(max_update_count, mUUIDMap.size()); - uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey); - while ((update_counter-- > 0) && !mUUIDMap.empty()) - { - if (iter == mUUIDMap.end()) - { - iter = mUUIDMap.begin(); + if (imagep->isInDebug() || imagep->isUnremovable()) + { + //update_counter--; + return; //is in debug, ignore. + } + + F32 lazy_flush_timeout = 30.f; // stop decoding + F32 max_inactive_time = 20.f; // actually delete + S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference + + // + // Flush formatted images using a lazy flush + // + S32 num_refs = imagep->getNumRefs(); + if (num_refs == min_refs) + { + if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout) + { + // Remove the unused image from the image list + deleteImage(imagep); + imagep = NULL; // should destroy the image + } + return; + } + else + { + if (imagep->hasSavedRawImage()) + { + if (imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time) + { + imagep->destroySavedRawImage(); } - mLastUpdateKey = iter->first; - LLPointer<LLViewerFetchedTexture> imagep = iter->second; - ++iter; // safe to increment now + } - if(imagep->isInDebug() || imagep->isUnremovable()) - { - update_counter--; - continue; //is in debug, ignore. - } + if (imagep->isDeleted()) + { + return; + } + else if (imagep->isDeletionCandidate()) + { + imagep->destroyTexture(); + return; + } + else if (imagep->isInactive()) + { + if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time) + { + imagep->setDeletionCandidate(); + } + return; + } + else + { + imagep->getLastReferencedTimer()->reset(); - // - // Flush formatted images using a lazy flush - // - S32 num_refs = imagep->getNumRefs(); - if (num_refs == min_refs) - { - if(reset_timer) - { - imagep->getLastReferencedTimer()->reset(); - } - else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout) - { - // Remove the unused image from the image list - deleteImage(imagep); - imagep = NULL; // should destroy the image - } - continue; - } - else - { - if(imagep->hasSavedRawImage()) - { - if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time) - { - imagep->destroySavedRawImage() ; - } - } - - if(imagep->isDeleted()) - { - continue ; - } - else if(imagep->isDeletionCandidate()) - { - imagep->destroyTexture() ; - continue ; - } - else if(imagep->isInactive()) - { - if(reset_timer) - { - imagep->getLastReferencedTimer()->reset(); - } - else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time) - { - imagep->setDeletionCandidate() ; - } - continue ; - } - else - { - imagep->getLastReferencedTimer()->reset(); - - //reset texture state. - imagep->setInactive() ; - } - } + //reset texture state. + imagep->setInactive(); + } + } - if (!imagep->isInImageList()) - { - continue; - } - if(imagep->isInFastCacheList()) - { - continue; //wait for loading from the fast cache. - } + if (!imagep->isInImageList()) + { + return; + } + if (imagep->isInFastCacheList()) + { + return; //wait for loading from the fast cache. + } - imagep->processTextureStats(); - F32 old_priority = imagep->getDecodePriority(); - F32 old_priority_test = llmax(old_priority, 0.0f); - F32 decode_priority = imagep->calcDecodePriority(); - F32 decode_priority_test = llmax(decode_priority, 0.0f); - // Ignore < 20% difference - if ((decode_priority_test < old_priority_test * .8f) || - (decode_priority_test > old_priority_test * 1.25f)) - { - mImageList.erase(imagep) ; - imagep->setDecodePriority(decode_priority); - mImageList.insert(imagep); - } - } - } + imagep->processTextureStats(); } void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level) @@ -973,17 +917,9 @@ void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debu } const F32 DEBUG_PRIORITY = 100000.f; - F32 old_priority_test = llmax(tex->getDecodePriority(), 0.0f); - F32 decode_priority_test = DEBUG_PRIORITY; - - // Ignore < 20% difference - if ((decode_priority_test < old_priority_test * .8f) || - (decode_priority_test > old_priority_test * 1.25f)) - { - removeImageFromList(tex); - tex->setDecodePriority(decode_priority_test); - addImageToList(tex); - } + removeImageFromList(tex); + tex->mMaxVirtualSize = DEBUG_PRIORITY; + addImageToList(tex); } /* @@ -1033,10 +969,6 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time) LLViewerFetchedTexture *imagep = *curiter; imagep->createTexture(); imagep->postCreateTexture(); - if (create_timer.getElapsedTimeF32() > max_time) - { - break; - } } mCreateTextureList.erase(mCreateTextureList.begin(), enditer); return create_timer.getElapsedTimeF32(); @@ -1064,10 +996,6 @@ F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time) enditer = iter; LLViewerFetchedTexture *imagep = *curiter; imagep->loadFromFastCache(); - if (timer.getElapsedTimeF32() > max_time) - { - break; - } } mFastCacheList.erase(mFastCacheList.begin(), enditer); return timer.getElapsedTimeF32(); @@ -1086,8 +1014,7 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep) } imagep->processTextureStats(); - F32 decode_priority = LLViewerFetchedTexture::maxDecodePriority() ; - imagep->setDecodePriority(decode_priority); + imagep->sMaxVirtualSize = LLViewerFetchedTexture::sMaxVirtualSize; addImageToList(imagep); return ; @@ -1096,76 +1023,55 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep) F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - LLTimer image_op_timer; - - // Update fetch for N images each frame - static const S32 MAX_HIGH_PRIO_COUNT = gSavedSettings.getS32("TextureFetchUpdateHighPriority"); // default: 32 - static const S32 MAX_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMaxMediumPriority"); // default: 256 - static const S32 MIN_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMinMediumPriority"); // default: 32 - static const F32 MIN_PRIORITY_THRESHOLD = gSavedSettings.getF32("TextureFetchUpdatePriorityThreshold"); // default: 0.0 - static const bool SKIP_LOW_PRIO = gSavedSettings.getBOOL("TextureFetchUpdateSkipLowPriority"); // default: false - - size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*MAX_HIGH_PRIO_COUNT*gFrameIntervalSeconds.value())+1, MAX_HIGH_PRIO_COUNT); - max_priority_count = llmin(max_priority_count, mImageList.size()); - - size_t total_update_count = mUUIDMap.size(); - size_t max_update_count = llmin((S32) (MAX_UPDATE_COUNT*MAX_UPDATE_COUNT*gFrameIntervalSeconds.value())+1, MAX_UPDATE_COUNT); - max_update_count = llmin(max_update_count, total_update_count); - - // MAX_HIGH_PRIO_COUNT high priority entries - typedef std::vector<LLViewerFetchedTexture*> entries_list_t; - entries_list_t entries; - size_t update_counter = max_priority_count; - image_priority_list_t::iterator iter1 = mImageList.begin(); - while(update_counter > 0) - { - entries.push_back(*iter1); - - ++iter1; - update_counter--; - } - - // MAX_UPDATE_COUNT cycled entries - update_counter = max_update_count; - if(update_counter > 0) - { - uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchKey); - while ((update_counter > 0) && (total_update_count > 0)) - { - if (iter2 == mUUIDMap.end()) - { - iter2 = mUUIDMap.begin(); - } - LLViewerFetchedTexture* imagep = iter2->second; - // Skip the textures where there's really nothing to do so to give some times to others. Also skip the texture if it's already in the high prio set. - if (!SKIP_LOW_PRIO || (SKIP_LOW_PRIO && ((imagep->getDecodePriority() > MIN_PRIORITY_THRESHOLD) || imagep->hasFetcher()))) + LLTimer image_op_timer; + + typedef std::vector<LLPointer<LLViewerFetchedTexture> > entries_list_t; + entries_list_t entries; + + // update N textures at beginning of mImageList + U32 update_count = 0; + static const S32 MIN_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMinCount"); // default: 32 + // WIP -- dumb code here + //update MIN_UPDATE_COUNT or 10% of other textures, whichever is greater + update_count = llmax((U32) MIN_UPDATE_COUNT, (U32) mUUIDMap.size()/10); + update_count = llmin(update_count, (U32) mUUIDMap.size()); + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vtluift - copy"); + + // copy entries out of UUID map for updating + entries.reserve(update_count); + uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey); + while (update_count-- > 0) + { + if (iter == mUUIDMap.end()) { - entries.push_back(imagep); - update_counter--; + iter = mUUIDMap.begin(); } + + if (iter->second->getGLTexture()) + { + entries.push_back(iter->second); + } + ++iter; + } + } + + for (auto& imagep : entries) + { + if (imagep->getNumRefs() > 1) // make sure this image hasn't been deleted before attempting to update (may happen as a side effect of some other image updating) + { + updateImageDecodePriority(imagep); + imagep->updateFetch(); + } + } + + if (entries.size() > 0) + { + LLViewerFetchedTexture* imagep = *entries.rbegin(); + mLastUpdateKey = LLTextureKey(imagep->getID(), (ETexListType)imagep->getTextureListType()); + } - iter2++; - total_update_count--; - } - } - - S32 fetch_count = 0; - size_t min_update_count = llmin(MIN_UPDATE_COUNT,(S32)(entries.size()-max_priority_count)); - S32 min_count = max_priority_count + min_update_count; - for (entries_list_t::iterator iter3 = entries.begin(); - iter3 != entries.end(); ) - { - LLViewerFetchedTexture* imagep = *iter3++; - fetch_count += (imagep->updateFetch() ? 1 : 0); - if (min_count <= min_update_count) - { - mLastFetchKey = LLTextureKey(imagep->getID(), (ETexListType)imagep->getTextureListType()); - } - if ((min_count-- <= 0) && (image_op_timer.getElapsedTimeF32() > max_time)) - { - break; - } - } return image_op_timer.getElapsedTimeF32(); } @@ -1209,8 +1115,6 @@ void LLViewerTextureList::decodeAllImages(F32 max_time) { LLViewerFetchedTexture* imagep = *iter; imagep->processTextureStats(); - F32 decode_priority = imagep->calcDecodePriority(); - imagep->setDecodePriority(decode_priority); addImageToList(imagep); } image_list.clear(); @@ -1349,156 +1253,6 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage return compressedImage; } -// Returns min setting for TextureMemory (in MB) -S32Megabytes LLViewerTextureList::getMinVideoRamSetting() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - U32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); - //min texture mem sets to 64M if total physical mem is more than 1.5GB - return (system_ram > U32Megabytes(1500)) ? S32Megabytes(64) : gMinVideoRam ; -} - -//static -// Returns max setting for TextureMemory (in MB) -S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - S32Megabytes max_texmem; - if (gGLManager.mVRAM != 0) - { - // Treat any card with < 32 MB (shudder) as having 32 MB - // - it's going to be swapping constantly regardless - S32Megabytes max_vram(gGLManager.mVRAM); - - if(gGLManager.mIsAMD) - { - //shrink the availabe vram for ATI cards because some of them do not handel texture swapping well. - max_vram = max_vram * 0.75f; - } - - max_vram = llmax(max_vram, getMinVideoRamSetting()); - max_texmem = max_vram; - if (!get_recommended) - max_texmem *= 2; - } - else - { - if (!get_recommended) - { - max_texmem = (S32Megabytes)512; - } - else if (gSavedSettings.getBOOL("NoHardwareProbe")) //did not do hardware detection at startup - { - max_texmem = (S32Megabytes)512; - } - else - { - max_texmem = (S32Megabytes)128; - } - } - - S32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); // In MB - //LL_INFOS() << "*** DETECTED " << system_ram << " MB of system memory." << LL_ENDL; - if (get_recommended) - max_texmem = llmin(max_texmem, system_ram/2); - else - max_texmem = llmin(max_texmem, system_ram); - - // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise - max_texmem = llmin(max_texmem, (S32Megabytes) (mem_multiplier * max_texmem)); - - max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), gMaxVideoRam); - - return max_texmem; -} - -bool LLViewerTextureList::isPrioRequestsFetched() -{ - static LLCachedControl<F32> prio_threshold(gSavedSettings, "TextureFetchUpdatePriorityThreshold", 0.0f); - static LLCachedControl<F32> fetching_textures_threshold(gSavedSettings, "TextureListFetchingThreshold", 0.97f); - S32 fetching_tex_count = 0; - S32 tex_count_threshold = gTextureList.mImageList.size() * (1 - fetching_textures_threshold); - - for (LLViewerTextureList::image_priority_list_t::iterator iter = gTextureList.mImageList.begin(); - iter != gTextureList.mImageList.end(); ) - { - LLPointer<LLViewerFetchedTexture> imagep = *iter++; - if (imagep->getDecodePriority() > prio_threshold) - { - if (imagep->hasFetcher() || imagep->isFetching()) - { - fetching_tex_count++; - if (fetching_tex_count >= tex_count_threshold) - { - return false; - } - } - } - } - - return true; -} - -const S32Megabytes VIDEO_CARD_FRAMEBUFFER_MEM(12); -const S32Megabytes MIN_MEM_FOR_NON_TEXTURE(512); -void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - // Initialize the image pipeline VRAM settings - S32Megabytes cur_mem(gSavedSettings.getS32("TextureMemory")); - F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); - S32Megabytes default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default - if (mem == (S32Bytes)0) - { - mem = cur_mem > (S32Bytes)0 ? cur_mem : default_mem; - } - else if (mem < (S32Bytes)0) - { - mem = default_mem; - } - - mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier)); - if (mem != cur_mem) - { - gSavedSettings.setS32("TextureMemory", mem.value()); - return; //listener will re-enter this function - } - - if (gGLManager.mVRAM == 0) - { - LL_WARNS() << "VRAM amount not detected, defaulting to " << mem << " MB" << LL_ENDL; - } - - // TODO: set available resident texture mem based on use by other subsystems - // currently max(12MB, VRAM/4) assumed... - - S32Megabytes vb_mem = mem; - S32Megabytes fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4); - mMaxResidentTexMemInMegaBytes = (vb_mem - fb_mem) ; //in MB - - mMaxTotalTextureMemInMegaBytes = mMaxResidentTexMemInMegaBytes * 2; - if (mMaxResidentTexMemInMegaBytes > (S32Megabytes)640) - { - mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes / 4); - } - - //system mem - S32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); - - //minimum memory reserved for non-texture use. - //if system_raw >= 1GB, reserve at least 512MB for non-texture use; - //otherwise reserve half of the system_ram for non-texture use. - S32Megabytes min_non_texture_mem = llmin(system_ram / 2, MIN_MEM_FOR_NON_TEXTURE) ; - - if (mMaxTotalTextureMemInMegaBytes > system_ram - min_non_texture_mem) - { - mMaxTotalTextureMemInMegaBytes = system_ram - min_non_texture_mem ; - } - - LL_INFOS() << "Total Video Memory set to: " << vb_mem << " MB" << LL_ENDL; - LL_INFOS() << "Available Texture Memory set to: " << (vb_mem - fb_mem) << " MB" << LL_ENDL; -} - /////////////////////////////////////////////////////////////////////////////// // static diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 99394e550c..cc6523c23e 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -124,25 +124,20 @@ public: void handleIRCallback(void **data, const S32 number); - S32Megabytes getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; } - S32Megabytes getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;} S32 getNumImages() { return mImageList.size(); } - void updateMaxResidentTexMem(S32Megabytes mem); - void doPreloadImages(); void doPrefetchImages(); void clearFetchingRequests(); void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level); - static S32Megabytes getMinVideoRamSetting(); - static S32Megabytes getMaxVideoRamSetting(bool get_recommended, float mem_multiplier); - - static bool isPrioRequestsFetched(); - private: - void updateImagesDecodePriorities(); + // do some book keeping on the specified texture + // - updates decode priority + // - updates desired discard level + // - cleans up textures that haven't been referenced in awhile + void updateImageDecodePriority(LLViewerFetchedTexture* imagep); F32 updateImagesCreateTextures(F32 max_time); F32 updateImagesFetchTextures(F32 max_time); void updateImagesUpdateStats(); @@ -215,17 +210,14 @@ private: typedef std::map< LLTextureKey, LLPointer<LLViewerFetchedTexture> > uuid_map_t; uuid_map_t mUUIDMap; LLTextureKey mLastUpdateKey; - LLTextureKey mLastFetchKey; - typedef std::set<LLPointer<LLViewerFetchedTexture>, LLViewerFetchedTexture::Compare> image_priority_list_t; + typedef std::set < LLPointer<LLViewerFetchedTexture> > image_priority_list_t; image_priority_list_t mImageList; // simply holds on to LLViewerFetchedTexture references to stop them from being purged too soon std::set<LLPointer<LLViewerFetchedTexture> > mImagePreloads; BOOL mInitialized ; - S32Megabytes mMaxResidentTexMemInMegaBytes; - S32Megabytes mMaxTotalTextureMemInMegaBytes; LLFrameTimer mForceDecodeTimer; private: diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index aa8d58cc8a..e9815a7872 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -493,24 +493,12 @@ public: if (gSavedSettings.getBOOL("DebugShowTime")) { - { - const U32 y_inc2 = 15; - LLFrameTimer& timer = gTextureTimer; - F32 time = timer.getElapsedTimeF32(); - S32 hours = (S32)(time / (60*60)); - S32 mins = (S32)((time - hours*(60*60)) / 60); - S32 secs = (S32)((time - hours*(60*60) - mins*60)); - addText(xpos, ypos, llformat("Texture: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc2; - } - - { F32 time = gFrameTimeSeconds; S32 hours = (S32)(time / (60*60)); S32 mins = (S32)((time - hours*(60*60)) / 60); S32 secs = (S32)((time - hours*(60*60) - mins*60)); addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; } - } if (gSavedSettings.getBOOL("DebugShowMemory")) { @@ -5640,7 +5628,6 @@ void LLViewerWindow::stopGL(BOOL save_state) // Pause texture decode threads (will get unpaused during main loop) LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getImageDecodeThread()->pause(); LLAppViewer::getTextureFetch()->pause(); gSky.destroyGL(); @@ -5687,8 +5674,6 @@ void LLViewerWindow::stopGL(BOOL save_state) LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin()); shader->unload(); } - - LL_INFOS() << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemory.value() << " bytes" << LL_ENDL; } } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e55ee21414..30e3d77d29 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5707,7 +5707,6 @@ void LLVOAvatar::checkTextureLoading() } const F32 SELF_ADDITIONAL_PRI = 0.75f ; -const F32 ADDITIONAL_PRI = 0.5f; void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level) { //Note: @@ -5722,15 +5721,6 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel mMinPixelArea = llmin(pixel_area, mMinPixelArea); imagep->addTextureStats(pixel_area / texel_area_ratio); imagep->setBoostLevel(boost_level); - - if(boost_level != LLGLTexture::BOOST_AVATAR_BAKED_SELF) - { - imagep->setAdditionalDecodePriority(ADDITIONAL_PRI) ; - } - else - { - imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; - } } //virtual diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 60a69a4ac4..4080a61fb0 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1825,7 +1825,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const } else { - const LLViewerFetchedTexture* image = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() ); + LLViewerFetchedTexture* image = dynamic_cast<LLViewerFetchedTexture*>( local_tex_obj->getImage() ); LL_INFOS() << "LocTex " << name << ": " << "Discard " << image->getDiscardLevel() << ", " @@ -1835,7 +1835,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const // makes textures easier to steal << image->getID() << " " #endif - << "Priority: " << image->getDecodePriority() + << "Priority: " << image->getMaxVirtualSize() << LL_ENDL; } } @@ -2074,8 +2074,7 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV << " glocdisc: " << getLocalDiscardLevel(tex_index, wearable_index) << " discard: " << image->getDiscardLevel() << " desired: " << image->getDesiredDiscardLevel() - << " decode: " << image->getDecodePriority() - << " addl: " << image->getAdditionalDecodePriority() + << " vsize: " << image->getMaxVirtualSize() << " ts: " << image->getTextureState() << " bl: " << image->getBoostLevel() << " fl: " << image->isFullyLoaded() // this is not an accessor for mFullyLoaded - see comment there. @@ -2453,7 +2452,6 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); imagep->setBoostLevel(getAvatarBoostLevel()); - imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; imagep->resetTextureStats(); imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); imagep->addTextureStats( desired_pixels / texel_area_ratio ); @@ -2823,7 +2821,6 @@ void LLVOAvatarSelf::deleteScratchTextures() LL_DEBUGS() << "Clearing Scratch Textures " << (S32Kilobytes)sScratchTexBytes << LL_ENDL; delete_and_clear(sScratchTexNames); - LLImageGL::sGlobalTextureMemory -= sScratchTexBytes; sScratchTexBytes = S32Bytes(0); } } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index d654c470e2..ad11fb3908 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -696,12 +696,13 @@ void LLVOVolume::animateTextures() void LLVOVolume::updateTextures() { - const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds - if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + //const F32 TEXTURE_AREA_REFRESH_TIME = 1.f; // seconds + //if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) { updateTextureVirtualSize(); - if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) + /*if (mDrawable.notNull() && !isVisible() && !mDrawable->isActive()) { //delete vertex buffer to free up some VRAM LLSpatialGroup* group = mDrawable->getSpatialGroup(); if (group && (group->mVertexBuffer.notNull() || !group->mBufferMap.empty() || !group->mDrawMap.empty())) @@ -712,9 +713,7 @@ void LLVOVolume::updateTextures() //it becomes visible group->setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); } - } - - + }*/ } } @@ -788,6 +787,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) const S32 num_faces = mDrawable->getNumFaces(); F32 min_vsize=999999999.f, max_vsize=0.f; LLViewerCamera* camera = LLViewerCamera::getInstance(); + std::stringstream debug_text; for (S32 i = 0; i < num_faces; i++) { LLFace* face = mDrawable->getFace(i); @@ -814,10 +814,14 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) else { vsize = face->getTextureVirtualSize(); + imagep->addTextureStats(vsize); } - mPixelArea = llmax(mPixelArea, face->getPixelArea()); + mPixelArea = llmax(mPixelArea, face->getPixelArea()); + // if the face has gotten small enough to turn off texture animation and texture + // animation is running, rebuild the render batch for this face to turn off + // texture animation if (face->mTextureMatrix != NULL) { if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || @@ -837,10 +841,11 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; if(img) { - F32 pri = img->getDecodePriority(); + debug_text << img->getDiscardLevel() << ":" << img->getDesiredDiscardLevel() << ":" << img->getWidth() << ":" << (S32) sqrtf(vsize) << ":" << (S32) sqrtf(img->getMaxVirtualSize()) << "\n"; + /*F32 pri = img->getDecodePriority(); pri = llmax(pri, 0.0f); if (pri < min_vsize) min_vsize = pri; - if (pri > max_vsize) max_vsize = pri; + if (pri > max_vsize) max_vsize = pri;*/ } } else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) @@ -872,14 +877,6 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) F32 lodf = ((F32)(lod + 1.0f)/4.f); F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ; mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); - - //if the sculpty very close to the view point, load first - { - LLVector3 lookAt = getPositionAgent() - camera->getOrigin(); - F32 dist = lookAt.normVec() ; - F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ; - mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; - } } S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture @@ -923,7 +920,8 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) } else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + //setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + setDebugText(debug_text.str()); } else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) { diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 32c8ce66a0..2b400c5586 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -395,7 +395,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const mHandler = LLXMLRPCTransaction::Handler::ptr_t(new Handler( mHttpRequest, this )); - mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID, 0, + mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID, mURI, body.get(), httpOpts, httpHeaders, mHandler); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9161b43159..91d276c8df 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -442,6 +442,7 @@ void LLPipeline::connectRefreshCachedSettingsSafe(const std::string name) void LLPipeline::init() { + LL_WARNS() << "Begin pipeline initialization" << LL_ENDL; // TODO: Remove after testing refreshCachedSettings(); mRT = &mMainRT; @@ -460,6 +461,7 @@ void LLPipeline::init() mInitialized = true; stop_glerror(); + LL_WARNS() << "No GL errors yet. Pipeline initialization will continue." << LL_ENDL; // TODO: Remove after testing //create render pass pools getPool(LLDrawPool::POOL_ALPHA); @@ -521,7 +523,9 @@ void LLPipeline::init() // Enable features + LL_WARNS() << "Shader initialization start" << LL_ENDL; // TODO: Remove after testing LLViewerShaderMgr::instance()->setShaders(); + LL_WARNS() << "Shader initialization end" << LL_ENDL; // TODO: Remove after testing stop_glerror(); @@ -3745,7 +3749,7 @@ void LLPipeline::touchTexture(LLViewerTexture* tex, F32 vsize) if (tex) { LLImageGL* gl_tex = tex->getGLTexture(); - if (gl_tex && gl_tex->updateBindStats(gl_tex->mTextureMemory)) + if (gl_tex && gl_tex->updateBindStats()) { tex->setActive(); tex->addTextureStats(vsize); @@ -3815,25 +3819,47 @@ void LLPipeline::postSort(LLCamera& camera) group->rebuildGeom(); } - for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j) - { - LLSpatialGroup::drawmap_elem_t& src_vec = j->second; - if (!hasRenderType(j->first)) - { - continue; - } - - for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k) - { + for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j) + { + LLSpatialGroup::drawmap_elem_t& src_vec = j->second; + if (!hasRenderType(j->first)) + { + continue; + } + + // DEBUG -- force a texture virtual size update every frame + /*if (group->getSpatialPartition()->mDrawableType == LLPipeline::RENDER_TYPE_VOLUME) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("plps - update vsize"); + auto& entries = group->getData(); + for (auto& entry : entries) + { + if (entry) + { + auto* data = entry->getDrawable(); + if (data) + { + LLVOVolume* volume = ((LLDrawable*)data)->getVOVolume(); + if (volume) + { + volume->updateTextureVirtualSize(true); + } + } + } + } + }*/ + + for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k) + { LLDrawInfo* info = *k; - - sCull->pushDrawInfo(j->first, info); + + sCull->pushDrawInfo(j->first, info); if (!sShadowRender && !sReflectionRender && !gCubeSnapshot) { touchTextures(info); addTrianglesDrawn(info->mCount, info->mDrawMode); } - } + } } if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA)) diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index b7708b057d..97a87d56f4 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -272,22 +272,6 @@ Hardware </text> - <slider - control_name="TextureMemory" - decimal_digits="0" - follows="left|top" - height="16" - increment="16" - initial_value="32" - label="Texture Memory (MB):" - label_width="185" - layout="topleft" - left="30" - max_val="4096" - name="GraphicsCardTextureMemory" - tool_tip="Amount of memory to allocate for textures. Defaults to video card memory. Reducing this may improve performance but may also make textures blurry." - top_delta="16" - width="335" /> <check_box control_name="RenderAnisotropic" diff --git a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml b/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml deleted file mode 100644 index 9278a1a598..0000000000 --- a/indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml +++ /dev/null @@ -1,440 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - legacy_header_height="18" - can_minimize="false" - height="600" - layout="topleft" - name="TexFetchDebugger" - help_topic="texfetchdebugger" - title="Texture Fetching Debugger" - width="540"> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left="10" - name="total_num_fetched_label" - top="30" - width="400"> - 1, Total number of fetched textures: [NUM] - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_num_fetching_requests_label" - top_delta="25" - width="400"> - 2, Total number of fetching requests: [NUM] - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_num_cache_hits_label" - top_delta="25" - width="400"> - 3, Total number of cache hits: [NUM] - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_num_visible_tex_label" - top_delta="25" - width="400"> - 4, Total number of visible textures: [NUM] - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_num_visible_tex_fetch_req_label" - top_delta="25" - width="450"> - 5, Total number of visible texture fetching requests: [NUM] - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_fetched_data_label" - top_delta="25" - width="530"> - 6, Total number of fetched data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_fetched_vis_data_label" - top_delta="25" - width="480"> - 7, Total number of visible data: [SIZE1]KB, Decoded Data: [SIZE2]KB - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_fetched_rendered_data_label" - top_delta="25" - width="530"> - 8, Total number of rendered data: [SIZE1]KB, Decoded Data: [SIZE2]KB, [PIXEL]MPixels - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_time_cache_read_label" - top_delta="25" - width="400"> - 9, Total time on cache readings: [TIME] seconds - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_time_cache_write_label" - top_delta="25" - width="400"> - 10, Total time on cache writings: [TIME] seconds - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_time_decode_label" - top_delta="25" - width="400"> - 11, Total time on decodings: [TIME] seconds - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_time_gl_label" - top_delta="25" - width="400"> - 12, Total time on gl texture creation: [TIME] seconds - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_time_http_label" - top_delta="25" - width="400"> - 13, Total time on HTTP fetching: [TIME] seconds - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_time_fetch_label" - top_delta="25" - width="400"> - 14, Total time on entire fetching: [TIME] seconds - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_time_refetch_vis_cache_label" - top_delta="25" - width="540"> - 15, Refetching visibles from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_time_refetch_all_cache_label" - top_delta="25" - width="540"> - 16, Refetching all textures from cache, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_time_refetch_vis_http_label" - top_delta="25" - width="540"> - 17, Refetching visibles from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels - </text> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="total_time_refetch_all_http_label" - top_delta="25" - width="540"> - 18, Refetching all textures from HTTP, Time: [TIME] seconds, Fetched: [SIZE]KB, [PIXEL]MPixels - </text> - <spinner - decimal_digits="2" - follows="left|top" - height="20" - increment="0.01" - initial_value="1.0" - label="19, Ratio of Texel/Pixel:" - label_width="130" - layout="topleft" - left_delta="0" - max_val="10.0" - min_val="0.01" - name="texel_pixel_ratio" - top_delta="30" - width="200"> - <spinner.commit_callback - function="TexFetchDebugger.ChangeTexelPixelRatio" /> - </spinner> - <text - type="string" - length="1" - follows="left|top" - height="25" - layout="topleft" - left_delta="0" - name="texture_source_label" - top_delta="30" - width="110"> - 20, Texture Source: - </text> - <radio_group - control_name="TextureFetchSource" - follows="top|left" - draw_border="false" - height="25" - layout="topleft" - left_pad="0" - name="texture_source" - top_delta="0" - width="264"> - <radio_item - height="16" - label="Cache + HTTP" - layout="topleft" - left="3" - name="0" - top="0" - width="100" /> - <radio_item - height="16" - label="HTTP Only" - layout="topleft" - left_delta="100" - name="1" - top_delta="0" - width="200" /> - </radio_group> - <button - follows="left|top" - height="20" - label="Start" - layout="topleft" - left="10" - name="start_btn" - top_delta="20" - width="70"> - <button.commit_callback - function="TexFetchDebugger.Start" /> - </button> - <button - follows="left|top" - height="20" - label="Reset" - layout="topleft" - left_pad="7" - name="clear_btn" - top_delta="0" - width="70"> - <button.commit_callback - function="TexFetchDebugger.Clear" /> - </button> - <button - follows="left|top" - height="20" - label="Close" - layout="topleft" - left_pad="7" - name="close_btn" - top_delta="0" - width="70"> - <button.commit_callback - function="TexFetchDebugger.Close" /> - </button> - <button - follows="left|top" - height="22" - label="Reset Fetching Time" - layout="topleft" - left_pad="175" - name="reset_time_btn" - top_delta="0" - width="120"> - <button.commit_callback - function="TexFetchDebugger.ResetFetchTime" /> - </button> - <button - follows="left|top" - height="20" - label="Cache Read" - layout="topleft" - left="10" - name="cacheread_btn" - top_delta="20" - width="80"> - <button.commit_callback - function="TexFetchDebugger.CacheRead" /> - </button> - <button - follows="left|top" - height="20" - label="Cache Write" - layout="topleft" - left_pad="7" - name="cachewrite_btn" - top_delta="0" - width="80"> - <button.commit_callback - function="TexFetchDebugger.CacheWrite" /> - </button> - <button - follows="left|top" - height="20" - label="HTTP" - layout="topleft" - left_pad="7" - name="http_btn" - top_delta="0" - width="70"> - <button.commit_callback - function="TexFetchDebugger.HTTPLoad" /> - </button> - <button - follows="left|top" - height="20" - label="Decode" - layout="topleft" - left_pad="7" - name="decode_btn" - top_delta="0" - width="70"> - <button.commit_callback - function="TexFetchDebugger.Decode" /> - </button> - <button - follows="left|top" - height="20" - label="GL Texture" - layout="topleft" - left_pad="7" - name="gl_btn" - top_delta="0" - width="70"> - <button.commit_callback - function="TexFetchDebugger.GLTexture" /> - </button> - <button - follows="left|top" - height="20" - label="Refetch Vis Cache" - layout="topleft" - left="10" - name="refetchviscache_btn" - top_delta="20" - width="120"> - <button.commit_callback - function="TexFetchDebugger.RefetchVisCache" /> - </button> - <button - follows="left|top" - height="20" - label="Refetch All Cache" - layout="topleft" - left_pad="7" - name="refetchallcache_btn" - top_delta="0" - width="120"> - <button.commit_callback - function="TexFetchDebugger.RefetchAllCache" /> - </button> - <button - follows="left|top" - height="20" - label="Refetch Vis HTTP" - layout="topleft" - left_pad="7" - name="refetchvishttp_btn" - top_delta="0" - width="120"> - <button.commit_callback - function="TexFetchDebugger.RefetchVisHTTP" /> - </button> - <button - follows="left|top" - height="20" - label="Refetch All HTTP" - layout="topleft" - left_pad="7" - name="refetchallhttp_btn" - top_delta="0" - width="120"> - <button.commit_callback - function="TexFetchDebugger.RefetchAllHTTP" /> - </button> -</floater> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index beb5a5048d..cf99240908 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2465,20 +2465,6 @@ function="World.EnvPreset" function="Advanced.ToggleConsole" parameter="scene monitor" /> </menu_item_check> - <menu_item_call - enabled="false" - visible="false" - label="Texture Fetch Debug Console" - name="Texture Fetch Debug Console"> - <menu_item_call.on_click - function="Floater.Show" - parameter="tex_fetch_debugger" /> - <on_enable - function="Develop.SetTexFetchDebugger" /> - <on_visible - function="Develop.SetTexFetchDebugger" /> - </menu_item_call> - <menu_item_separator/> <menu_item_call diff --git a/indra/newview/tests/llviewercontrollistener_test.cpp b/indra/newview/tests/llviewercontrollistener_test.cpp new file mode 100644 index 0000000000..6d100ef984 --- /dev/null +++ b/indra/newview/tests/llviewercontrollistener_test.cpp @@ -0,0 +1,174 @@ +/** + * @file llviewercontrollistener_test.cpp + * @author Nat Goodspeed + * @date 2022-06-09 + * @brief Test for llviewercontrollistener. + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Copyright (c) 2022, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" +// associated header +#include "llviewercontrollistener.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "../test/lltut.h" +#include "../test/catch_and_store_what_in.h" // catch_what() +#include "commoncontrol.h" +#include "llcontrol.h" // LLControlGroup +#include "llviewercontrollistener.h" + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + void ensure_contains(const std::string& msg, const std::string& substr) + { + ensure_contains("Exception does not contain " + substr, msg, substr); + } + + struct llviewercontrollistener_data + { + LLControlGroup Global{"FakeGlobal"}; + + llviewercontrollistener_data() + { + Global.declareString("strvar", "woof", "string variable"); + // together we will stroll the boolvar, ma cherie + Global.declareBOOL("boolvar", TRUE, "bool variable"); + } + }; + typedef test_group<llviewercontrollistener_data> llviewercontrollistener_group; + typedef llviewercontrollistener_group::object object; + llviewercontrollistener_group llviewercontrollistenergrp("llviewercontrollistener"); + + template<> template<> + void object::test<1>() + { + set_test_name("CommonControl no listener"); + // Not implemented: the linker drags in LLViewerControlListener when + // we bring in LLViewerControl. + } + + template<> template<> + void object::test<2>() + { + set_test_name("CommonControl bad group"); + std::string threw{ catch_what<LL::CommonControl::ParamError>( + [](){ LL::CommonControl::get("Nonexistent", "Variable"); }) }; + ensure_contains(threw, "group"); + ensure_contains(threw, "Nonexistent"); + } + + template<> template<> + void object::test<3>() + { + set_test_name("CommonControl bad variable"); + std::string threw{ catch_what<LL::CommonControl::ParamError>( + [](){ LL::CommonControl::get("FakeGlobal", "Nonexistent"); }) }; + ensure_contains(threw, "key"); + ensure_contains(threw, "Nonexistent"); + } + + template<> template<> + void object::test<4>() + { + set_test_name("CommonControl toggle string"); + std::string threw{ catch_what<LL::CommonControl::ParamError>( + [](){ LL::CommonControl::toggle("FakeGlobal", "strvar"); }) }; + ensure_contains(threw, "non-boolean"); + ensure_contains(threw, "strvar"); + } + + template<> template<> + void object::test<5>() + { + set_test_name("CommonControl list bad group"); + std::string threw{ catch_what<LL::CommonControl::ParamError>( + [](){ LL::CommonControl::get_vars("Nonexistent"); }) }; + ensure_contains(threw, "group"); + ensure_contains(threw, "Nonexistent"); + } + + template<> template<> + void object::test<6>() + { + set_test_name("CommonControl get"); + auto strvar{ LL::CommonControl::get("FakeGlobal", "strvar") }; + ensure_equals(strvar, "woof"); + auto boolvar{ LL::CommonControl::get("FakeGlobal", "boolvar") }; + ensure(boolvar); + } + + template<> template<> + void object::test<7>() + { + set_test_name("CommonControl set, set_default, toggle"); + + std::string newstr{ LL::CommonControl::set("FakeGlobal", "strvar", "mouse").asString() }; + ensure_equals(newstr, "mouse"); + ensure_equals(LL::CommonControl::get("FakeGlobal", "strvar").asString(), "mouse"); + ensure_equals(LL::CommonControl::set_default("FakeGlobal", "strvar").asString(), "woof"); + + bool newbool{ LL::CommonControl::set("FakeGlobal", "boolvar", false) }; + ensure(! newbool); + ensure(! LL::CommonControl::get("FakeGlobal", "boolvar").asBoolean()); + ensure(LL::CommonControl::set_default("FakeGlobal", "boolvar").asBoolean()); + ensure(! LL::CommonControl::toggle("FakeGlobal", "boolvar").asBoolean()); + } + + template<> template<> + void object::test<8>() + { + set_test_name("CommonControl get_def"); + LLSD def{ LL::CommonControl::get_def("FakeGlobal", "strvar") }; + ensure_equals( + def, + llsd::map("name", "strvar", + "type", "String", + "value", "woof", + "comment", "string variable")); + } + + template<> template<> + void object::test<9>() + { + set_test_name("CommonControl get_groups"); + std::vector<std::string> groups{ LL::CommonControl::get_groups() }; + ensure_equals(groups.size(), 1); + ensure_equals(groups[0], "FakeGlobal"); + } + + template<> template<> + void object::test<10>() + { + set_test_name("CommonControl get_vars"); + LLSD vars{ LL::CommonControl::get_vars("FakeGlobal") }; + // convert from array (unpredictable order) to map + LLSD varsmap{ LLSD::emptyMap() }; + for (auto& var : llsd::inArray(vars)) + { + varsmap[var["name"].asString()] = var; + } + // comparing maps is order-insensitive + ensure_equals( + varsmap, + llsd::map( + "strvar", + llsd::map("name", "strvar", + "type", "String", + "value", "woof", + "comment", "string variable"), + "boolvar", + llsd::map("name", "boolvar", + "type", "Boolean", + "value", TRUE, + "comment", "bool variable"))); + } +} // namespace tut diff --git a/indra/test/test.cpp b/indra/test/test.cpp index bb48216b2b..28f25087ac 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -401,7 +401,7 @@ public: { // Per http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages std::string result; - BOOST_FOREACH(char c, str) + for (char c : str) { switch (c) { |