blob: 2d3ae256128d5366a85fe70b27598927e1e475a7 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2008-2014 NVIDIA Corporation.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick 3D.
**
** $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 <QtQuick3DRuntimeRender/private/qssgrendergpuprofiler_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
#include <QtQuick3DRender/private/qssgrendertimerquery_p.h>
#include <QtQuick3DRender/private/qssgrendersync_p.h>
#include <QtQuick3DRender/private/qssgrendercontext_p.h>
#define RECORDED_FRAME_DELAY 3
#define RECORDED_FRAME_DELAY_MASK 0x0003
QT_BEGIN_NAMESPACE
struct QSSGGpuTimerInfo
{
QAtomicInt ref;
bool m_absoluteTime = false;
quint8 m_writeID = 0;
quint8 m_readID = 0;
quint8 m_averageTimeWriteID = 0;
quint64 m_averageTime[10];
quint32 m_frameID[RECORDED_FRAME_DELAY];
QSSGRef<QSSGRenderTimerQuery> m_timerStartQueryObjects[RECORDED_FRAME_DELAY];
QSSGRef<QSSGRenderTimerQuery> m_timerEndQueryObjects[RECORDED_FRAME_DELAY];
QSSGRef<QSSGRenderSync> m_timerSyncObjects[RECORDED_FRAME_DELAY];
QSSGGpuTimerInfo() { memset(m_averageTime, 0x0, 10 * sizeof(quint64)); }
void incrementWriteCounter()
{
m_writeID++;
m_writeID %= RECORDED_FRAME_DELAY_MASK;
}
void incrementReadCounter()
{
m_readID++;
m_readID %= RECORDED_FRAME_DELAY_MASK;
}
void incrementAveragedWriteCounter()
{
m_averageTimeWriteID++;
m_averageTimeWriteID %= 10;
}
void startTimerQuery(quint32 frameID)
{
m_frameID[m_writeID] = frameID;
if (m_absoluteTime)
m_timerStartQueryObjects[m_writeID]->setTimerQuery();
else
m_timerStartQueryObjects[m_writeID]->begin();
}
void endTimerQuery()
{
if (m_absoluteTime)
m_timerEndQueryObjects[m_writeID]->setTimerQuery();
else
m_timerStartQueryObjects[m_writeID]->end();
incrementWriteCounter();
}
void addSync()
{
m_timerSyncObjects[m_writeID]->sync();
m_timerSyncObjects[m_writeID]->wait();
}
double averagedElapsedTimeInMs()
{
double time = double((m_averageTime[0] + m_averageTime[1] + m_averageTime[2] + m_averageTime[3] + m_averageTime[4]
+ m_averageTime[5] + m_averageTime[6] + m_averageTime[7] + m_averageTime[8] + m_averageTime[9])
/ 10)
/ double(1.0e06);
return time;
}
double elapsedTimeInMs(quint32 frameID)
{
double time = 0;
if (((frameID - m_frameID[m_readID]) < 2) || (m_readID == m_writeID))
return time;
if (m_absoluteTime) {
quint64 startTime, endTime;
m_timerStartQueryObjects[m_readID]->result(&startTime);
m_timerEndQueryObjects[m_readID]->result(&endTime);
m_averageTime[m_averageTimeWriteID] = endTime - startTime;
} else {
quint64 elapsedTime;
m_timerStartQueryObjects[m_readID]->result(&elapsedTime);
m_averageTime[m_averageTimeWriteID] = elapsedTime;
}
incrementReadCounter();
incrementAveragedWriteCounter();
return averagedElapsedTimeInMs();
}
};
QSSGRenderGPUProfiler::QSSGRenderGPUProfiler(const QSSGRef<QSSGRenderContextInterface> &inContext, const QSSGRef<QSSGRenderContext> &inRenderContext)
: m_renderContext(inRenderContext), m_context(inContext), m_vertexCount(0)
{
}
QSSGRenderGPUProfiler::~QSSGRenderGPUProfiler() { m_strToGpuTimerMap.clear(); }
void QSSGRenderGPUProfiler::startTimer(QString &nameID, bool absoluteTime, bool sync)
{
QSSGRef<QSSGGpuTimerInfo> theGpuTimerData = getOrCreateGpuTimerInfo(nameID);
if (theGpuTimerData) {
if (sync)
theGpuTimerData->addSync();
theGpuTimerData->m_absoluteTime = absoluteTime;
theGpuTimerData->startTimerQuery(m_context->frameCount());
}
}
void QSSGRenderGPUProfiler::endTimer(QString &nameID)
{
QSSGRef<QSSGGpuTimerInfo> theGpuTimerData = getOrCreateGpuTimerInfo(nameID);
if (theGpuTimerData) {
theGpuTimerData->endTimerQuery();
}
}
double QSSGRenderGPUProfiler::elapsed(const QString &nameID) const
{
double time = 0;
QSSGRef<QSSGGpuTimerInfo> theGpuTimerData = getGpuTimerInfo(nameID);
if (theGpuTimerData) {
time = theGpuTimerData->elapsedTimeInMs(m_context->frameCount());
}
return time;
}
const QVector<QString> &QSSGRenderGPUProfiler::timerIDs() const { return m_timerIds; }
void QSSGRenderGPUProfiler::addVertexCount(quint32 count) { m_vertexCount += count; }
quint32 QSSGRenderGPUProfiler::getAndResetVertexCount() const
{
quint32 v = m_vertexCount;
m_vertexCount = 0;
return v;
}
QSSGRef<QSSGGpuTimerInfo> QSSGRenderGPUProfiler::getOrCreateGpuTimerInfo(QString &nameID)
{
TStrGpuTimerInfoMap::const_iterator theIter = m_strToGpuTimerMap.find(nameID);
if (theIter != m_strToGpuTimerMap.end())
return theIter.value();
QSSGRef<QSSGGpuTimerInfo> theGpuTimerData = QSSGRef<QSSGGpuTimerInfo>(new QSSGGpuTimerInfo());
if (theGpuTimerData) {
// create queries
for (quint32 i = 0; i < RECORDED_FRAME_DELAY; i++) {
theGpuTimerData->m_timerStartQueryObjects[i] = QSSGRenderTimerQuery::create(m_renderContext);
theGpuTimerData->m_timerEndQueryObjects[i] = QSSGRenderTimerQuery::create(m_renderContext);
theGpuTimerData->m_timerSyncObjects[i] = QSSGRenderSync::create(m_renderContext);
theGpuTimerData->m_frameID[i] = 0;
}
m_strToGpuTimerMap.insert(nameID, theGpuTimerData);
m_timerIds.push_back(nameID);
}
return theGpuTimerData;
}
QSSGRef<QSSGGpuTimerInfo> QSSGRenderGPUProfiler::getGpuTimerInfo(const QString &nameID) const
{
TStrGpuTimerInfoMap::const_iterator theIter = m_strToGpuTimerMap.find(nameID);
if (theIter != m_strToGpuTimerMap.end())
return theIter.value();
return nullptr;
}
QT_END_NAMESPACE