diff options
Diffstat (limited to 'src/foundation/Qt3DSPerfTimer.cpp')
-rw-r--r-- | src/foundation/Qt3DSPerfTimer.cpp | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/foundation/Qt3DSPerfTimer.cpp b/src/foundation/Qt3DSPerfTimer.cpp new file mode 100644 index 0000000..06fb5d3 --- /dev/null +++ b/src/foundation/Qt3DSPerfTimer.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2012 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "foundation/Qt3DSPerfTimer.h" +#include "foundation/Qt3DSMutex.h" +#include "foundation/Qt3DSAtomic.h" +#include "foundation/Qt3DSBroadcastingAllocator.h" +#include "EASTL/hash_map.h" +#include "EASTL/string.h" +#include "EASTL/vector.h" +#include "EASTL/sort.h" + +using namespace qt3ds::foundation; +using namespace qt3ds; + +namespace { +struct STimerEntry +{ + QT3DSU64 m_Total; + QT3DSU64 m_Max; + QT3DSU32 m_UpdateCount; + CRegisteredString m_Tag; + size_t m_Order; + + STimerEntry(CRegisteredString tag, size_t order) + : m_Total(0) + , m_Max(0) + , m_UpdateCount(0) + , m_Tag(tag) + , m_Order(order) + { + } + void Update(QT3DSU64 increment) + { + m_Total += increment; + m_Max = increment > m_Max ? increment : m_Max; + ++m_UpdateCount; + } + + void Output(NVFoundationBase &fnd, QT3DSU32 inFramesPassed) + { + Q_UNUSED(fnd) + if (m_Total) { + QT3DSU64 tensNanos = Time::sCounterFreq.toTensOfNanos(m_Total); + QT3DSU64 maxNanos = Time::sCounterFreq.toTensOfNanos(m_Max); + + double milliseconds = tensNanos / 100000.0; + double maxMilliseconds = maxNanos / 100000.0; + if (inFramesPassed == 0) + qCWarning(WARNING, PERF_INFO, "%s - %fms", m_Tag.c_str(), milliseconds); + else { + milliseconds /= inFramesPassed; + qCWarning(WARNING, PERF_INFO, "%s - %fms/frame-total %fms-max %u hits", + m_Tag.c_str(), milliseconds, maxMilliseconds, m_UpdateCount); + } + } + } + + void Reset() + { + m_Total = 0; + m_Max = 0; + m_UpdateCount = 0; + } + + bool operator<(const STimerEntry &other) const { return m_Order < other.m_Order; } +}; +struct SPerfTimer : public IPerfTimer +{ + typedef eastl::hash_map<CRegisteredString, STimerEntry> THashMapType; + NVFoundationBase &m_Foundation; + // This object needs its own string table because it is used during the binary load process with + // the application string table gets booted up. + NVScopedRefCounted<IStringTable> m_StringTable; + THashMapType m_Entries; + eastl::vector<STimerEntry> m_PrintEntries; + Mutex m_Mutex; + QT3DSI32 mRefCount; + + SPerfTimer(NVFoundationBase &fnd) + : m_Foundation(fnd) + , m_StringTable(IStringTable::CreateStringTable(fnd.getAllocator())) + , m_Mutex(fnd.getAllocator()) + , mRefCount(0) + { + } + + QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator()) + + void Update(const char *inId, QT3DSU64 inAmount) override + { + Mutex::ScopedLock __locker(m_Mutex); + CRegisteredString theStr(m_StringTable->RegisterStr(inId)); + THashMapType::iterator theFind = + m_Entries.insert(eastl::make_pair(theStr, STimerEntry(theStr, m_Entries.size()))).first; + theFind->second.Update(inAmount); + } + + // Dump current summation of timer data. + void OutputTimerData(QT3DSU32 inFramesPassed = 0) override + { + Mutex::ScopedLock __locker(m_Mutex); + m_PrintEntries.clear(); + for (THashMapType::iterator iter = m_Entries.begin(), end = m_Entries.end(); iter != end; + ++iter) { + m_PrintEntries.push_back(iter->second); + iter->second.Reset(); + } + + eastl::sort(m_PrintEntries.begin(), m_PrintEntries.end()); + + for (QT3DSU32 idx = 0, end = (QT3DSU32)m_PrintEntries.size(); idx < end; ++idx) { + m_PrintEntries[idx].Output(m_Foundation, inFramesPassed); + } + } + + void ResetTimerData() override + { + Mutex::ScopedLock __locker(m_Mutex); + for (THashMapType::iterator iter = m_Entries.begin(), end = m_Entries.end(); iter != end; + ++iter) { + iter->second.Reset(); + } + } + + virtual void ClearPerfKeys() + { + Mutex::ScopedLock __locker(m_Mutex); + m_Entries.clear(); + } +}; +} + +IPerfTimer &IPerfTimer::CreatePerfTimer(NVFoundationBase &fnd) +{ + return *QT3DS_NEW(fnd.getAllocator(), SPerfTimer)(fnd); +} |