Merge remote-tracking branch 'remotes/origin/DRTVWR-563' into DRTVWR-559

master
Dave Parks 2022-08-30 10:46:36 -05:00
commit 197ac7cc20
105 changed files with 2038 additions and 4481 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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"];
}

View File

@ -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) */

View File

@ -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)
{

View File

@ -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();

View File

@ -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());

View File

@ -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

View File

@ -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();
mRequestHash.erase(req);
req->deleteRequest();
// check();
}
continue;
}
llassert_always(req->getStatus() == STATUS_QUEUED);
break;
unlockData();
}
U32 start_priority = 0 ;
if (req)
{
req->setStatus(STATUS_INPROGRESS);
start_priority = req->getPriority();
}
unlockData();
else
{
llassert_always(req->getStatus() == STATUS_QUEUED);
// 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 (req)
{
req->setStatus(STATUS_INPROGRESS);
}
unlockData();
if (complete)
{
lockData();
req->setStatus(STATUS_COMPLETE);
req->finishRequest(true);
if (req->getFlags() & FLAG_AUTO_COMPLETE)
{
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();
}
// 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();
S32 pending = getPending();
return pending;
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
}
}
}
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)
{
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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();
}
//============================================================================

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);

View File

@ -161,10 +161,16 @@ namespace LL
void postEvery(const std::chrono::duration<Rep, Period>& interval,
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 --------------------------*/

View File

@ -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;

View File

@ -62,7 +62,6 @@ HttpOperation::HttpOperation():
mReplyQueue(),
mUserHandler(),
mReqPolicy(HttpRequest::DEFAULT_POLICY_ID),
mReqPriority(0U),
mTracing(HTTP_TRACE_OFF),
mMyHandle(LLCORE_HTTP_HANDLE_INVALID)
{

View File

@ -181,7 +181,6 @@ protected:
public:
// Request Data
HttpRequest::policy_t mReqPolicy;
HttpRequest::priority_t mReqPriority;
// Reply Data
HttpStatus mStatus;

View File

@ -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;

View File

@ -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
// ---------------------------------------

View File

@ -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

View File

@ -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_

View File

@ -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)

View File

@ -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
///

View File

@ -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

View File

@ -146,15 +146,6 @@ public:
/// Threading: callable by worker thread.
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.
///

View File

@ -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)
{

View File

@ -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
// ====================================

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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)
{

View File

@ -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

View File

@ -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();
}

View File

@ -276,7 +276,6 @@ protected:
void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
public:
static S32 sGlobalRawMemory;
static S32 sRawImageCount;
private:

View File

@ -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;

View File

@ -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);
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;
return getPending();
}
LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
S32 LLImageDecodeThread::getPending()
{
return mThreadPool->getQueue().size();
}
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();
}

View File

@ -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

View File

@ -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");
}
}
}

View File

@ -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
//

View File

@ -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)
{

View File

@ -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()

View File

@ -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)

View File

@ -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;

View File

@ -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)
{
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -145,6 +145,8 @@ if (WINDOWS)
list(APPEND llwindow_LINK_LIBRARIES
comdlg32 # Common Dialogs for ChooseColor
ole32
dxgi
d3d9
)
endif (WINDOWS)

View File

@ -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

View File

@ -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()

View File

@ -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 {}
};

View File

@ -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...

View File

@ -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;

View File

@ -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)

View File

@ -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();

View File

@ -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}"

View File

@ -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>
@ -10458,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 &lt; value &lt;= 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>
@ -12548,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>
@ -12658,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>
@ -12691,21 +12681,10 @@
<key>Value</key>
<real>0.0</real>
</map>
<key>TextureFetchSource</key>
<key>TextureFetchUpdateMinCount</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>
<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>
@ -12713,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>
@ -12867,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>

View File

@ -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
RenderPBR 1 1

View File

@ -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

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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) );
}

View File

@ -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)
{

View File

@ -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();
}

View File

@ -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

View File

@ -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,

View File

@ -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
** **

View File

@ -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)

View File

@ -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);
};

View File

@ -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)

View File

@ -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,

View File

@ -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.

View File

@ -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 |

View File

@ -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())
{

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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
{

View File

@ -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);

View File

@ -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));

View File

@ -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.

View File

@ -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>);

View File

@ -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)

View File

@ -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.
*

View File

@ -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[] ;

View File

@ -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;

View File

@ -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 ;

View File

@ -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
if (imagep->isInDebug() || imagep->isUnremovable())
{
//update_counter--;
return; //is in debug, ignore.
}
//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();
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() ;
}
}
//reset texture state.
imagep->setInactive();
}
}
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();
if (!imagep->isInImageList())
{
return;
}
if (imagep->isInFastCacheList())
{
return; //wait for loading from the fast cache.
}
//reset texture state.
imagep->setInactive() ;
}
}
if (!imagep->isInImageList())
{
continue;
}
if(imagep->isInFastCacheList())
{
continue; //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
LLTimer image_op_timer;
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())))
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

View File

@ -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:

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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))
{

View File

@ -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);
}

View File

@ -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))

Some files were not shown because too many files have changed in this diff Show More