From a3fd0801c3030ff9a5a6761c9618f381aa965983 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 26 Mar 2018 20:59:37 +0100
Subject: SL-897 - display for DebugAnimatedObjects now includes streaming cost
 triangle count

---
 indra/newview/llcontrolavatar.cpp  |  7 ++-
 indra/newview/llmeshrepository.cpp | 90 +++++++++++++++++++++++++++++++++++---
 indra/newview/llmeshrepository.h   |  2 +
 indra/newview/llviewerobject.cpp   |  5 +++
 indra/newview/llviewerobject.h     |  1 +
 indra/newview/llvovolume.cpp       |  9 ++++
 indra/newview/llvovolume.h         |  1 +
 7 files changed, 106 insertions(+), 9 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index e1715d567b..a16fa3cd26 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -242,7 +242,9 @@ void LLControlAvatar::updateDebugText()
         std::string lod_string;
         S32 total_tris = 0;
         S32 total_verts = 0;
-        S32 est_tris = 0;
+        F32 est_tris = 0.f;
+        F32 est_streaming_tris = 0.f;
+        
         for (std::vector<LLVOVolume*>::iterator it = volumes.begin();
              it != volumes.end(); ++it)
         {
@@ -251,6 +253,7 @@ void LLControlAvatar::updateDebugText()
             total_tris += volp->getTriangleCount(&verts);
             total_verts += verts;
             est_tris += volp->getEstTrianglesMax();
+            est_streaming_tris += volp->getEstTrianglesStreamingCost();
             lod_string += llformat("%d",volp->getLOD());
             if (volp && volp->mDrawable)
             {
@@ -287,7 +290,7 @@ void LLControlAvatar::updateDebugText()
         addDebugText(llformat("CAV obj %d anim %d active %s impost %d",
                               total_linkset_count, animated_volume_count, active_string.c_str(), (S32) isImpostor()));
         addDebugText(llformat("types %s lods %s", type_string.c_str(), lod_string.c_str()));
-        addDebugText(llformat("tris %d (est %d), verts %d", total_tris, est_tris, total_verts));
+        addDebugText(llformat("tris %d (est %.1f, streaming %.1f), verts %d", total_tris, est_tris, est_streaming_tris, total_verts));
         addDebugText(llformat("pxarea %s", LLStringOps::getReadableNumber(getPixelArea()).c_str()));
 #if 0
         std::string region_name = "no region";
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 4f0fb56ba6..b27fdefb83 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -4062,9 +4062,14 @@ void LLMeshRepository::uploadError(LLSD& args)
 	mUploadErrorQ.push(args);
 }
 
-F32 LLMeshRepository::getEstTrianglesMax(LLUUID mesh_id)
+bool LLMeshRepository::getLODSizes(LLUUID mesh_id, std::vector<S32>& lod_byte_sizes, std::vector<F32>& lod_tri_counts)
 {
-    F32 triangles_max = 0.f;
+    lod_byte_sizes.resize(4);
+    lod_tri_counts.resize(4);
+
+    std::fill(lod_byte_sizes.begin(), lod_byte_sizes.end(), 0);
+    std::fill(lod_tri_counts.begin(), lod_tri_counts.end(), 0.f);
+    
     if (mThread && mesh_id.notNull())
     {
         LLMutexLock lock(mThread->mHeaderMutex);
@@ -4076,22 +4081,93 @@ F32 LLMeshRepository::getEstTrianglesMax(LLUUID mesh_id)
                 || !header.has("lowest_lod")
                 || (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION))
             {
-                return 0.f;
+                return false;
             }
 
             S32 bytes_high = header["high_lod"]["size"].asInteger();
             S32 bytes_med = header["medium_lod"]["size"].asInteger();
+            if (bytes_med == 0)
+            {
+                bytes_med = bytes_high;
+            }
             S32 bytes_low = header["low_lod"]["size"].asInteger();
+            if (bytes_low == 0)
+            {
+                bytes_low = bytes_med;
+            }
             S32 bytes_lowest = header["lowest_lod"]["size"].asInteger();
-            S32 bytes_max = llmax(bytes_high, bytes_med, bytes_low, bytes_lowest);
+            if (bytes_lowest == 0)
+            {
+                bytes_lowest = bytes_low;
+            }
+            lod_byte_sizes[0] = bytes_high;
+            lod_byte_sizes[1] = bytes_med;
+            lod_byte_sizes[2] = bytes_low;
+            lod_byte_sizes[3] = bytes_lowest;
 
             F32 METADATA_DISCOUNT = (F32) gSavedSettings.getU32("MeshMetaDataDiscount");  //discount 128 bytes to cover the cost of LLSD tags and compression domain overhead
             F32 MINIMUM_SIZE = (F32) gSavedSettings.getU32("MeshMinimumByteSize"); //make sure nothing is "free"
             F32 bytes_per_triangle = (F32) gSavedSettings.getU32("MeshBytesPerTriangle");
-            triangles_max = llmax((F32) bytes_max-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle;
+
+            for (S32 i=0; i<4; i++)
+            {
+                lod_tri_counts[i] = llmax((F32) lod_byte_sizes[i]-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle; 
+            }
+
+            return true;
+        }
+    }
+    return false;
+}
+
+F32 LLMeshRepository::getEstTrianglesMax(LLUUID mesh_id)
+{
+    std::vector<S32> lod_byte_sizes;
+    std::vector<F32> lod_tri_counts;
+    bool succ = getLODSizes(mesh_id, lod_byte_sizes, lod_tri_counts);
+    if (!succ)
+    {
+        return 0.f;
+    }
+    
+    return llmax(lod_tri_counts[0], lod_tri_counts[1], lod_tri_counts[2], lod_tri_counts[3]);
+}
+
+F32 LLMeshRepository::getEstTrianglesStreamingCost(LLUUID mesh_id)
+{
+    std::vector<S32> lod_byte_sizes;
+    std::vector<F32> tris_by_lod;
+    bool succ = getLODSizes(mesh_id, lod_byte_sizes, tris_by_lod);
+
+    if (!succ)
+    {
+        LL_DEBUGS("StreamingCost") << "couldn't get tris_by_lod" << LL_ENDL;
+        return 0.f;
+    }
+
+    LL_DEBUGS("StreamingCost") << "tris_by_lod: "
+                               << tris_by_lod[0] << ", "
+                               << tris_by_lod[1] << ", "
+                               << tris_by_lod[2] << ", "
+                               << tris_by_lod[3] << LL_ENDL;
+
+    F32 charged_tris = tris_by_lod[0];
+    F32 allowed_tris = tris_by_lod[0];
+    const F32 ENFORCE_FLOOR = 64.0f;
+    for (S32 i=1; i<4; i++)
+    {
+        // How many tris can we have in this LOD without affecting land impact?
+        // - normally an LOD should be at most half the size of the previous one.
+        // - once we reach a floor of ENFORCE_FLOOR, don't require LODs to get any smaller.
+        allowed_tris = llclamp(allowed_tris/2.0f,ENFORCE_FLOOR,tris_by_lod[i]);
+        F32 excess_tris = tris_by_lod[i]-allowed_tris;
+        if (excess_tris>0.f)
+        {
+            LL_DEBUGS("StreamingCost") << "excess tris in lod[" << i << "] " << excess_tris << " allowed " << allowed_tris <<  LL_ENDL;
+            charged_tris += excess_tris;
         }
     }
-    return triangles_max;
+    return charged_tris;
 }
 
 F32 LLMeshRepository::getStreamingCost(LLUUID mesh_id, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
@@ -4203,7 +4279,7 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32
 	F32 weighted_avg = triangles_high*high_area +
 					   triangles_mid*mid_area +
 					   triangles_low*low_area +
-					  triangles_lowest*lowest_area;
+					   triangles_lowest*lowest_area;
 
 	if (unscaled_value)
 	{
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index d2eac449f7..bae3f66a72 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -472,8 +472,10 @@ public:
 	
 	static LLDeadmanTimer sQuiescentTimer;		// Time-to-complete-mesh-downloads after significant events
 
+    bool getLODSizes(LLUUID mesh_id, std::vector<S32>& lod_byte_sizes, std::vector<F32>& lod_tri_counts);
     // Estimated triangle count of the largest LOD
     F32 getEstTrianglesMax(LLUUID mesh_id);
+    F32 getEstTrianglesStreamingCost(LLUUID mesh_id);
 	F32 getStreamingCost(LLUUID mesh_id, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
 	static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
 
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 531f9a9527..f606abedf5 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -3692,6 +3692,11 @@ F32 LLViewerObject::getEstTrianglesMax() const
     return 0.f;
 }
 
+F32 LLViewerObject::getEstTrianglesStreamingCost() const
+{
+    return 0.f;
+}
+
 F32 LLViewerObject::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_value) const
 {
 	return 0.f;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index ab0e74bc97..2fe14c2fcf 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -365,6 +365,7 @@ public:
     S32 getAnimatedObjectMaxTris() const;
     F32 recursiveGetEstTrianglesMax() const;
     virtual F32 getEstTrianglesMax() const;
+    virtual F32 getEstTrianglesStreamingCost() const;
 	virtual F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL, F32* unscaled_value = NULL) const;
 	virtual U32 getTriangleCount(S32* vcount = NULL) const;
 	virtual U32 getHighLODTriangleCount();
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 69c2d2cccd..3b5129d994 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3905,6 +3905,15 @@ F32 LLVOVolume::getEstTrianglesMax() const
     return 0.f;
 }
 
+F32 LLVOVolume::getEstTrianglesStreamingCost() const
+{
+	if (isMesh() && getVolume())
+	{
+		return gMeshRepo.getEstTrianglesStreamingCost(getVolume()->getParams().getSculptID());
+	}
+    return 0.f;
+}
+
 F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_value) const
 {
 	F32 radius = getScale().length()*0.5f;
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 4aec48e8ff..f6738945d8 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -135,6 +135,7 @@ public:
 				typedef std::map<LLUUID, S32> texture_cost_t;
 				U32 	getRenderCost(texture_cost_t &textures) const;
     /*virtual*/	F32		getEstTrianglesMax() const;
+    /*virtual*/	F32		getEstTrianglesStreamingCost() const;
 				F32		getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_value) const;
 	/*virtual*/	F32		getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL) { return getStreamingCost(bytes, visible_bytes, NULL); }
 
-- 
cgit v1.2.3