From dc7b2adbebea2bd332de52d90dbbe651ee94031c Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 2 Oct 2024 15:25:11 -0700 Subject: secondlife/viewer#2472: Debug tools for labeling textures --- indra/llrender/llgltexture.cpp | 62 +++++++++++++++++++++ indra/llrender/llgltexture.h | 3 + indra/newview/app_settings/settings.xml | 11 ++++ indra/newview/llviewertexturelist.cpp | 98 ++++++++++++++++++++++++++++++++- indra/newview/llviewertexturelist.h | 11 ++++ 5 files changed, 183 insertions(+), 2 deletions(-) diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index 4dcca5a726..9a2b2ef524 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -168,6 +168,68 @@ bool LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, return ret ; } +void LLGLTexture::getGLObjectLabel(std::string& label, bool& error) const +{ + if (!mGLTexturep) + { + error = true; + label.clear(); + return; + } + LLGLuint texname = mGLTexturep->getTexName(); + if (!texname) + { + error = true; + label.clear(); + return; + } + static GLsizei max_length = 0; + if (max_length == 0) { glGetIntegerv(GL_MAX_LABEL_LENGTH, &max_length); } + static char * clabel = new char[max_length+1]; + GLsizei length; + glGetObjectLabel(GL_TEXTURE, texname, max_length+1, &length, clabel); + error = false; + label.assign(clabel, length); +} + +std::string LLGLTexture::setGLObjectLabel(const std::string& prefix, bool append_texname) const +{ + llassert(mGLTexturep); + if (mGLTexturep) + { + LLGLuint texname = mGLTexturep->getTexName(); + llassert(texname); + if (texname) + { + static GLsizei max_length = 0; + if (max_length == 0) { glGetIntegerv(GL_MAX_LABEL_LENGTH, &max_length); } + + if (append_texname) + { + std::string label_with_texname = prefix + "_" + std::to_string(texname); + label_with_texname.resize(std::min(size_t(max_length), label_with_texname.size())); + glObjectLabel(GL_TEXTURE, texname, (GLsizei)label_with_texname.size(), label_with_texname.c_str()); + return label_with_texname; + } + else + { + if (prefix.size() <= max_length) + { + glObjectLabel(GL_TEXTURE, texname, (GLsizei)prefix.size(), prefix.c_str()); + return prefix; + } + else + { + const std::string label(prefix.c_str(), max_length); + glObjectLabel(GL_TEXTURE, texname, (GLsizei)label.size(), label.c_str()); + return label; + } + } + } + } + return ""; +} + void LLGLTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, bool swap_bytes) { llassert(mGLTexturep.notNull()) ; diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 122d2a7f9c..22f2ed5131 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -118,6 +118,9 @@ public: LLGLuint getTexName() const ; bool createGLTexture() ; + void getGLObjectLabel(std::string& label, bool& error) const; + std::string setGLObjectLabel(const std::string& prefix, bool append_texname = false) const; + // Create a GL Texture from an image raw // discard_level - mip level, 0 for highest resultion mip // imageraw - the image to copy from diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ce6d9148c6..5d3f3d58c6 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7932,6 +7932,17 @@ Value 0 + RenderDebugTextureLabel + + Comment + Enable texture labels via glObjectLabel. Requires restart for some features. + Persist + 1 + Type + Boolean + Value + 0 + RenderDelayCreation Comment diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 7b89ae4e44..99df814f32 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -364,10 +364,31 @@ void LLViewerTextureList::shutdown() mInitialized = false ; //prevent loading textures again. } +namespace +{ + +std::string tex_name_as_string(const LLViewerFetchedTexture* image) +{ + if (!image->getGLTexture()) { return std::string("N/A"); } + return std::to_string(image->getGLTexture()->getTexName()); +} + +const std::string& tex_label_as_string(const LLViewerFetchedTexture* image, std::string& label) +{ + bool error; + image->getGLObjectLabel(label, error); + if (error) { label.assign("N/A"); } + return label; +} + +}; + void LLViewerTextureList::dump() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - LL_INFOS() << "LLViewerTextureList::dump()" << LL_ENDL; + LL_INFOS() << __FUNCTION__ << "()" << LL_ENDL; + + std::string label; for (image_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it) { LLViewerFetchedTexture* image = *it; @@ -378,6 +399,9 @@ void LLViewerTextureList::dump() << " discard " << image->getDiscardLevel() << " desired " << image->getDesiredDiscardLevel() << " http://asset.siva.lindenlab.com/" << image->getID() << ".texture" + << " faces " << image->getTotalNumFaces() + << " texname " << tex_name_as_string(image) + << " label \"" << tex_label_as_string(image, label) << "\"" << LL_ENDL; } } @@ -422,7 +446,13 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& std::string url = "file://" + full_path; - return getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); + LLViewerFetchedTexture* tex = getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); + static LLCachedControl debug_texture_label(gSavedSettings, "RenderDebugTextureLabel", false); + if (debug_texture_label()) + { + gTextureList.mNameTextureList.push_back(LLViewerTextureList::NameElement(tex, filename)); + } + return tex; } LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& url, @@ -844,6 +874,10 @@ void LLViewerTextureList::updateImages(F32 max_time) //handle results from decode threads updateImagesCreateTextures(remaining_time); + // Label all images (if enabled) + updateImagesNameTextures(); + labelAll(); + bool didone = false; for (image_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); ) @@ -1113,6 +1147,62 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time) return create_timer.getElapsedTimeF32(); } +void LLViewerTextureList::updateImagesNameTextures() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + if (gGLManager.mIsDisabled) { return; } + static LLCachedControl debug_texture_label(gSavedSettings, "RenderDebugTextureLabel", false); + if (!debug_texture_label()) { return; } + + static GLsizei max_length = 0; + if (max_length == 0) { glGetIntegerv(GL_MAX_LABEL_LENGTH, &max_length); } + + auto it = mNameTextureList.begin(); + while (it != mNameTextureList.end()) // For ALL textures needing names + { + if (it->mTex->hasGLTexture()) + { + if(it->mTex->getTexName()) + { + it->mTex->setGLObjectLabel(it->mPrefix, true); + it = mNameTextureList.erase(it); // Assume no rename needed + } + else + { + ++it; // Not ready + } + } + else + { + ++it; // Not ready + } + } +} + +void LLViewerTextureList::labelAll() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + static LLCachedControl debug_texture_label(gSavedSettings, "RenderDebugTextureLabel", false); + if (!debug_texture_label()) { return; } + + static const std::string local_prefix = "lltexlocal"; + static const std::string other_prefix = "lltexother"; + + std::string label; + bool error; + for (image_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it) + { + LLViewerFetchedTexture* image = *it; + image->getGLObjectLabel(label, error); + if (!error && label.empty()) + { + const S32 category = image->getGLTexture()->getCategory(); + const std::string& new_prefix = category == LLGLTexture::LOCAL ? local_prefix : other_prefix; + image->setGLObjectLabel(new_prefix, true); + } + } +} + F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -1295,6 +1385,10 @@ void LLViewerTextureList::decodeAllImages(F32 max_time) max_time = llmax(max_time, .001f); F32 create_time = updateImagesCreateTextures(max_time); + // Label all images (if enabled) + updateImagesNameTextures(); + labelAll(); + LL_DEBUGS("ViewerImages") << "decodeAllImages() took " << timer.getElapsedTimeF32() << " seconds. " << " fetch_pending " << fetch_pending << " create_time " << create_time diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 7c7112f4cf..6424e5c3f0 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -153,6 +153,9 @@ private: void updateImagesUpdateStats(); F32 updateImagesLoadingFastCache(F32 max_time); + void updateImagesNameTextures(); + void labelAll(); + void addImage(LLViewerFetchedTexture *image, ETexListType tex_type); void deleteImage(LLViewerFetchedTexture *image); @@ -214,6 +217,14 @@ public: // images that have been loaded but are waiting to be uploaded to GL image_queue_t mCreateTextureList; + struct NameElement + { + NameElement(LLViewerFetchedTexture* tex, const std::string& prefix) : mTex(tex), mPrefix(prefix) {} + LLPointer mTex; + std::string mPrefix; + }; + std::vector mNameTextureList; + // images that must be downscaled quickly so we don't run out of memory image_queue_t mDownScaleQueue; -- cgit v1.2.3 From 322b4fb9c4c37787bd219dd97012f121309d591a Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 3 Oct 2024 16:43:04 -0700 Subject: secondlife/viewer#2472: Feedback Disable if not supported for OpenGL version Minimize performance footguns Simplify for clause --- indra/llrender/llgltexture.cpp | 9 +++++++++ indra/newview/app_settings/settings.xml | 13 ++++++++++++- indra/newview/llviewertexturelist.cpp | 27 +++++++++++++++++++-------- indra/newview/llviewertexturelist.h | 2 +- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index 9a2b2ef524..bb4205b319 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -170,6 +170,13 @@ bool LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, void LLGLTexture::getGLObjectLabel(std::string& label, bool& error) const { + // GL_VERSION_4_3 + if (gGLManager.mGLVersion < 4.29f) + { + error = true; + label.clear(); + return; + } if (!mGLTexturep) { error = true; @@ -194,6 +201,8 @@ void LLGLTexture::getGLObjectLabel(std::string& label, bool& error) const std::string LLGLTexture::setGLObjectLabel(const std::string& prefix, bool append_texname) const { + if (gGLManager.mGLVersion < 4.29f) { return ""; } // GL_VERSION_4_3 + llassert(mGLTexturep); if (mGLTexturep) { diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 5d3f3d58c6..4d0cffa2a9 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7935,7 +7935,18 @@ RenderDebugTextureLabel Comment - Enable texture labels via glObjectLabel. Requires restart for some features. + Enable texture labels via glObjectLabel. + Persist + 0 + Type + Boolean + Value + 0 + + RenderDebugTextureLabelLocalFiles + + Comment + Enumerate textures with local file names. Doesn't do anything until RenderDebugTextureLabel is set to true. Requires restart. Persist 1 Type diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 99df814f32..4c13105d5d 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -447,7 +447,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& std::string url = "file://" + full_path; LLViewerFetchedTexture* tex = getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); - static LLCachedControl debug_texture_label(gSavedSettings, "RenderDebugTextureLabel", false); + static LLCachedControl debug_texture_label(gSavedSettings, "RenderDebugTextureLabelLocalFiles", false); if (debug_texture_label()) { gTextureList.mNameTextureList.push_back(LLViewerTextureList::NameElement(tex, filename)); @@ -1160,12 +1160,24 @@ void LLViewerTextureList::updateImagesNameTextures() auto it = mNameTextureList.begin(); while (it != mNameTextureList.end()) // For ALL textures needing names { - if (it->mTex->hasGLTexture()) + LLViewerFetchedTexture* tex = it->mTex; + // Check that the texture is in the list first (otherwise it may be a dead pointer) + // A raw pointer ensures textures are cleaned up when this code isn't running. + const bool alive = mImageList.find(tex) != mImageList.end(); + + if (alive) { - if(it->mTex->getTexName()) + if (tex->hasGLTexture()) { - it->mTex->setGLObjectLabel(it->mPrefix, true); - it = mNameTextureList.erase(it); // Assume no rename needed + if(tex->getTexName()) + { + tex->setGLObjectLabel(it->mPrefix, true); + it = mNameTextureList.erase(it); // Assume no rename needed + } + else + { + ++it; // Not ready + } } else { @@ -1174,7 +1186,7 @@ void LLViewerTextureList::updateImagesNameTextures() } else { - ++it; // Not ready + it = mNameTextureList.erase(it); // Remove dead pointer } } } @@ -1190,9 +1202,8 @@ void LLViewerTextureList::labelAll() std::string label; bool error; - for (image_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it) + for (LLViewerFetchedTexture* image : mImageList) { - LLViewerFetchedTexture* image = *it; image->getGLObjectLabel(label, error); if (!error && label.empty()) { diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 6424e5c3f0..08dd2d0f7f 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -220,7 +220,7 @@ public: struct NameElement { NameElement(LLViewerFetchedTexture* tex, const std::string& prefix) : mTex(tex), mPrefix(prefix) {} - LLPointer mTex; + LLViewerFetchedTexture* mTex; std::string mPrefix; }; std::vector mNameTextureList; -- cgit v1.2.3 From de95bd3187b61ca1152c14bc9bd112da61027d4c Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 3 Oct 2024 18:25:37 -0700 Subject: secondlife/viewer#2472: Also don't persist local file enumeration beyond next session --- indra/llrender/llgl.cpp | 1 + indra/llrender/llgl.h | 1 + indra/newview/app_settings/settings.xml | 4 ++-- indra/newview/llappviewer.cpp | 8 ++++++++ indra/newview/llviewertexturelist.cpp | 3 +-- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 15fb289de3..a60f1efbdf 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -65,6 +65,7 @@ bool gDebugSession = false; bool gDebugGLSession = false; +bool gDebugTextureLabelLocalFilesSession = false; bool gClothRipple = false; bool gHeadlessClient = false; bool gNonInteractive = false; diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index f5b1e8d786..8d7ac56d79 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -48,6 +48,7 @@ extern bool gDebugGL; extern bool gDebugSession; extern bool gDebugGLSession; +extern bool gDebugTextureLabelLocalFilesSession; extern llofstream gFailLog; #define LL_GL_ERRS LL_ERRS("RenderState") diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4d0cffa2a9..cb32789cad 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7943,10 +7943,10 @@ Value 0 - RenderDebugTextureLabelLocalFiles + RenderDebugTextureLabelLocalFilesSession Comment - Enumerate textures with local file names. Doesn't do anything until RenderDebugTextureLabel is set to true. Requires restart. + Enumerate textures with local file names. Doesn't do anything until RenderDebugTextureLabel is set to true. Requires restart AND applies on the next session only. Persist 1 Type diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 521e6eee1a..7fc97558f1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2860,6 +2860,14 @@ bool LLAppViewer::initConfiguration() gSavedSettings.setBOOL("RenderDebugGLSession", false); } + if (gSavedSettings.getBOOL("RenderDebugTextureLabelLocalFilesSession")) + { + gDebugTextureLabelLocalFilesSession = true; + // Texture label accounting for local files takes up memory in the + // background, so don't persist. + gSavedSettings.setBOOL("RenderDebugTextureLabelLocalFilesSession", false); + } + const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent"); if (skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) { diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 4c13105d5d..752cfb3884 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -447,8 +447,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& std::string url = "file://" + full_path; LLViewerFetchedTexture* tex = getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); - static LLCachedControl debug_texture_label(gSavedSettings, "RenderDebugTextureLabelLocalFiles", false); - if (debug_texture_label()) + if (gDebugTextureLabelLocalFilesSession) { gTextureList.mNameTextureList.push_back(LLViewerTextureList::NameElement(tex, filename)); } -- cgit v1.2.3