diff options
author | Dave Parks <davep@lindenlab.com> | 2021-10-11 16:03:40 +0000 |
---|---|---|
committer | Dave Parks <davep@lindenlab.com> | 2021-10-11 16:03:40 +0000 |
commit | d00272e0cc9974f35a46f0c313ee2c0e11cddbda (patch) | |
tree | 48e1e3cc9c89107c28e58b69a35e25802c84014c /indra/llrender | |
parent | 2238f89db70a754614b01bb85adc5f16a63e7eb4 (diff) |
SL-16099 Multi-threaded OpenGL usage on Windows, enable Core Profile and VAOs by default.
Diffstat (limited to 'indra/llrender')
-rw-r--r-- | indra/llrender/llcubemap.cpp | 2 | ||||
-rw-r--r-- | indra/llrender/llfontfreetype.cpp | 1 | ||||
-rw-r--r-- | indra/llrender/llglslshader.cpp | 2 | ||||
-rw-r--r-- | indra/llrender/llgltexture.cpp | 2 | ||||
-rw-r--r-- | indra/llrender/llimagegl.cpp | 330 | ||||
-rw-r--r-- | indra/llrender/llimagegl.h | 35 | ||||
-rw-r--r-- | indra/llrender/llrender.cpp | 2 | ||||
-rw-r--r-- | indra/llrender/llrender.h | 2 |
8 files changed, 260 insertions, 116 deletions
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 5947bca670..d7f7b2f58e 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -150,6 +150,7 @@ void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages void LLCubeMap::initGLData() { + LL_PROFILE_ZONE_SCOPED; for (int i = 0; i < 6; i++) { mImages[i]->setSubImage(mRawImages[i], 0, 0, RESOLUTION, RESOLUTION); @@ -453,6 +454,7 @@ BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max, void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col) { + LL_PROFILE_ZONE_SCOPED; F32 v_min, v_max, h_min, h_max; LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3]; center.normVec(); diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index c41730ebaa..e18161e53c 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -460,6 +460,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const { + LL_PROFILE_ZONE_SCOPED; if (mFTFace == NULL) return NULL; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 2fb3b8257d..394fcd2b2f 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -208,6 +208,7 @@ void LLGLSLShader::dumpStats() //static void LLGLSLShader::startProfile() { + LL_PROFILE_ZONE_SCOPED; if (sProfileEnabled && sCurBoundShaderPtr) { sCurBoundShaderPtr->placeProfileQuery(); @@ -218,6 +219,7 @@ void LLGLSLShader::startProfile() //static void LLGLSLShader::stopProfile(U32 count, U32 mode) { + LL_PROFILE_ZONE_SCOPED; if (sProfileEnabled && sCurBoundShaderPtr) { sCurBoundShaderPtr->readProfileQuery(count, mode); diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index ad501687ed..a279e85bae 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -262,6 +262,7 @@ LLTexUnit::eTextureType LLGLTexture::getTarget(void) const BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) { + LL_PROFILE_ZONE_SCOPED; llassert(mGLTexturep.notNull()) ; return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ; @@ -269,6 +270,7 @@ BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) { + LL_PROFILE_ZONE_SCOPED; llassert(mGLTexturep.notNull()) ; return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 276fa55e15..aff29bd857 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -39,6 +39,7 @@ #include "llgl.h" #include "llglslshader.h" #include "llrender.h" +#include "llwindow.h" //---------------------------------------------------------------------------- const F32 MIN_TEXTURE_LIFETIME = 10.f; @@ -170,15 +171,32 @@ BOOL is_little_endian() return (*c == 0x78) ; } + +LLImageGLThread* LLImageGLThread::sInstance = nullptr; + //static -void LLImageGL::initClass(S32 num_catagories, BOOL skip_analyze_alpha /* = false */) +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(); +} + +//static +void LLImageGL::updateClass() +{ + LL_PROFILE_ZONE_SCOPED; + LLImageGLThread::sInstance->executeCallbacks(); } //static void LLImageGL::cleanupClass() -{ +{ + LL_PROFILE_ZONE_SCOPED; + LLImageGLThread::sInstance->mFunctionQueue.close(); + delete LLImageGLThread::sInstance; + LLImageGLThread::sInstance = nullptr; } //static @@ -656,6 +674,7 @@ void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_for void LLImageGL::setImage(const LLImageRaw* imageraw) { + LL_PROFILE_ZONE_SCOPED; llassert((imageraw->getWidth() == getWidth(mCurrentDiscardLevel)) && (imageraw->getHeight() == getHeight(mCurrentDiscardLevel)) && (imageraw->getComponents() == getComponents())); @@ -699,9 +718,8 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } llverify(gGL.getTexUnit(0)->bind(this)); - - - if (mUseMipMaps) + + if (mUseMipMaps) { if (data_hasmips) { @@ -781,7 +799,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE); } - LLImageGL::setManualImage(mTarget, 0, mFormatInternal, + LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, data_in, mAllowCompression); @@ -878,7 +896,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) stop_glerror(); } - LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression); + LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression); if (m == 0) { analyzeAlpha(data_in, w, h); @@ -1067,6 +1085,7 @@ void LLImageGL::postAddToAtlas() BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) { + LL_PROFILE_ZONE_SCOPED; if (!width || !height) { return TRUE; @@ -1163,6 +1182,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) { + LL_PROFILE_ZONE_SCOPED; return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update); } @@ -1201,119 +1221,119 @@ void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) // static static LLTrace::BlockTimerStatHandle FTM_SET_MANUAL_IMAGE("setManualImage"); -void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression) +void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void* pixels, bool allow_compression) { - LL_RECORD_BLOCK_TIME(FTM_SET_MANUAL_IMAGE); - bool use_scratch = false; - U32* scratch = NULL; - if (LLRender::sGLCoreProfile) - { - if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) - { //GL_ALPHA is deprecated, convert to RGBA - use_scratch = true; - scratch = new U32[width*height]; + LL_RECORD_BLOCK_TIME(FTM_SET_MANUAL_IMAGE); + bool use_scratch = false; + U32* scratch = NULL; + if (LLRender::sGLCoreProfile) + { + if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) + { //GL_ALPHA is deprecated, convert to RGBA + use_scratch = true; + scratch = new U32[width * height]; - U32 pixel_count = (U32) (width*height); - for (U32 i = 0; i < pixel_count; i++) - { - U8* pix = (U8*) &scratch[i]; - pix[0] = pix[1] = pix[2] = 0; - pix[3] = ((U8*) pixels)[i]; - } - - pixformat = GL_RGBA; - intformat = GL_RGBA8; - } + U32 pixel_count = (U32)(width * height); + for (U32 i = 0; i < pixel_count; i++) + { + U8* pix = (U8*)&scratch[i]; + pix[0] = pix[1] = pix[2] = 0; + pix[3] = ((U8*)pixels)[i]; + } - if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) - { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA - use_scratch = true; - scratch = new U32[width*height]; + pixformat = GL_RGBA; + intformat = GL_RGBA8; + } - U32 pixel_count = (U32) (width*height); - for (U32 i = 0; i < pixel_count; i++) - { - U8 lum = ((U8*) pixels)[i*2+0]; - U8 alpha = ((U8*) pixels)[i*2+1]; + if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) + { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA + use_scratch = true; + scratch = new U32[width * height]; - U8* pix = (U8*) &scratch[i]; - pix[0] = pix[1] = pix[2] = lum; - pix[3] = alpha; - } - - pixformat = GL_RGBA; - intformat = GL_RGBA8; - } + U32 pixel_count = (U32)(width * height); + for (U32 i = 0; i < pixel_count; i++) + { + U8 lum = ((U8*)pixels)[i * 2 + 0]; + U8 alpha = ((U8*)pixels)[i * 2 + 1]; - if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) - { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB - use_scratch = true; - scratch = new U32[width*height]; + U8* pix = (U8*)&scratch[i]; + pix[0] = pix[1] = pix[2] = lum; + pix[3] = alpha; + } - U32 pixel_count = (U32) (width*height); - for (U32 i = 0; i < pixel_count; i++) - { - U8 lum = ((U8*) pixels)[i]; - - U8* pix = (U8*) &scratch[i]; - pix[0] = pix[1] = pix[2] = lum; - pix[3] = 255; - } - - pixformat = GL_RGBA; - intformat = GL_RGB8; - } - } + pixformat = GL_RGBA; + intformat = GL_RGBA8; + } - if (LLImageGL::sCompressTextures && allow_compression) - { - switch (intformat) - { - case GL_RGB: - case GL_RGB8: - intformat = GL_COMPRESSED_RGB; - break; - case GL_SRGB: - case GL_SRGB8: - intformat = GL_COMPRESSED_SRGB; - break; - case GL_RGBA: - case GL_RGBA8: - intformat = GL_COMPRESSED_RGBA; - break; - case GL_SRGB_ALPHA: - case GL_SRGB8_ALPHA8: - intformat = GL_COMPRESSED_SRGB_ALPHA; - break; - case GL_LUMINANCE: - case GL_LUMINANCE8: - intformat = GL_COMPRESSED_LUMINANCE; - break; - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE8_ALPHA8: - intformat = GL_COMPRESSED_LUMINANCE_ALPHA; - break; - case GL_ALPHA: - case GL_ALPHA8: - intformat = GL_COMPRESSED_ALPHA; - break; - default: - LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL; - break; - } - } + if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) + { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB + use_scratch = true; + scratch = new U32[width * height]; - stop_glerror(); - { - LL_PROFILE_ZONE_NAMED("glTexImage2D"); - glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); - } - stop_glerror(); + U32 pixel_count = (U32)(width * height); + for (U32 i = 0; i < pixel_count; i++) + { + U8 lum = ((U8*)pixels)[i]; - if (use_scratch) - { - delete [] scratch; - } + U8* pix = (U8*)&scratch[i]; + pix[0] = pix[1] = pix[2] = lum; + pix[3] = 255; + } + + pixformat = GL_RGBA; + intformat = GL_RGB8; + } + } + + if (LLImageGL::sCompressTextures && allow_compression) + { + switch (intformat) + { + case GL_RGB: + case GL_RGB8: + intformat = GL_COMPRESSED_RGB; + break; + case GL_SRGB: + case GL_SRGB8: + intformat = GL_COMPRESSED_SRGB; + break; + case GL_RGBA: + case GL_RGBA8: + intformat = GL_COMPRESSED_RGBA; + break; + case GL_SRGB_ALPHA: + case GL_SRGB8_ALPHA8: + intformat = GL_COMPRESSED_SRGB_ALPHA; + break; + case GL_LUMINANCE: + case GL_LUMINANCE8: + intformat = GL_COMPRESSED_LUMINANCE; + break; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE8_ALPHA8: + intformat = GL_COMPRESSED_LUMINANCE_ALPHA; + break; + case GL_ALPHA: + case GL_ALPHA8: + intformat = GL_COMPRESSED_ALPHA; + break; + default: + LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL; + break; + } + } + + stop_glerror(); + { + LL_PROFILE_ZONE_NAMED("glTexImage2D"); + glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); + } + stop_glerror(); + + if (use_scratch) + { + delete[] scratch; + } } //create an empty GL texture: just create a texture name @@ -1336,6 +1356,7 @@ BOOL LLImageGL::createGLTexture() if(mTexName) { LLImageGL::deleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ; + mTexName = 0; } @@ -1697,7 +1718,7 @@ void LLImageGL::destroyGLTexture() mTextureMemory = (S32Bytes)0; } - LLImageGL::deleteTextures(1, &mTexName); + LLImageGL::deleteTextures(1, &mTexName); mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mTexName = 0; mGLTextureCreated = FALSE ; @@ -2238,3 +2259,90 @@ void LLImageGL::resetCurTexSizebar() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips); */ + +LLImageGLThread::LLImageGLThread(LLWindow* window) + : LLThread("LLImageGL"), mWindow(window) +{ + mFinished = false; + + mContext = mWindow->createSharedContext(); +} + +// post a function to be executed on the LLImageGL background thread + +bool LLImageGLThread::post(const std::function<void()>& func) +{ + try + { + if (mFunctionQueue.size() < mFunctionQueue.capacity()) + { + //NOTE: tryPushFront will return immediately if the lock is held + // desired behavior here is to push and return true unless the + // queue is full or closed + mFunctionQueue.pushFront(func); + } + else + { + return false; + } + } + 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 + { + mCallbackQueue.pushFront(callback); + } + catch (LLThreadSafeQueueInterrupt e) + { + //thread is closing, drop request + return false; + } + + return true; +} + +void LLImageGLThread::executeCallbacks() +{ + LL_PROFILE_ZONE_SCOPED; + //executed from main thread + std::function<void()> callback; + while (mCallbackQueue.tryPopBack(callback)) + { + LL_PROFILE_ZONE_NAMED("iglt - callback"); + callback(); + } +} + +void LLImageGLThread::run() +{ + mWindow->makeContextCurrent(mContext); + gGL.init(); + try + { + while (true) + { + LL_PROFILE_ZONE_SCOPED; + std::function<void()> curFunc = mFunctionQueue.popBack(); + { + LL_PROFILE_ZONE_NAMED("iglt - function") + curFunc(); + } + } + } + catch (LLThreadSafeQueueInterrupt e) + { + //queue is closed, fall out of run loop + } + gGL.shutdown(); + mWindow->destroySharedContext(mContext); +} diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 61ddc8d59b..8e9b483c2d 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -35,9 +35,11 @@ #include "llrefcount.h" #include "v2math.h" #include "llunits.h" - +#include "llthreadsafequeue.h" #include "llrender.h" class LLTextureAtlas ; +class LLWindow; + #define BYTES_TO_MEGA_BYTES(x) ((x) >> 20) #define MEGA_BYTES_TO_BYTES(x) ((x) << 20) @@ -102,7 +104,7 @@ public: void setAllowCompression(bool allow) { mAllowCompression = allow; } static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true); - + BOOL createGLTexture() ; BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = sMaxCategories-1); @@ -265,7 +267,8 @@ public: #endif public: - static void initClass(S32 num_catagories, BOOL skip_analyze_alpha = false); + static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false); + static void updateClass(); static void cleanupClass() ; private: @@ -301,4 +304,30 @@ public: }; +class LLImageGLThread : public LLThread +{ +public: + LLImageGLThread(LLWindow* window); + + // post a function to be executed on the LLImageGL background thread + 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; + + LLThreadSafeQueue<std::function<void()>> mFunctionQueue; + LLThreadSafeQueue<std::function<void()>> mCallbackQueue; + + LLWindow* mWindow; + void* mContext; + LLAtomicBool mFinished; + + static LLImageGLThread* sInstance; +}; + + #endif // LL_LLIMAGEGL_H diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 43b4441ea8..b6711e44e3 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -36,7 +36,7 @@ #include "lltexture.h" #include "llshadermgr.h" -LLRender gGL; +thread_local LLRender gGL; // Handy copies of last good GL matrices F32 gGLModelView[16]; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index af8568f8a3..c08c2d6881 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -511,7 +511,7 @@ extern F32 gGLLastProjection[16]; extern F32 gGLProjection[16]; extern S32 gGLViewport[4]; -extern LLRender gGL; +extern thread_local LLRender gGL; // This rotation matrix moves the default OpenGL reference frame // (-Z at, Y up) to Cory's favorite reference frame (X at, Z up) |