From 390c13643096bb6e16e82d2c4e913f18f4d69ba0 Mon Sep 17 00:00:00 2001 From: Beq Date: Wed, 13 Oct 2021 02:04:05 +0100 Subject: [PATCH] Migrate perfstats away from telemetry/profiling perfstats is now a standalone module. --- indra/llcommon/CMakeLists.txt | 19 +- indra/llcommon/fsperfstats.cpp | 36 +++ indra/llcommon/fsperfstats.h | 299 +++++++++++++++++++++++++ indra/llcommon/fstelemetry.cpp | 6 - indra/llcommon/fstelemetry.h | 167 +------------- indra/newview/llappviewer.cpp | 14 +- indra/newview/llavatarrendernotifier.h | 5 + indra/newview/lldrawpool.cpp | 22 ++ indra/newview/lldrawpoolalpha.cpp | 44 ++++ indra/newview/lldrawpoolavatar.cpp | 50 ++++- indra/newview/lldrawpoolbump.cpp | 39 ++++ indra/newview/lldrawpoolmaterials.cpp | 25 ++- indra/newview/llface.cpp | 15 ++ indra/newview/llfloaterperformance.cpp | 37 +-- indra/newview/llviewerdisplay.cpp | 7 +- indra/newview/llviewerjointmesh.cpp | 18 ++ indra/newview/llvoavatar.cpp | 13 +- indra/newview/llvovolume.cpp | 16 +- 18 files changed, 619 insertions(+), 213 deletions(-) create mode 100644 indra/llcommon/fsperfstats.cpp create mode 100644 indra/llcommon/fsperfstats.h diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 9664617fa4..463f8286a0 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -258,13 +258,18 @@ set(llcommon_HEADER_FILES StackWalker.h ) -# Add all nd* files. memory pool, intrinsics, ... -# Tracy Profiler support -list(APPEND llcommon_SOURCE_FILES fstelemetry.cpp) -if (USE_TRACY_PROFILER) - list(APPEND llcommon_SOURCE_FILES fstracyclient.cpp) -endif() - + # Tracy Profiler support + list(APPEND llcommon_SOURCE_FILES fstelemetry.cpp) + if (USE_TRACY_PROFILER) + list(APPEND llcommon_SOURCE_FILES fstracyclient.cpp) + endif() + # Tracy Profiler support + # Performance stast support + list(APPEND llcommon_SOURCE_FILES fsperfstats.cpp) + list(APPEND llcommon_HEADER_FILES fsperfstats.h) + # + + # Add all nd* files. memory pool, intrinsics, ... SET( llcommon_ND_SOURCE_FILES nd/ndexceptions.cpp nd/ndlogthrottle.cpp diff --git a/indra/llcommon/fsperfstats.cpp b/indra/llcommon/fsperfstats.cpp new file mode 100644 index 0000000000..f428b83d9f --- /dev/null +++ b/indra/llcommon/fsperfstats.cpp @@ -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{ {} }; + +} \ No newline at end of file diff --git a/indra/llcommon/fsperfstats.h b/indra/llcommon/fsperfstats.h new file mode 100644 index 0000000000..cab3679dcd --- /dev/null +++ b/indra/llcommon/fsperfstats.h @@ -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 +#include +#include + +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(StatsEnum::STATS_COUNT)>; + // using StatsBlock = std::unordered_map; + + static int writeBuffer; + static std::array 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(std::chrono::steady_clock::now() - start).count(); + stats[writeBuffer][static_cast(type)] += val; + }; + + static inline void toggleBuffer() + { + if(enabled()) + { + // stats[writeBuffer][static_cast(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(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(type)];} + }; + + template + class RecordObjectTime + { + using StatsEnum = ObjStatType; + using StatsArray = std::array(StatsEnum::STATS_COUNT)>; + using StatsBlock = std::unordered_map; + + static int writeBuffer; + static std::array stats; + + static std::array max; + static std::array 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(std::chrono::steady_clock::now() - start).count(); + if(key) + { + stats[writeBuffer][key][static_cast(type)] += val; + stats[writeBuffer][key][static_cast(ST::RENDER_COMBINED)] += val; + if(max[writeBuffer][static_cast(type)] < stats[writeBuffer][key][static_cast(type)]) + { + max[writeBuffer][static_cast(type)] = stats[writeBuffer][key][static_cast(type)]; + } + if(max[writeBuffer][static_cast(ST::RENDER_COMBINED)] < stats[writeBuffer][key][static_cast(ST::RENDER_COMBINED)]) + { + max[writeBuffer][static_cast(ST::RENDER_COMBINED)] = stats[writeBuffer][key][static_cast(ST::RENDER_COMBINED)]; + } + sum[writeBuffer][static_cast(type)] += val; + sum[writeBuffer][static_cast(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(ST::RENDER_COMBINED)]; + // auto avg = stats[(writeBuffer+1)%2][stat_entry.first][static_cast(ST::RENDER_COMBINED)]; + // stat_entry.second[static_cast(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(ST::STATS_COUNT),0); + } + statsMap.clear(); + std::fill_n(max[writeBuffer].begin(),static_cast(ST::STATS_COUNT),0); + std::fill_n(sum[writeBuffer].begin(),static_cast(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(type)];} + static inline uint64_t getSum(StatsEnum type){return sum[(writeBuffer+1)%2][static_cast(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(type)];} + }; + template + class RecordAttachmentTime + { + using StatsEnum = ObjStatType; + using StatsArray = std::array(StatsEnum::STATS_COUNT)>; + using StatsBlock = std::unordered_map; + + static int writeBuffer; + static std::array stats; + + static std::array max; + static std::array 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(std::chrono::steady_clock::now() - start).count(); + stats[writeBuffer][key][static_cast(type)] += val; + stats[writeBuffer][key][static_cast(ST::RENDER_COMBINED)] += val; + if(max[writeBuffer][static_cast(type)] < stats[writeBuffer][key][static_cast(type)]) + { + max[writeBuffer][static_cast(type)] = stats[writeBuffer][key][static_cast(type)]; + } + if(max[writeBuffer][static_cast(ST::RENDER_COMBINED)] < stats[writeBuffer][key][static_cast(ST::RENDER_COMBINED)]) + { + max[writeBuffer][static_cast(ST::RENDER_COMBINED)] = stats[writeBuffer][key][static_cast(ST::RENDER_COMBINED)]; + } + sum[writeBuffer][static_cast(type)] += val; + sum[writeBuffer][static_cast(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(ST::STATS_COUNT),0); + } + statsMap.clear(); + std::fill_n(max[writeBuffer].begin(),static_cast(ST::STATS_COUNT),0); + std::fill_n(sum[writeBuffer].begin(),static_cast(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(type)];} + static inline uint64_t getSum(StatsEnum type){return sum[(writeBuffer+1)%2][static_cast(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(type)];} + }; + + static inline void toggleBuffer() + { + // RecordObjectTime::toggleBuffer(); + RecordSceneTime::toggleBuffer(); + } + + template< typename T > + int RecordObjectTime::writeBuffer{0}; + + template< typename T > + bool RecordObjectTime::collectionEnabled{true}; + + template< typename T > + std::array< typename RecordObjectTime< T >::StatsArray, 2 > RecordObjectTime::max; + + template< typename T > + std::array< typename RecordObjectTime< T >::StatsArray, 2 > RecordObjectTime::sum; + + template< typename T > + std::array< typename RecordObjectTime< T >::StatsBlock, 2 > RecordObjectTime< T >::stats{ {{}} }; + + template< typename T > + int RecordAttachmentTime::writeBuffer{0}; + + template< typename T > + bool RecordAttachmentTime::collectionEnabled{true}; + + template< typename T > + std::array< typename RecordAttachmentTime< T >::StatsArray, 2 > RecordAttachmentTime::max; + + template< typename T > + std::array< typename RecordAttachmentTime< T >::StatsArray, 2 > RecordAttachmentTime::sum; + + template< typename T > + std::array< typename RecordAttachmentTime< T >::StatsBlock, 2 > RecordAttachmentTime< T >::stats{ {{}} }; +}// namespace FSPerfStats + + + + + +#endif \ No newline at end of file diff --git a/indra/llcommon/fstelemetry.cpp b/indra/llcommon/fstelemetry.cpp index 12c31d521d..7be6e4b6bb 100644 --- a/indra/llcommon/fstelemetry.cpp +++ b/indra/llcommon/fstelemetry.cpp @@ -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{ {} }; - } \ No newline at end of file diff --git a/indra/llcommon/fstelemetry.h b/indra/llcommon/fstelemetry.h index 3d8560bb3d..ca9d33f9fe 100644 --- a/indra/llcommon/fstelemetry.h +++ b/indra/llcommon/fstelemetry.h @@ -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(StatsEnum::STATS_COUNT)>; - // using StatsBlock = std::unordered_map; - - static int writeBuffer; - static std::array 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(std::chrono::steady_clock::now() - start).count(); - stats[writeBuffer][static_cast(type)] += val; - }; - - static inline void toggleBuffer() - { - if(enabled()) - { - // stats[writeBuffer][static_cast(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(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(type)];} - }; - - template - class RecordObjectTime - { - using StatsEnum = ObjStatType; - using StatsArray = std::array(StatsEnum::STATS_COUNT)>; - using StatsBlock = std::unordered_map; - - static int writeBuffer; - static std::array stats; - - static std::array max; - static std::array 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(std::chrono::steady_clock::now() - start).count(); - if(key) - { - stats[writeBuffer][key][static_cast(type)] += val; - stats[writeBuffer][key][static_cast(ST::RENDER_COMBINED)] += val; - if(max[writeBuffer][static_cast(type)] < stats[writeBuffer][key][static_cast(type)]) - { - max[writeBuffer][static_cast(type)] = stats[writeBuffer][key][static_cast(type)]; - } - if(max[writeBuffer][static_cast(ST::RENDER_COMBINED)] < stats[writeBuffer][key][static_cast(ST::RENDER_COMBINED)]) - { - max[writeBuffer][static_cast(ST::RENDER_COMBINED)] = stats[writeBuffer][key][static_cast(ST::RENDER_COMBINED)]; - } - sum[writeBuffer][static_cast(type)] += val; - sum[writeBuffer][static_cast(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(ST::STATS_COUNT),0); - } - statsMap.clear(); - std::fill_n(max[writeBuffer].begin(),static_cast(ST::STATS_COUNT),0); - std::fill_n(sum[writeBuffer].begin(),static_cast(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(type)];} - static inline uint64_t getSum(StatsEnum type){return sum[(writeBuffer+1)%2][static_cast(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(type)];} - }; - - static inline void toggleBuffer() - { - // RecordObjectTime::toggleBuffer(); - RecordSceneTime::toggleBuffer(); - } - - template< typename T > - int RecordObjectTime::writeBuffer{0}; - - template< typename T > - bool RecordObjectTime::collectionEnabled{true}; - - template< typename T > - std::array< typename RecordObjectTime< T >::StatsArray, 2 > RecordObjectTime::max; - - template< typename T > - std::array< typename RecordObjectTime< T >::StatsArray, 2 > RecordObjectTime::sum; - - template< typename T > - std::array< typename RecordObjectTime< T >::StatsBlock, 2 > RecordObjectTime< T >::stats{ {{}} }; - }// namespace FSTelemetry #endif \ No newline at end of file diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 17fac803cb..b74d5a58c5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -286,6 +286,7 @@ #include "fsassetblacklist.h" #include "fstelemetry.h" // Tracy profiler support +#include "fsperfstats.h" // 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; // Tracy support delineate Frame LLPROFILE_UPDATE(); } - FSTelemetry::RecordSceneTime::toggleBuffer(); - FSTelemetry::RecordObjectTime::toggleBuffer(); + FSPerfStats::RecordSceneTime::toggleBuffer(); + FSPerfStats::RecordObjectTime::toggleBuffer(); + FSPerfStats::RecordAttachmentTime::toggleBuffer(); return ! LLApp::isRunning(); } diff --git a/indra/newview/llavatarrendernotifier.h b/indra/newview/llavatarrendernotifier.h index 37130bfcf6..e8077d55c0 100644 --- a/indra/newview/llavatarrendernotifier.h +++ b/indra/newview/llavatarrendernotifier.h @@ -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; }; diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index d583a692f9..8224394b14 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -50,6 +50,7 @@ #include "lldrawpoolwlsky.h" #include "llglslshader.h" #include "llglcommonfunc.h" +#include "fsperfstats.h" // 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) { + // Capture render times + LLViewerObject* rootAtt{}; + std::unique_ptr> 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>(new FSPerfStats::RecordAttachmentTime(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));} + } + } + // if (!params.mCount) { return; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 87bf2cb098..3fbcab9d4a 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -48,6 +48,7 @@ #include "lldrawpoolwater.h" #include "llspatialpartition.h" #include "llglcommonfunc.h" +#include "fsperfstats.h" // 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; + // Capture render times + std::unique_ptr> 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>(new FSPerfStats::RecordAttachmentTime(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));} + } + } + // if (params.mParticle) { @@ -679,6 +701,28 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) continue; } + // Capture render times + std::unique_ptr> 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>(new FSPerfStats::RecordAttachmentTime(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));} + } + } + // + // 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 diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 767027e60d..51fd2760d0 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -59,6 +59,8 @@ // void drawBoxOutline(const LLVector3& pos,const LLVector3& size); // llspatialpartition.cpp // #include "llnetmap.h" +#include "fsperfstats.h" // 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 T(avatarp, FSTelemetry::ObjStatType::RENDER_SHADOWS); + FSPerfStats::RecordObjectTime 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 T(avatarp, FSTelemetry::ObjStatType::RENDER_GEOMETRY); + FSPerfStats::RecordObjectTime T(avatarp, FSPerfStats::ObjStatType::RENDER_GEOMETRY); // Add avatar hitbox debug static LLCachedControl 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()) { // 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 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) diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index c7cb6567b5..b8dcdbb0be 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -47,6 +47,7 @@ #include "pipeline.h" #include "llspatialpartition.h" #include "llviewershadermgr.h" +#include "fsperfstats.h" // 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; + // Capture render times + LLViewerObject* rootAtt{}; + std::unique_ptr> 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>(new FSPerfStats::RecordAttachmentTime(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));} + } + // 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) { + // Capture render times + std::unique_ptr> 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>(new FSPerfStats::RecordAttachmentTime(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));} + } + } + // applyModelMatrix(params); bool tex_setup = false; diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 05b0c1f1a9..710cf5f80b 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -31,6 +31,7 @@ #include "llviewershadermgr.h" #include "pipeline.h" #include "llglcommonfunc.h" +#include "fsperfstats.h" // 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; - + + // Capture render times + std::unique_ptr> 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>(new FSPerfStats::RecordAttachmentTime(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));} + } + } + // + 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); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 316951c316..e0251f6d23 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -59,6 +59,7 @@ // [RLVa:KB] - Checked: RLVa-2.0.0 #include "rlvhandler.h" // [/RLVa:KB] +#include "fsperfstats.h" // 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> 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>(new FSPerfStats::RecordAttachmentTime(rootAtt->getAttachmentItemID().getCRC32(), FSPerfStats::ObjStatType::RENDER_GEOMETRY));} + } LLVolume* volume = NULL; if (drawable->isState(LLDrawable::RIGGED)) diff --git a/indra/newview/llfloaterperformance.cpp b/indra/newview/llfloaterperformance.cpp index 8e0ca64368..4a18522244 100644 --- a/indra/newview/llfloaterperformance.cpp +++ b/indra/newview/llfloaterperformance.cpp @@ -46,6 +46,7 @@ #include "pipeline.h" #include "llviewercontrol.h" #include "fsavatarrenderpersistence.h" +#include "fsperfstats.h" // performance stats support const F32 REFRESH_INTERVAL = 1.0f; const S32 BAR_LEFT_PAD = 2; @@ -176,13 +177,13 @@ void LLFloaterPerformance::draw() getChild("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::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::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::getMax(FSTelemetry::ObjStatType::RENDER_COMBINED); + auto av_render_max = FSPerfStats::RecordObjectTime::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::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::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::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::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::iterator char_iter = valid_nearby_avs.begin(); - auto render_max = FSTelemetry::RecordObjectTime::getMax(FSTelemetry::ObjStatType::RENDER_COMBINED); + auto render_max = FSPerfStats::RecordObjectTime::getMax(FSPerfStats::ObjStatType::RENDER_COMBINED); while (char_iter != valid_nearby_avs.end()) { LLVOAvatar* avatar = dynamic_cast(*char_iter); @@ -471,7 +478,7 @@ void LLFloaterPerformance::populateNearbyList() continue; // S32 complexity_short = llmax((S32)avatar->getVisualComplexity() / 1000, 1); - auto render_av = FSTelemetry::RecordObjectTime::get(avatar,FSTelemetry::ObjStatType::RENDER_COMBINED); + auto render_av = FSPerfStats::RecordObjectTime::get(avatar,FSPerfStats::ObjStatType::RENDER_COMBINED); auto is_slow = avatar->isTooSlow(true); // auto is_slow_without_shadows = avatar->isTooSlow(); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 0bb91556e8..db2f65f4d6 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -85,6 +85,7 @@ // [/RLVa:KB] #include "llpresetsmanager.h" #include "fsdata.h" +#include "fsperfstats.h" // performance stats support extern LLPointer 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) diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index d2cfe2cf98..0361986a27 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -55,6 +55,7 @@ #include "m3math.h" #include "m4math.h" #include "llmatrix4a.h" +#include "fsperfstats.h" // 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 T(vobj?vobj->getAttachmentItemID().getCRC32():0, FSPerfStats::ObjStatType::RENDER_GEOMETRY); + U32 triangle_count = 0; S32 diffuse_channel = LLDrawPoolAvatar::sDiffuseChannel; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6e962c94b3..c9490b12c2 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -134,6 +134,7 @@ #include "fslslbridge.h" // Movelock position refresh #include "fsdiscordconnect.h" // tapping a place that happens on landing in world to start up discord +#include "fsperfstats.h" // 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 ) // { + FSZone; // 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::get(this,FSTelemetry::ObjStatType::RENDER_COMBINED); - render_geom_time = FSTelemetry::RecordObjectTime::get(this,FSTelemetry::ObjStatType::RENDER_GEOMETRY); + render_time = FSPerfStats::RecordObjectTime::get(this,FSPerfStats::ObjStatType::RENDER_COMBINED); + render_geom_time = FSPerfStats::RecordObjectTime::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::get(this,FSTelemetry::ObjStatType::RENDER_COMBINED); - abuse_constness->mGeomTime = FSTelemetry::RecordObjectTime::get(this,FSTelemetry::ObjStatType::RENDER_GEOMETRY); + abuse_constness->mRenderTime = FSPerfStats::RecordObjectTime::get(this,FSPerfStats::ObjStatType::RENDER_COMBINED); + abuse_constness->mGeomTime = FSPerfStats::RecordObjectTime::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 diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 7ce1730b26..2141ec6caa 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -91,6 +91,7 @@ #include "rlvlocks.h" // [/RLVa:KB] #include "llviewernetwork.h" +#include "fsperfstats.h" // 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);// move out one scope (but are these even useful as dupes?) + // LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB);// 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);// 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 T(rootAtt?rootAtt->getAttachmentItemID().getCRC32():0, FSPerfStats::ObjStatType::RENDER_GEOMETRY); // avoid unfortunate sleep during trylock by static check //if(debugLoggingEnabled("AnimatedObjectsLinkset")) static auto debug_logging_on = debugLoggingEnabled("AnimatedObjectsLinkset");