Initial intergation of ART with LL Perf floater

master
Beq 2021-09-06 17:28:30 +01:00
parent 31f358f451
commit 8b80fa2779
8 changed files with 199 additions and 3 deletions

View File

@ -28,4 +28,11 @@
namespace FSTelemetry
{
bool active{false};
int RecordSceneTime::writeBuffer{0};
bool RecordSceneTime::collectionEnabled{true};
std::array< typename RecordSceneTime::StatsArray, 2 > RecordSceneTime::stats{ {} };
}

View File

@ -63,9 +63,178 @@
#define FSTelemetryIsConnected
#endif // TRACY_ENABLE
#include <chrono>
#include <array>
#include <unordered_map>
namespace FSTelemetry
{
extern bool active;
}
enum class ObjStatType_t{
RENDER_GEOMETRY=0,
RENDER_SHADOWS,
RENDER_COMBINED,
STATS_COUNT
};
enum class SceneStatType_t{
RENDER_GEOMETRY=0,
RENDER_SHADOWS,
RENDER_HUDS,
RENDER_UI,
RENDER_COMBINED,
RENDER_SWAP,
RENDER_FRAME,
RENDER_SLEEP,
RENDER_LFS,
RENDER_MESHREPO,
RENDER_FPSLIMIT,
RENDER_FPS,
STATS_COUNT
};
using ObjStatType = ObjStatType_t;
using SceneStatType = SceneStatType_t;
class RecordSceneTime
{
using StatsEnum = SceneStatType;
using StatsArray = std::array<uint64_t, static_cast<size_t>(StatsEnum::STATS_COUNT)>;
// using StatsBlock = std::unordered_map<T, StatsArray>;
static int writeBuffer;
static std::array<StatsArray,2> stats;
static bool collectionEnabled;
RecordSceneTime(const RecordSceneTime&) = delete;
RecordSceneTime() = delete;
const StatsEnum type;
std::chrono::steady_clock::time_point start;
public:
static inline void enable(){collectionEnabled=true;};
static inline void disable(){collectionEnabled=false;};
static inline bool enabled(){return(collectionEnabled);};
RecordSceneTime(SceneStatType type):start{std::chrono::steady_clock::now()}, type{type} {}
~RecordSceneTime()
{
auto val = std::chrono::duration<uint64_t, std::nano>(std::chrono::steady_clock::now() - start).count();
stats[writeBuffer][static_cast<size_t>(type)] += val;
};
static inline void toggleBuffer()
{
if(enabled())
{
// stats[writeBuffer][static_cast<size_t>(SceneStatType::RENDER_FPS)] = LLTrace::get_frame_recording().getPeriodMeanPerSec(LLStatViewer::FPS,3); // last 3 Frames
writeBuffer = (writeBuffer+1)%2;
}; // not we are relying on atomic updates here. The risk is low and would cause minor errors in the stats display.
auto& statsArray = stats[writeBuffer];
std::fill_n(statsArray.begin() ,static_cast<size_t>(SceneStatType::STATS_COUNT),0);
}
static inline int getReadBufferIndex(){return (writeBuffer+1)%2;};
static inline StatsArray getCurrentStatsBuffer(){ return stats[getReadBufferIndex()];}
static inline uint64_t get(StatsEnum type){return stats[getReadBufferIndex()][static_cast<size_t>(type)];}
};
template <typename T>
class RecordObjectTime
{
using StatsEnum = ObjStatType;
using StatsArray = std::array<uint64_t, static_cast<size_t>(StatsEnum::STATS_COUNT)>;
using StatsBlock = std::unordered_map<T, StatsArray>;
static int writeBuffer;
static std::array<StatsBlock,2> stats;
static std::array<StatsArray,2> max;
static std::array<StatsArray,2> sum;
static bool collectionEnabled;
RecordObjectTime(const RecordObjectTime&) = delete;
RecordObjectTime() = delete;
const T key;
const StatsEnum type;
std::chrono::steady_clock::time_point start;
public:
static inline void enable(){collectionEnabled=true;};
static inline void disable(){collectionEnabled=false;};
static inline bool enabled(){return(collectionEnabled);};
RecordObjectTime(T key, ObjStatType type):start{std::chrono::steady_clock::now()}, key{key}, type{type} {}
~RecordObjectTime()
{
using ST = StatsEnum;
// Note: nullptr is used as the key for global stats
auto val = std::chrono::duration<uint64_t, std::nano>(std::chrono::steady_clock::now() - start).count();
if(key)
{
stats[writeBuffer][key][static_cast<size_t>(type)] += val;
stats[writeBuffer][key][static_cast<size_t>(ST::RENDER_COMBINED)] += val;
if(max[writeBuffer][static_cast<size_t>(type)] < stats[writeBuffer][key][static_cast<size_t>(type)])
{
max[writeBuffer][static_cast<size_t>(type)] = stats[writeBuffer][key][static_cast<size_t>(type)];
}
if(max[writeBuffer][static_cast<size_t>(ST::RENDER_COMBINED)] < stats[writeBuffer][key][static_cast<size_t>(ST::RENDER_COMBINED)])
{
max[writeBuffer][static_cast<size_t>(ST::RENDER_COMBINED)] = stats[writeBuffer][key][static_cast<size_t>(ST::RENDER_COMBINED)];
}
sum[writeBuffer][static_cast<size_t>(type)] += val;
sum[writeBuffer][static_cast<size_t>(ST::RENDER_COMBINED)] += val;
}
};
static inline void toggleBuffer()
{
using ST = StatsEnum;
if(enabled())
{
writeBuffer = (writeBuffer+1)%2;
}; // note we are relying on atomic updates here. The risk is low and would cause minor errors in the stats display.
auto& statsMap = stats[writeBuffer];
for(auto& stat_entry : statsMap)
{
std::fill_n(stat_entry.second.begin() ,static_cast<size_t>(ST::STATS_COUNT),0);
}
statsMap.clear();
std::fill_n(max[writeBuffer].begin(),static_cast<size_t>(ST::STATS_COUNT),0);
std::fill_n(sum[writeBuffer].begin(),static_cast<size_t>(ST::STATS_COUNT),0);
}
static inline int getReadbufferIndex(){return (writeBuffer+1)%2;};
static inline StatsBlock& getCurrentStatsBuffer(){ return stats[(writeBuffer+1)%2]; }
static inline uint64_t getMax(StatsEnum type){return max[(writeBuffer+1)%2][static_cast<size_t>(type)];}
static inline uint64_t getSum(StatsEnum type){return sum[(writeBuffer+1)%2][static_cast<size_t>(type)];}
static inline uint64_t getNum(){return stats[(writeBuffer+1)%2].size();}
static inline uint64_t get(T key, StatsEnum type){return stats[(writeBuffer+1)%2][key][static_cast<size_t>(type)];}
};
static inline void toggleBuffer()
{
// RecordObjectTime<LLVOAvatar*>::toggleBuffer();
RecordSceneTime::toggleBuffer();
}
template< typename T >
int RecordObjectTime<T>::writeBuffer{0};
template< typename T >
bool RecordObjectTime<T>::collectionEnabled{true};
template< typename T >
std::array< typename RecordObjectTime< T >::StatsArray, 2 > RecordObjectTime<T>::max;
template< typename T >
std::array< typename RecordObjectTime< T >::StatsArray, 2 > RecordObjectTime<T>::sum;
template< typename T >
std::array< typename RecordObjectTime< T >::StatsBlock, 2 > RecordObjectTime< T >::stats{ {{}} };
}// namespace FSTelemetry
#endif

View File

@ -1631,6 +1631,9 @@ bool LLAppViewer::frame()
bool LLAppViewer::doFrame()
{
{
FSTelemetry::RecordSceneTime T (FSTelemetry::SceneStatType::RENDER_FRAME);
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
LLSD newFrame;
// <FS:Beq> telemetry enabling.
@ -1828,6 +1831,7 @@ bool LLAppViewer::doFrame()
static LLCachedControl<S32> yield_time(gSavedSettings, "YieldTime", -1);
if(yield_time >= 0)
{
FSTelemetry::RecordSceneTime T ( FSTelemetry::SceneStatType::RENDER_SLEEP );
LL_RECORD_BLOCK_TIME(FTM_YIELD);
ms_sleep(yield_time);
}
@ -1922,6 +1926,7 @@ bool LLAppViewer::doFrame()
if (fsLimitFramerate && LLStartUp::getStartupState() == STATE_STARTED && !gTeleportDisplay && !logoutRequestSent() && max_fps > F_APPROXIMATELY_ZERO)
{
// Sleep a while to limit frame rate.
FSTelemetry::RecordSceneTime T (FSTelemetry::SceneStatType::RENDER_FPSLIMIT);
F32 min_frame_time = 1.f / (F32)max_fps;
S32 milliseconds_to_sleep = llclamp((S32)((min_frame_time - frameTimer.getElapsedTimeF64()) * 1000.f), 0, 1000);
if (milliseconds_to_sleep > 0)
@ -1961,6 +1966,9 @@ bool LLAppViewer::doFrame()
}
FSFrameMark; // <FS:Beq> Tracy support delineate Frame
LLPROFILE_UPDATE();
}
FSTelemetry::RecordSceneTime::toggleBuffer();
FSTelemetry::RecordObjectTime<LLVOAvatar*>::toggleBuffer();
return ! LLApp::isRunning();
}

View File

@ -579,6 +579,8 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
{
return;
}
FSTelemetry::RecordObjectTime<LLVOAvatar*> T(avatarp, FSTelemetry::ObjStatType::RENDER_SHADOWS);
LLVOAvatar::AvatarOverallAppearance oa = avatarp->getOverallAppearance();
BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor();
if (oa == LLVOAvatar::AOA_INVISIBLE ||
@ -1494,6 +1496,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
return;
}
FSTelemetry::RecordObjectTime<LLVOAvatar*> T(avatarp, FSTelemetry::ObjStatType::RENDER_GEOMETRY);
// <FS:Zi> Add avatar hitbox debug
static LLCachedControl<bool> render_hitbox(gSavedSettings, "DebugRenderHitboxes", false);

View File

@ -334,19 +334,21 @@ void LLFloaterPerformance::populateNearbyList()
getNearbyAvatars(valid_nearby_avs);
std::vector<LLCharacter*>::iterator char_iter = valid_nearby_avs.begin();
auto render_max = FSTelemetry::RecordObjectTime<LLVOAvatar*>::getMax(FSTelemetry::ObjStatType::RENDER_COMBINED);
while (char_iter != valid_nearby_avs.end())
{
LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*char_iter);
if (avatar && (LLVOAvatar::AOA_INVISIBLE != avatar->getOverallAppearance()))
{
S32 complexity_short = llmax((S32)avatar->getVisualComplexity() / 1000, 1);;
S32 complexity_short = llmax((S32)avatar->getVisualComplexity() / 1000, 1);
auto render_av = FSTelemetry::RecordObjectTime<LLVOAvatar*>::get(avatar,FSTelemetry::ObjStatType::RENDER_COMBINED);
LLSD item;
item["id"] = avatar->getID();
LLSD& row = item["columns"];
row[0]["column"] = "complex_visual";
row[0]["type"] = "bar";
LLSD& value = row[0]["value"];
value["ratio"] = (F32)complexity_short / mNearbyMaxComplexity * 1000;
value["ratio"] = (double)render_av / render_max;
value["bottom"] = BAR_BOTTOM_PAD;
value["left_pad"] = BAR_LEFT_PAD;
value["right_pad"] = BAR_RIGHT_PAD;

View File

@ -1192,6 +1192,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
void render_hud_attachments()
{
FSTelemetry::RecordSceneTime T (FSTelemetry::SceneStatType::RENDER_HUDS);
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
gGL.matrixMode(LLRender::MM_MODELVIEW);
@ -1399,6 +1400,7 @@ bool setup_hud_matrices(const LLRect& screen_region)
void render_ui(F32 zoom_factor, int subfield)
{
FSTelemetry::RecordSceneTime T (FSTelemetry::SceneStatType::RENDER_UI);
LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
LLGLState::checkStates();
@ -1484,6 +1486,7 @@ static LLTrace::BlockTimerStatHandle FTM_SWAP("Swap");
void swap()
{
FSTelemetry::RecordSceneTime T (FSTelemetry::SceneStatType::RENDER_SWAP);
LL_RECORD_BLOCK_TIME(FTM_SWAP);
if (gDisplaySwapBuffers)

View File

@ -390,6 +390,8 @@ bool LLPipeline::sRenderTextures = true;
bool LLPipeline::sUseDepthTexture = false;
// [/RLVa:KB]
static U32 sShowTrueARC; // <FS:Beq/> True when we have the TrueArc overlay active.
// EventHost API LLPipeline listener.
static LLPipelineListener sPipelineListener;

View File

@ -621,6 +621,8 @@ public:
static bool sUseDepthTexture;
// [/RLVa:KB]
static U32 sShowTrueARC; // <FS:Beq/> True when we have the TrueArc overlay active.
static LLTrace::EventStatHandle<S64> sStatBatchSize;
//screen texture