diff options
author | cosmic-linden <111533034+cosmic-linden@users.noreply.github.com> | 2023-04-05 09:55:33 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-05 11:55:33 -0500 |
commit | d6d634d29ff351450306e211982a98a0050f1b42 (patch) | |
tree | 3c4b5a6779669756277fffaab320074476e17543 /indra | |
parent | b28971e4bf8cb41ea9eecead2b5676720355e30b (diff) |
SL-19331: Move media updates off-thread on select hardware (#153)
* SL-19331: Have media updates on the LLImageGL thread even when texture updates are on the main thread. Add config.
Off-thread media updates seem work best performance-wise when using glTexImage2D, not sub_image_lines. Otherwise, there are lots of main thread stalls.
* SL-19331: Bump featuretable
* SL-19331: Cleanup, annotate comment
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llrender/llimagegl.cpp | 44 | ||||
-rw-r--r-- | indra/llrender/llimagegl.h | 9 | ||||
-rw-r--r-- | indra/newview/app_settings/settings.xml | 15 | ||||
-rw-r--r-- | indra/newview/featuretable.txt | 8 | ||||
-rw-r--r-- | indra/newview/featuretable_mac.txt | 5 | ||||
-rw-r--r-- | indra/newview/lldrawpoolbump.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llstartup.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llviewermedia.cpp | 7 | ||||
-rw-r--r-- | indra/newview/llviewertexture.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llviewertexturelist.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llviewerwindow.cpp | 4 |
11 files changed, 63 insertions, 41 deletions
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 5b0690bc79..3e3a3095e3 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -42,6 +42,8 @@ #include "llwindow.h" #include "llframetimer.h" +extern LL_COMMON_API bool on_main_thread(); + #if !LL_IMAGEGL_THREAD_CHECK #define checkActiveThread() #endif @@ -132,7 +134,8 @@ bool LLImageGL::sCompressTextures = false; std::set<LLImageGL*> LLImageGL::sImageList; -bool LLImageGLThread::sEnabled = false; +bool LLImageGLThread::sEnabledTextures = false; +bool LLImageGLThread::sEnabledMedia = false; //**************************************************************************************************** //The below for texture auditing use only @@ -242,14 +245,16 @@ BOOL is_little_endian() } //static -void LLImageGL::initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha /* = false */, bool multi_threaded /* = false */) +void LLImageGL::initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha /* = false */, bool thread_texture_loads /* = false */, bool thread_media_updates /* = false */) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; sSkipAnalyzeAlpha = skip_analyze_alpha; - if (multi_threaded) + if (thread_texture_loads || thread_media_updates) { LLImageGLThread::createInstance(window); + LLImageGLThread::sEnabledTextures = thread_texture_loads; + LLImageGLThread::sEnabledMedia = thread_media_updates; } } @@ -260,6 +265,7 @@ void LLImageGL::cleanupClass() LLImageGLThread::deleteSingleton(); } + //static S32 LLImageGL::dataFormatBits(S32 dataformat) { @@ -1125,9 +1131,20 @@ U32 type_width_from_pixtype(U32 pixtype) return type_width; } +bool should_stagger_image_set(bool compressed) +{ +#if LL_DARWIN + return false; +#else + // glTexSubImage2D doesn't work with compressed textures on select tested Nvidia GPUs on Windows 10 -Cosmic,2023-03-08 + // Setting media textures off-thread seems faster when not using sub_image_lines (Nvidia/Windows 10) -Cosmic,2023-03-31 + return !compressed && on_main_thread(); +#endif +} + // Equivalent to calling glSetSubImage2D(target, miplevel, x_offset, y_offset, width, height, pixformat, pixtype, src), assuming the total width of the image is data_width // However, instead there are multiple calls to glSetSubImage2D on smaller slices of the image -void subImageLines(U32 target, S32 miplevel, S32 x_offset, S32 y_offset, S32 width, S32 height, U32 pixformat, U32 pixtype, const U8* src, S32 data_width) +void sub_image_lines(U32 target, S32 miplevel, S32 x_offset, S32 y_offset, S32 width, S32 height, U32 pixformat, U32 pixtype, const U8* src, S32 data_width) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -1223,11 +1240,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL; stop_glerror(); -#if LL_DARWIN - const bool use_sub_image = false; -#else - const bool use_sub_image = !isCompressed(); -#endif + const bool use_sub_image = should_stagger_image_set(isCompressed()); if (!use_sub_image) { // *TODO: Why does this work here, in setSubImage, but not in @@ -1238,7 +1251,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 } else { - subImageLines(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, sub_datap, data_width); + sub_image_lines(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, sub_datap, data_width); } gGL.getTexUnit(0)->disable(); stop_glerror(); @@ -1455,13 +1468,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt LL_PROFILE_ZONE_NUM(height); free_cur_tex_image(); -#if LL_DARWIN - const bool use_sub_image = false; -#else - // glTexSubImage2D doesn't work with compressed textures on select tested Nvidia GPUs on Windows 10 -Cosmic,2023-03-08 - // *TODO: Small chance that glCompressedTexImage2D/glCompressedTexSubImage2D may work better here - const bool use_sub_image = !compress; -#endif + const bool use_sub_image = should_stagger_image_set(compress); if (!use_sub_image) { LL_PROFILE_ZONE_NAMED("glTexImage2D alloc + copy"); @@ -1479,7 +1486,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt if (src) { LL_PROFILE_ZONE_NAMED("glTexImage2D copy"); - subImageLines(target, miplevel, 0, 0, width, height, pixformat, pixtype, src, width); + sub_image_lines(target, miplevel, 0, 0, width, height, pixformat, pixtype, src, width); } } alloc_tex_image(width, height, pixformat); @@ -2504,7 +2511,6 @@ LLImageGLThread::LLImageGLThread(LLWindow* window) , mWindow(window) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - sEnabled = true; mFinished = false; mContext = mWindow->createSharedContext(); diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 42f6efef77..87fb9e363e 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -287,7 +287,7 @@ public: #endif public: - static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false, bool multi_threaded = false); + static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false, bool thread_texture_loads = false, bool thread_media_updates = false); static void cleanupClass() ; private: @@ -329,8 +329,10 @@ public: class LLImageGLThread : public LLSimpleton<LLImageGLThread>, LL::ThreadPool { public: - // follows gSavedSettings "RenderGLMultiThreaded" - static bool sEnabled; + // follows gSavedSettings "RenderGLMultiThreadedTextures" + static bool sEnabledTextures; + // follows gSavedSettings "RenderGLMultiThreadedMedia" + static bool sEnabledMedia; LLImageGLThread(LLWindow* window); @@ -349,5 +351,4 @@ private: LLAtomicBool mFinished; }; - #endif // LL_LLIMAGEGL_H diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4490e3eec2..9ae33a85b4 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9909,10 +9909,21 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderGLMultiThreaded</key> + <key>RenderGLMultiThreadedTextures</key> <map> <key>Comment</key> - <string>Allow OpenGL to use multiple render contexts (reduces frame stutters from loading textures, doesn't play nice with Intel drivers).</string> + <string>Allow OpenGL to use multiple render contexts for loading textures (may reduce frame stutters, doesn't play nice with Intel drivers).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderGLMultiThreadedMedia</key> + <map> + <key>Comment</key> + <string>Allow OpenGL to use multiple render contexts for playing media (may reduce frame stutters, doesn't play nice with Intel drivers)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 3d634c7484..99007d52c2 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 53 +version 54 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended @@ -70,7 +70,8 @@ RenderUseStreamVBO 1 1 RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 RenderGLContextCoreProfile 1 1 -RenderGLMultiThreaded 1 0 +RenderGLMultiThreadedTextures 1 0 +RenderGLMultiThreadedMedia 1 1 RenderReflectionProbeResolution 1 128 RenderScreenSpaceReflections 1 1 @@ -311,9 +312,10 @@ list Intel RenderAnisotropic 1 0 RenderFSAASamples 1 0 RenderGLContextCoreProfile 1 0 +RenderGLMultiThreadedMedia 1 0 list AMD -RenderGLMultiThreaded 1 1 +RenderGLMultiThreadedTextures 1 1 list GL3 RenderFSAASamples 0 0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index eed790ddac..24023901d9 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -1,4 +1,4 @@ -version 48 +version 49 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended @@ -67,7 +67,8 @@ RenderUseStreamVBO 1 1 RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 RenderGLContextCoreProfile 1 1 -RenderGLMultiThreaded 1 0 +RenderGLMultiThreadedTextures 1 0 +RenderGLMultiThreadedMedia 1 0 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 2 RenderScreenSpaceReflections 1 1 diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 763943f9cc..45c74776e1 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1042,7 +1042,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); #if LL_BUMPLIST_MULTITHREADED - auto tex_queue = LLImageGLThread::sEnabled ? sTexUpdateQueue.lock() : nullptr; + auto tex_queue = LLImageGLThread::sEnabledTextures ? sTexUpdateQueue.lock() : nullptr; if (tex_queue) { //dispatch creation to background thread @@ -1154,7 +1154,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI }; #if LL_BUMPLIST_MULTITHREADED - auto main_queue = LLImageGLThread::sEnabled ? sMainQueue.lock() : nullptr; + auto main_queue = LLImageGLThread::sEnabledTextures ? sMainQueue.lock() : nullptr; if (main_queue) { //dispatch texture upload to background thread, issue GPU commands to generate normal map on main thread diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 0dc4746123..6bcee31b72 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -312,7 +312,7 @@ void update_texture_fetch() LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread gTextureList.updateImages(0.10f); - if (LLImageGLThread::sEnabled) + if (LLImageGLThread::sEnabledTextures) { std::shared_ptr<LL::WorkQueue> main_queue = LL::WorkQueue::getInstance("mainloop"); main_queue->runFor(std::chrono::milliseconds(1)); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index aae3bd7f25..c8e279c991 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2878,7 +2878,7 @@ void LLViewerMediaImpl::update() if (preMediaTexUpdate(media_tex, data, data_width, data_height, x_pos, y_pos, width, height)) { // Push update to worker thread - auto main_queue = LLImageGLThread::sEnabled ? mMainQueue.lock() : nullptr; + auto main_queue = LLImageGLThread::sEnabledMedia ? mMainQueue.lock() : nullptr; if (main_queue) { mTextureUpdatePending = true; @@ -2967,11 +2967,12 @@ void LLViewerMediaImpl::doMediaTexUpdate(LLViewerMediaTexture* media_tex, U8* da // wrap "data" in an LLImageRaw but do NOT make a copy LLPointer<LLImageRaw> raw = new LLImageRaw(data, media_tex->getWidth(), media_tex->getHeight(), media_tex->getComponents(), true); - + // *NOTE: Recreating the GL texture each media update may seem wasteful // (note the texture creation in preMediaTexUpdate), however, it apparently // prevents GL calls from blocking, due to poor bookkeeping of state of - // updated textures by the OpenGL implementation. + // updated textures by the OpenGL implementation. (Windows 10/Nvidia) + // -Cosmic,2023-04-04 // Allocate GL texture based on LLImageRaw but do NOT copy to GL LLGLuint tex_name = 0; media_tex->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER, true, &tex_name); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index ca8cdbaea9..29c8700105 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1578,7 +1578,7 @@ void LLViewerFetchedTexture::scheduleCreateTexture() } #endif mNeedsCreateTexture = true; - auto mainq = LLImageGLThread::sEnabled ? mMainQueue.lock() : nullptr; + auto mainq = LLImageGLThread::sEnabledTextures ? mMainQueue.lock() : nullptr; if (mainq) { ref(); diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 09a1cd5148..1449844588 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1230,7 +1230,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time) LLViewerFetchedTexture* imagep = *iter++; imagep->updateFetch(); } - std::shared_ptr<LL::WorkQueue> main_queue = LLImageGLThread::sEnabled ? LL::WorkQueue::getInstance("mainloop") : NULL; + std::shared_ptr<LL::WorkQueue> main_queue = LLImageGLThread::sEnabledTextures ? LL::WorkQueue::getInstance("mainloop") : NULL; // Run threads S32 fetch_pending = 0; while (1) @@ -1239,7 +1239,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time) LLAppViewer::instance()->getImageDecodeThread()->update(1); // unpauses the image thread fetch_pending = LLAppViewer::instance()->getTextureFetch()->update(1); // unpauses the texture fetch thread - if (LLImageGLThread::sEnabled) + if (LLImageGLThread::sEnabledTextures) { main_queue->runFor(std::chrono::milliseconds(1)); fetch_pending += main_queue->size(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ad9e3da379..3fee3766a9 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1975,8 +1975,8 @@ LLViewerWindow::LLViewerWindow(const Params& p) } // Init the image list. Must happen after GL is initialized and before the images that - // LLViewerWindow needs are requested. - LLImageGL::initClass(mWindow, LLViewerTexture::MAX_GL_IMAGE_CATEGORY, false, gSavedSettings.getBOOL("RenderGLMultiThreaded")); + // LLViewerWindow needs are requested, as well as before LLViewerMedia starts updating images. + LLImageGL::initClass(mWindow, LLViewerTexture::MAX_GL_IMAGE_CATEGORY, false, gSavedSettings.getBOOL("RenderGLMultiThreadedTextures"), gSavedSettings.getBOOL("RenderGLMultiThreadedMedia")); gTextureList.init(); LLViewerTextureManager::init() ; gBumpImageList.init(); |