From dc7b2adbebea2bd332de52d90dbbe651ee94031c Mon Sep 17 00:00:00 2001
From: Cosmic Linden <cosmic@lindenlab.com>
Date: Wed, 2 Oct 2024 15:25:11 -0700
Subject: secondlife/viewer#2472: Debug tools for labeling textures

---
 indra/newview/app_settings/settings.xml | 11 ++++
 indra/newview/llviewertexturelist.cpp   | 98 ++++++++++++++++++++++++++++++++-
 indra/newview/llviewertexturelist.h     | 11 ++++
 3 files changed, 118 insertions(+), 2 deletions(-)

(limited to 'indra/newview')

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 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>RenderDebugTextureLabel</key>
+    <map>
+      <key>Comment</key>
+      <string>Enable texture labels via glObjectLabel. Requires restart for some features.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
   <key>RenderDelayCreation</key>
   <map>
     <key>Comment</key>
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<bool> 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<bool> 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<bool> 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<LLViewerFetchedTexture> mTex;
+        std::string mPrefix;
+    };
+    std::vector<NameElement> mNameTextureList;
+
     // images that must be downscaled quickly so we don't run out of memory
     image_queue_t mDownScaleQueue;
 
-- 
cgit v1.2.3