summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunitaiLinden <davep@lindenlab.com>2023-05-01 17:05:09 -0500
committerGitHub <noreply@github.com>2023-05-01 17:05:09 -0500
commit334d71e9107ae3c4d35b181f2ed6e5c9ff1de519 (patch)
tree6a6b64de2c9736c62695f7c5709159ca6e9e0455
parent04604a921d35cf877073828f98a05ae83d03c96e (diff)
SL-19656 Rewrite avatar and attachment render metrics to not interfere with render pipe and be representative of actual render cost instead of driver synchronization time.
* SL-19656 Rewrite avatar and attachment render metrics to not interfere with render pipe and be representative of actual render cost instead of driver synchronization time. * SL-19656 Remove now dead code (trackAttachments et al). * SL-19656 Fix for crash on GL <= 3.2
-rw-r--r--indra/newview/lldrawpool.cpp70
-rw-r--r--indra/newview/lldrawpoolalpha.cpp36
-rw-r--r--indra/newview/lldrawpoolavatar.cpp5
-rw-r--r--indra/newview/lldrawpoolbump.cpp36
-rw-r--r--indra/newview/lldrawpoolmaterials.cpp14
-rw-r--r--indra/newview/llfloaterperformance.cpp246
-rw-r--r--indra/newview/llfloaterperformance.h4
-rw-r--r--indra/newview/llperfstats.cpp13
-rw-r--r--indra/newview/llperfstats.h73
-rw-r--r--indra/newview/llviewerjointmesh.cpp10
-rw-r--r--indra/newview/llviewerobject.h4
-rw-r--r--indra/newview/llvoavatar.cpp3
-rw-r--r--indra/newview/llvoavatar.h39
-rw-r--r--indra/newview/llvovolume.cpp22
-rw-r--r--indra/newview/llworld.cpp8
-rw-r--r--indra/newview/llworld.h4
-rw-r--r--indra/newview/pipeline.cpp125
-rw-r--r--indra/newview/pipeline.h3
18 files changed, 324 insertions, 391 deletions
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 34d8f8b9ce..187e290066 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -52,8 +52,6 @@
#include "llglcommonfunc.h"
#include "llvoavatar.h"
#include "llviewershadermgr.h"
-#include "llperfstats.h"
-
S32 LLDrawPool::sNumDrawPools = 0;
@@ -387,22 +385,11 @@ void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, bool texture)
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Perf stats
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo *pparams = *k;
if (pparams)
{
-#if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if(pparams->mFace)
- {
- LLViewerObject* vobj = pparams->mFace->getViewerObject();
- if(vobj->isAttachment())
- {
- trackAttachments(vobj, false, &ratPtr);
- }
- }
-#endif
pushBatch(*pparams, texture);
}
}
@@ -415,23 +402,11 @@ void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, bool textu
LLVOAvatar* lastAvatar = nullptr;
U64 lastMeshId = 0;
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Perf stats
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo* pparams = *k;
if (pparams)
{
-#if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if(pparams->mFace)
- {
- LLViewerObject* vobj = pparams->mFace->getViewerObject();
- if(vobj->isAttachment())
- {
- trackAttachments( vobj, true ,&ratPtr);
- }
- }
-#endif
-
if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
{
uploadMatrixPalette(*pparams);
@@ -447,7 +422,6 @@ void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, bool textu
void LLRenderPass::pushBatches(U32 type, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{};
auto* begin = gPipeline.beginRenderMap(type);
auto* end = gPipeline.endRenderMap(type);
for (LLCullResult::drawinfo_iterator i = begin; i != end; )
@@ -455,16 +429,6 @@ void LLRenderPass::pushBatches(U32 type, bool texture, bool batch_textures)
LLDrawInfo* pparams = *i;
LLCullResult::increment_iterator(i, end);
-#if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if(pparams->mFace)
- {
- LLViewerObject* vobj = pparams->mFace->getViewerObject();
- if(vobj->isAttachment())
- {
- trackAttachments( vobj, false, &ratPtr);
- }
- }
-#endif
pushBatch(*pparams, texture, batch_textures);
}
}
@@ -476,23 +440,11 @@ void LLRenderPass::pushRiggedBatches(U32 type, bool texture, bool batch_textures
U64 lastMeshId = 0;
auto* begin = gPipeline.beginRenderMap(type);
auto* end = gPipeline.endRenderMap(type);
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Perf stats
for (LLCullResult::drawinfo_iterator i = begin; i != end; )
{
LLDrawInfo* pparams = *i;
LLCullResult::increment_iterator(i, end);
-#if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if(pparams->mFace)
- {
- LLViewerObject* vobj = pparams->mFace->getViewerObject();
- if(vobj->isAttachment())
- {
- trackAttachments( vobj, true, &ratPtr);
- }
- }
-#endif
-
if (pparams->mAvatar.notNull() && (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash))
{
uploadMatrixPalette(*pparams);
@@ -507,23 +459,12 @@ void LLRenderPass::pushRiggedBatches(U32 type, bool texture, bool batch_textures
void LLRenderPass::pushMaskBatches(U32 type, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{};
auto* begin = gPipeline.beginRenderMap(type);
auto* end = gPipeline.endRenderMap(type);
for (LLCullResult::drawinfo_iterator i = begin; i != end; )
{
LLDrawInfo* pparams = *i;
LLCullResult::increment_iterator(i, end);
-#if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if((*pparams).mFace)
- {
- LLViewerObject* vobj = (*pparams).mFace->getViewerObject();
- if(vobj->isAttachment())
- {
- trackAttachments( vobj, false, &ratPtr);
- }
- }
-#endif
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);
pushBatch(*pparams, texture, batch_textures);
}
@@ -534,7 +475,6 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_text
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLVOAvatar* lastAvatar = nullptr;
U64 lastMeshId = 0;
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{};
auto* begin = gPipeline.beginRenderMap(type);
auto* end = gPipeline.endRenderMap(type);
for (LLCullResult::drawinfo_iterator i = begin; i != end; )
@@ -544,16 +484,6 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_text
LLCullResult::increment_iterator(i, end);
llassert(pparams);
-#if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if((*pparams).mFace)
- {
- LLViewerObject* vobj = (*pparams).mFace->getViewerObject();
- if(vobj->isAttachment())
- {
- trackAttachments( vobj, true, &ratPtr);
- }
- }
-#endif
if (LLGLSLShader::sCurBoundShaderPtr)
{
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index da4c963a97..404039189b 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -49,7 +49,6 @@
#include "llspatialpartition.h"
#include "llglcommonfunc.h"
#include "llvoavatar.h"
-#include "llperfstats.h"
#include "llenvironment.h"
@@ -349,22 +348,10 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
{
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA+pass]; // <-- hacky + pass to use PASS_ALPHA_RIGGED on second pass
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Render time Stats collection
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
-# if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if(params.mFace)
- {
- LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
- if(vobj->isAttachment())
- {
- trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
- }
- }
-#endif
-
bool rigged = (params.mAvatar != nullptr);
gHighlightProgram.bind(rigged);
gGL.diffuseColor4f(1, 0, 0, 1);
@@ -548,17 +535,9 @@ void LLDrawPoolAlpha::renderRiggedEmissives(std::vector<LLDrawInfo*>& emissives)
LLVOAvatar* lastAvatar = nullptr;
U64 lastMeshId = 0;
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Render time Stats collection
for (LLDrawInfo* draw : emissives)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("Emissives");
-# if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- auto vobj = draw->mFace?draw->mFace->getViewerObject():nullptr;
- if(vobj && vobj->isAttachment())
- {
- trackAttachments( vobj, draw->mFace->isState(LLFace::RIGGED), &ratPtr );
- }
-#endif
bool tex_setup = TexSetup(draw, false);
if (lastAvatar != draw->mAvatar || lastMeshId != draw->mSkinInfo->mHash)
@@ -687,7 +666,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
LLSpatialGroup::drawmap_elem_t& draw_info = rigged ? group->mDrawMap[LLRenderPass::PASS_ALPHA_RIGGED] : group->mDrawMap[LLRenderPass::PASS_ALPHA];
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Render time Stats collection
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
@@ -700,18 +678,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
LLRenderPass::applyModelMatrix(params);
-# if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if(params.mFace)
- {
- LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
-
- if(vobj->isAttachment())
- {
- trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
- }
- }
-#endif
-
LLMaterial* mat = NULL;
LLGLTFMaterial *gltf_mat = params.mGLTFMaterial;
@@ -905,8 +871,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
}
}
- ratPtr.reset(); // force the final batch to terminate to avoid double counting on the subsidiary batches for FB and Emmissives
-
// render emissive faces into alpha channel for bloom effects
if (!depth_only)
{
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index c398087b20..19b23609a6 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -52,7 +52,6 @@
#include "llviewerpartsim.h"
#include "llviewercontrol.h" // for gSavedSettings
#include "llviewertexturelist.h"
-#include "llperfstats.h"
static U32 sShaderLevel = 0;
@@ -370,9 +369,8 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
{
return;
}
- LLPerfStats::RecordAvatarTime T(avatarp->getID(), LLPerfStats::StatType_t::RENDER_SHADOWS);
- LLVOAvatar::AvatarOverallAppearance oa = avatarp->getOverallAppearance();
+ LLVOAvatar::AvatarOverallAppearance oa = avatarp->getOverallAppearance();
BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor();
// no shadows if the shadows are causing this avatar to breach the limit.
if (avatarp->isTooSlow() || impostor || (oa == LLVOAvatar::AOA_INVISIBLE))
@@ -741,7 +739,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
return;
}
- LLPerfStats::RecordAvatarTime T(avatarp->getID(), LLPerfStats::StatType_t::RENDER_GEOMETRY);
if (!single_avatar && !avatarp->isFullyLoaded() )
{
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index a548740ec4..9ed776f49e 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -49,7 +49,6 @@
#include "llspatialpartition.h"
#include "llviewershadermgr.h"
#include "llmodel.h"
-#include "llperfstats.h"
//#include "llimagebmp.h"
//#include "../tools/imdebug/imdebug.h"
@@ -406,19 +405,10 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, bool texture =
{
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{};
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
-#if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
- if( vobj && vobj->isAttachment() )
- {
- trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
- }
-#endif
-
applyModelMatrix(params);
params.mVertexBuffer->setBuffer();
@@ -568,25 +558,12 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
LLVOAvatar* avatar = nullptr;
U64 skin = 0;
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{};
for (LLCullResult::drawinfo_iterator i = begin; i != end; )
{
LLDrawInfo& params = **i;
LLCullResult::increment_iterator(i, end);
-#if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if(params.mFace)
- {
- LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
-
- if(vobj && vobj->isAttachment())
- {
- trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
- }
- }
-#endif
-
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(params.mAlphaMaskCutoff);
LLDrawPoolBump::bindBumpMap(params, bump_channel);
@@ -1215,23 +1192,10 @@ void LLDrawPoolBump::pushBumpBatches(U32 type)
LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{};
for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
{
LLDrawInfo& params = **i;
-#if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if(params.mFace)
- {
- LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
-
- if( vobj && vobj->isAttachment() )
- {
- trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
- }
- }
-#endif
-
if (LLDrawPoolBump::bindBumpMap(params))
{
if (mRigged)
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index e025651cce..6a7e05ac74 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -32,7 +32,6 @@
#include "pipeline.h"
#include "llglcommonfunc.h"
#include "llvoavatar.h"
-#include "llperfstats.h"
LLDrawPoolMaterials::LLDrawPoolMaterials()
: LLRenderPass(LLDrawPool::POOL_MATERIALS)
@@ -151,7 +150,6 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{};
F32 lastIntensity = 0.f;
F32 lastFullbright = 0.f;
F32 lastMinimumAlpha = 0.f;
@@ -201,18 +199,6 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
LLCullResult::increment_iterator(i, end);
-#if 0 // TODO SL-19656 figure out how to reenable trackAttachments()
- if(params.mFace)
- {
- LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
-
- if( vobj && vobj->isAttachment() )
- {
- trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
- }
- }
-#endif
-
if (specular > -1 && params.mSpecColor != lastSpecular)
{
lastSpecular = params.mSpecColor;
diff --git a/indra/newview/llfloaterperformance.cpp b/indra/newview/llfloaterperformance.cpp
index 3321374f65..25b744a5ab 100644
--- a/indra/newview/llfloaterperformance.cpp
+++ b/indra/newview/llfloaterperformance.cpp
@@ -57,8 +57,6 @@ const S32 BAR_RIGHT_PAD = 5;
const S32 BAR_BOTTOM_PAD = 9;
constexpr auto AvType {LLPerfStats::ObjType_t::OT_AVATAR};
-constexpr auto AttType {LLPerfStats::ObjType_t::OT_ATTACHMENT};
-constexpr auto HudType {LLPerfStats::ObjType_t::OT_HUD};
class LLExceptionsContextMenu : public LLListContextMenu
{
@@ -83,8 +81,7 @@ protected:
LLFloaterPerformance::LLFloaterPerformance(const LLSD& key)
: LLFloater(key),
- mUpdateTimer(new LLTimer()),
- mNearbyMaxComplexity(0)
+ mUpdateTimer(new LLTimer())
{
mContextMenu = new LLExceptionsContextMenu(this);
}
@@ -247,47 +244,82 @@ void LLFloaterPerformance::populateHUDList()
mHUDList->clearRows();
mHUDList->updateColumns(true);
- hud_complexity_list_t complexity_list = LLHUDRenderNotifier::getInstance()->getHUDComplexityList();
-
- hud_complexity_list_t::iterator iter = complexity_list.begin();
- hud_complexity_list_t::iterator end = complexity_list.end();
-
- auto huds_max_render_time_raw = LLPerfStats::StatsRecorder::getMax(HudType, LLPerfStats::StatType_t::RENDER_GEOMETRY);
- for (iter = complexity_list.begin(); iter != end; ++iter)
- {
- LLHUDComplexity hud_object_complexity = *iter;
-
- auto hud_render_time_raw = LLPerfStats::StatsRecorder::get(HudType, hud_object_complexity.objectId, LLPerfStats::StatType_t::RENDER_GEOMETRY);
-
- LLSD item;
- item["special_id"] = hud_object_complexity.objectId;
- item["target"] = LLNameListCtrl::SPECIAL;
- LLSD& row = item["columns"];
- row[0]["column"] = "complex_visual";
- row[0]["type"] = "bar";
- LLSD& value = row[0]["value"];
- value["ratio"] = (F32)hud_render_time_raw / huds_max_render_time_raw;
- value["bottom"] = BAR_BOTTOM_PAD;
- value["left_pad"] = BAR_LEFT_PAD;
- value["right_pad"] = BAR_RIGHT_PAD;
-
- row[1]["column"] = "complex_value";
- row[1]["type"] = "text";
- row[1]["value"] = llformat( "%.f", llmax(LLPerfStats::raw_to_us(hud_render_time_raw), (double)1));
- row[1]["font"]["name"] = "SANSSERIF";
-
- row[2]["column"] = "name";
- row[2]["type"] = "text";
- row[2]["value"] = hud_object_complexity.objectName;
- row[2]["font"]["name"] = "SANSSERIF";
-
- LLScrollListItem* obj = mHUDList->addElement(item);
- if (obj)
+ LLVOAvatar* avatar = gAgentAvatarp;
+
+ gPipeline.profileAvatar(avatar, true);
+
+ LLVOAvatar::attachment_map_t::iterator iter;
+ LLVOAvatar::attachment_map_t::iterator begin = avatar->mAttachmentPoints.begin();
+ LLVOAvatar::attachment_map_t::iterator end = avatar->mAttachmentPoints.end();
+
+ // get max gpu render time of all attachments
+ F32 max_gpu_time = -1.f;
+
+ for (iter = begin; iter != end; ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object && attached_object->isHUDAttachment())
+ {
+ max_gpu_time = llmax(max_gpu_time, attached_object->mGPURenderTime);
+ }
+ }
+ }
+
+
+ for (iter = begin; iter != end; ++iter)
+ {
+ if (!iter->second)
{
- LLScrollListText* value_text = dynamic_cast<LLScrollListText*>(obj->getColumn(1));
- if (value_text)
+ continue;
+ }
+
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object && attached_object->isHUDAttachment())
{
- value_text->setAlignment(LLFontGL::HCENTER);
+ F32 gpu_time = attached_object->mGPURenderTime;
+
+ LLSD item;
+ item["special_id"] = attached_object->getID();
+ item["target"] = LLNameListCtrl::SPECIAL;
+ LLSD& row = item["columns"];
+ row[0]["column"] = "complex_visual";
+ row[0]["type"] = "bar";
+ LLSD& value = row[0]["value"];
+ value["ratio"] = gpu_time / max_gpu_time;
+ value["bottom"] = BAR_BOTTOM_PAD;
+ value["left_pad"] = BAR_LEFT_PAD;
+ value["right_pad"] = BAR_RIGHT_PAD;
+
+ row[1]["column"] = "complex_value";
+ row[1]["type"] = "text";
+ // show gpu time in us
+ row[1]["value"] = llformat("%.f", gpu_time * 1000.f);
+ row[1]["font"]["name"] = "SANSSERIF";
+
+ row[2]["column"] = "name";
+ row[2]["type"] = "text";
+ row[2]["value"] = attached_object->getAttachmentItemName();
+ row[2]["font"]["name"] = "SANSSERIF";
+
+ LLScrollListItem* obj = mHUDList->addElement(item);
+ if (obj)
+ {
+ LLScrollListText* value_text = dynamic_cast<LLScrollListText*>(obj->getColumn(1));
+ if (value_text)
+ {
+ value_text->setAlignment(LLFontGL::HCENTER);
+ }
+ }
}
}
}
@@ -303,50 +335,82 @@ void LLFloaterPerformance::populateObjectList()
mObjectList->clearRows();
mObjectList->updateColumns(true);
- object_complexity_list_t complexity_list = LLAvatarRenderNotifier::getInstance()->getObjectComplexityList();
+ LLVOAvatar* avatar = gAgentAvatarp;
- object_complexity_list_t::iterator iter = complexity_list.begin();
- object_complexity_list_t::iterator end = complexity_list.end();
+ gPipeline.profileAvatar(avatar, true);
- // for consistency we lock the buffer while we build the list. In theory this is uncontended as the buffer should only toggle on end of frame
- {
- std::lock_guard<std::mutex> guard{ LLPerfStats::bufferToggleLock };
- auto att_max_render_time_raw = LLPerfStats::StatsRecorder::getMax(AttType, LLPerfStats::StatType_t::RENDER_COMBINED);
+ LLVOAvatar::attachment_map_t::iterator iter;
+ LLVOAvatar::attachment_map_t::iterator begin = avatar->mAttachmentPoints.begin();
+ LLVOAvatar::attachment_map_t::iterator end = avatar->mAttachmentPoints.end();
- for (iter = complexity_list.begin(); iter != end; ++iter)
- {
- LLObjectComplexity object_complexity = *iter;
+ // get max gpu render time of all attachments
+ F32 max_gpu_time = -1.f;
- auto attach_render_time_raw = LLPerfStats::StatsRecorder::get(AttType, object_complexity.objectId, LLPerfStats::StatType_t::RENDER_COMBINED);
- LLSD item;
- item["special_id"] = object_complexity.objectId;
- item["target"] = LLNameListCtrl::SPECIAL;
- LLSD& row = item["columns"];
- row[0]["column"] = "complex_visual";
- row[0]["type"] = "bar";
- LLSD& value = row[0]["value"];
- value["ratio"] = ((F32)attach_render_time_raw) / att_max_render_time_raw;
- value["bottom"] = BAR_BOTTOM_PAD;
- value["left_pad"] = BAR_LEFT_PAD;
- value["right_pad"] = BAR_RIGHT_PAD;
-
- row[1]["column"] = "complex_value";
- row[1]["type"] = "text";
- row[1]["value"] = llformat("%.f", llmax(LLPerfStats::raw_to_us(attach_render_time_raw), (double)1));
- row[1]["font"]["name"] = "SANSSERIF";
+ for (iter = begin; iter != end; ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object && !attached_object->isHUDAttachment())
+ {
+ max_gpu_time = llmax(max_gpu_time, attached_object->mGPURenderTime);
+ }
+ }
+ }
- row[2]["column"] = "name";
- row[2]["type"] = "text";
- row[2]["value"] = object_complexity.objectName;
- row[2]["font"]["name"] = "SANSSERIF";
+ {
+ for (iter = begin; iter != end; ++iter)
+ {
+ if (!iter->second)
+ {
+ continue;
+ }
- LLScrollListItem* obj = mObjectList->addElement(item);
- if (obj)
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLScrollListText* value_text = dynamic_cast<LLScrollListText*>(obj->getColumn(1));
- if (value_text)
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object && !attached_object->isHUDAttachment())
{
- value_text->setAlignment(LLFontGL::HCENTER);
+ F32 gpu_time = attached_object->mGPURenderTime;
+
+ LLSD item;
+ item["special_id"] = attached_object->getID();
+ item["target"] = LLNameListCtrl::SPECIAL;
+ LLSD& row = item["columns"];
+ row[0]["column"] = "complex_visual";
+ row[0]["type"] = "bar";
+ LLSD& value = row[0]["value"];
+ value["ratio"] = gpu_time / max_gpu_time;
+ value["bottom"] = BAR_BOTTOM_PAD;
+ value["left_pad"] = BAR_LEFT_PAD;
+ value["right_pad"] = BAR_RIGHT_PAD;
+
+ row[1]["column"] = "complex_value";
+ row[1]["type"] = "text";
+ // show gpu time in us
+ row[1]["value"] = llformat("%.f", gpu_time * 1000.f);
+ row[1]["font"]["name"] = "SANSSERIF";
+
+ row[2]["column"] = "name";
+ row[2]["type"] = "text";
+ row[2]["value"] = attached_object->getAttachmentItemName();
+ row[2]["font"]["name"] = "SANSSERIF";
+
+ LLScrollListItem* obj = mObjectList->addElement(item);
+ if (obj)
+ {
+ LLScrollListText* value_text = dynamic_cast<LLScrollListText*>(obj->getColumn(1));
+ if (value_text)
+ {
+ value_text->setAlignment(LLFontGL::HCENTER);
+ }
+ }
}
}
}
@@ -358,6 +422,7 @@ void LLFloaterPerformance::populateObjectList()
void LLFloaterPerformance::populateNearbyList()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
static LLCachedControl<bool> showTunedART(gSavedSettings, "ShowTunedART");
S32 prev_pos = mNearbyList->getScrollPos();
LLUUID prev_selected_id = mNearbyList->getStringUUIDSelectedItem();
@@ -366,22 +431,16 @@ void LLFloaterPerformance::populateNearbyList()
static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0);
std::vector<LLCharacter*> valid_nearby_avs;
- mNearbyMaxComplexity = LLWorld::getInstance()->getNearbyAvatarsAndCompl(valid_nearby_avs);
+ mNearbyMaxGPUTime = LLWorld::getInstance()->getNearbyAvatarsAndMaxGPUTime(valid_nearby_avs);
std::vector<LLCharacter*>::iterator char_iter = valid_nearby_avs.begin();
- LLPerfStats::bufferToggleLock.lock();
- auto av_render_max_raw = LLPerfStats::StatsRecorder::getMax(AvType, LLPerfStats::StatType_t::RENDER_COMBINED);
- LLPerfStats::bufferToggleLock.unlock();
-
while (char_iter != valid_nearby_avs.end())
{
LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*char_iter);
if (avatar && (LLVOAvatar::AOA_INVISIBLE != avatar->getOverallAppearance()))
{
- LLPerfStats::bufferToggleLock.lock();
- auto render_av_raw = LLPerfStats::StatsRecorder::get(AvType, avatar->getID(),LLPerfStats::StatType_t::RENDER_COMBINED);
- LLPerfStats::bufferToggleLock.unlock();
+ F32 render_av_gpu_ms = avatar->getGPURenderTime();
auto is_slow = avatar->isTooSlow();
LLSD item;
@@ -392,7 +451,7 @@ void LLFloaterPerformance::populateNearbyList()
LLSD& value = row[0]["value"];
// The ratio used in the bar is the current cost, as soon as we take action this changes so we keep the
// pre-tune value for the numerical column and sorting.
- value["ratio"] = (double)render_av_raw / av_render_max_raw;
+ value["ratio"] = render_av_gpu_ms / mNearbyMaxGPUTime;
value["bottom"] = BAR_BOTTOM_PAD;
value["left_pad"] = BAR_LEFT_PAD;
value["right_pad"] = BAR_RIGHT_PAD;
@@ -405,14 +464,15 @@ void LLFloaterPerformance::populateNearbyList()
}
else
{
- row[1]["value"] = llformat( "%.f", LLPerfStats::raw_to_us( render_av_raw ) );
+ // use GPU time in us
+ row[1]["value"] = llformat( "%.f", render_av_gpu_ms * 1000.f);
}
row[1]["font"]["name"] = "SANSSERIF";
- row[2]["column"] = "name";
- row[2]["type"] = "text";
- row[2]["value"] = avatar->getFullname();
- row[2]["font"]["name"] = "SANSSERIF";
+ row[3]["column"] = "name";
+ row[3]["type"] = "text";
+ row[3]["value"] = avatar->getFullname();
+ row[3]["font"]["name"] = "SANSSERIF";
LLScrollListItem* av_item = mNearbyList->addElement(item);
if(av_item)
diff --git a/indra/newview/llfloaterperformance.h b/indra/newview/llfloaterperformance.h
index 00f904f6d6..620dbac5bb 100644
--- a/indra/newview/llfloaterperformance.h
+++ b/indra/newview/llfloaterperformance.h
@@ -94,7 +94,9 @@ private:
LLTimer* mUpdateTimer;
- S32 mNearbyMaxComplexity;
+ // maximum GPU time of nearby avatars in ms according to LLWorld::getNearbyAvatarsAndMaxGPUTime
+ // -1.f if no profile has happened yet
+ F32 mNearbyMaxGPUTime = -1.f;
boost::signals2::connection mMaxARTChangedSignal;
};
diff --git a/indra/newview/llperfstats.cpp b/indra/newview/llperfstats.cpp
index c63aae2089..b680d8761b 100644
--- a/indra/newview/llperfstats.cpp
+++ b/indra/newview/llperfstats.cpp
@@ -199,18 +199,7 @@ namespace LLPerfStats
// LL_INFOS("scenestats") << "Scenestat: " << static_cast<size_t>(statEntry) << " before=" << avg << " new=" << val << " newavg=" << statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null][static_cast<size_t>(statEntry)] << LL_ENDL;
}
}
-// Allow attachment times etc to update even when FPS limited or sleeping.
- auto& statsMap = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_ATTACHMENT)];
- for(auto& stat_entry : statsMap)
- {
- auto val = stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)];
- if(val > SMOOTHING_PERIODS){
- auto avg = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_ATTACHMENT)][stat_entry.first][static_cast<size_t>(ST::RENDER_COMBINED)];
- stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)] = avg + (val / SMOOTHING_PERIODS) - (avg / SMOOTHING_PERIODS);
- }
- }
-
-
+
auto& statsMapAv = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_AVATAR)];
for(auto& stat_entry : statsMapAv)
{
diff --git a/indra/newview/llperfstats.h b/indra/newview/llperfstats.h
index dbb88a141d..a4768272b9 100644
--- a/indra/newview/llperfstats.h
+++ b/indra/newview/llperfstats.h
@@ -69,8 +69,6 @@ namespace LLPerfStats
enum class ObjType_t{
OT_GENERAL=0, // Also Unknown. Used for n/a type stats such as scenery
OT_AVATAR,
- OT_ATTACHMENT,
- OT_HUD,
OT_COUNT
};
enum class StatType_t{
@@ -260,31 +258,6 @@ namespace LLPerfStats
doUpd(avKey, ot, type, val);
return;
}
-
- if (ot == ObjType_t::OT_ATTACHMENT)
- {
- if( !upd.isHUD ) // don't include HUD cost in self.
- {
- LL_PROFILE_ZONE_NAMED("Att as Av")
- // For all attachments that are not rigged we add them to the avatar (for all avatars) cost.
- doUpd(avKey, ObjType_t::OT_AVATAR, type, val);
- }
- if( avKey == focusAv )
- {
- LL_PROFILE_ZONE_NAMED("Att as Att")
- // For attachments that are for the focusAv (self for now) we record them for the attachment/complexity view
- if(upd.isHUD)
- {
- ot = ObjType_t::OT_HUD;
- }
- // LL_INFOS("perfstats") << "frame: " << gFrameCount << " Attachment update("<< (type==StatType_t::RENDER_GEOMETRY?"GEOMETRY":"SHADOW") << ": " << key.asString() << " = " << val << LL_ENDL;
- doUpd(key, ot, type, val);
- }
- // else
- // {
- // // LL_INFOS("perfstats") << "frame: " << gFrameCount << " non-self Att update("<< (type==StatType_t::RENDER_GEOMETRY?"GEOMETRY":"SHADOW") << ": " << key.asString() << " = " << val << " for av " << avKey.asString() << LL_ENDL;
- // }
- }
}
static inline void doUpd(const LLUUID& key, ObjType_t ot, StatType_t type, uint64_t val)
@@ -409,51 +382,7 @@ namespace LLPerfStats
using RecordSceneTime = RecordTime<ObjType_t::OT_GENERAL>;
using RecordAvatarTime = RecordTime<ObjType_t::OT_AVATAR>;
- using RecordAttachmentTime = RecordTime<ObjType_t::OT_ATTACHMENT>;
- using RecordHudAttachmentTime = RecordTime<ObjType_t::OT_HUD>;
-
-};// namespace LLPerfStats
-
-// helper functions
-using RATptr = std::unique_ptr<LLPerfStats::RecordAttachmentTime>;
-using RSTptr = std::unique_ptr<LLPerfStats::RecordSceneTime>;
-template <typename T>
-static inline void trackAttachments(const T * vobj, bool isRigged, RATptr* ratPtrp)
-{
- if( !vobj ){ ratPtrp->reset(); return;};
-
- const T* rootAtt{vobj};
- if (rootAtt->isAttachment())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
-
- while( !rootAtt->isRootEdit() )
- {
- rootAtt = (T*)(rootAtt->getParent());
- }
-
- auto avPtr = (T*)(rootAtt->getParent());
- if(!avPtr){ratPtrp->reset(); return;}
-
- auto& av = avPtr->getID();
- auto& obj = rootAtt->getAttachmentItemID();
- if (!*ratPtrp || (*ratPtrp)->stat.objID != obj || (*ratPtrp)->stat.avID != av)
- {
- if (*ratPtrp)
- {
- // deliberately reset to ensure destruction before construction of replacement.
- ratPtrp->reset();
- };
- *ratPtrp = std::make_unique<LLPerfStats::RecordAttachmentTime>(
- av,
- obj,
- ( LLPipeline::sShadowRender?LLPerfStats::StatType_t::RENDER_SHADOWS : LLPerfStats::StatType_t::RENDER_GEOMETRY ),
- isRigged,
- rootAtt->isHUDAttachment());
- }
- }
- return;
-};
+};// namespace LLPerfStats
#endif
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 00e1179896..5ce8f4023d 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -227,16 +227,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
return 0;
}
- // render time capture
- // This path does not appear to have attachments. Prove this then remove.
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{};
- auto vobj = mFace->getViewerObject();
- if( vobj && vobj->isAttachment() )
- {
- trackAttachments( vobj, mFace->isState(LLFace::RIGGED), &ratPtr );
- LL_WARNS("trackAttachments") << "Attachment render time is captuted." << LL_ENDL;
- }
-
U32 triangle_count = 0;
S32 diffuse_channel = LLDrawPoolAvatar::sDiffuseChannel;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index fe27227e6b..cd2363a1b9 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -941,6 +941,10 @@ public:
// reflection probe state
bool mIsReflectionProbe = false; // if true, this object should register itself with LLReflectionProbeManager
LLPointer<LLReflectionMap> mReflectionProbe = nullptr; // reflection probe coupled to this viewer object. If not null, should be deregistered when this object is destroyed
+
+ // the amount of GPU time (in ms) it took to render this object according to LLPipeline::profileAvatar
+ // -1.f if no profile data available
+ F32 mGPURenderTime = -1.f;
};
///////////////////
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 5b8f4767db..e38a6457f4 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -8357,7 +8357,7 @@ void LLVOAvatar::updateTooSlow()
{
// use the cached values.
render_time_raw = mRenderTime;
- render_geom_time_raw = mGeomTime;
+ render_geom_time_raw = mGeomTime;
}
bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf();
@@ -10984,6 +10984,7 @@ void LLVOAvatar::accountRenderComplexityForObject(
// Calculations for mVisualComplexity value
void LLVOAvatar::calculateUpdateRenderComplexity()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
/*****************************************************************
* This calculation should not be modified by third party viewers,
* since it is used to limit rendering and should be uniform for
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 1502c25b4d..0bb19c4420 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -305,8 +305,27 @@ public:
static const U32 VISUAL_COMPLEXITY_UNKNOWN;
void updateVisualComplexity();
- U32 getVisualComplexity() { return mVisualComplexity; }; // Numbers calculated here by rendering AV
- F32 getAttachmentSurfaceArea() { return mAttachmentSurfaceArea; }; // estimated surface area of attachments
+ // get the GPU time in ms of rendering this avatar including all attachments
+ // returns -1 if this avatar has not been profiled using gPipeline.profileAvatar
+ F32 getGPURenderTime() { return mGPURenderTime; }
+
+ // get the CPU time in ms of rendering this avatar including all attachments
+ // return -1 if this avatar has not been profiled using gPipeline.mProfileAvatar
+ F32 getCPURenderTime() { return mCPURenderTime; }
+
+ // get the number of samples passed during the avatar profile
+ // return -1 if this avatar has not been profiled using gPipeline.mProfileAvatar
+ S32 getGPUSamplesPassed() { return mGPUSamplesPassed; }
+
+ // get the number of triangles rendered during the avatar profile
+ // return -1 if this avatar has not been profiled using gPipeline.mProfileAvatar
+ S32 getGPUTrianglesRendered() { return mGPUTrianglesRendered; }
+
+ // DEPRECATED -- obsolete avatar render cost
+ U32 getVisualComplexity() { return mVisualComplexity; };
+
+ // DEPRECATED -- obsolete surface area calculation
+ F32 getAttachmentSurfaceArea() { return mAttachmentSurfaceArea; };
U32 getReportedVisualComplexity() { return mReportedVisualComplexity; }; // Numbers as reported by the SL server
void setReportedVisualComplexity(U32 value) { mReportedVisualComplexity = value; };
@@ -523,6 +542,7 @@ public:
S32 mSpecialRenderMode; // special lighting
private:
+ friend class LLPipeline;
AvatarOverallAppearance mOverallAppearance;
F32 mAttachmentSurfaceArea; //estimated surface area of attachments
U32 mAttachmentVisibleTriangleCount;
@@ -535,7 +555,22 @@ private:
S32 mUpdatePeriod;
S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer.
+ // profile results
+
+ // GPU render time in ms
+ F32 mGPURenderTime = -1.f;
+
+ // CPU render time in ms
+ F32 mCPURenderTime = -1.f;
+
+ // number of samples passed according to GPU
+ S32 mGPUSamplesPassed = -1;
+
+ // number of triangles rendered according to GPU
+ S32 mGPUTrianglesRendered = -1;
+
// the isTooComplex method uses these mutable values to avoid recalculating too frequently
+ // DEPRECATED -- obsolete avatar render cost values
mutable U32 mVisualComplexity;
mutable bool mVisualComplexityStale;
U32 mReportedVisualComplexity; // from other viewers through the simulator
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 12ceb86e52..da5a505d3b 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -88,7 +88,6 @@
#include "llcallstack.h"
#include "llsculptidsize.h"
#include "llavatarappearancedefines.h"
-#include "llperfstats.h"
#include "llgltfmateriallist.h"
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
@@ -5657,7 +5656,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
LL_PROFILE_ZONE_NAMED("rebuildGeom - face list");
//get all the faces into a list
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{};
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin();
drawable_iter != group->getDataEnd(); ++drawable_iter)
{
@@ -5693,11 +5691,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
continue;
}
- if(vobj->isAttachment())
- {
- trackAttachments( vobj, drawablep->isState(LLDrawable::RIGGED),&ratPtr);
- }
-
LLVolume* volume = vobj->getVolume();
if (volume)
{
@@ -6095,8 +6088,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
U32 buffer_count = 0;
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{};
- for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
+ for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
{
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
@@ -6106,11 +6098,6 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
if (!vobj) continue;
- if (vobj->isAttachment())
- {
- trackAttachments( vobj, drawablep->isState(LLDrawable::RIGGED), &ratPtr );
- }
-
if (debugLoggingEnabled("AnimatedObjectsLinkset"))
{
if (vobj->isAnimatedObject() && vobj->isRiggedMesh())
@@ -6479,16 +6466,11 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
U32 indices_index = 0;
U16 index_offset = 0;
- std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr;
while (face_iter < i)
{
//update face indices for new buffer
facep = *face_iter;
- LLViewerObject* vobj = facep->getViewerObject();
- if(vobj && vobj->isAttachment())
- {
- trackAttachments(vobj, LLPipeline::sShadowRender, &ratPtr);
- }
+
if (buffer.isNull())
{
// Bulk allocation failed
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 72c8cb371f..732ef1da6c 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -1424,10 +1424,10 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi
}
}
-S32 LLWorld::getNearbyAvatarsAndCompl(std::vector<LLCharacter*> &valid_nearby_avs)
+F32 LLWorld::getNearbyAvatarsAndMaxGPUTime(std::vector<LLCharacter*> &valid_nearby_avs)
{
static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
- S32 nearby_max_complexity = 0;
+ F32 nearby_max_complexity = 0;
F32 radius = render_far_clip * render_far_clip;
std::vector<LLCharacter*>::iterator char_iter = LLCharacter::sInstances.begin();
while (char_iter != LLCharacter::sInstances.end())
@@ -1441,8 +1441,8 @@ S32 LLWorld::getNearbyAvatarsAndCompl(std::vector<LLCharacter*> &valid_nearby_av
char_iter++;
continue;
}
- avatar->calculateUpdateRenderComplexity();
- nearby_max_complexity = llmax(nearby_max_complexity, (S32)avatar->getVisualComplexity());
+ gPipeline.profileAvatar(avatar);
+ nearby_max_complexity = llmax(nearby_max_complexity, avatar->getGPURenderTime());
valid_nearby_avs.push_back(*char_iter);
}
char_iter++;
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index b2be36d72c..f78cbcaa48 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -172,7 +172,9 @@ public:
// or if the circuit to this simulator had been lost.
bool isRegionListed(const LLViewerRegion* region) const;
- S32 getNearbyAvatarsAndCompl(std::vector<LLCharacter*> &valid_nearby_avs);
+ // profile nearby avatars using gPipeline.profileAvatar and update their render times
+ // return max GPU time
+ F32 getNearbyAvatarsAndMaxGPUTime(std::vector<LLCharacter*> &valid_nearby_avs);
private:
void clearHoleWaterObjects();
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 2912d0da82..df8b8a552a 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -10070,7 +10070,88 @@ void LLPipeline::renderRiggedGroups(LLRenderPass* pass, U32 type, bool texture)
static LLTrace::BlockTimerStatHandle FTM_GENERATE_IMPOSTOR("Generate Impostor");
-void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
+void LLPipeline::profileAvatar(LLVOAvatar* avatar, bool profile_attachments)
+{
+ if (gGLManager.mGLVersion < 3.25f)
+ { // profiling requires GL 3.3 or later
+ return;
+ }
+ LLGLSLShader* cur_shader = LLGLSLShader::sCurBoundShaderPtr;
+
+ mRT->deferredScreen.bindTarget();
+ mRT->deferredScreen.clear();
+
+ bool profile_enabled = LLGLSLShader::sProfileEnabled;
+ LLGLSLShader::sProfileEnabled = true;
+
+ if (!profile_attachments)
+ {
+ // profile entire avatar all at once
+
+ // use gDebugProgram as a proxy for getting profile results
+ gDebugProgram.clearStats();
+ gDebugProgram.placeProfileQuery();
+ LLGLSLShader::sProfileEnabled = false;
+
+ LLTimer cpu_timer;
+
+ generateImpostor(avatar, false, true);
+
+ avatar->mCPURenderTime = (F32)cpu_timer.getElapsedTimeF32() * 1000.f;
+
+ LLGLSLShader::sProfileEnabled = true;
+ gDebugProgram.readProfileQuery();
+
+ avatar->mGPURenderTime = gDebugProgram.mTimeElapsed / 1000000.f;
+
+ avatar->mGPUSamplesPassed = gDebugProgram.mSamplesDrawn;
+ avatar->mGPUTrianglesRendered = gDebugProgram.mTrianglesDrawn;
+ }
+ else
+ {
+ // profile attachments one at a time
+ LLVOAvatar::attachment_map_t::iterator iter;
+ LLVOAvatar::attachment_map_t::iterator begin = avatar->mAttachmentPoints.begin();
+ LLVOAvatar::attachment_map_t::iterator end = avatar->mAttachmentPoints.end();
+
+ for (iter = begin;
+ iter != end;
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object)
+ {
+ gDebugProgram.clearStats();
+ gDebugProgram.placeProfileQuery();
+ LLGLSLShader::sProfileEnabled = false;
+
+ generateImpostor(avatar, false, true, attached_object);
+ LLGLSLShader::sProfileEnabled = true;
+ gDebugProgram.readProfileQuery();
+
+ attached_object->mGPURenderTime = gDebugProgram.mTimeElapsed / 1000000.f;
+
+ // TODO: maybe also record triangles and samples
+ }
+ }
+ }
+ }
+
+ LLGLSLShader::sProfileEnabled = profile_enabled;
+ mRT->deferredScreen.flush();
+
+ if (cur_shader)
+ {
+ cur_shader->bind();
+ }
+}
+
+void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool for_profile, LLViewerObject* specific_attachment)
{
LL_RECORD_BLOCK_TIME(FTM_GENERATE_IMPOSTOR);
LL_PROFILE_GPU_ZONE("generateImpostor");
@@ -10090,11 +10171,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
assertInitialized();
// previews can't be muted or impostered
- bool visually_muted = !preview_avatar && avatar->isVisuallyMuted();
+ bool visually_muted = !for_profile && !preview_avatar && avatar->isVisuallyMuted();
LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID()
<< " is " << ( visually_muted ? "" : "not ") << "visually muted"
<< LL_ENDL;
- bool too_complex = !preview_avatar && avatar->isTooComplex();
+ bool too_complex = !for_profile && !preview_avatar && avatar->isTooComplex();
LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID()
<< " is " << ( too_complex ? "" : "not ") << "too complex"
<< LL_ENDL;
@@ -10129,6 +10210,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
);
}
+ if (specific_attachment && specific_attachment->isHUDAttachment())
+ { //enable HUD rendering
+ setRenderTypeMask(RENDER_TYPE_HUD, END_RENDER_TYPES);
+ }
+
S32 occlusion = sUseOcclusion;
sUseOcclusion = 0;
@@ -10185,20 +10271,30 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
}
else
{
- LLVOAvatar::attachment_map_t::iterator iter;
- for (iter = avatar->mAttachmentPoints.begin();
- iter != avatar->mAttachmentPoints.end();
- ++iter)
+ if (specific_attachment)
{
- LLViewerJointAttachment *attachment = iter->second;
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
+ markVisible(specific_attachment->mDrawable->getSpatialBridge(), *viewer_camera);
+ }
+ else
+ {
+ LLVOAvatar::attachment_map_t::iterator iter;
+ LLVOAvatar::attachment_map_t::iterator begin = avatar->mAttachmentPoints.begin();
+ LLVOAvatar::attachment_map_t::iterator end = avatar->mAttachmentPoints.end();
+
+ for (iter = begin;
+ iter != end;
+ ++iter)
{
- LLViewerObject* attached_object = attachment_iter->get();
- if (attached_object)
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object)
+ {
+ markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+ }
}
}
}
@@ -10327,6 +10423,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
LLDrawPoolAvatar::sMinimumAlpha = old_alpha;
+ if (!for_profile)
{ //create alpha mask based on depth buffer (grey out if muted)
if (LLPipeline::sRenderDeferred)
{
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index dbd1a34f61..45842a3948 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -132,7 +132,8 @@ public:
bool allocateShadowBuffer(U32 resX, U32 resY);
void resetVertexBuffers(LLDrawable* drawable);
- void generateImpostor(LLVOAvatar* avatar, bool preview_avatar = false);
+ void profileAvatar(LLVOAvatar* avatar, bool profile_attachments = false);
+ void generateImpostor(LLVOAvatar* avatar, bool preview_avatar = false, bool for_profile = false, LLViewerObject* specific_attachment = nullptr);
void bindScreenToTexture();
void renderFinalize();
void copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst);