summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/llappviewer.cpp2
-rw-r--r--indra/newview/llfloaterperformance.cpp11
-rw-r--r--indra/newview/llperfstats.cpp67
-rw-r--r--indra/newview/llperfstats.h68
-rw-r--r--indra/newview/llviewerstats.cpp2
-rw-r--r--indra/newview/llvoavatar.cpp146
-rw-r--r--indra/newview/llvoavatar.h30
-rw-r--r--indra/newview/llworld.cpp6
-rw-r--r--indra/newview/pipeline.cpp42
9 files changed, 201 insertions, 173 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 6efbaeacf7..c9fc0e2cc8 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -4698,6 +4698,8 @@ void LLAppViewer::idle()
LLFrameTimer::updateFrameTime();
LLFrameTimer::updateFrameCount();
LLEventTimer::updateClass();
+ LLPerfStats::updateClass();
+
// LLApp::stepFrame() performs the above three calls plus mRunner.run().
// Not sure why we don't call stepFrame() here, except that LLRunner seems
// completely redundant with LLEventTimer.
diff --git a/indra/newview/llfloaterperformance.cpp b/indra/newview/llfloaterperformance.cpp
index 8c5745aa43..19fc3e673e 100644
--- a/indra/newview/llfloaterperformance.cpp
+++ b/indra/newview/llfloaterperformance.cpp
@@ -456,15 +456,8 @@ void LLFloaterPerformance::populateNearbyList()
row[1]["column"] = "complex_value";
row[1]["type"] = "text";
- if (is_slow && !showTunedART)
- {
- row[1]["value"] = llformat( "%.f", LLPerfStats::raw_to_us( avatar->getLastART() ) );
- }
- else
- {
- // use GPU time in us
- row[1]["value"] = llformat( "%.f", render_av_gpu_ms * 1000.f);
- }
+ // use GPU time in us
+ row[1]["value"] = llformat( "%.f", render_av_gpu_ms * 1000.f);
row[1]["font"]["name"] = "SANSSERIF";
row[3]["column"] = "name";
diff --git a/indra/newview/llperfstats.cpp b/indra/newview/llperfstats.cpp
index b680d8761b..2281475d4a 100644
--- a/indra/newview/llperfstats.cpp
+++ b/indra/newview/llperfstats.cpp
@@ -39,6 +39,11 @@ extern LLControlGroup gSavedSettings;
namespace LLPerfStats
{
+ // avatar timing metrics in ms (updated once per mainloop iteration)
+ std::atomic<F32> sTotalAvatarTime = 0.f;
+ std::atomic<F32> sAverageAvatarTime = 0.f;
+ std::atomic<F32> sMaxAvatarTime = 0.f;
+
std::atomic<int64_t> tunedAvatars{0};
std::atomic<U64> renderAvatarMaxART_ns{(U64)(ART_UNLIMITED_NANOS)}; // highest render time we'll allow without culling features
bool belowTargetFPS{false};
@@ -141,14 +146,12 @@ namespace LLPerfStats
resetChanges();
}
- StatsRecorder::StatsRecorder():q(1024*16),t(&StatsRecorder::run)
+ StatsRecorder::StatsRecorder():q(1024*16)
{
// create a queue
- // create a thread to consume from the queue
tunables.initialiseFromSettings();
LLPerfStats::cpu_hertz = (F64)LLTrace::BlockTimer::countsPerSecond();
LLPerfStats::vsync_max_fps = gViewerWindow->getWindow()->getRefreshRate();
- t.detach();
}
// static
@@ -200,20 +203,6 @@ namespace LLPerfStats
}
}
- auto& statsMapAv = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_AVATAR)];
- for(auto& stat_entry : statsMapAv)
- {
- for(auto& stat : avatarStatsToAvg)
- {
- auto val = stat_entry.second[static_cast<size_t>(stat)];
- if(val > SMOOTHING_PERIODS)
- {
- auto avg = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_AVATAR)][stat_entry.first][static_cast<size_t>(stat)];
- stat_entry.second[static_cast<size_t>(stat)] = avg + (val / SMOOTHING_PERIODS) - (avg / SMOOTHING_PERIODS);
- }
- }
- }
-
// swap the buffers
if(enabled())
{
@@ -293,6 +282,36 @@ namespace LLPerfStats
}
}
+ // called once per main loop iteration on main thread
+ void updateClass()
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+
+ sTotalAvatarTime = LLVOAvatar::getTotalGPURenderTime();
+ sAverageAvatarTime = LLVOAvatar::getAverageGPURenderTime();
+ sMaxAvatarTime = LLVOAvatar::getMaxGPURenderTime();
+
+ auto& general = LL::WorkQueue::getInstance("General");
+
+ if (general)
+ {
+ general->post([] { StatsRecorder::update(); });
+ }
+ }
+
+ // called once per main loop iteration on General thread
+ void StatsRecorder::update()
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ StatsRecord upd;
+ auto& instance{ StatsRecorder::getInstance() };
+
+ while (enabled() && !LLApp::isQuitting() && instance.q.tryPop(upd))
+ {
+ instance.processUpdate(upd);
+ }
+ }
+
//static
int StatsRecorder::countNearbyAvatars(S32 distance)
{
@@ -327,6 +346,8 @@ namespace LLPerfStats
// static
void StatsRecorder::updateAvatarParams()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+
if(tunables.autoTuneTimeout)
{
LLPerfStats::lastSleepedFrame = gFrameCount;
@@ -380,10 +401,10 @@ namespace LLPerfStats
}
}
- auto av_render_max_raw = LLPerfStats::StatsRecorder::getMax(ObjType_t::OT_AVATAR, LLPerfStats::StatType_t::RENDER_COMBINED);
+ auto av_render_max_raw = ms_to_raw(sMaxAvatarTime);
// Is our target frame time lower than current? If so we need to take action to reduce draw overheads.
// cumulative avatar time (includes idle processing, attachments and base av)
- auto tot_avatar_time_raw = LLPerfStats::StatsRecorder::getSum(ObjType_t::OT_AVATAR, LLPerfStats::StatType_t::RENDER_COMBINED);
+ auto tot_avatar_time_raw = ms_to_raw(sTotalAvatarTime);
// The frametime budget we have based on the target FPS selected
auto target_frame_time_raw = (U64)llround(LLPerfStats::cpu_hertz / (target_fps == 0 ? 1 : target_fps));
@@ -417,7 +438,7 @@ namespace LLPerfStats
// if so we've got work to do
// how much of the frame was spent on non avatar related work?
- U64 non_avatar_time_raw = tot_frame_time_raw - tot_avatar_time_raw;
+ U64 non_avatar_time_raw = tot_frame_time_raw > tot_avatar_time_raw ? tot_frame_time_raw - tot_avatar_time_raw : 0;
// If the target frame time < scene time (estimated as non_avatar time)
U64 target_avatar_time_raw;
@@ -475,7 +496,11 @@ namespace LLPerfStats
{
new_render_limit_ns = renderAvatarMaxART_ns;
}
- new_render_limit_ns -= LLPerfStats::ART_MIN_ADJUST_DOWN_NANOS;
+
+ if (new_render_limit_ns > LLPerfStats::ART_MIN_ADJUST_DOWN_NANOS)
+ {
+ new_render_limit_ns -= LLPerfStats::ART_MIN_ADJUST_DOWN_NANOS;
+ }
// bounce at the bottom to prevent "no limit"
new_render_limit_ns = std::max((U64)new_render_limit_ns, (U64)LLPerfStats::ART_MINIMUM_NANOS);
diff --git a/indra/newview/llperfstats.h b/indra/newview/llperfstats.h
index a4768272b9..bb5677f237 100644
--- a/indra/newview/llperfstats.h
+++ b/indra/newview/llperfstats.h
@@ -42,6 +42,10 @@ extern U32 gFrameCount;
extern LLUUID gAgentID;
namespace LLPerfStats
{
+
+ // called once per main loop iteration
+ void updateClass();
+
// Note if changing these, they should correspond with the log range of the correpsonding sliders
static constexpr U64 ART_UNLIMITED_NANOS{50000000};
static constexpr U64 ART_MINIMUM_NANOS{100000};
@@ -68,7 +72,6 @@ namespace LLPerfStats
enum class ObjType_t{
OT_GENERAL=0, // Also Unknown. Used for n/a type stats such as scenery
- OT_AVATAR,
OT_COUNT
};
enum class StatType_t{
@@ -162,6 +165,9 @@ namespace LLPerfStats
using Queue = LLThreadSafeQueue<StatsRecord>;
public:
+ // called once per main loop iteration on General thread
+ static void update();
+
static inline StatsRecorder& getInstance()
{
static StatsRecorder instance;
@@ -241,7 +247,6 @@ namespace LLPerfStats
auto ot{upd.objType};
auto& key{upd.objID};
- auto& avKey{upd.avID};
auto type {upd.statType};
auto val {upd.time};
@@ -251,13 +256,6 @@ namespace LLPerfStats
doUpd(key, ot, type,val);
return;
}
-
- if (ot == ObjType_t::OT_AVATAR)
- {
- // LL_INFOS("perfstats") << "Avatar update:" << LL_ENDL;
- doUpd(avKey, ot, type, val);
- return;
- }
}
static inline void doUpd(const LLUUID& key, ObjType_t ot, StatType_t type, uint64_t val)
@@ -286,42 +284,7 @@ namespace LLPerfStats
static void toggleBuffer();
static void clearStatsBuffers();
- // thread entry
- static void run()
- {
- StatsRecord upd[10];
- auto & instance {StatsRecorder::getInstance()};
- LL_PROFILER_SET_THREAD_NAME("PerfStats");
-
- while( enabled() && !LLApp::isExiting() )
- {
- auto count = 0;
- while (count < 10)
- {
- if (instance.q.tryPopFor(std::chrono::milliseconds(10), upd[count]))
- {
- count++;
- }
- else
- {
- break;
- }
- }
- //LL_PROFILER_THREAD_BEGIN("PerfStats");
- if(count)
- {
- // LL_INFOS("perfstats") << "processing " << count << " updates." << LL_ENDL;
- for(auto i =0; i < count; i++)
- {
- instance.processUpdate(upd[i]);
- }
- }
- //LL_PROFILER_THREAD_END("PerfStats");
- }
- }
-
Queue q;
- std::thread t;
~StatsRecorder() = default;
StatsRecorder(const StatsRecorder&) = delete;
@@ -354,13 +317,6 @@ namespace LLPerfStats
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
};
- template < ObjType_t OD = ObjTypeDiscriminator,
- std::enable_if_t<OD == ObjType_t::OT_AVATAR> * = nullptr>
- RecordTime( const LLUUID & av, StatType_t type ):RecordTime<ObjTypeDiscriminator>(std::move(av), LLUUID::null, type)
- {
- //LL_PROFILE_ZONE_COLOR(tracy::Color::Purple);
- };
-
~RecordTime()
{
if(!LLPerfStats::StatsRecorder::enabled())
@@ -375,13 +331,19 @@ namespace LLPerfStats
};
};
-
+
inline double raw_to_ns(U64 raw) { return (static_cast<double>(raw) * 1000000000.0) / LLPerfStats::cpu_hertz; };
inline double raw_to_us(U64 raw) { return (static_cast<double>(raw) * 1000000.0) / LLPerfStats::cpu_hertz; };
inline double raw_to_ms(U64 raw) { return (static_cast<double>(raw) * 1000.0) / LLPerfStats::cpu_hertz; };
+ inline U64 ns_to_raw(double ns) { return (U64)(LLPerfStats::cpu_hertz * (ns / 1000000000.0)); }
+ inline U64 us_to_raw(double us) { return (U64)(LLPerfStats::cpu_hertz * (us / 1000000.0)); }
+ inline U64 ms_to_raw(double ms) { return (U64)(LLPerfStats::cpu_hertz * (ms / 1000.0));
+
+ }
+
+
using RecordSceneTime = RecordTime<ObjType_t::OT_GENERAL>;
- using RecordAvatarTime = RecordTime<ObjType_t::OT_AVATAR>;
};// namespace LLPerfStats
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 609e8290da..37999e58ff 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -472,7 +472,7 @@ void update_statistics()
auto tot_frame_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_FRAME);
// cumulative avatar time (includes idle processing, attachments and base av)
- auto tot_avatar_time_raw = LLPerfStats::StatsRecorder::getSum(LLPerfStats::ObjType_t::OT_AVATAR, LLPerfStats::StatType_t::RENDER_COMBINED);
+ auto tot_avatar_time_raw = LLPerfStats::us_to_raw(LLVOAvatar::getTotalGPURenderTime());
// cumulative avatar render specific time (a bit arbitrary as the processing is too.)
// auto tot_av_idle_time_raw = LLPerfStats::StatsRecorder::getSum(AvType, LLPerfStats::StatType_t::RENDER_IDLE);
// auto tot_avatar_render_time_raw = tot_avatar_time_raw - tot_av_idle_time_raw;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 95e9321d6f..af65588709 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2562,7 +2562,6 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
return;
}
// record time and refresh "tooSlow" status
- LLPerfStats::RecordAvatarTime T(getID(), LLPerfStats::StatType_t::RENDER_IDLE); // per avatar "idle" time.
updateTooSlow();
static LLCachedControl<bool> disable_all_render_types(gSavedSettings, "DisableAllRenderTypes");
@@ -8310,14 +8309,6 @@ bool LLVOAvatar::isTooSlow() const
return mTooSlow;
}
-// use Avatar Render Time as complexity metric
-// markARTStale - Mark stale and set the frameupdate to now so that we can wait at least one frame to get a revised number.
-void LLVOAvatar::markARTStale()
-{
- mARTStale=true;
- mLastARTUpdateFrame = LLFrameTimer::getFrameCount();
-}
-
// Udpate Avatar state based on render time
void LLVOAvatar::updateTooSlow()
{
@@ -8328,41 +8319,9 @@ void LLVOAvatar::updateTooSlow()
// mTooSlow - Is the avatar flagged as being slow (includes shadow time)
// mTooSlowWithoutShadows - Is the avatar flagged as being slow even with shadows removed.
- // mARTStale - the rendertime we have is stale because of an update. We need to force a re-render to re-assess slowness
-
- if( mARTStale )
- {
- if ( LLFrameTimer::getFrameCount() - mLastARTUpdateFrame < 5 )
- {
- // LL_INFOS() << this->getFullname() << " marked stale " << LL_ENDL;
- // we've not had a chance to update yet (allow a few to be certain a full frame has passed)
- return;
- }
-
- mARTStale = false;
- mTooSlow = false;
- mTooSlowWithoutShadows = false;
- // LL_INFOS() << this->getFullname() << " refreshed ART combined = " << mRenderTime << " @ " << mLastARTUpdateFrame << LL_ENDL;
- }
-
- // Either we're not stale or we've updated.
-
- U64 render_time_raw;
- U64 render_geom_time_raw;
-
- if( !mTooSlow )
- {
- // we are fully rendered, so we use the live values
- std::lock_guard<std::mutex> lock{LLPerfStats::bufferToggleLock};
- render_time_raw = LLPerfStats::StatsRecorder::get(LLPerfStats::ObjType_t::OT_AVATAR, id, LLPerfStats::StatType_t::RENDER_COMBINED);
- render_geom_time_raw = LLPerfStats::StatsRecorder::get(LLPerfStats::ObjType_t::OT_AVATAR, id, LLPerfStats::StatType_t::RENDER_GEOMETRY);
- }
- else
- {
- // use the cached values.
- render_time_raw = mRenderTime;
- render_geom_time_raw = mGeomTime;
- }
+
+ // get max render time in ms
+ F32 max_art_ms = (F32) (LLPerfStats::renderAvatarMaxART_ns / 1000000.0);
bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf();
@@ -8378,19 +8337,13 @@ void LLVOAvatar::updateTooSlow()
}
bool exceeds_max_ART =
- ((LLPerfStats::renderAvatarMaxART_ns > 0) && (LLPerfStats::raw_to_ns(render_time_raw) >= LLPerfStats::renderAvatarMaxART_ns));
+ ((LLPerfStats::renderAvatarMaxART_ns > 0) &&
+ (mGPURenderTime >= max_art_ms)); // NOTE: don't use getGPURenderTime accessor here to avoid "isTooSlow" feedback loop
if (exceeds_max_ART && !ignore_tune)
{
- if( !mTooSlow ) // if we were previously not slow (with or without shadows.)
- {
- // if we weren't capped, we are now
- mLastARTUpdateFrame = LLFrameTimer::getFrameCount();
- mRenderTime = render_time_raw;
- mGeomTime = render_geom_time_raw;
- mARTStale = false;
- mTooSlow = true;
- }
+ mTooSlow = true;
+
if(!mTooSlowWithoutShadows) // if we were not previously above the full impostor cap
{
bool render_friend_or_exception = ( alwaysRenderFriends && LLAvatarTracker::instance().isBuddy( id ) ) ||
@@ -8398,13 +8351,12 @@ void LLVOAvatar::updateTooSlow()
if( (!isSelf() || allowSelfImpostor) && !render_friend_or_exception )
{
// Note: slow rendering Friends still get their shadows zapped.
- mTooSlowWithoutShadows = (LLPerfStats::raw_to_ns(render_geom_time_raw) >= LLPerfStats::renderAvatarMaxART_ns);
+ mTooSlowWithoutShadows = getGPURenderTime()*2.f >= max_art_ms; // NOTE: assumes shadow rendering doubles render time
}
}
}
else
{
- // LL_INFOS() << this->getFullname() << " ("<< (combined?"combined":"geometry") << ") good render time = " << LLPerfStats::raw_to_ns(render_time_raw) << " vs ("<< LLVOAvatar::sRenderTimeCap_ns << " set @ " << mLastARTUpdateFrame << LL_ENDL;
mTooSlow = false;
mTooSlowWithoutShadows = false;
@@ -11103,6 +11055,21 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
// HUD complexity
LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity_list);
}
+
+ //schedule an update to ART next frame if needed
+ if (LLPerfStats::tunables.userAutoTuneEnabled &&
+ LLPerfStats::tunables.userFPSTuningStrategy != LLPerfStats::TUNE_SCENE_ONLY &&
+ !isVisuallyMuted())
+ {
+ LLUUID id = getID(); // <== use id to make sure this avatar didn't get deleted between frames
+ LL::WorkQueue::getInstance("mainloop")->post([this, id]()
+ {
+ if (gObjectList.findObject(id) != nullptr)
+ {
+ gPipeline.profileAvatar(this);
+ }
+ });
+ }
}
}
@@ -11465,6 +11432,9 @@ void LLVOAvatar::readProfileQuery(S32 retries)
glGetQueryObjectui64v(mGPUTimerQuery, GL_QUERY_RESULT, &time_elapsed);
mGPURenderTime = time_elapsed / 1000000.f;
mGPUProfilePending = false;
+
+ setDebugText(llformat("%d", (S32)(mGPURenderTime * 1000.f)));
+
}
else
{ // wait until next frame
@@ -11477,3 +11447,67 @@ void LLVOAvatar::readProfileQuery(S32 retries)
}
}
+
+F32 LLVOAvatar::getGPURenderTime()
+{
+ return isVisuallyMuted() ? 0.f : mGPURenderTime;
+}
+
+// static
+F32 LLVOAvatar::getTotalGPURenderTime()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ F32 ret = 0.f;
+
+ for (LLCharacter* iter : LLCharacter::sInstances)
+ {
+ LLVOAvatar* inst = (LLVOAvatar*) iter;
+ ret += inst->getGPURenderTime();
+ }
+
+ return ret;
+}
+
+F32 LLVOAvatar::getMaxGPURenderTime()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ F32 ret = 0.f;
+
+ for (LLCharacter* iter : LLCharacter::sInstances)
+ {
+ LLVOAvatar* inst = (LLVOAvatar*)iter;
+ ret = llmax(inst->getGPURenderTime(), ret);
+ }
+
+ return ret;
+}
+
+F32 LLVOAvatar::getAverageGPURenderTime()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ F32 ret = 0.f;
+
+ S32 count = 0;
+
+ for (LLCharacter* iter : LLCharacter::sInstances)
+ {
+ LLVOAvatar* inst = (LLVOAvatar*)iter;
+ if (!inst->isTooSlow())
+ {
+ ret += inst->getGPURenderTime();
+ ++count;
+ }
+ }
+
+ if (count > 0)
+ {
+ ret /= count;
+ }
+
+ return ret;
+}
+
+
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 2ca44b041a..e8604464ae 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -309,11 +309,21 @@ public:
void readProfileQuery(S32 retries);
// 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; }
+ // returns 0.f if this avatar has not been profiled using gPipeline.profileAvatar
+ // or the avatar is visually muted
+ F32 getGPURenderTime();
+
+ // get the total GPU render time in ms of all avatars that have been benched
+ static F32 getTotalGPURenderTime();
+
+ // get the max GPU render time in ms of all avatars that have been benched
+ static F32 getMaxGPURenderTime();
+
+ // get the average GPU render time in ms of all avatars that have been benched
+ static F32 getAverageGPURenderTime();
// 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
+ // return 0.f if this avatar has not been profiled using gPipeline.mProfileAvatar
F32 getCPURenderTime() { return mCPURenderTime; }
@@ -401,8 +411,7 @@ public:
void logMetricsTimerRecord(const std::string& phase_name, F32 elapsed, bool completed);
void calcMutedAVColor();
- void markARTStale();
-
+
protected:
LLViewerStats::PhaseMap& getPhases() { return mPhases; }
BOOL updateIsFullyLoaded();
@@ -423,11 +432,6 @@ private:
LLFrameTimer mFullyLoadedTimer;
LLFrameTimer mRuthTimer;
- U32 mLastARTUpdateFrame{0};
- U64 mRenderTime{0};
- U64 mGeomTime{0};
- bool mARTStale{true};
- bool mARTCapped{false};
// variables to hold "slowness" status
bool mTooSlow{false};
bool mTooSlowWithoutShadows{false};
@@ -557,11 +561,11 @@ private:
// profile results
// GPU render time in ms
- F32 mGPURenderTime = -1.f;
+ F32 mGPURenderTime = 0.f;
bool mGPUProfilePending = false;
// CPU render time in ms
- F32 mCPURenderTime = -1.f;
+ F32 mCPURenderTime = 0.f;
// the isTooComplex method uses these mutable values to avoid recalculating too frequently
// DEPRECATED -- obsolete avatar render cost values
@@ -1203,8 +1207,6 @@ public:
// COF version of last appearance message received for this av.
S32 mLastUpdateReceivedCOFVersion;
- U64 getLastART() const { return mRenderTime; }
-
/** Diagnostics
** **
*******************************************************************************/
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 732ef1da6c..0e0dbdc071 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -1441,7 +1441,11 @@ F32 LLWorld::getNearbyAvatarsAndMaxGPUTime(std::vector<LLCharacter*> &valid_near
char_iter++;
continue;
}
- gPipeline.profileAvatar(avatar);
+
+ if (!avatar->isTooSlow())
+ {
+ gPipeline.profileAvatar(avatar);
+ }
nearby_max_complexity = llmax(nearby_max_complexity, avatar->getGPURenderTime());
valid_nearby_avs.push_back(*char_iter);
}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 4d9a8a594a..6ea86c4cbb 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -10073,6 +10073,9 @@ void LLPipeline::profileAvatar(LLVOAvatar* avatar, bool profile_attachments)
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ // don't continue to profile an avatar that is known to be too slow
+ llassert(!avatar->isTooSlow());
+
LLGLSLShader* cur_shader = LLGLSLShader::sCurBoundShaderPtr;
mRT->deferredScreen.bindTarget();
@@ -10345,25 +10348,28 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool
resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
- if (!avatar->mImpostor.isComplete())
- {
- avatar->mImpostor.allocate(resX, resY, GL_RGBA, true);
+ if (!for_profile)
+ {
+ if (!avatar->mImpostor.isComplete())
+ {
+ avatar->mImpostor.allocate(resX, resY, GL_RGBA, true);
- if (LLPipeline::sRenderDeferred)
- {
- addDeferredAttachments(avatar->mImpostor, true);
- }
-
- gGL.getTexUnit(0)->bind(&avatar->mImpostor);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
- else if(resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight())
- {
- avatar->mImpostor.resize(resX,resY);
- }
+ if (LLPipeline::sRenderDeferred)
+ {
+ addDeferredAttachments(avatar->mImpostor, true);
+ }
+
+ gGL.getTexUnit(0)->bind(&avatar->mImpostor);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
+ else if (resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight())
+ {
+ avatar->mImpostor.resize(resX, resY);
+ }
- avatar->mImpostor.bindTarget();
+ avatar->mImpostor.bindTarget();
+ }
}
F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha;
@@ -10466,7 +10472,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool
gGL.popMatrix();
}
- if (!preview_avatar)
+ if (!preview_avatar && !for_profile)
{
avatar->mImpostor.flush();
avatar->setImpostorDim(tdim);