summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/render/backend/frameprofiler_p.h259
-rw-r--r--src/render/backend/render-backend.pri3
2 files changed, 261 insertions, 1 deletions
diff --git a/src/render/backend/frameprofiler_p.h b/src/render/backend/frameprofiler_p.h
new file mode 100644
index 000000000..2412a8053
--- /dev/null
+++ b/src/render/backend/frameprofiler_p.h
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_FRAMEPROFILER_P_H
+#define QT3DRENDER_RENDER_FRAMEPROFILER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QOpenGLTimeMonitor>
+#include <Qt3DCore/private/qthreadpooler_p.h>
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+namespace Profiling {
+
+enum RecordingType
+{
+ DrawArray = 512,
+ DrawElement,
+ DispatchCompute,
+ StateUpdate,
+ UniformUpdate,
+ ShaderUpdate,
+ TextureUpload,
+ BufferUpload,
+ ShaderUpload,
+ ClearBuffer,
+ VAOUpdate,
+ VAOUpload,
+ RenderTargetUpdate
+};
+
+#ifdef QT3D_JOBS_RUN_STATS
+
+class FrameTimeRecorder
+{
+public:
+ FrameTimeRecorder()
+ {}
+
+ ~FrameTimeRecorder()
+ {
+ }
+
+ void init(int eventCount)
+ {
+ if (m_monitor.isCreated()) {
+ m_remainingEvents = m_monitor.sampleCount();
+ reset();
+ } else {
+ m_monitor.setSampleCount(eventCount * 2);
+ m_monitor.create();
+ m_remainingEvents = eventCount;
+ }
+ }
+
+ void startRecordEvent()
+ {
+ m_monitor.recordSample();
+ --m_remainingEvents;
+ }
+
+ void recordEvent(RecordingType type)
+ {
+ m_monitor.recordSample();
+ --m_remainingEvents;
+
+ GLRecording rec;
+ rec.type = type;
+ rec.startTime = Qt3DCore::QThreadPooler::m_jobsStatTimer.nsecsElapsed();
+ m_recordings.push_back(rec);
+ }
+
+ void reset()
+ {
+ m_monitor.reset();
+ m_recordings.clear();
+ }
+
+ inline bool canStillRecord() { return m_remainingEvents > 0; }
+
+ bool tryWriteResults()
+ {
+ if (m_monitor.isResultAvailable()) {
+ const QVector<GLuint64> samples = m_monitor.waitForSamples();
+ Q_ASSERT(samples.count() >= 2 * m_recordings.count());
+
+ int j = 0;
+ for (int i = 0, m = m_recordings.size(); i < m; ++i) {
+ const GLRecording rec = m_recordings.at(i);
+ Qt3DCore::JobRunStats glRecordingStat;
+
+ glRecordingStat.jobId.typeAndInstance[0] = rec.type;
+ glRecordingStat.jobId.typeAndInstance[1] = 0;
+ glRecordingStat.threadId = FrameTimeRecorder::GLThreadID;
+ glRecordingStat.startTime = rec.startTime;
+ glRecordingStat.endTime = rec.startTime + (samples.at(j + 1) - (samples.at(j)));
+
+ Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(glRecordingStat);
+ j += 2;
+ }
+ return true;
+ }
+ return false;
+ }
+
+private:
+ struct GLRecording
+ {
+ RecordingType type;
+ qint64 startTime;
+ };
+
+ static const int GLThreadID = 0x454;
+
+ QOpenGLTimeMonitor m_monitor;
+ QVector<GLRecording> m_recordings;
+ int m_remainingEvents = 0;
+};
+
+class FrameProfiler
+{
+public:
+ FrameProfiler()
+ : m_currentRecorder(nullptr)
+ {}
+
+ ~FrameProfiler()
+ {
+ qDeleteAll(m_recorders);
+ }
+
+ void startRecordEvent()
+ {
+ if (m_currentRecorder == nullptr) {
+ if (!m_availableRecorders.empty()) {
+ m_currentRecorder = m_availableRecorders.takeFirst();
+ } else {
+ m_recorders.push_back(new FrameTimeRecorder());
+ m_currentRecorder = m_recorders.last();
+ }
+ // We record events 10 by 10
+ m_currentRecorder->init(10);
+ }
+ m_currentRecorder->startRecordEvent();
+ }
+
+ void recordEvent(RecordingType type)
+ {
+ m_currentRecorder->recordEvent(type);
+ if (!m_currentRecorder->canStillRecord()) {
+ m_busyRecorders.push_back(m_currentRecorder);
+ m_currentRecorder = nullptr;
+ }
+ }
+
+ void writeResults()
+ {
+ for (int i = m_busyRecorders.size() - 1; i >= 0; --i) {
+ FrameTimeRecorder *recorder = m_busyRecorders.at(i);
+ if (recorder->tryWriteResults()) {
+ m_availableRecorders.push_back(m_busyRecorders.takeAt(i));
+ }
+ }
+ }
+
+private:
+ QVector<FrameTimeRecorder *> m_recorders;
+ QVector<FrameTimeRecorder *> m_availableRecorders;
+ QVector<FrameTimeRecorder *> m_busyRecorders;
+ FrameTimeRecorder *m_currentRecorder;
+};
+
+#endif
+
+class GLTimeRecorder
+{
+public:
+ explicit GLTimeRecorder(RecordingType type)
+ : m_type(type)
+ {
+#ifdef QT3D_JOBS_RUN_STATS
+ frameProfiler.startRecordEvent();
+#endif
+ }
+
+ ~GLTimeRecorder()
+ {
+#ifdef QT3D_JOBS_RUN_STATS
+ frameProfiler.recordEvent(m_type);
+#endif
+ }
+
+ static void writeResults()
+ {
+#ifdef QT3D_JOBS_RUN_STATS
+ frameProfiler.writeResults();
+#endif
+ }
+
+private:
+#ifdef QT3D_JOBS_RUN_STATS
+ static FrameProfiler frameProfiler;
+#endif
+ RecordingType m_type;
+};
+
+#ifdef QT3D_JOBS_RUN_STATS
+FrameProfiler GLTimeRecorder::frameProfiler;
+#endif
+
+} // Profiling
+
+} // Render
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_FRAMEPROFILER_P_H
diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri
index 9dc208f8b..9f517d714 100644
--- a/src/render/backend/render-backend.pri
+++ b/src/render/backend/render-backend.pri
@@ -38,7 +38,8 @@ HEADERS += \
$$PWD/commandexecuter_p.h \
$$PWD/uniform_p.h \
$$PWD/shaderparameterpack_p.h \
- $$PWD/renderviewbuilder_p.h
+ $$PWD/renderviewbuilder_p.h \
+ $$PWD/frameprofiler_p.h
SOURCES += \
$$PWD/renderthread.cpp \