diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2021-11-23 21:23:45 -0500 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2021-11-23 21:23:45 -0500 |
commit | d71e0a6d4778d4c67b8793ba569fee2db226bc8e (patch) | |
tree | dce713230aa611dbada3c6f78903d988b1ae06a4 /indra/llrender | |
parent | 67ace0df9953ce3264048c3946720a9df492edfa (diff) | |
parent | 8852cb9cbd25df8d25fa43cf39b222ab8381ebd6 (diff) |
SL-16094, SL-16400: Merge branch 'DRTVWR-546' into glthread
Diffstat (limited to 'indra/llrender')
-rw-r--r-- | indra/llrender/llgl.cpp | 3 | ||||
-rw-r--r-- | indra/llrender/llglslshader.cpp | 13 | ||||
-rw-r--r-- | indra/llrender/llglslshader.h | 8 | ||||
-rw-r--r-- | indra/llrender/llimagegl.cpp | 89 | ||||
-rw-r--r-- | indra/llrender/llimagegl.h | 27 | ||||
-rw-r--r-- | indra/llrender/llrender.cpp | 2 | ||||
-rw-r--r-- | indra/llrender/llshadermgr.cpp | 5 | ||||
-rw-r--r-- | indra/llrender/llshadermgr.h | 2 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 54 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.h | 22 |
10 files changed, 160 insertions, 65 deletions
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index c7f85aec21..b49b14615f 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1095,8 +1095,7 @@ void LLGLManager::initExtensions() mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts); mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts); mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts); - //mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts); - mHasDepthClamp = FALSE; + mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts); // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad #ifdef GL_ARB_framebuffer_object mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts); diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 08c9dd8769..2f1ce0eec9 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -970,6 +970,19 @@ void LLGLSLShader::bind() } } +void LLGLSLShader::bind(bool rigged) +{ + if (rigged) + { + llassert(mRiggedVariant); + mRiggedVariant->bind(); + } + else + { + bind(); + } +} + void LLGLSLShader::unbind() { LL_PROFILE_ZONE_SCOPED; diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 3b23cf1b28..6fdb789087 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -230,6 +230,8 @@ public: BOOL link(BOOL suppress_errors = FALSE); void bind(); + //helper to conditionally bind mRiggedVariant instead of this + void bind(bool rigged); void unbind(); // Unbinds any previously bound shader by explicitly binding no shader. @@ -267,7 +269,8 @@ public: LLShaderFeatures mFeatures; std::vector< std::pair< std::string, GLenum > > mShaderFiles; std::string mName; - boost::unordered_map<std::string, std::string> mDefines; + typedef std::unordered_map<std::string, std::string> defines_map_t; + defines_map_t mDefines; //statistcis for profiling shader performance U32 mTimerQuery; @@ -285,6 +288,9 @@ public: std::vector<U32> mTextureMagFilter; std::vector<U32> mTextureMinFilter; + // this pointer should be set to whichever shader represents this shader's rigged variant + LLGLSLShader* mRiggedVariant = nullptr; + private: void unloadInternal(); }; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 894eb8c773..ed0e3fb345 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -172,19 +172,31 @@ 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::createInstance(window); + LLImageGLThread::sInstance = new LLImageGLThread(window); + LLImageGLThread::sInstance->start(); +} + +//static +void LLImageGL::updateClass() +{ + LL_PROFILE_ZONE_SCOPED; + LLImageGLThread::sInstance->executeCallbacks(); } //static void LLImageGL::cleanupClass() { LL_PROFILE_ZONE_SCOPED; - LLImageGLThread::deleteSingleton(); + LLImageGLThread::sInstance->mFunctionQueue.close(); + delete LLImageGLThread::sInstance; + LLImageGLThread::sInstance = nullptr; } //static @@ -492,9 +504,6 @@ void LLImageGL::init(BOOL usemipmaps) #endif mCategory = -1; - - // Sometimes we have to post work for the main thread. - mMainQueue = LL::WorkQueue::getInstance("mainloop"); } void LLImageGL::cleanup() @@ -1527,7 +1536,8 @@ 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 (! on_main_thread()) + if (LLImageGLThread::sInstance != nullptr && + LLThread::currentID() == LLImageGLThread::sInstance->getID()) { { LL_PROFILE_ZONE_NAMED("cglt - sync"); @@ -1544,9 +1554,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } ref(); - LL::WorkQueue::postMaybe( - mMainQueue, - [=]() + LLImageGLThread::sInstance->postCallback([=]() { LL_PROFILE_ZONE_NAMED("cglt - delete callback"); if (old_texname != 0) @@ -2251,11 +2259,7 @@ void LLImageGL::resetCurTexSizebar() */ 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) - , mWindow(window) + : LLThread("LLImageGL"), mWindow(window) { LL_PROFILE_ZONE_SCOPED; mFinished = false; @@ -2264,6 +2268,61 @@ LLImageGLThread::LLImageGLThread(LLWindow* window) ThreadPool::start(); } +// post a function to be executed on the LLImageGL background thread + +bool LLImageGLThread::post(const std::function<void()>& func) +{ + try + { + mFunctionQueue.post(func); + } + catch (LLThreadSafeQueueInterrupt e) + { + return false; + } + + return true; +} + +//post a callback to be executed on the main thread + +bool LLImageGLThread::postCallback(const std::function<void()>& callback) +{ + try + { + if (!mCallbackQueue.tryPost(callback)) + { + mPendingCallbackQ.push(callback); + } + } + catch (LLThreadSafeQueueInterrupt e) + { + //thread is closing, drop request + return false; + } + + return true; +} + +void LLImageGLThread::executeCallbacks() +{ + LL_PROFILE_ZONE_SCOPED; + //executed from main thread + mCallbackQueue.runPending(); + + while (!mPendingCallbackQ.empty()) + { + if (mCallbackQueue.tryPost(mPendingCallbackQ.front())) + { + mPendingCallbackQ.pop(); + } + else + { + break; + } + } +} + void LLImageGLThread::run() { LL_PROFILE_ZONE_SCOPED; @@ -2271,7 +2330,7 @@ void LLImageGLThread::run() // WorkQueue, likewise cleanup afterwards. mWindow->makeContextCurrent(mContext); gGL.init(); - ThreadPool::run(); + mFunctionQueue.runUntilClose(); gGL.shutdown(); mWindow->destroySharedContext(mContext); } diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index ae773bb362..bb46dbc639 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -37,7 +37,6 @@ #include "llunits.h" #include "llthreadsafequeue.h" #include "llrender.h" -#include "threadpool.h" #include "workqueue.h" class LLTextureAtlas ; @@ -199,7 +198,6 @@ private: void freePickMask(); LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL - LL::WorkQueue::weak_t mMainQueue; U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel U16 mPickMaskWidth; U16 mPickMaskHeight; @@ -273,6 +271,7 @@ public: public: static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false); + static void updateClass(); static void cleanupClass() ; private: @@ -308,24 +307,34 @@ public: }; -class LLImageGLThread : public LLSimpleton<LLImageGLThread>, LL::ThreadPool +class LLImageGLThread : public LLThread { public: LLImageGLThread(LLWindow* window); // post a function to be executed on the LLImageGL background thread - template <typename CALLABLE> - bool post(CALLABLE&& func) - { - return getQueue().postIfOpen(std::forward<CALLABLE>(func)); - } + bool post(const std::function<void()>& func); + + //post a callback to be executed on the main thread + bool postCallback(const std::function<void()>& callback); + + void executeCallbacks(); void run() override; -private: + // Work Queue for background thread + LL::WorkQueue mFunctionQueue; + + // Work Queue for main thread (run from updateClass) + LL::WorkQueue mCallbackQueue; + LLWindow* mWindow; void* mContext = nullptr; LLAtomicBool mFinished; + + std::queue<std::function<void()>> mPendingCallbackQ; + + static LLImageGLThread* sInstance; }; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index aad04beea2..0c180ed50d 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1283,7 +1283,7 @@ void LLRender::syncLightState() void LLRender::syncMatrices() { - static const U32 name[] = + static const U32 name[] = { LLShaderMgr::MODELVIEW_MATRIX, LLShaderMgr::PROJECTION_MATRIX, diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index e8c6295930..a9a4314afa 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -165,6 +165,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) if (features->hasObjectSkinning) { + shader->mRiggedVariant = shader; if (!shader->attachVertexObject("avatar/objectSkinV.glsl")) { return FALSE; @@ -599,7 +600,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string& } } -GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines, S32 texture_index_channels) +GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines, S32 texture_index_channels) { // endsure work-around for missing GLSL funcs gets propogated to feature shader files (e.g. srgbF.glsl) @@ -774,7 +775,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (defines) { - for (boost::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter) + for (std::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter) { std::string define = "#define " + iter->first + " " + iter->second + "\n"; extra_code_text[extra_code_count++] = (GLcharARB *) strdup(define.c_str()); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 3908efd4ec..67c0d6ab10 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -264,7 +264,7 @@ public: void dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text); BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE); BOOL validateProgramObject(GLhandleARB obj); - GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1); + GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1); // Implemented in the application to actually point to the shader directory. virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 5ea07ddcb1..46654cc5b9 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -157,12 +157,12 @@ LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType) std::fill(mMissCount.begin(), mMissCount.end(), 0); } -volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) +U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) { LL_PROFILE_ZONE_SCOPED llassert(vbo_block_size(size) == size); - volatile U8* ret = NULL; + U8* ret = NULL; U32 i = vbo_block_index(size); @@ -256,7 +256,7 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) return ret; } -void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size) +void LLVBOPool::release(U32 name, U8* buffer, U32 size) { llassert(vbo_block_size(size) == size); @@ -749,7 +749,7 @@ void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 mMappable = false; gGL.syncMatrices(); - U16* idx = ((U16*)(U8*)mAlignedIndexOffset) + indices_offset; + U16* idx = ((U16*)getIndicesPointer()) + indices_offset; LL_PROFILER_GPU_ZONEC("gl.DrawRangeElements", 0xFFFF00) glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, @@ -1539,7 +1539,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) // Map for data access -volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) +U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) { LL_PROFILE_ZONE_SCOPED; bindGLBuffer(true); @@ -1601,7 +1601,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo } else { - volatile U8* src = NULL; + U8* src = NULL; waitFence(); if (gGLManager.mHasMapBufferRange) { @@ -1660,7 +1660,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo llassert(src != NULL); - mMappedData = LL_NEXT_ALIGNED_ADDRESS<volatile U8>(src); + mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); mAlignedOffset = mMappedData - src; stop_glerror(); @@ -1716,7 +1716,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo } -volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) +U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) { LL_PROFILE_ZONE_SCOPED; bindGLIndices(true); @@ -1786,7 +1786,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range } else { - volatile U8* src = NULL; + U8* src = NULL; waitFence(); if (gGLManager.mHasMapBufferRange) { @@ -2068,7 +2068,7 @@ template <class T,S32 type> struct VertexBufferStrider { if (type == LLVertexBuffer::TYPE_INDEX) { - volatile U8* ptr = vbo.mapIndexBuffer(index, count, map_range); + U8* ptr = vbo.mapIndexBuffer(index, count, map_range); if (ptr == NULL) { @@ -2084,7 +2084,7 @@ template <class T,S32 type> struct VertexBufferStrider { S32 stride = LLVertexBuffer::sTypeSize[type]; - volatile U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); + U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); if (ptr == NULL) { @@ -2454,29 +2454,37 @@ void LLVertexBuffer::setBuffer(U32 data_mask) void LLVertexBuffer::setBufferFast(U32 data_mask) { - //set up pointers if the data mask is different ... - bool setup = (sLastMask != data_mask); + if (useVBOs()) + { + //set up pointers if the data mask is different ... + bool setup = (sLastMask != data_mask); - - const bool bindBuffer = bindGLBufferFast(); - const bool bindIndices = bindGLIndicesFast(); + const bool bindBuffer = bindGLBufferFast(); + const bool bindIndices = bindGLIndicesFast(); - setup = setup || bindBuffer || bindIndices; + setup = setup || bindBuffer || bindIndices; + + setupClientArrays(data_mask); - setupClientArrays(data_mask); - - if (data_mask && setup) + if (data_mask && setup) + { + setupVertexBufferFast(data_mask); + sSetCount++; + } + } + else { - setupVertexBufferFast(data_mask); - sSetCount++; + //fallback to slow path when not using VBOs + setBuffer(data_mask); } } + // virtual (default) void LLVertexBuffer::setupVertexBuffer(U32 data_mask) { stop_glerror(); - volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; + U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; if (gDebugGL && ((data_mask & mTypeMask) != data_mask)) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 1b400b3aad..baf8407fc6 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -64,10 +64,10 @@ public: const U32 mType; //size MUST be a power of 2 - volatile U8* allocate(U32& name, U32 size, bool for_seed = false); + U8* allocate(U32& name, U32 size, bool for_seed = false); //size MUST be the size provided to allocate that returned the given name - void release(U32 name, volatile U8* buffer, U32 size); + void release(U32 name, U8* buffer, U32 size); //batch allocate buffers to be provided to the application on demand void seedPool(); @@ -82,7 +82,7 @@ public: { public: U32 mGLName; - volatile U8* mClientData; + U8* mClientData; }; typedef std::list<Record> record_list_t; @@ -234,8 +234,8 @@ public: LLVertexBuffer(U32 typemask, S32 usage); // map for data access - volatile U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); - volatile U8* mapIndexBuffer(S32 index, S32 count, bool map_range); + U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); + U8* mapIndexBuffer(S32 index, S32 count, bool map_range); void bindForFeedback(U32 channel, U32 type, U32 index, U32 count); @@ -278,14 +278,14 @@ public: S32 getNumVerts() const { return mNumVerts; } S32 getNumIndices() const { return mNumIndices; } - volatile U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } - volatile U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } + U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } + U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } U32 getTypeMask() const { return mTypeMask; } bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); } S32 getSize() const; S32 getIndicesSize() const { return mIndicesSize; } - volatile U8* getMappedData() const { return mMappedData; } - volatile U8* getMappedIndices() const { return mMappedIndexData; } + U8* getMappedData() const { return mMappedData; } + U8* getMappedIndices() const { return mMappedIndexData; } S32 getOffset(S32 type) const { return mOffsets[type]; } S32 getUsage() const { return mUsage; } bool isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? true : false; } @@ -318,8 +318,8 @@ protected: U32 mGLIndices; // GL IBO handle U32 mGLArray; // GL VAO handle - volatile U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) - volatile U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) + U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) + U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) U32 mMappedDataUsingVBOs : 1; U32 mMappedIndexDataUsingVBOs : 1; |