Migrate perfstats away from telemetry/profiling

perfstats is now a standalone module.
master
Beq 2021-10-13 02:04:05 +01:00
parent af4fe2fd2d
commit 390c136430
18 changed files with 619 additions and 213 deletions

View File

@ -258,13 +258,18 @@ set(llcommon_HEADER_FILES
StackWalker.h
)
# <FS:ND> Add all nd* files. memory pool, intrinsics, ...
# <FS:Beq> Tracy Profiler support
list(APPEND llcommon_SOURCE_FILES fstelemetry.cpp)
if (USE_TRACY_PROFILER)
list(APPEND llcommon_SOURCE_FILES fstracyclient.cpp)
endif()
# <FS:Beq> Tracy Profiler support
list(APPEND llcommon_SOURCE_FILES fstelemetry.cpp)
if (USE_TRACY_PROFILER)
list(APPEND llcommon_SOURCE_FILES fstracyclient.cpp)
endif()
# </FS:Beq> Tracy Profiler support
# <FS:Beq> Performance stast support
list(APPEND llcommon_SOURCE_FILES fsperfstats.cpp)
list(APPEND llcommon_HEADER_FILES fsperfstats.h)
# </FS:Beq>
# <FS:ND> Add all nd* files. memory pool, intrinsics, ...
SET( llcommon_ND_SOURCE_FILES
nd/ndexceptions.cpp
nd/ndlogthrottle.cpp

View File

@ -0,0 +1,36 @@
/**
* @file fsperfstats.cpp
* @brief Stats collection to support perf floater and auto tune
*
* $LicenseInfo:firstyear=2021&license=fsviewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (C) 2021, The Phoenix Firestorm Project, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
* http://www.firestormviewer.org
* $/LicenseInfo$
*/
#include "fsperfstats.h"
namespace FSPerfStats
{
int RecordSceneTime::writeBuffer{0};
bool RecordSceneTime::collectionEnabled{true};
std::array< typename RecordSceneTime::StatsArray, 2 > RecordSceneTime::stats{ {} };
}

View File

@ -0,0 +1,299 @@
#pragma once
#ifndef FS_PERFSTATS_H_INCLUDED
#define FS_PERFSTATS_H_INCLUDED
/**
* @file fsperfstats.h
* @brief Statistics collection to support autotune and perf flaoter.
*
* $LicenseInfo:firstyear=2021&license=fsviewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (C) 2021, The Phoenix Firestorm Project, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
* http://www.firestormviewer.org
* $/LicenseInfo$
*/
#include <chrono>
#include <array>
#include <unordered_map>
namespace FSPerfStats
{
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,
RENDER_IDLE,
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
constexpr auto period{500};
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;
// auto& statsMap = stats[writeBuffer];
// for(auto& stat_entry : statsMap)
// {
// auto val = stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)];
// auto avg = stats[(writeBuffer+1)%2][stat_entry.first][static_cast<size_t>(ST::RENDER_COMBINED)];
// stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)] = avg + (val/500) - (avg/500);
// }
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)];}
};
template <typename T>
class RecordAttachmentTime
{
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;
RecordAttachmentTime(const RecordAttachmentTime&) = delete;
RecordAttachmentTime() = 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);};
RecordAttachmentTime(T key, ObjStatType type):start{std::chrono::steady_clock::now()}, key{key}, type{type} {}
~RecordAttachmentTime()
{
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();
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{ {{}} };
template< typename T >
int RecordAttachmentTime<T>::writeBuffer{0};
template< typename T >
bool RecordAttachmentTime<T>::collectionEnabled{true};
template< typename T >
std::array< typename RecordAttachmentTime< T >::StatsArray, 2 > RecordAttachmentTime<T>::max;
template< typename T >
std::array< typename RecordAttachmentTime< T >::StatsArray, 2 > RecordAttachmentTime<T>::sum;
template< typename T >
std::array< typename RecordAttachmentTime< T >::StatsBlock, 2 > RecordAttachmentTime< T >::stats{ {{}} };
}// namespace FSPerfStats
#endif

View File

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

View File

@ -46,6 +46,7 @@
#define FSPlot( name, value ) TracyPlot( name, value)
#define FSFrameMark FrameMark
#define FSThreadName( name ) tracy::SetThreadName( name )
#define FSMessageL ( message ) tracy::Profiler::Message( message, 0 )
#define FSTelemetryIsConnected TracyIsConnected
#else // (no telemetry)
@ -60,6 +61,7 @@
#define FSPlot( name, value )
#define FSFrameMark
#define FSThreadName( name )
#define FSMessageL ( message )
#define FSTelemetryIsConnected
#endif // TRACY_ENABLE
@ -71,171 +73,6 @@ 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,
RENDER_IDLE,
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

@ -286,6 +286,7 @@
#include "fsassetblacklist.h"
#include "fstelemetry.h" // <FS:Beq> Tracy profiler support
#include "fsperfstats.h" // <FS:Beq> performance stats support
#if LL_LINUX && LL_GTK
#include "glib.h"
@ -1632,7 +1633,7 @@ bool LLAppViewer::frame()
bool LLAppViewer::doFrame()
{
{
FSTelemetry::RecordSceneTime T (FSTelemetry::SceneStatType::RENDER_FRAME);
FSPerfStats::RecordSceneTime T (FSPerfStats::SceneStatType::RENDER_FRAME);
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
LLSD newFrame;
@ -1770,7 +1771,7 @@ bool LLAppViewer::doFrame()
// Update state based on messages, user input, object idle.
{
FSTelemetry::RecordSceneTime T (FSTelemetry::SceneStatType::RENDER_IDLE);
FSPerfStats::RecordSceneTime T (FSPerfStats::SceneStatType::RENDER_IDLE);
pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
@ -1850,7 +1851,7 @@ bool LLAppViewer::doFrame()
// of equal priority on Windows
if (milliseconds_to_sleep > 0)
{
FSTelemetry::RecordSceneTime T ( FSTelemetry::SceneStatType::RENDER_SLEEP );
FSPerfStats::RecordSceneTime T ( FSPerfStats::SceneStatType::RENDER_SLEEP );
ms_sleep(milliseconds_to_sleep);
// also pause worker threads during this wait period
LLAppViewer::getTextureCache()->pause();
@ -1928,7 +1929,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);
FSPerfStats::RecordSceneTime T (FSPerfStats::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)
@ -1969,8 +1970,9 @@ bool LLAppViewer::doFrame()
FSFrameMark; // <FS:Beq> Tracy support delineate Frame
LLPROFILE_UPDATE();
}
FSTelemetry::RecordSceneTime::toggleBuffer();
FSTelemetry::RecordObjectTime<const LLVOAvatar*>::toggleBuffer();
FSPerfStats::RecordSceneTime::toggleBuffer();
FSPerfStats::RecordObjectTime<const LLVOAvatar*>::toggleBuffer();
FSPerfStats::RecordAttachmentTime<U32>::toggleBuffer();
return ! LLApp::isRunning();
}

View File

@ -30,6 +30,9 @@
#define LL_llavatarrendernotifier_H
#include "llnotificationptr.h"
#include "llviewerobject.h"
#include "llhudobject.h"
class LLViewerRegion;
@ -45,6 +48,7 @@ struct LLHUDComplexity
objectName = "";
objectsCost = 0;
objectsCount = 0;
objectPtr = nullptr;
texturesCost = 0;
texturesCount = 0;
largeTexturesCount = 0;
@ -58,6 +62,7 @@ struct LLHUDComplexity
U32 texturesCost;
U32 texturesCount;
U32 largeTexturesCount;
const LLViewerObject * objectPtr;
F64Bytes texturesMemoryTotal;
};

View File

@ -50,6 +50,7 @@
#include "lldrawpoolwlsky.h"
#include "llglslshader.h"
#include "llglcommonfunc.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
S32 LLDrawPool::sNumDrawPools = 0;
@ -452,6 +453,27 @@ void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)
void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
{
// <FS:Beq> Capture render times
LLViewerObject* rootAtt{};
std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>> T{};
if(params.mFace)
{
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if(vobj->isAttachment())
{
auto par = (LLViewerObject*)vobj->getParent();
rootAtt = vobj;
while( par->isAttachment() )
{
rootAtt = par;
par = (LLViewerObject*)par->getParent();
}
LL_INFOS() << "pushBatch recording time for ATT@" << rootAtt << " " << (rootAtt?rootAtt->getAttachmentItemName():"null") << " as " << rootAtt->getAttachmentItemID().getCRC32() << LL_ENDL;
if(rootAtt){T = std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>>(new FSPerfStats::RecordAttachmentTime<U32>(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));}
}
}
// </FS:Beq>
if (!params.mCount)
{
return;

View File

@ -48,6 +48,7 @@
#include "lldrawpoolwater.h"
#include "llspatialpartition.h"
#include "llglcommonfunc.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
@ -352,6 +353,27 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
// <FS:Beq> Capture render times
std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>> T{};
if(params.mFace)
{
LLViewerObject* rootAtt{};
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if(vobj->isAttachment())
{
auto par = (LLViewerObject*)vobj->getParent();
rootAtt = vobj;
while( par->isAttachment() )
{
rootAtt = par;
par = (LLViewerObject*)par->getParent();
}
LL_INFOS() << "recording time for ATT@" << rootAtt << " " << (rootAtt?rootAtt->getAttachmentItemName():"null") << " as " << rootAtt->getAttachmentItemID().getCRC32() << LL_ENDL;
if(rootAtt){T = std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>>(new FSPerfStats::RecordAttachmentTime<U32>(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));}
}
}
// </FS:Beq>
if (params.mParticle)
{
@ -679,6 +701,28 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
continue;
}
// <FS:Beq> Capture render times
std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>> T{};
if(params.mFace)
{
LLViewerObject* rootAtt{};
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if(vobj->isAttachment())
{
auto par = (LLViewerObject*)vobj->getParent();
rootAtt = vobj;
while( par->isAttachment() )
{
rootAtt = par;
par = (LLViewerObject*)par->getParent();
}
LL_INFOS() << "ALPHA recording time for ATT@" << rootAtt << " " << (rootAtt?rootAtt->getAttachmentItemName():"null") << " as " << rootAtt->getAttachmentItemID().getCRC32() << LL_ENDL;
if(rootAtt){T = std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>>(new FSPerfStats::RecordAttachmentTime<U32>(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));}
}
}
// </FS:Beq>
// Fix for bug - NORSPEC-271
// If the face is more than 90% transparent, then don't update the Depth buffer for Dof
// We don't want the nearly invisible objects to cause of DoF effects

View File

@ -59,6 +59,8 @@
// void drawBoxOutline(const LLVector3& pos,const LLVector3& size); // llspatialpartition.cpp
// </FS:Zi>
#include "llnetmap.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK;
static U32 sBufferUsage = GL_STREAM_DRAW_ARB;
@ -579,7 +581,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
{
return;
}
FSTelemetry::RecordObjectTime<const LLVOAvatar*> T(avatarp, FSTelemetry::ObjStatType::RENDER_SHADOWS);
FSPerfStats::RecordObjectTime<const LLVOAvatar*> T(avatarp, FSPerfStats::ObjStatType::RENDER_SHADOWS);
LLVOAvatar::AvatarOverallAppearance oa = avatarp->getOverallAppearance();
BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor();
@ -1465,6 +1467,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == -1)
{
FSZoneN("pass -1");
for (S32 i = 1; i < getNumPasses(); i++)
{ //skip foot shadows
prerender();
@ -1481,7 +1484,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
return;
}
LLVOAvatar *avatarp = NULL;
LLVOAvatar *avatarp { nullptr };
if (single_avatar)
{
@ -1501,12 +1504,13 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
return;
}
FSTelemetry::RecordObjectTime<const LLVOAvatar*> T(avatarp, FSTelemetry::ObjStatType::RENDER_GEOMETRY);
FSPerfStats::RecordObjectTime<const LLVOAvatar*> T(avatarp, FSPerfStats::ObjStatType::RENDER_GEOMETRY);
// <FS:Zi> Add avatar hitbox debug
static LLCachedControl<bool> render_hitbox(gSavedSettings, "DebugRenderHitboxes", false);
if (render_hitbox && pass == 2)
{
FSZoneN("render_hitbox");
LLGLSLShader* current_shader_program = NULL;
// load the debug output shader
@ -1589,6 +1593,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (!single_avatar && !avatarp->isFullyLoaded() )
{
FSZoneN("avatar not loaded");
if (pass==0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0))
{
// debug code to draw a sphere in place of avatar
@ -1636,6 +1641,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 0)
{
FSZoneN("pass 0");
if (!LLPipeline::sReflectionRender)
{
LLVOAvatar::sNumVisibleAvatars++;
@ -1644,6 +1650,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
// if (impostor || (LLVOAvatar::AV_DO_NOT_RENDER == avatarp->getVisualMuteSettings() && !avatarp->needsImpostorUpdate()))
if (impostor || (LLVOAvatar::AOA_NORMAL != avatarp->getOverallAppearance() && !avatarp->needsImpostorUpdate()))
{
FSZoneN("render impostor");
if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete())
{
// <FS:Ansariel> FIRE-9179: Crash fix
@ -1669,6 +1676,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 1)
{
FSZoneN("render rigid meshes (eyeballs)");
// render rigid meshes (eyeballs) first
avatarp->renderRigid();
return;
@ -1676,12 +1684,15 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 3)
{
FSZoneN("pass 3");
if (is_deferred_render)
{
FSZoneN("deferred rigged simple");
renderDeferredRiggedSimple(avatarp);
}
else
{
FSZoneN("non-deferred rigged");
renderRiggedSimple(avatarp);
if (LLPipeline::sRenderDeferred)
@ -1705,12 +1716,15 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 4)
{
FSZoneN("pass 4");
if (is_deferred_render)
{
FSZoneN("deferred rigged bump");
renderDeferredRiggedBump(avatarp);
}
else
{
FSZoneN("non-deferred fullbright");
renderRiggedFullbright(avatarp);
}
@ -1719,6 +1733,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (is_deferred_render && pass >= 5 && pass <= 21)
{
FSZoneN("deferred passes 5-21");
S32 p = pass-5;
if (p != 1 &&
@ -1726,6 +1741,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
p != 9 &&
p != 13)
{
FSZoneN("deferred rigged material");
renderDeferredRiggedMaterial(avatarp, p);
}
return;
@ -1736,6 +1752,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 5)
{
FSZoneN("rigged shiny");
renderRiggedShinySimple(avatarp);
return;
@ -1743,6 +1760,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 6)
{
FSZoneN("rigged FB shiny");
renderRiggedFullbrightShiny(avatarp);
return;
}
@ -1751,10 +1769,12 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
if (pass == 7)
{
FSZoneN("pass 7 rigged Alpha");
renderRiggedAlpha(avatarp);
if (LLPipeline::sRenderDeferred && !is_post_deferred_render)
{ //render transparent materials under water
FSZoneN("rigged Alpha Blend");
LLGLEnable blend(GL_BLEND);
gGL.setColorMask(true, true);
@ -1775,6 +1795,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 8)
{
FSZoneN("pass 8 rigged FB Alpha");
renderRiggedFullbrightAlpha(avatarp);
return;
}
@ -1791,6 +1812,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
{
FSZoneN("post deferred rigged Alpha");
LLGLEnable blend(GL_BLEND);
renderDeferredRiggedMaterial(avatarp, p);
}
@ -1798,6 +1820,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
else if (pass == 9)
{
FSZoneN("pass 9 - rigged glow");
renderRiggedGlow(avatarp);
return;
}
@ -1805,6 +1828,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass == 13)
{
FSZoneN("pass 13 - rigged glow");
renderRiggedGlow(avatarp);
return;
@ -1812,6 +1836,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
{
FSZoneN("shader level > CLOTH");
LLMatrix4 rot_mat;
LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
@ -1837,6 +1862,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if( !single_avatar || (avatarp == single_avatar) )
{
FSZoneN("renderSkinned");
avatarp->renderSkinned();
}
}
@ -2254,7 +2280,24 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
{
continue;
}
auto self = avatar->isSelf();
LLViewerObject * parentAttachment{nullptr};
if(self && vobj->isAttachment())
{
LLViewerObject * vtop = vobj;
LLViewerObject * par = (LLViewerObject *) vobj->getParent();
while (par && !(par->asAvatar()))
{
vtop = par;
par = (LLViewerObject *)vtop->getParent();
}
parentAttachment = vtop;
}
FSPerfStats::RecordAttachmentTime<U32> T(parentAttachment?parentAttachment->getAttachmentItemID().getCRC32():0, FSPerfStats::ObjStatType::RENDER_GEOMETRY);
LLVolume* volume = vobj->getVolume();
S32 te = face->getTEOffset();
@ -2555,6 +2598,7 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
{
for (U32 i = 0; i < mRiggedFace[type].size(); ++i)
{
FSZoneN("updateRiggedVBO");
LLFace* face = mRiggedFace[type][i];
LLDrawable* drawable = face->getDrawable();
if (!drawable)

View File

@ -47,6 +47,7 @@
#include "pipeline.h"
#include "llspatialpartition.h"
#include "llviewershadermgr.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
//#include "llimagebmp.h"
//#include "../tools/imdebug/imdebug.h"
@ -646,7 +647,24 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
// <FS:Beq> Capture render times
LLViewerObject* rootAtt{};
std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>> T{};
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if(vobj->isAttachment())
{
auto par = (LLViewerObject*)vobj->getParent();
rootAtt = vobj;
while( par->isAttachment() )
{
rootAtt = par;
par = (LLViewerObject*)par->getParent();
}
LL_INFOS() << "recording time for ATT@" << rootAtt << " " << (rootAtt?rootAtt->getAttachmentItemName():"null") << " as " << rootAtt->getAttachmentItemID().getCRC32() << LL_ENDL;
if(rootAtt){T = std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>>(new FSPerfStats::RecordAttachmentTime<U32>(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));}
}
// </FS:Beq>
applyModelMatrix(params);
if (params.mGroup)
@ -1512,6 +1530,27 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask)
void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
{
// <FS:Beq> Capture render times
std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>> T{};
if(params.mFace)
{
LLViewerObject* rootAtt{};
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if(vobj->isAttachment())
{
auto par = (LLViewerObject*)vobj->getParent();
rootAtt = vobj;
while( par->isAttachment() )
{
rootAtt = par;
par = (LLViewerObject*)par->getParent();
}
// LL_INFOS() << "recording time for ATT@" << rootAtt << " " << (rootAtt?rootAtt->getAttachmentItemName():"null") << " as " << rootAtt->getAttachmentItemID().getCRC32() << LL_ENDL;
if(rootAtt){T = std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>>(new FSPerfStats::RecordAttachmentTime<U32>(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));}
}
}
// </FS:Beq>
applyModelMatrix(params);
bool tex_setup = false;

View File

@ -31,6 +31,7 @@
#include "llviewershadermgr.h"
#include "pipeline.h"
#include "llglcommonfunc.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
S32 diffuse_channel = -1;
@ -138,7 +139,29 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
{
LLDrawInfo& params = **i;
// <FS:Beq> Capture render times
std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>> T{};
if(params.mFace)
{
LLViewerObject* rootAtt{};
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
if(vobj->isAttachment())
{
auto par = (LLViewerObject*)vobj->getParent();
rootAtt = vobj;
while( par->isAttachment() )
{
rootAtt = par;
par = (LLViewerObject*)par->getParent();
}
LL_INFOS() << "MATERIALS recording time for ATT@" << rootAtt << " " << (rootAtt?rootAtt->getAttachmentItemName():"null") << " as " << rootAtt->getAttachmentItemID().getCRC32() << LL_ENDL;
if(rootAtt){T = std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>>(new FSPerfStats::RecordAttachmentTime<U32>(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));}
}
}
// </FS:Beq>
mShader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]);
mShader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity);

View File

@ -59,6 +59,7 @@
// [RLVa:KB] - Checked: RLVa-2.0.0
#include "rlvhandler.h"
// [/RLVa:KB]
#include "fsperfstats.h" // <FS:Beq> performance stats support
#if LL_LINUX
// Work-around spurious used before init warning on Vector4a
@ -642,6 +643,20 @@ void renderFace(LLDrawable* drawable, LLFace *face)
LLVOVolume* vobj = drawable->getVOVolume();
if (vobj)
{
LLVOVolume* rootAtt{};
std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>> T{};
if(vobj->isAttachment())
{
auto par = (LLVOVolume*)vobj->getParent();
rootAtt = vobj;
while( par->isAttachment() )
{
rootAtt = par;
par = (LLVOVolume*)par->getParent();
}
// LL_INFOS() << "recording time for ATT@" << rootAtt << " " << (rootAtt?rootAtt->getAttachmentItemName():"null") << LL_ENDL;
if(rootAtt){T = std::unique_ptr<FSPerfStats::RecordAttachmentTime<U32>>(new FSPerfStats::RecordAttachmentTime<U32>(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));}
}
LLVolume* volume = NULL;
if (drawable->isState(LLDrawable::RIGGED))

View File

@ -46,6 +46,7 @@
#include "pipeline.h"
#include "llviewercontrol.h"
#include "fsavatarrenderpersistence.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
const F32 REFRESH_INTERVAL = 1.0f;
const S32 BAR_LEFT_PAD = 2;
@ -176,13 +177,13 @@ void LLFloaterPerformance::draw()
getChild<LLTextBox>("fps_value")->setValue((S32)llround(fps));
auto tot_frame_time_ns = 1000000000/fps;
auto target_frame_time_ns = 1000000000/(target_fps==0?1:target_fps);
auto tot_avatar_time = FSTelemetry::RecordObjectTime<const LLVOAvatar*>::getSum(FSTelemetry::ObjStatType::RENDER_COMBINED);
auto tot_huds_time = FSTelemetry::RecordSceneTime::get(FSTelemetry::SceneStatType::RENDER_HUDS) ;
auto tot_sleep_time = FSTelemetry::RecordSceneTime::get(FSTelemetry::SceneStatType::RENDER_SLEEP);
auto tot_ui_time = FSTelemetry::RecordSceneTime::get(FSTelemetry::SceneStatType::RENDER_UI);
auto tot_idle_time = FSTelemetry::RecordSceneTime::get(FSTelemetry::SceneStatType::RENDER_IDLE);
auto tot_limit_time = FSTelemetry::RecordSceneTime::get(FSTelemetry::SceneStatType::RENDER_FPSLIMIT);
auto tot_swap_time = FSTelemetry::RecordSceneTime::get(FSTelemetry::SceneStatType::RENDER_SWAP);
auto tot_avatar_time = FSPerfStats::RecordObjectTime<const LLVOAvatar*>::getSum(FSPerfStats::ObjStatType::RENDER_COMBINED);
auto tot_huds_time = FSPerfStats::RecordSceneTime::get(FSPerfStats::SceneStatType::RENDER_HUDS) ;
auto tot_sleep_time = FSPerfStats::RecordSceneTime::get(FSPerfStats::SceneStatType::RENDER_SLEEP);
auto tot_ui_time = FSPerfStats::RecordSceneTime::get(FSPerfStats::SceneStatType::RENDER_UI);
auto tot_idle_time = FSPerfStats::RecordSceneTime::get(FSPerfStats::SceneStatType::RENDER_IDLE);
auto tot_limit_time = FSPerfStats::RecordSceneTime::get(FSPerfStats::SceneStatType::RENDER_FPSLIMIT);
auto tot_swap_time = FSPerfStats::RecordSceneTime::get(FSPerfStats::SceneStatType::RENDER_SWAP);
// once the rest is extracted what is left is the scene cost (we don't include non-render activities such as network here prlloy should.)
auto tot_scene_time = tot_frame_time_ns - tot_avatar_time - tot_huds_time - tot_ui_time - tot_sleep_time - tot_limit_time - tot_swap_time;
@ -241,7 +242,7 @@ void LLFloaterPerformance::draw()
if( auto_tune )
{
auto av_render_max = FSTelemetry::RecordObjectTime<const LLVOAvatar*>::getMax(FSTelemetry::ObjStatType::RENDER_COMBINED);
auto av_render_max = FSPerfStats::RecordObjectTime<const LLVOAvatar*>::getMax(FSPerfStats::ObjStatType::RENDER_COMBINED);
// if( target_frame_time_ns <= tot_frame_time_ns )
// {
@ -344,10 +345,12 @@ void LLFloaterPerformance::populateHUDList()
max_complexity = llmax(max_complexity, (*iter).objectsCost);
}
auto huds_max_render_time = FSPerfStats::RecordObjectTime<LLHUDObject*>::getMax(FSPerfStats::ObjStatType::RENDER_GEOMETRY);
for (iter = complexity_list.begin(); iter != end; ++iter)
{
LLHUDComplexity hud_object_complexity = *iter;
S32 obj_cost_short = llmax((S32)hud_object_complexity.objectsCost / 1000, 1);
LLHUDComplexity hud_object_complexity = *iter;
auto hud_ptr = hud_object_complexity.objectPtr;
auto hud_render_time = FSPerfStats::RecordObjectTime<const LLViewerObject*>::get(hud_ptr, FSPerfStats::ObjStatType::RENDER_GEOMETRY);
LLSD item;
item["special_id"] = hud_object_complexity.objectId;
item["target"] = LLNameListCtrl::SPECIAL;
@ -404,10 +407,13 @@ void LLFloaterPerformance::populateObjectList()
max_complexity = llmax(max_complexity, (*iter).objectCost);
}
auto max_render_time = FSPerfStats::RecordAttachmentTime<U32>::getMax(FSPerfStats::ObjStatType::RENDER_GEOMETRY);
for (iter = complexity_list.begin(); iter != end; ++iter)
{
LLObjectComplexity object_complexity = *iter;
S32 obj_cost_short = llmax((S32)object_complexity.objectCost / 1000, 1);
// S32 obj_cost_short = llmax((S32)object_complexity.objectCost / 1000, 1);
auto attach_render_time = FSPerfStats::RecordAttachmentTime<U32>::get(object_complexity.objectId.getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY);
LLSD item;
item["special_id"] = object_complexity.objectId;
item["target"] = LLNameListCtrl::SPECIAL;
@ -415,14 +421,15 @@ void LLFloaterPerformance::populateObjectList()
row[0]["column"] = "complex_visual";
row[0]["type"] = "bar";
LLSD& value = row[0]["value"];
value["ratio"] = (F32)obj_cost_short / max_complexity * 1000;
value["ratio"] = (F32)attach_render_time / max_render_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";
row[1]["value"] = std::to_string(obj_cost_short);
// row[1]["value"] = std::to_string(obj_cost_short);
row[1]["value"] = llformat("%.3f",((double)attach_render_time / 1000000));
row[1]["font"]["name"] = "SANSSERIF";
row[2]["column"] = "name";
@ -460,7 +467,7 @@ void LLFloaterPerformance::populateNearbyList()
getNearbyAvatars(valid_nearby_avs);
std::vector<LLCharacter*>::iterator char_iter = valid_nearby_avs.begin();
auto render_max = FSTelemetry::RecordObjectTime<const LLVOAvatar*>::getMax(FSTelemetry::ObjStatType::RENDER_COMBINED);
auto render_max = FSPerfStats::RecordObjectTime<const LLVOAvatar*>::getMax(FSPerfStats::ObjStatType::RENDER_COMBINED);
while (char_iter != valid_nearby_avs.end())
{
LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*char_iter);
@ -471,7 +478,7 @@ void LLFloaterPerformance::populateNearbyList()
continue;
// S32 complexity_short = llmax((S32)avatar->getVisualComplexity() / 1000, 1);
auto render_av = FSTelemetry::RecordObjectTime<const LLVOAvatar*>::get(avatar,FSTelemetry::ObjStatType::RENDER_COMBINED);
auto render_av = FSPerfStats::RecordObjectTime<const LLVOAvatar*>::get(avatar,FSPerfStats::ObjStatType::RENDER_COMBINED);
auto is_slow = avatar->isTooSlow(true);
// auto is_slow_without_shadows = avatar->isTooSlow();

View File

@ -85,6 +85,7 @@
// [/RLVa:KB]
#include "llpresetsmanager.h"
#include "fsdata.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
extern LLPointer<LLViewerTexture> gStartTexture;
extern bool gShiftFrame;
@ -1192,7 +1193,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
void render_hud_attachments()
{
FSTelemetry::RecordSceneTime T (FSTelemetry::SceneStatType::RENDER_HUDS);
FSPerfStats::RecordSceneTime T (FSPerfStats::SceneStatType::RENDER_HUDS);
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
gGL.matrixMode(LLRender::MM_MODELVIEW);
@ -1400,7 +1401,7 @@ bool setup_hud_matrices(const LLRect& screen_region)
void render_ui(F32 zoom_factor, int subfield)
{
FSTelemetry::RecordSceneTime T (FSTelemetry::SceneStatType::RENDER_UI);
FSPerfStats::RecordSceneTime T (FSPerfStats::SceneStatType::RENDER_UI);
LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
LLGLState::checkStates();
@ -1486,7 +1487,7 @@ static LLTrace::BlockTimerStatHandle FTM_SWAP("Swap");
void swap()
{
FSTelemetry::RecordSceneTime T (FSTelemetry::SceneStatType::RENDER_SWAP);
FSPerfStats::RecordSceneTime T (FSPerfStats::SceneStatType::RENDER_SWAP);
LL_RECORD_BLOCK_TIME(FTM_SWAP);
if (gDisplaySwapBuffers)

View File

@ -55,6 +55,7 @@
#include "m3math.h"
#include "m4math.h"
#include "llmatrix4a.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
#if !LL_DARWIN && !LL_LINUX
extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB;
@ -222,6 +223,7 @@ int compare_int(const void *a, const void *b)
//--------------------------------------------------------------------
U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
{
FSZone;
if (!mValid || !mMesh || !mFace || !mVisible ||
!mFace->getVertexBuffer() ||
mMesh->getNumFaces() == 0 ||
@ -230,6 +232,22 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
return 0;
}
auto vobj = mFace->getViewerObject();
if(vobj && !vobj->asAvatar() && vobj->getAvatar()->isSelf())
{
LLViewerObject * vtop = vobj;
LLViewerObject * par = (LLViewerObject *) vobj->getParent();
while (par && !(par->asAvatar()))
{
vtop = par;
par = (LLViewerObject *)vtop->getParent();
}
vobj = vtop;
}
FSPerfStats::RecordAttachmentTime<U32> T(vobj?vobj->getAttachmentItemID().getCRC32():0, FSPerfStats::ObjStatType::RENDER_GEOMETRY);
U32 triangle_count = 0;
S32 diffuse_channel = LLDrawPoolAvatar::sDiffuseChannel;

View File

@ -134,6 +134,7 @@
#include "fslslbridge.h" // <FS:PP> Movelock position refresh
#include "fsdiscordconnect.h" // <FS:LO> tapping a place that happens on landing in world to start up discord
#include "fsperfstats.h" // <FS:Beq> performance stats support
extern F32 SPEED_ADJUST_MAX;
extern F32 SPEED_ADJUST_MAX_SEC;
@ -6928,6 +6929,7 @@ const LLUUID& LLVOAvatar::getID() const
LLJoint *LLVOAvatar::getJoint( const JointKey &name )
// </FS:ND>
{
FSZone;
//<FS:ND> Query by JointKey rather than just a string, the key can be a U32 index for faster lookup
//joint_map_t::iterator iter = mJointMap.find( name );
@ -9161,8 +9163,8 @@ bool LLVOAvatar::isTooSlow(bool combined) const
if(!mARTCapped)
{
// no cap, so we use the live values
render_time = FSTelemetry::RecordObjectTime<const LLVOAvatar*>::get(this,FSTelemetry::ObjStatType::RENDER_COMBINED);
render_geom_time = FSTelemetry::RecordObjectTime<const LLVOAvatar*>::get(this,FSTelemetry::ObjStatType::RENDER_GEOMETRY);
render_time = FSPerfStats::RecordObjectTime<const LLVOAvatar*>::get(this,FSPerfStats::ObjStatType::RENDER_COMBINED);
render_geom_time = FSPerfStats::RecordObjectTime<const LLVOAvatar*>::get(this,FSPerfStats::ObjStatType::RENDER_GEOMETRY);
}
else
{
@ -9175,8 +9177,8 @@ bool LLVOAvatar::isTooSlow(bool combined) const
if(!mARTCapped)
{
// if we weren't capped, we are now
abuse_constness->mRenderTime = FSTelemetry::RecordObjectTime<const LLVOAvatar*>::get(this,FSTelemetry::ObjStatType::RENDER_COMBINED);
abuse_constness->mGeomTime = FSTelemetry::RecordObjectTime<const LLVOAvatar*>::get(this,FSTelemetry::ObjStatType::RENDER_GEOMETRY);
abuse_constness->mRenderTime = FSPerfStats::RecordObjectTime<const LLVOAvatar*>::get(this,FSPerfStats::ObjStatType::RENDER_COMBINED);
abuse_constness->mGeomTime = FSPerfStats::RecordObjectTime<const LLVOAvatar*>::get(this,FSPerfStats::ObjStatType::RENDER_GEOMETRY);
abuse_constness->mARTStale = false;
abuse_constness->mARTCapped = true;
abuse_constness->mLastARTUpdateFrame = LLFrameTimer::getFrameCount();
@ -10500,8 +10502,6 @@ void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& conte
updateMeshTextures();
updateMeshVisibility();
markARTStale();
}
LLViewerTexture* LLVOAvatar::getBakedTexture(const U8 te)
@ -11682,6 +11682,7 @@ void LLVOAvatar::updateVisualComplexity()
LL_DEBUGS("AvatarRender") << "avatar " << getID() << " appearance changed" << LL_ENDL;
// Set the cache time to in the past so it's updated ASAP
mVisualComplexityStale = true;
markARTStale();
}
// Account for the complexity of a single top-level object associated

View File

@ -91,6 +91,7 @@
#include "rlvlocks.h"
// [/RLVa:KB]
#include "llviewernetwork.h"
#include "fsperfstats.h" // <FS:Beq> performance stats support
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
const F32 FORCE_CULL_AREA = 8.f;
@ -6360,7 +6361,7 @@ static LLTrace::BlockTimerStatHandle FTM_REBUILD_MESH_FLUSH("Flush Mesh");
void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
{
llassert(group);
LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB);// <FS:Beq> move out one scope (but are these even useful as dupes?)
// LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB);// <FS:Beq> High volume remove (roughly 1000:1 ratio to inside the if statement)
if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY))
{
// LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB);// <FS:Beq> move out one scope (but are these even useful as dupes?)
@ -6382,6 +6383,19 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )
{
LLVOVolume* vobj = drawablep->getVOVolume();
LLVOVolume* rootAtt{};
if(vobj->isAttachment())
{
auto par = (LLVOVolume*)vobj->getParent();
rootAtt = vobj;
while( par->isAttachment() )
{
rootAtt = par;
par = (LLVOVolume*)par->getParent();
}
LL_INFOS() << "recording time for ATT@" << rootAtt << " " << (rootAtt?rootAtt->getAttachmentItemName():"null") << LL_ENDL;
}
FSPerfStats::RecordAttachmentTime<U32> T(rootAtt?rootAtt->getAttachmentItemID().getCRC32():0, FSPerfStats::ObjStatType::RENDER_GEOMETRY);
//<FS:Beq> avoid unfortunate sleep during trylock by static check
//if(debugLoggingEnabled("AnimatedObjectsLinkset"))
static auto debug_logging_on = debugLoggingEnabled("AnimatedObjectsLinkset");