1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QQUICK3DPROFILER_P_H
5#define QQUICK3DPROFILER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/private/qabstractanimation_p.h>
19#include <QtQuick/private/qtquickglobal_p.h>
20#include <QtQuick3DUtils/private/qtquick3dutilsglobal_p.h>
21
22
23#if QT_CONFIG(qml_debug)
24#include <QtQml/private/qqmlprofilerdefinitions_p.h>
25#endif
26
27#include <QtCore/qurl.h>
28#include <QtCore/qsize.h>
29#include <QtCore/qmutex.h>
30#include <QtCore/qthreadstorage.h>
31
32QT_BEGIN_NAMESPACE
33
34#if !QT_CONFIG(qml_debug)
35
36#define Q_QUICK3D_PROFILE_IF_ENABLED(feature, Code)
37
38struct QQuick3DProfiler {
39
40};
41
42#define Q_QUICK3D_PROFILING_ENABLED false
43#define Q_QUICK3D_PROFILE_REGISTER_D(obj)
44#define Q_QUICK3D_PROFILE_REGISTER(obj)
45#define Q_QUICK3D_PROFILE_ID
46#define Q_QUICK3D_PROFILE_GET_ID
47#define Q_QUICK3D_PROFILE_ASSIGN_ID_SG(obj, bgnode)
48#define Q_QUICK3D_PROFILE_ASSIGN_ID(bgnode, obj)
49
50#else
51
52#define Q_QUICK3D_PROFILE_IF_ENABLED(feature, Code)\
53 if (QQuick3DProfiler::featuresEnabled & (1 << feature)) {\
54 Code;\
55 } else\
56 (void)0
57
58#define Q_QUICK3D_PROFILING_ENABLED (QQuick3DProfiler::featuresEnabled > 0)
59#define Q_QUICK3D_PROFILE_REGISTER_D(obj) d->profilingId = QQuick3DProfiler::registerObject(obj)
60#define Q_QUICK3D_PROFILE_REGISTER(obj) profilingId = QQuick3DProfiler::registerObject(obj)
61#define Q_QUICK3D_PROFILE_ID int profilingId = -1;
62#define Q_QUICK3D_PROFILE_GET_ID(Object) \
63 QQuick3DObjectPrivate::get(Object)->profilingId
64#define Q_QUICK3D_PROFILE_ASSIGN_ID_SG(obj, bgnode) \
65 if (bgnode) \
66 (bgnode)->profilingId = Q_QUICK3D_PROFILE_GET_ID(obj);
67#define Q_QUICK3D_PROFILE_ASSIGN_ID(bgnode, obj) \
68 (obj)->profilingId = (bgnode)->profilingId;
69
70
71struct Q_QUICK3DUTILS_EXPORT QQuick3DProfilerData
72{
73 static constexpr int s_numSupportedIds = 2;
74 QQuick3DProfilerData() {}
75
76 QQuick3DProfilerData(qint64 time, int messageType, int detailType, qint64 d1, qint64 d2)
77 : time(time), messageType(messageType), detailType(detailType), subdata1(d1), subdata2(d2) {}
78 QQuick3DProfilerData(qint64 time, int messageType, int detailType, qint64 d1, qint64 d2, const QList<int> &ids);
79
80 qint64 time = 0;
81 qint32 messageType = 0;
82 qint32 detailType = 0;
83 qint64 subdata1 = 0;
84 qint64 subdata2 = 0;
85 qint32 ids[s_numSupportedIds] = {0}; // keep this even sized
86};
87
88Q_DECLARE_TYPEINFO(QQuick3DProfilerData, Q_RELOCATABLE_TYPE);
89
90class QQuick3DProfilerSceneGraphData : public QQmlProfilerDefinitions {
91private:
92 static const uint s_numSceneGraphTimings = 2;
93 static const uint s_numNestedTimings = 5;
94 struct Timings {
95 uint nesting = 0;
96 qint64 values[s_numNestedTimings][s_numSceneGraphTimings + 1];
97 };
98 template<uint size>
99 struct TimingData
100 {
101 Timings timings[size];
102 };
103 QThreadStorage<TimingData<MaximumQuick3DFrameType>> eventTimings;
104public:
105 template<int type, bool inc>
106 qint64 *timings()
107 {
108 Timings *timings;
109 qint64 *t;
110 timings = &eventTimings.localData().timings[type];
111 if (inc) {
112 Q_ASSERT(timings->nesting < s_numNestedTimings);
113 t = timings->values[timings->nesting];
114 timings->nesting++;
115 } else {
116 timings->nesting--;
117 t = timings->values[timings->nesting];
118 }
119 return t;
120 }
121};
122
123class Q_QUICK3DUTILS_EXPORT QQuick3DProfiler : public QObject, public QQmlProfilerDefinitions {
124 Q_OBJECT
125public:
126
127 enum Quick3DStage {
128 Quick3DStageBegin,
129 Quick3DStageEnd
130 };
131
132 template<int FrameType>
133 static void recordSceneGraphTimestamp(uint position)
134 {
135 s_instance->m_sceneGraphData.timings<FrameType, true>()[position] = s_instance->timestamp();
136 }
137 template<int FrameType>
138 static void reportQuick3DFrame(uint position, quint64 payload)
139 {
140 qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType, false>();
141 timings[position] = s_instance->timestamp();
142 s_instance->processMessage(message: QQuick3DProfilerData(
143 timings[position], Quick3DFrame, FrameType,
144 timings[1] - timings[0],
145 payload));
146 }
147 template<int FrameType>
148 static void reportQuick3DFrame(uint position, quint64 payload, const QByteArray str)
149 {
150 qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType, false>();
151 timings[position] = s_instance->timestamp();
152 int sid = registerString(string: str);
153 QList<int> poids;
154 poids << sid;
155 s_instance->processMessage(message: QQuick3DProfilerData(
156 timings[position], Quick3DFrame, FrameType,
157 timings[1] - timings[0],
158 payload,
159 poids));
160 }
161 template<int FrameType>
162 static void reportQuick3DFrame(uint position, quint64 payload, int poid)
163 {
164 qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType, false>();
165 timings[position] = s_instance->timestamp();
166 QList<int> poids;
167 poids << poid;
168 s_instance->processMessage(message: QQuick3DProfilerData(
169 timings[position], Quick3DFrame, FrameType,
170 timings[1] - timings[0],
171 payload,
172 poids));
173 }
174 template<int FrameType>
175 static void reportQuick3DFrame(uint position, quint64 payload, int poid, const QByteArray str)
176 {
177 qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType, false>();
178 timings[position] = s_instance->timestamp();
179 int sid = registerString(string: str);
180 QList<int> poids;
181 poids << poid << sid;
182 s_instance->processMessage(message: QQuick3DProfilerData(
183 timings[position], Quick3DFrame, FrameType,
184 timings[1] - timings[0],
185 payload,
186 poids));
187 }
188 template<int FrameType>
189 static void reportQuick3DFrame(uint position, quint64 payload, const QList<int> &poids)
190 {
191 qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType, false>();
192 timings[position] = s_instance->timestamp();
193 s_instance->processMessage(message: QQuick3DProfilerData(
194 timings[position], Quick3DFrame, FrameType,
195 timings[1] - timings[0],
196 payload,
197 poids));
198 }
199
200
201 qint64 timestamp() { return m_timer.nsecsElapsed(); }
202
203 static quint64 featuresEnabled;
204
205 static void initialize(QObject *parent);
206
207 ~QQuick3DProfiler() override;
208
209 static int registerObject(const QObject *object);
210 static int registerString(const QByteArray &string);
211
212signals:
213 void dataReady(const QVector<QQuick3DProfilerData> &data, const QHash<int, QByteArray> &eventData);
214
215protected:
216 friend class QQuick3DProfilerAdapter;
217 static QMutex s_eventDataMutex;
218 static QHash<QByteArray, int> s_eventData;
219 static QHash<int, QByteArray> s_eventDataRev;
220 static QQuick3DProfiler *s_instance;
221 QMutex m_dataMutex;
222 QElapsedTimer m_timer;
223 QVector<QQuick3DProfilerData> m_data;
224 QQuick3DProfilerSceneGraphData m_sceneGraphData;
225
226 QQuick3DProfiler(QObject *parent);
227
228 void processMessage(const QQuick3DProfilerData &message)
229 {
230 QMutexLocker lock(&m_dataMutex);
231 m_data.append(t: message);
232 }
233
234 void startProfilingImpl(quint64 features);
235 void stopProfilingImpl();
236 void reportDataImpl();
237 void setTimer(const QElapsedTimer &t);
238};
239
240#endif // QT_CONFIG(qml_debug)
241
242#define Q_QUICK3D_PROFILE(feature, Method) \
243 Q_QUICK3D_PROFILE_IF_ENABLED(feature, QQuick3DProfiler::Method)
244
245#define Q_QUICK3D_PROFILE_START(Type) \
246 Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \
247 (QQuick3DProfiler::recordSceneGraphTimestamp<Type>(QQuick3DProfiler::Quick3DStageBegin)))
248
249#define Q_QUICK3D_PROFILE_END(Type) \
250 Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \
251 (QQuick3DProfiler::reportQuick3DFrame<Type>(QQuick3DProfiler::Quick3DStageEnd, 0, 0)))
252
253#define Q_QUICK3D_PROFILE_END_WITH_PAYLOAD(Type, Payload) \
254 Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \
255 (QQuick3DProfiler::reportQuick3DFrame<Type>(QQuick3DProfiler::Quick3DStageEnd, \
256 Payload)))
257
258#define Q_QUICK3D_PROFILE_END_WITH_STRING(Type, Payload, Str) \
259 Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \
260 (QQuick3DProfiler::reportQuick3DFrame<Type>(QQuick3DProfiler::Quick3DStageEnd, \
261 Payload, Str)))
262#define Q_QUICK3D_PROFILE_END_WITH_ID(Type, Payload, POID) \
263 Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \
264 (QQuick3DProfiler::reportQuick3DFrame<Type>(QQuick3DProfiler::Quick3DStageEnd, \
265 Payload, POID)))
266#define Q_QUICK3D_PROFILE_END_WITH_IDS(Type, Payload, POIDs) \
267 Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \
268 (QQuick3DProfiler::reportQuick3DFrame<Type>(QQuick3DProfiler::Quick3DStageEnd, \
269 Payload, POIDs)))
270#define Q_QUICK3D_PROFILE_END_WITH_ALL(Type, Payload, POID, Str) \
271 Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \
272 (QQuick3DProfiler::reportQuick3DFrame<Type>(QQuick3DProfiler::Quick3DStageEnd, \
273 Payload, POID, Str)))
274
275#define QSSG_RENDERPASS_NAME(passName, level, face) \
276 QByteArrayLiteral(passName)+ QByteArrayLiteral("_level_") + QByteArray::number(level) \
277 + QByteArrayLiteral("_face_") + QByteArrayView(QSSGBaseTypeHelpers::toString(QSSGRenderTextureCubeFace(face)))
278
279QT_END_NAMESPACE
280
281#endif
282

source code of qtquick3d/src/utils/qquick3dprofiler_p.h