diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4f4a2d4a82..8147288391 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -15247,6 +15247,28 @@ Change of this parameter will affect the layout of buttons in notification toast Value 0 + StatsFrametimeSampleSeconds + + Comment + The number of seconds to sample extended frametime data (percentiles, stddev). + Persist + 1 + Type + S32 + Value + 5 + + StatsFrametimeEventThreshold + + Comment + The percentage that the frametime difference must exceed in order to register a frametime event. 0.1 = 10%, 0.25 = 25%, etc. + Persist + 1 + Type + F32 + Value + 0.1 + SystemLanguage Comment diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 6b89590072..9d1b13f691 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1956,14 +1956,8 @@ bool LLToolPie::shouldAllowFirstMediaInteraction(const LLPickInfo& pick, bool mo LL_DEBUGS_ONCE() << "FirstClickPref == MEDIA_FIRST_CLICK_NONE" << LL_ENDL; return false; } - // All objects (overriding PRIM_MEDIA_FIRST_CLICK_INTERACT) - if(FirstClickPref == MEDIA_FIRST_CLICK_ALL) - { - LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_ALL" << LL_ENDL; - return true; - } // Every check beyond this point requires PRIM_MEDIA_FIRST_CLICK_INTERACT to be TRUE - if(!moap_flag) + if(!moap_flag && !(FirstClickPref & MEDIA_FIRST_CLICK_BYPASS_MOAP_FLAG)) { LL_DEBUGS_ONCE() << "PRIM_MEDIA_FIRST_CLICK_INTERACT not set" << LL_ENDL; return false; diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index 3c3cdfe22d..6ca5c49264 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -101,15 +101,11 @@ private: MEDIA_FIRST_CLICK_FRIEND = 1 << 3, // 0b00001000 (8) MEDIA_FIRST_CLICK_LAND = 1 << 4, // 0b00010000 (16) - // Covers any object with PRIM_MEDIA_FIRST_CLICK_INTERACT (combines all other flags) - MEDIA_FIRST_CLICK_ANY = MEDIA_FIRST_CLICK_HUD & - MEDIA_FIRST_CLICK_OWN & - MEDIA_FIRST_CLICK_GROUP & - MEDIA_FIRST_CLICK_FRIEND & - MEDIA_FIRST_CLICK_LAND, + // Covers any object with PRIM_MEDIA_FIRST_CLICK_INTERACT (combines all previous flags) + MEDIA_FIRST_CLICK_ANY = ~(3<<30), // 0b00111111111111111111111111111111 // Covers all media regardless of other rules or PRIM_MEDIA_FIRST_CLICK_INTERACT - MEDIA_FIRST_CLICK_ALL = 1 << 30 // 0b01000000000000000000000000000000 (1073741824) + MEDIA_FIRST_CLICK_BYPASS_MOAP_FLAG = 1 << 30 // 0b01000000000000000000000000000000 (1073741824) }; bool shouldAllowFirstMediaInteraction(const LLPickInfo& info, bool moap_flag); bool handleMediaClick(const LLPickInfo& info); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index e0e1d5052f..341e75cc64 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -226,7 +226,16 @@ SimMeasurement SIM_PHYSICS_MEM("physicsmemoryallocated", "", LL LLTrace::SampleStatHandle FRAMETIME_JITTER("frametimejitter", "Average delta between successive frame times"), FRAMETIME("frametime", "Measured frame time"), - SIM_PING("simpingstat"); + SIM_PING("simpingstat"), + FRAMETIME_JITTER_99TH("frametimejitter99", "99th percentile of frametime jitter over the last 5 seconds."), + FRAMETIME_JITTER_95TH("frametimejitter95", "99th percentile of frametime jitter over the last 5 seconds."), + FRAMETIME_99TH("frametime99", "99th percentile of frametime over the last 5 seconds."), + FRAMETIME_95TH("frametime95", "99th percentile of frametime over the last 5 seconds."), + FRAMETIME_JITTER_CUMULATIVE("frametimejitcumulative", "Cumulative frametime jitter over the session."), + FRAMETIME_JITTER_STDDEV("frametimejitterstddev", "Standard deviation of frametime jitter in a 5 second period."), + FRAMETIME_STDDEV("frametimestddev", "Standard deviation of frametime in a 5 second period."); + +LLTrace::SampleStatHandle FRAMETIME_JITTER_EVENTS("frametimeevents", "Number of frametime events in the session. Applies when jitter exceeds 10% of the previous frame."); LLTrace::EventStatHandle > AGENT_POSITION_SNAP("agentpositionsnap", "agent position corrections"); @@ -270,6 +279,38 @@ void LLViewerStats::resetStats() getRecording().reset(); } +// Helper for calculating Nth percentile with linear interpolation +template +T calcPercentile(const std::vector& sorted, double percent) +{ + if (sorted.empty()) + return T(0); + double idx = percent * (sorted.size() - 1); + size_t idx_below = static_cast(std::floor(idx)); + size_t idx_above = static_cast(std::ceil(idx)); + if (idx_below == idx_above) + return sorted[idx_below]; + double weight_above = idx - idx_below; + return sorted[idx_below] * (1.0 - weight_above) + sorted[idx_above] * weight_above; +} + +template +T calcStddev(const std::vector& values) +{ + if (values.size() < 2) + return T(0); + double sum = 0, sq_sum = 0; + for (const auto& v : values) + { + double d = v.value(); + sum += d; + sq_sum += d * d; + } + double mean = sum / values.size(); + double variance = (sq_sum / values.size()) - (mean * mean); + return T(std::sqrt(variance)); +} + void LLViewerStats::updateFrameStats(const F64Seconds time_diff) { if (gFrameCount && mLastTimeDiff > (F64Seconds)0.0) @@ -278,8 +319,50 @@ void LLViewerStats::updateFrameStats(const F64Seconds time_diff) // old stats that were never really used F64Seconds jit = (F64Seconds)std::fabs((mLastTimeDiff - time_diff)); sample(LLStatViewer::FRAMETIME_JITTER, jit); - } + mTotalFrametimeJitter += jit; + sample(LLStatViewer::FRAMETIME_JITTER_CUMULATIVE, mTotalFrametimeJitter); + static LLCachedControl frameTimeEventThreshold(gSavedSettings, "StatsFrametimeEventThreshold", 0.1f); + + if (time_diff - mLastTimeDiff > mLastTimeDiff * frameTimeEventThreshold()) + { + sample(LLStatViewer::FRAMETIME_JITTER_EVENTS, mFrameJitterEvents++); + } + + mFrameTimes.push_back(time_diff); + mFrameTimesJitter.push_back(jit); + + mLastFrameTimeSample += time_diff; + + static LLCachedControl frameTimeSampleSeconds(gSavedSettings, "StatsFrametimeSampleSeconds", 5); + + if (mLastFrameTimeSample >= frameTimeSampleSeconds()) + { + std::sort(mFrameTimes.begin(), mFrameTimes.end()); + std::sort(mFrameTimesJitter.begin(), mFrameTimesJitter.end()); + + // Use new helpers for calculations + F64Seconds frame_time_stddev = calcStddev(mFrameTimes); + sample(LLStatViewer::FRAMETIME_STDDEV, frame_time_stddev); + + F64Seconds ninety_ninth_percentile = calcPercentile(mFrameTimes, 0.99); + F64Seconds ninety_fifth_percentile = calcPercentile(mFrameTimes, 0.95); + sample(LLStatViewer::FRAMETIME_99TH, ninety_ninth_percentile); + sample(LLStatViewer::FRAMETIME_95TH, ninety_fifth_percentile); + + frame_time_stddev = calcStddev(mFrameTimesJitter); + sample(LLStatViewer::FRAMETIME_JITTER_STDDEV, frame_time_stddev); + + ninety_ninth_percentile = calcPercentile(mFrameTimesJitter, 0.99); + ninety_fifth_percentile = calcPercentile(mFrameTimesJitter, 0.95); + sample(LLStatViewer::FRAMETIME_JITTER_99TH, ninety_ninth_percentile); + sample(LLStatViewer::FRAMETIME_JITTER_95TH, ninety_fifth_percentile); + + mFrameTimes.clear(); + mFrameTimesJitter.clear(); + mLastFrameTimeSample = F64Seconds(0); + } + } mLastTimeDiff = time_diff; } diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 13c9239e31..04c86e447b 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -280,6 +280,13 @@ private: LLTrace::Recording mRecording; F64Seconds mLastTimeDiff; // used for time stat updates + F64Seconds mTotalFrametimeJitter; + + U32 mFrameJitterEvents; + + F64Seconds mLastFrameTimeSample; // used for frame time stats + std::vector mFrameTimes; // used for frame time stats + std::vector mFrameTimesJitter; // used for frame time jitter stats }; static const F32 SEND_STATS_PERIOD = 300.0f; diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml index 2b5cc98f3a..0a3af31ef5 100644 --- a/indra/newview/skins/default/xui/en/floater_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_stats.xml @@ -55,6 +55,38 @@ label="jitter" decimal_digits="1" stat="frametimejitter"/> + + + + + + + +