5#ifndef QQUICKPROFILER_P_H
6#define QQUICKPROFILER_P_H
19#include <QtCore/private/qabstractanimation_p.h>
20#include <QtQuick/private/qtquickglobal_p.h>
22#if QT_CONFIG(qml_debug)
23#include <QtQml/private/qqmlprofilerdefinitions_p.h>
26#include <QtCore/private/qnumeric_p.h>
27#include <QtCore/qurl.h>
28#include <QtCore/qsize.h>
29#include <QtCore/qmutex.h>
30#include <QtCore/qthreadstorage.h>
34#if !QT_CONFIG(qml_debug)
36#define Q_QUICK_PROFILE_IF_ENABLED(feature, Code)
44#define Q_QUICK_PROFILE_IF_ENABLED(feature, Code)
45 if (QQuickProfiler::featuresEnabled & (1
<< feature)) {
60 QQuickProfilerData() {}
62 QQuickProfilerData(qint64 time,
int messageType,
int detailType,
const QUrl &url,
int x = 0,
63 int y = 0,
int framerate = 0,
int count = 0) :
64 time(time), messageType(messageType), detailType(detailType), detailUrl(url), x(x), y(y),
65 framerate(framerate), count(count) {}
67 QQuickProfilerData(qint64 time,
int messageType,
int detailType,
int framerateOrInputType = 0,
68 int countOrInputA = 0,
int threadIdOrInputB = 0) :
69 time(time), messageType(messageType), detailType(detailType),
70 framerate(framerateOrInputType), count(countOrInputA), threadId(threadIdOrInputB) {}
74 QQuickProfilerData(qint64 time,
int messageType,
int detailType, qint64 d1, qint64 d2,
75 qint64 d3, qint64 d4, qint64 d5) :
76 time(time), messageType(messageType), detailType(detailType), subtime_1(d1), subtime_2(d2),
77 subtime_3(d3), subtime_4(d4), subtime_5(d5) {}
117class QQuickProfilerSceneGraphData :
public QQmlProfilerDefinitions {
119 static const uint s_numSceneGraphTimings = 5;
123 qint64 values[size][s_numSceneGraphTimings + 1];
126 static inline thread_local TimingData<NumRenderThreadFrameTypes> renderThreadTimings;
127 TimingData<NumGUIThreadFrameTypes> guiThreadTimings;
130 template<SceneGraphFrameType type>
133 if constexpr (type < NumRenderThreadFrameTypes)
134 return renderThreadTimings.values[type];
136 return guiThreadTimings.values[type - NumRenderThreadFrameTypes];
140class Q_QUICK_EXPORT QQuickProfiler :
public QObject,
public QQmlProfilerDefinitions {
144 enum AnimationThread {
149 enum SceneGraphContextStage {
150 SceneGraphContextStart,
151 SceneGraphContextMaterialCompile
154 enum SceneGraphRendererStage {
155 SceneGraphRendererStart,
156 SceneGraphRendererPreprocess,
157 SceneGraphRendererUpdate,
158 SceneGraphRendererBinding,
159 SceneGraphRendererRender
162 enum SceneGraphAdaptationLayerStage {
163 SceneGraphAdaptationLayerStart,
164 SceneGraphAdaptationLayerGlyphRender,
165 SceneGraphAdaptationLayerGlyphStore
168 enum SceneGraphRenderLoopStage {
169 SceneGraphRenderLoopStart,
170 SceneGraphRenderLoopSync,
171 SceneGraphRenderLoopRender,
172 SceneGraphRenderLoopSwap
175 enum SceneGraphPolishStage {
176 SceneGraphPolishStart,
177 SceneGraphPolishPolish
180 enum SceneGraphPolishAndSyncStage {
181 SceneGraphPolishAndSyncStart,
182 SceneGraphPolishAndSyncPolish,
183 SceneGraphPolishAndSyncWait,
184 SceneGraphPolishAndSyncSync,
185 SceneGraphPolishAndSyncAnimations
188 enum SceneGraphTexturePrepareStage {
189 SceneGraphTexturePrepareStart,
190 SceneGraphTexturePrepareBind,
191 SceneGraphTexturePrepareConvert,
192 SceneGraphTexturePrepareSwizzle,
193 SceneGraphTexturePrepareUpload,
194 SceneGraphTexturePrepareMipmap
197 enum SceneGraphTextureDeletionStage {
198 SceneGraphTextureDeletionStart,
199 SceneGraphTextureDeletionDelete
202 template<EventType DetailType, InputEventType InputType>
203 static void inputEvent(
int x,
int y = 0)
205 s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(), 1 << Event,
206 1 << DetailType, InputType, x, y));
209 static void animationFrame(qint64 delta, AnimationThread threadId)
211 const qsizetype animCount = QUnifiedTimer::instance()->runningAnimationCount();
213 if (animCount > 0 && delta > 0) {
214 s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(), 1 << Event,
215 1 << AnimationFrame, 1000 / (
int)delta ,
216 qt_saturate<
int>(animCount),
221 template<SceneGraphFrameType FrameType1, SceneGraphFrameType FrameType2>
222 static void startSceneGraphFrame()
224 startSceneGraphFrame<FrameType1>();
225 s_instance->m_sceneGraphData.timings<FrameType2>()[0] =
226 s_instance->m_sceneGraphData.timings<FrameType1>()[0];
229 template<SceneGraphFrameType FrameType>
230 static void startSceneGraphFrame()
232 s_instance->m_sceneGraphData.timings<FrameType>()[0] = s_instance->timestamp();
235 template<SceneGraphFrameType FrameType>
236 static void recordSceneGraphTimestamp(uint position)
238 s_instance->m_sceneGraphData.timings<FrameType>()[position] = s_instance->timestamp();
241 template<SceneGraphFrameType FrameType, uint Skip>
242 static void skipSceneGraphTimestamps(uint position)
244 qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType>();
245 const qint64 last = timings[position];
246 for (uint i = 0; i < Skip; ++i)
247 timings[++position] = last;
250 template<SceneGraphFrameType FrameType,
bool Record>
251 static void reportSceneGraphFrame(uint position, quint64 payload = ~0)
253 qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType>();
255 timings[position] = s_instance->timestamp();
256 s_instance->processMessage(QQuickProfilerData(
257 timings[position], 1 << SceneGraphFrame, 1 << FrameType,
258 position > 0 ? timings[1] - timings[0] : payload,
259 position > 1 ? timings[2] - timings[1] : payload,
260 position > 2 ? timings[3] - timings[2] : payload,
261 position > 3 ? timings[4] - timings[3] : payload,
262 position > 4 ? timings[5] - timings[4] : payload));
265 template<SceneGraphFrameType FrameType,
bool Record, SceneGraphFrameType SwitchTo>
266 static void reportSceneGraphFrame(uint position, quint64 payload = ~0)
268 reportSceneGraphFrame<FrameType, Record>(position, payload);
269 s_instance->m_sceneGraphData.timings<SwitchTo>()[0] =
270 s_instance->m_sceneGraphData.timings<FrameType>()[position];
273 template<PixmapEventType PixmapState>
274 static void pixmapStateChanged(
const QUrl &url)
276 s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(),
277 1 << PixmapCacheEvent, 1 << PixmapState, url));
280 static void pixmapLoadingFinished(
const QUrl &url,
const QSize &size)
282 s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(),
283 1 << PixmapCacheEvent,
284 (1 << PixmapLoadingFinished) | ((size.width() > 0 && size.height() > 0) ? (1 << PixmapSizeKnown) : 0),
285 url, size.width(), size.height()));
288 template<PixmapEventType CountType>
289 static void pixmapCountChanged(
const QUrl &url,
int count)
291 s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(),
292 1 << PixmapCacheEvent, 1 << CountType, url, 0, 0, 0, count));
295 static void registerAnimationCallback();
297 qint64 timestamp() {
return m_timer.nsecsElapsed(); }
299 static quint64 featuresEnabled;
301 static void initialize(QObject *parent);
303 ~QQuickProfiler() override;
306 void dataReady(
const QVector<QQuickProfilerData> &data);
309 friend class QQuickProfilerAdapter;
311 static QQuickProfiler *s_instance;
313 QElapsedTimer m_timer;
314 QVector<QQuickProfilerData> m_data;
315 QQuickProfilerSceneGraphData m_sceneGraphData;
317 QQuickProfiler(QObject *parent);
319 void processMessage(
const QQuickProfilerData &message)
321 QMutexLocker lock(&m_dataMutex);
322 if (Q_LIKELY(m_data.isEmpty() || m_data.last().time <= message.time)) {
323 m_data.append(message);
329 const auto it = std::find_if(
330 m_data.rbegin(), m_data.rend(),
331 [t = message.time](
const QQuickProfilerData &i) {
return i.time <= t; });
332 m_data.insert(it.base(), message);
335 void startProfilingImpl(quint64 features);
336 void stopProfilingImpl();
337 void reportDataImpl();
338 void setTimer(
const QElapsedTimer &t);
343#define Q_QUICK_PROFILE(feature, Method)
347#define Q_QUICK_SG_PROFILE_START(Type)
349 (QQuickProfiler::startSceneGraphFrame<Type>()))
352#define Q_QUICK_SG_PROFILE_RECORD(Type, position)
354 (QQuickProfiler::recordSceneGraphTimestamp<Type>(position)))
358#define Q_QUICK_SG_PROFILE_SKIP(Type, position, Skip)
360 (QQuickProfiler::skipSceneGraphTimestamps<Type, Skip>(position)))
363#define Q_QUICK_SG_PROFILE_START_SYNCHRONIZED(Type1, Type2)
365 (QQuickProfiler::startSceneGraphFrame<Type1, Type2>()))
369#define Q_QUICK_SG_PROFILE_SWITCH(Type1, Type2, position)
371 (QQuickProfiler::reportSceneGraphFrame<Type1, true, Type2>(
375#define Q_QUICK_SG_PROFILE_REPORT(Type, position)
377 (QQuickProfiler::reportSceneGraphFrame<Type, false>(position)))
381#define Q_QUICK_SG_PROFILE_END(Type, position)
383 (QQuickProfiler::reportSceneGraphFrame<Type, true>(position)))
388#define Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(Type, position, Payload)
390 (QQuickProfiler::reportSceneGraphFrame<Type, true>(position,
393#define Q_QUICK_INPUT_PROFILE(Type, DetailType, A, B)
395 (QQuickProfiler::inputEvent<Type, DetailType>(A, B)))
Q_DECLARE_TYPEINFO(QByteArrayView, Q_PRIMITIVE_TYPE)
void animationTimerCallback(qint64 delta)
#define Q_QUICK_PROFILE(feature, Method)
#define Q_QUICK_PROFILE_IF_ENABLED(feature, Code)