diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2021-11-05 12:33:31 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2021-11-05 12:33:31 -0400 | 
| commit | ff5496239bffadaca111b1e4380a01447f85843a (patch) | |
| tree | 990a2b72d8eea23f6ef7539079c515aab30625ac /indra | |
| parent | 834e7ca088b5f417235327cd290b42459c733594 (diff) | |
SL-16202: Use WorkQueue::postTo() for texture create/post handshake.
That is, when LLViewerFetchedTexture::scheduleCreateTexture() wants to call
createTexture() on the LLImageGLThread, but postCreateTexture() on the main
thread, use the "mainloop" WorkQueue to set up the handshake.
Give ThreadPool a public virtual run() method so a subclass can override with
desired behavior. This necessitates a virtual destructor. Add accessors for
embedded WorkQueue (for post calls), ThreadPool name and width (in threads).
Allow LLSimpleton::createInstance() to forward arguments to the subject
constructor.
Make LLImageGLThread an LLSimpleton - that abstraction didn't yet exist at the
time LLImageGLThread was coded. Also derive from ThreadPool rather than
LLThread. Make it a single-thread "pool" with a very large queue capacity.
Diffstat (limited to 'indra')
| -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;	  | 
