summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorNyx (Neal Orman) <nyx@lindenlab.com>2010-09-01 10:59:45 -0400
committerNyx (Neal Orman) <nyx@lindenlab.com>2010-09-01 10:59:45 -0400
commite3fec30097a28689a7022d06005d7d59a3004f0c (patch)
treee143c9775e3c2867bb95b7726598f5b057a04770 /indra/newview
parentd8fd52341a2ff47c6f929540628f2f0017c8b185 (diff)
CTS-231 WIP create new ARC algorithm to be more accurate and account for meshes
First pass - uses the new algorithm to hopefully be more accurate of render load on low-end machines. Also accounts for mesh complexity, including if a mesh is weighted or non-weighted. Code reviewed by davep
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llfloatertools.cpp8
-rw-r--r--indra/newview/llmeshrepository.cpp24
-rw-r--r--indra/newview/llmeshrepository.h3
-rw-r--r--indra/newview/llvoavatar.cpp17
-rw-r--r--indra/newview/llvovolume.cpp211
-rw-r--r--indra/newview/llvovolume.h5
6 files changed, 236 insertions, 32 deletions
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 5472531fa7..fa5d9b0892 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -1007,7 +1007,7 @@ void LLFloaterTools::onClickGridOptions()
S32 LLFloaterTools::calcRenderCost()
{
S32 cost = 0;
- std::set<LLUUID> textures;
+ LLVOVolume::texture_cost_t textures;
for (LLObjectSelection::iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->begin();
selection_iter != LLSelectMgr::getInstance()->getSelection()->end();
@@ -1020,7 +1020,11 @@ S32 LLFloaterTools::calcRenderCost()
if (viewer_volume)
{
cost += viewer_volume->getRenderCost(textures);
- cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST;
+ for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
+ {
+ // add the cost of each individual texture in the linkset
+ cost += iter->second;
+ }
textures.clear();
}
}
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 96a170ef07..069642b711 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -2104,6 +2104,30 @@ void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3
thread->start();
}
+S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
+{
+ if (mThread)
+ {
+ LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
+ if (iter != mThread->mMeshHeader.end())
+ {
+ LLSD& header = iter->second;
+
+ if (header.has("404"))
+ {
+ return -1;
+ }
+
+ S32 size = header[header_lod[lod]]["size"].asInteger();
+ return size;
+ }
+
+ }
+
+ return -1;
+
+}
+
void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data)
{
//write model file to memory buffer
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index d5e21c35cc..b26598ce31 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -405,8 +405,7 @@ public:
void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures);
-
-
+ S32 getMeshSize(const LLUUID& mesh_id, S32 lod);
typedef std::map<LLVolumeParams, std::set<LLUUID> > mesh_load_map;
mesh_load_map mLoadingMeshes[4];
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 0c8a518de0..a6b3c436f4 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -7968,7 +7968,7 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d
void LLVOAvatar::idleUpdateRenderCost()
{
- static const U32 ARC_BODY_PART_COST = 20;
+ static const U32 ARC_BODY_PART_COST = 200;
static const U32 ARC_LIMIT = 2048;
static std::set<LLUUID> all_textures;
@@ -7979,7 +7979,7 @@ void LLVOAvatar::idleUpdateRenderCost()
}
U32 cost = 0;
- std::set<LLUUID> textures;
+ LLVOVolume::texture_cost_t textures;
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
{
@@ -8017,16 +8017,24 @@ void LLVOAvatar::idleUpdateRenderCost()
}
}
}
+
}
+
+ for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
+ {
+ // add the cost of each individual texture in the linkset
+ cost += iter->second;
+ }
+
// Diagnostic output to identify all avatar-related textures.
// Does not affect rendering cost calculation.
// Could be wrapped in a debug option if output becomes problematic.
if (isSelf())
{
// print any attachment textures we didn't already know about.
- for (std::set<LLUUID>::iterator it = textures.begin(); it != textures.end(); ++it)
+ for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it)
{
- LLUUID image_id = *it;
+ LLUUID image_id = it->first;
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
continue;
if (all_textures.find(image_id) == all_textures.end())
@@ -8057,7 +8065,6 @@ void LLVOAvatar::idleUpdateRenderCost()
}
}
}
- cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST;
setDebugText(llformat("%d", cost));
F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 0a7611c527..bf4cfc870f 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -2872,17 +2872,31 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const
// total cost is returned value + 5 * size of the resulting set.
// Cannot include cost of textures, as they may be re-used in linked
// children, and cost should only be increased for unique textures -Nyx
-U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
+U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
{
// base cost of each prim should be 10 points
static const U32 ARC_PRIM_COST = 10;
+
+ // get access to params we'll need at various points
+ LLVolumeParams volume_params = getVolume()->getParams();
+ LLPathParams path_params = volume_params.getPathParams();
+ LLProfileParams profile_params = volume_params.getProfileParams();
+
// per-prim costs
static const U32 ARC_INVISI_COST = 1;
- static const U32 ARC_SHINY_COST = 1;
- static const U32 ARC_GLOW_COST = 1;
- static const U32 ARC_FLEXI_COST = 8;
static const U32 ARC_PARTICLE_COST = 16;
- static const U32 ARC_BUMP_COST = 4;
+ static const U32 ARC_CUT_COST = 1;
+ static const U32 ARC_TEXTURE_COST = 5;
+
+ // per-prim multipliers
+ static const U32 ARC_HOLLOW_MULT = 2;
+ static const U32 ARC_TWIST_MULT = 2;
+ static const U32 ARC_CIRC_PROF_MULT = 2;
+ static const U32 ARC_CIRC_PATH_MULT = 2;
+ static const U32 ARC_GLOW_MULT = 2;
+ static const U32 ARC_BUMP_MULT = 2;
+ static const U32 ARC_FLEXI_MULT = 4;
+ static const U32 ARC_SHINY_MULT = 2;
// per-face costs
static const U32 ARC_PLANAR_COST = 1;
@@ -2901,6 +2915,61 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
U32 scale = 0;
U32 bump = 0;
U32 planar = 0;
+ U32 cuts = 0;
+ U32 hollow = 0;
+ U32 twist = 0;
+ U32 circular_profile = 0;
+ U32 circular_path = 0;
+
+ const LLDrawable* drawablep = mDrawable;
+
+ if (isSculpted())
+ {
+ if (isMesh())
+ {
+ // base cost is dependent on mesh complexity
+ // note that 3 is the highest LOD as of the time of this coding.
+ S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(),3);
+ if ( size > 0)
+ {
+ if (gMeshRepo.getSkinInfo(volume_params.getSculptID()))
+ {
+ // weighted attachment - 1 point for every 3 bytes
+ shame = (U32)(size / 3.f);
+ }
+ else
+ {
+ // non-weighted attachment - 1 point for every 4 bytes
+ shame = (U32)(size / 4.f);
+ }
+
+ if (shame == 0)
+ {
+ // someone made a really tiny mesh.
+ shame = 1;
+ }
+ }
+ else
+ {
+ // something went wrong - user should know their content isn't render-free
+ return 0;
+ }
+ }
+ else
+ {
+ const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLUUID sculpt_id = sculpt_params->getSculptTexture();
+ if (textures.find(sculpt_id) == textures.end())
+ {
+ LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(sculpt_id);
+ if (texture)
+ {
+ S32 texture_cost = ARC_TEXTURE_COST * (texture->getFullHeight() / 128 + texture->getFullWidth() / 128 + 1);
+ textures.insert(texture_cost_t::value_type(sculpt_id, texture_cost));
+ }
+ }
+ }
+ }
if (isFlexible())
{
@@ -2913,14 +2982,63 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
const LLVector3& sc = getScale();
scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2];
+ if (scale > 4)
+ {
+ // scale is a multiplier, cap it at 4.
+ scale = 4;
+ }
- const LLDrawable* drawablep = mDrawable;
+ // add points for cut prims
+ if (path_params.getBegin() != 0.f || path_params.getEnd() != 1.f)
+ {
+ ++cuts;
+ }
- if (isSculpted())
+ if (profile_params.getBegin() != 0.f || profile_params.getEnd() != 1.f)
+ {
+ ++cuts;
+ }
+
+ // double cost for hollow prims / sculpties
+ if (volume_params.getHollow() != 0.f)
{
- const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- LLUUID sculpt_id = sculpt_params->getSculptTexture();
- textures.insert(sculpt_id);
+ hollow = 1;
+ }
+
+ // twist - scale by twist extent / 90
+ if (volume_params.getTwistBegin() != 0.f)
+ {
+ U32 scale = abs((S32)(volume_params.getTwistBegin() / 90.f) + 1);
+ twist += scale;
+ }
+
+ // twist - scale by twist extent / 90
+ if (volume_params.getTwist() != 0.f)
+ {
+ U32 scale = abs((S32)(volume_params.getTwist() / 90.f) + 1);
+ twist += scale;
+ }
+
+ // double cost for circular profiles / sculpties
+ if (profile_params.getCurveType() == LL_PCODE_PROFILE_CIRCLE ||
+ profile_params.getCurveType() == LL_PCODE_PROFILE_CIRCLE_HALF)
+ {
+ circular_profile = 1;
+ }
+
+ // double cost for circular paths / sculpties
+ if (path_params.getCurveType() == LL_PCODE_PATH_CIRCLE ||
+ path_params.getCurveType() == LL_PCODE_PATH_CIRCLE2)
+ {
+ circular_path = 1;
+ }
+
+ // treat sculpties as hollow prims with circular paths & profiles
+ if (isSculpted() && !isMesh())
+ {
+ hollow = 1;
+ circular_profile = 1;
+ circular_path = 1;
}
for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
@@ -2931,7 +3049,11 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
if (img)
{
- textures.insert(img->getID());
+ if (textures.find(img->getID()) == textures.end())
+ {
+ S32 texture_cost = ARC_TEXTURE_COST * (img->getFullHeight() / 128 + img->getFullWidth() / 128 + 1);
+ textures.insert(texture_cost_t::value_type(img->getID(), texture_cost));
+ }
}
if (face->getPoolType() == LLDrawPool::POOL_ALPHA)
@@ -2940,21 +3062,24 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
}
else if (img && img->getPrimaryFormat() == GL_ALPHA)
{
- invisi = 1;
+ invisi++;
}
if (te)
{
if (te->getBumpmap())
{
+ // bump is a multiplier, don't add per-face
bump = 1;
}
if (te->getShiny())
{
+ // shiny is a multiplier, don't add per-face
shiny = 1;
}
if (te->getGlow() > 0.f)
{
+ // glow is a multiplier, don't add per-face
glow = 1;
}
if (face->mTextureMatrix != NULL)
@@ -2968,17 +3093,63 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
}
}
+ // shame currently has the "base" cost of 10 for normal prims, variable for mesh
- shame += invisi * ARC_INVISI_COST;
- shame += shiny * ARC_SHINY_COST;
- shame += glow * ARC_GLOW_COST;
- shame += alpha * ARC_ALPHA_COST;
- shame += flexi * ARC_FLEXI_COST;
+ // add modifier settings
+ shame += cuts * ARC_CUT_COST;
+ shame += planar * ARC_PLANAR_COST;
shame += animtex * ARC_ANIM_TEX_COST;
+ shame += alpha * ARC_ALPHA_COST;
+ shame += invisi * ARC_INVISI_COST;
+
+ // multiply shame by multipliers
+ if (hollow)
+ {
+ shame *= hollow * ARC_HOLLOW_MULT;
+ }
+
+ if (twist)
+ {
+ shame *= twist * ARC_TWIST_MULT;
+ }
+
+ if (circular_profile)
+ {
+ shame *= circular_profile * ARC_CIRC_PROF_MULT;
+ }
+
+ if (circular_path)
+ {
+ shame *= circular_path * ARC_CIRC_PATH_MULT;
+ }
+
+ if (glow)
+ {
+ shame *= glow * ARC_GLOW_MULT;
+ }
+
+ if (bump)
+ {
+ shame *= bump * ARC_BUMP_MULT;
+ }
+
+ if (flexi)
+ {
+ shame *= flexi * ARC_FLEXI_MULT;
+ }
+
+ if (shiny)
+ {
+ shame *= shiny * ARC_SHINY_MULT;
+ }
+
+ if (scale)
+ {
+ shame *= scale;
+ }
+
+ // add additional costs
shame += particles * ARC_PARTICLE_COST;
- shame += bump * ARC_BUMP_COST;
- shame += planar * ARC_PLANAR_COST;
- shame += scale;
LLViewerObject::const_child_list_t& child_list = getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index f97214295a..eeb98726c9 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -120,7 +120,8 @@ public:
const LLMatrix4& getRelativeXform() const { return mRelativeXform; }
const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; }
/*virtual*/ const LLMatrix4 getRenderMatrix() const;
- U32 getRenderCost(std::set<LLUUID> &textures) const;
+ typedef std::map<LLUUID, S32> texture_cost_t;
+ U32 getRenderCost(texture_cost_t &textures) const;
/*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
S32 face = -1, // which face to check, -1 = ALL_SIDES
@@ -330,8 +331,6 @@ public:
static LLPointer<LLObjectMediaDataClient> sObjectMediaClient;
static LLPointer<LLObjectMediaNavigateClient> sObjectMediaNavigateClient;
- static const U32 ARC_TEXTURE_COST = 5;
-
protected:
static S32 sNumLODChanges;