diff options
-rw-r--r-- | indra/llcommon/llsingleton.h | 20 | ||||
-rw-r--r-- | indra/llcommon/threadpool.cpp | 7 | ||||
-rw-r--r-- | indra/llcommon/threadpool.h | 18 | ||||
-rw-r--r-- | indra/llrender/llimagegl.cpp | 22 | ||||
-rw-r--r-- | indra/llrender/llimagegl.h | 11 | ||||
-rw-r--r-- | indra/newview/llviewertexture.cpp | 34 | ||||
-rw-r--r-- | indra/newview/llviewertexture.h | 4 |
7 files changed, 76 insertions, 40 deletions
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 24d01812c9..fdd5bdfea9 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -847,22 +847,24 @@ template<class T> class LLSimpleton { public: - static T* sInstance; - - static void createInstance() - { + template <typename... ARGS> + static void createInstance(ARGS&&... args) + { llassert(sInstance == nullptr); - sInstance = new T(); + sInstance = new T(std::forward<ARGS>(args)...); } - + static inline T* getInstance() { return sInstance; } static inline T& instance() { return *getInstance(); } static inline bool instanceExists() { return sInstance != nullptr; } - static void deleteSingleton() { - delete sInstance; - sInstance = nullptr; + static void deleteSingleton() { + delete sInstance; + sInstance = nullptr; } + +private: + static T* sInstance; }; template <class T> diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index e4fa0eccf3..cf25cc838e 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -70,6 +70,11 @@ void LL::ThreadPool::close() void LL::ThreadPool::run(const std::string& name) { LL_DEBUGS("ThreadPool") << name << " starting" << LL_ENDL; - mQueue.runUntilClose(); + run(); LL_DEBUGS("ThreadPool") << name << " stopping" << LL_ENDL; } + +void LL::ThreadPool::run() +{ + mQueue.runUntilClose(); +} diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index 6e3858508b..1ca24aec58 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -30,9 +30,25 @@ namespace LL * relevant WorkQueue. */ ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024); - ~ThreadPool(); + virtual ~ThreadPool(); + + /** + * ThreadPool listens for application shutdown messages on the "LLApp" + * LLEventPump. Call close() to shut down this ThreadPool early. + */ void close(); + std::string getName() const { return mName; } + size_t getWidth() const { return mThreads.size(); } + /// obtain a non-const reference to the WorkQueue to post work to it + WorkQueue& getQueue() { return mQueue; } + + /** + * Override run() if you need special processing. The default run() + * implementation simply calls WorkQueue::runUntilClose(). + */ + virtual void run(); + private: void run(const std::string& name); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 71c48801ac..1b6920fe3b 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -172,24 +172,19 @@ BOOL is_little_endian() return (*c == 0x78) ; } -LLImageGLThread* LLImageGLThread::sInstance = nullptr; - //static void LLImageGL::initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha /* = false */) { LL_PROFILE_ZONE_SCOPED; sSkipAnalyzeAlpha = skip_analyze_alpha; - LLImageGLThread::sInstance = new LLImageGLThread(window); - LLImageGLThread::sInstance->start(); + LLImageGLThread::createInstance(window); } //static void LLImageGL::cleanupClass() { LL_PROFILE_ZONE_SCOPED; - LLImageGLThread::sInstance->mFunctionQueue.close(); - delete LLImageGLThread::sInstance; - LLImageGLThread::sInstance = nullptr; + LLImageGLThread::deleteSingleton(); } //static @@ -1532,8 +1527,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread - if (LLImageGLThread::sInstance != nullptr && - LLThread::currentID() == LLImageGLThread::sInstance->getID()) + if (! on_main_thread()) { { LL_PROFILE_ZONE_NAMED("cglt - sync"); @@ -2257,7 +2251,11 @@ void LLImageGL::resetCurTexSizebar() */ LLImageGLThread::LLImageGLThread(LLWindow* window) - : LLThread("LLImageGL"), mWindow(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) + , mWindow(window) { mFinished = false; @@ -2266,9 +2264,11 @@ LLImageGLThread::LLImageGLThread(LLWindow* window) void LLImageGLThread::run() { + // We must perform setup on this thread before actually servicing our + // WorkQueue, likewise cleanup afterwards. mWindow->makeContextCurrent(mContext); gGL.init(); - mFunctionQueue.runUntilClose(); + ThreadPool::run(); gGL.shutdown(); mWindow->destroySharedContext(mContext); } diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index b9de481aae..27496def1d 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -37,6 +37,7 @@ #include "llunits.h" #include "llthreadsafequeue.h" #include "llrender.h" +#include "threadpool.h" #include "workqueue.h" class LLTextureAtlas ; @@ -307,7 +308,7 @@ public: }; -class LLImageGLThread : public LLThread +class LLImageGLThread : public LLSimpleton<LLImageGLThread>, LL::ThreadPool { public: LLImageGLThread(LLWindow* window); @@ -316,19 +317,15 @@ public: template <typename CALLABLE> bool post(CALLABLE&& func) { - return mFunctionQueue.postIfOpen(std::forward<CALLABLE>(func)); + return getQueue().postIfOpen(std::forward<CALLABLE>(func)); } void run() override; - // Work Queue for background thread - LL::WorkQueue mFunctionQueue; - +private: LLWindow* mWindow; void* mContext; LLAtomicBool mFinished; - - static LLImageGLThread* sInstance; }; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 9f3819f7d1..498e4ef8bc 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -679,6 +679,9 @@ void LLViewerTexture::init(bool firstinit) mVolumeList[LLRender::LIGHT_TEX].clear(); mVolumeList[LLRender::SCULPT_TEX].clear(); + + mMainQueue = LL::WorkQueue::getInstance("mainloop"); + mImageQueue = LL::WorkQueue::getInstance("LLImageGL"); } //virtual @@ -1622,17 +1625,26 @@ void LLViewerFetchedTexture::scheduleCreateTexture() { mNeedsCreateTexture = TRUE; #if LL_WINDOWS //flip to 0 to revert to single-threaded OpenGL texture uploads - if (!LLImageGLThread::sInstance->post([this]() - { - //actually create the texture on a background thread - createTexture(); - LL::WorkQueue::getInstance("mainloop")->post([this]() - { - //finalize on main thread - postCreateTexture(); - unref(); - }); - })) + auto mainq = mMainQueue.lock(); + if (mainq) + { + mainq->postTo( + mImageQueue, + // work to be done on LLImageGL worker thread + [this]() + { + //actually create the texture on a background thread + createTexture(); + }, + // callback to be run on main thread + [this]() + { + //finalize on main thread + postCreateTexture(); + unref(); + }); + } + else #endif { gTextureList.mCreateTextureList.insert(this); diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index f9f1bfef44..4cd4c7cd39 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -35,6 +35,7 @@ #include "llrender.h" #include "llmetricperformancetester.h" #include "httpcommon.h" +#include "workqueue.h" #include <map> #include <list> @@ -213,6 +214,9 @@ protected: //do not use LLPointer here. LLViewerMediaTexture* mParcelMedia ; + LL::WorkQueue::weak_t mMainQueue; + LL::WorkQueue::weak_t mImageQueue; + static F32 sTexelPixelRatio; public: static const U32 sCurrentFileVersion; |