summaryrefslogtreecommitdiff
path: root/indra/newview/llmeshrepository.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llmeshrepository.cpp')
-rw-r--r--indra/newview/llmeshrepository.cpp266
1 files changed, 261 insertions, 5 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 2c1980922a..e38bd8846d 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -4214,22 +4214,80 @@ void LLMeshRepository::uploadError(LLSD& args)
mUploadErrorQ.push(args);
}
-F32 LLMeshRepository::getStreamingCost(LLUUID mesh_id, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
+F32 LLMeshRepository::getEstTrianglesMax(LLUUID mesh_id)
{
+ LLMeshCostData costs;
+ if (getCostData(mesh_id, costs))
+ {
+ return costs.getEstTrisMax();
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+F32 LLMeshRepository::getEstTrianglesStreamingCost(LLUUID mesh_id)
+{
+ LLMeshCostData costs;
+ if (getCostData(mesh_id, costs))
+ {
+ return costs.getEstTrisForStreamingCost();
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+// FIXME replace with calc based on LLMeshCostData
+F32 LLMeshRepository::getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
+{
+ F32 result = 0.f;
if (mThread && mesh_id.notNull())
{
LLMutexLock lock(mThread->mHeaderMutex);
LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
{
- return getStreamingCost(iter->second, radius, bytes, bytes_visible, lod, unscaled_value);
+ result = getStreamingCostLegacy(iter->second, radius, bytes, bytes_visible, lod, unscaled_value);
+ }
+ }
+ if (result > 0.f)
+ {
+ LLMeshCostData data;
+ if (getCostData(mesh_id, data))
+ {
+ F32 ref_streaming_cost = data.getRadiusBasedStreamingCost(radius);
+ F32 ref_weighted_tris = data.getRadiusWeightedTris(radius);
+ if (!is_approx_equal(ref_streaming_cost,result))
+ {
+ LL_WARNS() << mesh_id << "streaming mismatch " << result << " " << ref_streaming_cost << LL_ENDL;
+ }
+ if (unscaled_value && !is_approx_equal(ref_weighted_tris,*unscaled_value))
+ {
+ LL_WARNS() << mesh_id << "weighted_tris mismatch " << *unscaled_value << " " << ref_weighted_tris << LL_ENDL;
+ }
+ if (bytes && (*bytes != data.getSizeTotal()))
+ {
+ LL_WARNS() << mesh_id << "bytes mismatch " << *bytes << " " << data.getSizeTotal() << LL_ENDL;
+ }
+ if (bytes_visible && (lod >=0) && (lod < 4) && (*bytes_visible != data.getSizeByLOD(lod)))
+ {
+ LL_WARNS() << mesh_id << "bytes_visible mismatch " << *bytes_visible << " " << data.getSizeByLOD(lod) << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS() << "getCostData failed!!!" << LL_ENDL;
}
}
- return 0.f;
+ return result;
}
+// FIXME replace with calc based on LLMeshCostData
//static
-F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
+F32 LLMeshRepository::getStreamingCostLegacy(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
{
if (header.has("404")
|| !header.has("lowest_lod")
@@ -4323,7 +4381,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)
{
@@ -4333,6 +4391,204 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32
return weighted_avg/gSavedSettings.getU32("MeshTriangleBudget")*15000.f;
}
+LLMeshCostData::LLMeshCostData()
+{
+ mSizeByLOD.resize(4);
+ mEstTrisByLOD.resize(4);
+
+ std::fill(mSizeByLOD.begin(), mSizeByLOD.end(), 0);
+ std::fill(mEstTrisByLOD.begin(), mEstTrisByLOD.end(), 0.f);
+}
+
+bool LLMeshCostData::init(const LLSD& header)
+{
+ mSizeByLOD.resize(4);
+ mEstTrisByLOD.resize(4);
+
+ std::fill(mSizeByLOD.begin(), mSizeByLOD.end(), 0);
+ std::fill(mEstTrisByLOD.begin(), mEstTrisByLOD.end(), 0.f);
+
+ 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();
+ if (bytes_lowest == 0)
+ {
+ bytes_lowest = bytes_low;
+ }
+ mSizeByLOD[0] = bytes_lowest;
+ mSizeByLOD[1] = bytes_low;
+ mSizeByLOD[2] = bytes_med;
+ mSizeByLOD[3] = bytes_high;
+
+ 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");
+
+ for (S32 i=0; i<4; i++)
+ {
+ mEstTrisByLOD[i] = llmax((F32) mSizeByLOD[i]-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle;
+ }
+
+ return true;
+}
+
+
+S32 LLMeshCostData::getSizeByLOD(S32 lod)
+{
+ if (llclamp(lod,0,3) != lod)
+ {
+ return 0;
+ }
+ return mSizeByLOD[lod];
+}
+
+S32 LLMeshCostData::getSizeTotal()
+{
+ return mSizeByLOD[0] + mSizeByLOD[1] + mSizeByLOD[2] + mSizeByLOD[3];
+}
+
+F32 LLMeshCostData::getEstTrisByLOD(S32 lod)
+{
+ if (llclamp(lod,0,3) != lod)
+ {
+ return 0.f;
+ }
+ return mEstTrisByLOD[lod];
+}
+
+F32 LLMeshCostData::getEstTrisMax()
+{
+ return llmax(mEstTrisByLOD[0], mEstTrisByLOD[1], mEstTrisByLOD[2], mEstTrisByLOD[3]);
+}
+
+F32 LLMeshCostData::getRadiusWeightedTris(F32 radius)
+{
+ F32 max_distance = 512.f;
+
+ F32 dlowest = llmin(radius/0.03f, max_distance);
+ F32 dlow = llmin(radius/0.06f, max_distance);
+ F32 dmid = llmin(radius/0.24f, max_distance);
+
+ F32 triangles_lowest = mEstTrisByLOD[0];
+ F32 triangles_low = mEstTrisByLOD[1];
+ F32 triangles_mid = mEstTrisByLOD[2];
+ F32 triangles_high = mEstTrisByLOD[3];
+
+ F32 max_area = 102944.f; //area of circle that encompasses region (see MAINT-6559)
+ F32 min_area = 1.f;
+
+ F32 high_area = llmin(F_PI*dmid*dmid, max_area);
+ F32 mid_area = llmin(F_PI*dlow*dlow, max_area);
+ F32 low_area = llmin(F_PI*dlowest*dlowest, max_area);
+ F32 lowest_area = max_area;
+
+ lowest_area -= low_area;
+ low_area -= mid_area;
+ mid_area -= high_area;
+
+ high_area = llclamp(high_area, min_area, max_area);
+ mid_area = llclamp(mid_area, min_area, max_area);
+ low_area = llclamp(low_area, min_area, max_area);
+ lowest_area = llclamp(lowest_area, min_area, max_area);
+
+ F32 total_area = high_area + mid_area + low_area + lowest_area;
+ high_area /= total_area;
+ mid_area /= total_area;
+ low_area /= total_area;
+ lowest_area /= total_area;
+
+ F32 weighted_avg = triangles_high*high_area +
+ triangles_mid*mid_area +
+ triangles_low*low_area +
+ triangles_lowest*lowest_area;
+
+ return weighted_avg;
+}
+
+F32 LLMeshCostData::getEstTrisForStreamingCost()
+{
+ LL_DEBUGS("StreamingCost") << "tris_by_lod: "
+ << mEstTrisByLOD[0] << ", "
+ << mEstTrisByLOD[1] << ", "
+ << mEstTrisByLOD[2] << ", "
+ << mEstTrisByLOD[3] << LL_ENDL;
+
+ F32 charged_tris = mEstTrisByLOD[3];
+ F32 allowed_tris = mEstTrisByLOD[3];
+ const F32 ENFORCE_FLOOR = 64.0f;
+ for (S32 i=2; i>=0; 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,mEstTrisByLOD[i]);
+ F32 excess_tris = mEstTrisByLOD[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 charged_tris;
+}
+
+F32 LLMeshCostData::getRadiusBasedStreamingCost(F32 radius)
+{
+ return getRadiusWeightedTris(radius)/gSavedSettings.getU32("MeshTriangleBudget")*15000.f;
+}
+
+F32 LLMeshCostData::getTriangleBasedStreamingCost()
+{
+ F32 result = ANIMATED_OBJECT_COST_PER_KTRI * 0.001 * getEstTrisForStreamingCost();
+ return result;
+}
+
+bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data)
+{
+ data = LLMeshCostData();
+
+ if (mThread && mesh_id.notNull())
+ {
+ LLMutexLock lock(mThread->mHeaderMutex);
+ LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
+ if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
+ {
+ LLSD& header = iter->second;
+
+ bool header_invalid = (header.has("404")
+ || !header.has("lowest_lod")
+ || (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION));
+ if (!header_invalid)
+ {
+ return getCostData(header, data);
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+
+bool LLMeshRepository::getCostData(LLSD& header, LLMeshCostData& data)
+{
+ data = LLMeshCostData();
+
+ if (!data.init(header))
+ {
+ return false;
+ }
+
+ return true;
+}
LLPhysicsDecomp::LLPhysicsDecomp()
: LLThread("Physics Decomp")