summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/llsingleton.h20
-rw-r--r--indra/llcommon/threadpool.cpp7
-rw-r--r--indra/llcommon/threadpool.h18
-rw-r--r--indra/llrender/llimagegl.cpp22
-rw-r--r--indra/llrender/llimagegl.h11
-rw-r--r--indra/newview/llviewertexture.cpp34
-rw-r--r--indra/newview/llviewertexture.h4
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;