// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef QQUICK3DPROFILER_P_H #define QQUICK3DPROFILER_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include #if QT_CONFIG(qml_debug) #include #endif #include #include #include #include QT_BEGIN_NAMESPACE #if !QT_CONFIG(qml_debug) #define Q_QUICK3D_PROFILE_IF_ENABLED(feature, Code) struct QQuick3DProfiler { }; #define Q_QUICK3D_PROFILING_ENABLED false #define Q_QUICK3D_PROFILE_REGISTER_D(obj) #define Q_QUICK3D_PROFILE_REGISTER(obj) #define Q_QUICK3D_PROFILE_ID #define Q_QUICK3D_PROFILE_GET_ID #define Q_QUICK3D_PROFILE_ASSIGN_ID_SG(obj, bgnode) #define Q_QUICK3D_PROFILE_ASSIGN_ID(bgnode, obj) #else #define Q_QUICK3D_PROFILE_IF_ENABLED(feature, Code)\ if (QQuick3DProfiler::featuresEnabled & (1 << feature)) {\ Code;\ } else\ (void)0 #define Q_QUICK3D_PROFILING_ENABLED (QQuick3DProfiler::featuresEnabled > 0) #define Q_QUICK3D_PROFILE_REGISTER_D(obj) d->profilingId = QQuick3DProfiler::registerObject(obj) #define Q_QUICK3D_PROFILE_REGISTER(obj) profilingId = QQuick3DProfiler::registerObject(obj) #define Q_QUICK3D_PROFILE_ID int profilingId = -1; #define Q_QUICK3D_PROFILE_GET_ID(Object) \ QQuick3DObjectPrivate::get(Object)->profilingId #define Q_QUICK3D_PROFILE_ASSIGN_ID_SG(obj, bgnode) \ if (bgnode) \ (bgnode)->profilingId = Q_QUICK3D_PROFILE_GET_ID(obj); #define Q_QUICK3D_PROFILE_ASSIGN_ID(bgnode, obj) \ (obj)->profilingId = (bgnode)->profilingId; struct Q_QUICK3DUTILS_EXPORT QQuick3DProfilerData { static constexpr int s_numSupportedIds = 2; QQuick3DProfilerData() {} QQuick3DProfilerData(qint64 time, int messageType, int detailType, qint64 d1, qint64 d2) : time(time), messageType(messageType), detailType(detailType), subdata1(d1), subdata2(d2) {} QQuick3DProfilerData(qint64 time, int messageType, int detailType, qint64 d1, qint64 d2, const QList &ids); qint64 time = 0; qint32 messageType = 0; qint32 detailType = 0; qint64 subdata1 = 0; qint64 subdata2 = 0; qint32 ids[s_numSupportedIds] = {0}; // keep this even sized }; Q_DECLARE_TYPEINFO(QQuick3DProfilerData, Q_RELOCATABLE_TYPE); class QQuick3DProfilerSceneGraphData : public QQmlProfilerDefinitions { private: static const uint s_numSceneGraphTimings = 2; static const uint s_numNestedTimings = 5; struct Timings { uint nesting = 0; qint64 values[s_numNestedTimings][s_numSceneGraphTimings + 1] = {}; }; struct TimingData { Timings timings[MaximumQuick3DFrameType] = {}; }; QThreadStorage eventTimings; public: template qint64 *timings() { Timings *timings; qint64 *t; timings = &eventTimings.localData().timings[type]; if (inc) { Q_ASSERT(timings->nesting < s_numNestedTimings); t = timings->values[timings->nesting]; timings->nesting++; } else { timings->nesting--; t = timings->values[timings->nesting]; } return t; } }; class Q_QUICK3DUTILS_EXPORT QQuick3DProfiler : public QObject, public QQmlProfilerDefinitions { Q_OBJECT public: enum Quick3DStage { Quick3DStageBegin, Quick3DStageEnd }; template static void recordSceneGraphTimestamp(uint position) { s_instance->m_sceneGraphData.timings()[position] = s_instance->timestamp(); } template static void reportQuick3DFrame(uint position, quint64 payload) { qint64 *timings = s_instance->m_sceneGraphData.timings(); timings[position] = s_instance->timestamp(); s_instance->processMessage(QQuick3DProfilerData( timings[position], Quick3DFrame, FrameType, timings[1] - timings[0], payload)); } template static void reportQuick3DFrame(uint position, quint64 payload, const QByteArray str) { qint64 *timings = s_instance->m_sceneGraphData.timings(); timings[position] = s_instance->timestamp(); int sid = registerString(str); QList poids; poids << sid; s_instance->processMessage(QQuick3DProfilerData( timings[position], Quick3DFrame, FrameType, timings[1] - timings[0], payload, poids)); } template static void reportQuick3DFrame(uint position, quint64 payload, int poid) { qint64 *timings = s_instance->m_sceneGraphData.timings(); timings[position] = s_instance->timestamp(); QList poids; poids << poid; s_instance->processMessage(QQuick3DProfilerData( timings[position], Quick3DFrame, FrameType, timings[1] - timings[0], payload, poids)); } template static void reportQuick3DFrame(uint position, quint64 payload, int poid, const QByteArray str) { qint64 *timings = s_instance->m_sceneGraphData.timings(); timings[position] = s_instance->timestamp(); int sid = registerString(str); QList poids; poids << poid << sid; s_instance->processMessage(QQuick3DProfilerData( timings[position], Quick3DFrame, FrameType, timings[1] - timings[0], payload, poids)); } template static void reportQuick3DFrame(uint position, quint64 payload, const QList &poids) { qint64 *timings = s_instance->m_sceneGraphData.timings(); timings[position] = s_instance->timestamp(); s_instance->processMessage(QQuick3DProfilerData( timings[position], Quick3DFrame, FrameType, timings[1] - timings[0], payload, poids)); } qint64 timestamp() { return m_timer.nsecsElapsed(); } static quint64 featuresEnabled; static void initialize(QObject *parent); ~QQuick3DProfiler() override; static int registerObject(const QObject *object); static int registerString(const QByteArray &string); signals: void dataReady(const QVector &data, const QHash &eventData); protected: friend class QQuick3DProfilerAdapter; static QMutex s_eventDataMutex; static QHash s_eventData; static QHash s_eventDataRev; static QQuick3DProfiler *s_instance; QMutex m_dataMutex; QElapsedTimer m_timer; QVector m_data; QQuick3DProfilerSceneGraphData m_sceneGraphData; QQuick3DProfiler(QObject *parent); void processMessage(const QQuick3DProfilerData &message) { QMutexLocker lock(&m_dataMutex); m_data.append(message); } void startProfilingImpl(quint64 features); void stopProfilingImpl(); void reportDataImpl(); void setTimer(const QElapsedTimer &t); }; #endif // QT_CONFIG(qml_debug) #define Q_QUICK3D_PROFILE(feature, Method) \ Q_QUICK3D_PROFILE_IF_ENABLED(feature, QQuick3DProfiler::Method) #define Q_QUICK3D_PROFILE_START(Type) \ Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \ (QQuick3DProfiler::recordSceneGraphTimestamp(QQuick3DProfiler::Quick3DStageBegin))) #define Q_QUICK3D_PROFILE_END(Type) \ Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \ (QQuick3DProfiler::reportQuick3DFrame(QQuick3DProfiler::Quick3DStageEnd, 0, 0))) #define Q_QUICK3D_PROFILE_END_WITH_PAYLOAD(Type, Payload) \ Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \ (QQuick3DProfiler::reportQuick3DFrame(QQuick3DProfiler::Quick3DStageEnd, \ Payload))) #define Q_QUICK3D_PROFILE_END_WITH_STRING(Type, Payload, Str) \ Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \ (QQuick3DProfiler::reportQuick3DFrame(QQuick3DProfiler::Quick3DStageEnd, \ Payload, Str))) #define Q_QUICK3D_PROFILE_END_WITH_ID(Type, Payload, POID) \ Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \ (QQuick3DProfiler::reportQuick3DFrame(QQuick3DProfiler::Quick3DStageEnd, \ Payload, POID))) #define Q_QUICK3D_PROFILE_END_WITH_IDS(Type, Payload, POIDs) \ Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \ (QQuick3DProfiler::reportQuick3DFrame(QQuick3DProfiler::Quick3DStageEnd, \ Payload, POIDs))) #define Q_QUICK3D_PROFILE_END_WITH_ALL(Type, Payload, POID, Str) \ Q_QUICK3D_PROFILE_IF_ENABLED(QQuick3DProfiler::ProfileQuick3D, \ (QQuick3DProfiler::reportQuick3DFrame(QQuick3DProfiler::Quick3DStageEnd, \ Payload, POID, Str))) #define QSSG_RENDERPASS_NAME(passName, level, face) \ QByteArrayLiteral(passName)+ QByteArrayLiteral("_level_") + QByteArray::number(level) \ + QByteArrayLiteral("_face_") + QByteArrayView(QSSGBaseTypeHelpers::toString(QSSGRenderTextureCubeFace(face))) QT_END_NAMESPACE #endif