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.meow-7.2.2
parent
834e7ca088
commit
ff5496239b
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue