summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2019-12-05 10:33:32 +0000
committerMike Krus <mike.krus@kdab.com>2019-12-13 15:36:59 +0000
commitef886f79f99cdae94da8bf5a4ca6e94164d56677 (patch)
tree98caf12195cb24763292305326d40c6838066312
parent6e448dd5918c70ddfd0d52f62522fa49c02e8ba8 (diff)
Make tracing a runtime option
- Moved most of the code QSystemInformationService (private class for now) - Tracing can be enabled by setting QT3D_TRACE_ENABLED or calling QSystemInformationService::setTraceEnabled(bool) - Introduced QTaskLogger class to easy logging (RAII) Change-Id: I2a3e08e4371fcee3e9ef3cf575725f13f57d1a94 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/core/aspects/qaspectmanager.cpp91
-rw-r--r--src/core/jobs/qaspectjob_p.h67
-rw-r--r--src/core/jobs/qaspectjobmanager.cpp14
-rw-r--r--src/core/jobs/qaspectjobmanager_p.h4
-rw-r--r--src/core/jobs/qthreadpooler.cpp117
-rw-r--r--src/core/jobs/qthreadpooler_p.h15
-rw-r--r--src/core/jobs/task.cpp20
-rw-r--r--src/core/jobs/task_p.h4
-rw-r--r--src/core/services/nullservices_p.h14
-rw-r--r--src/core/services/qservicelocator.cpp5
-rw-r--r--src/core/services/qsysteminformationservice.cpp243
-rw-r--r--src/core/services/qsysteminformationservice_p.h19
-rw-r--r--src/core/services/qsysteminformationservice_p_p.h80
-rw-r--r--src/logic/callbackjob.cpp2
-rw-r--r--src/render/jobs/calcboundingvolumejob.cpp2
-rw-r--r--src/render/jobs/calcgeometrytrianglevolumes.cpp2
-rw-r--r--src/render/jobs/expandboundingvolumejob.cpp2
-rw-r--r--src/render/jobs/filterentitybycomponentjob_p.h2
-rw-r--r--src/render/jobs/filterlayerentityjob.cpp2
-rw-r--r--src/render/jobs/framecleanupjob.cpp2
-rw-r--r--src/render/jobs/frustumcullingjob.cpp2
-rw-r--r--src/render/jobs/genericlambdajob_p.h4
-rw-r--r--src/render/jobs/lightgatherer.cpp2
-rw-r--r--src/render/jobs/loadbufferjob.cpp2
-rw-r--r--src/render/jobs/loadgeometryjob.cpp2
-rw-r--r--src/render/jobs/loadscenejob.cpp2
-rw-r--r--src/render/jobs/sendbuffercapturejob.cpp2
-rw-r--r--src/render/jobs/sendrendercapturejob.cpp2
-rw-r--r--src/render/jobs/updateentitylayersjob.cpp2
-rw-r--r--src/render/jobs/updatemeshtrianglelistjob.cpp2
-rw-r--r--src/render/jobs/updateshaderdatatransformjob.cpp2
-rw-r--r--src/render/jobs/updateskinningpalettejob.cpp2
-rw-r--r--src/render/jobs/updatetreeenabledjob.cpp2
-rw-r--r--src/render/jobs/updateworldtransformjob.cpp2
-rw-r--r--src/render/renderers/opengl/jobs/filtercompatibletechniquejob.cpp2
-rw-r--r--src/render/renderers/opengl/jobs/materialparametergathererjob.cpp2
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp2
-rw-r--r--src/render/renderers/opengl/jobs/renderviewinitializerjob.cpp2
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp42
-rw-r--r--tests/auto/core/qservicelocator/tst_qservicelocator.cpp14
-rw-r--r--tests/auto/core/threadpooler/tst_threadpooler.cpp2
41 files changed, 442 insertions, 361 deletions
diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp
index f24248399..240955a06 100644
--- a/src/core/aspects/qaspectmanager.cpp
+++ b/src/core/aspects/qaspectmanager.cpp
@@ -57,6 +57,7 @@
#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/private/qscheduler_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p_p.h>
#include <Qt3DCore/private/qthreadpooler_p.h>
#include <Qt3DCore/private/qtickclock_p.h>
#include <Qt3DCore/private/qtickclockservice_p.h>
@@ -449,57 +450,49 @@ void QAspectManager::processFrame()
//
// Doing this as the first call in the new frame ensures the lock free approach works
// without any such data race.
-#if QT_CONFIG(qt3d_profile_jobs)
- const quint32 arbiterId = 4096;
- JobRunStats changeArbiterStats;
- changeArbiterStats.jobId.typeAndInstance[0] = arbiterId;
- changeArbiterStats.jobId.typeAndInstance[1] = 0;
- changeArbiterStats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
- changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
-#endif
-
- // Tell the NodePostConstructorInit to process any pending nodes which will add them to our list of
- // tree changes
- m_postConstructorInit->processNodes();
-
- // Add and Remove Nodes
- const QVector<NodeTreeChange> nodeTreeChanges = std::move(m_nodeTreeChanges);
- for (const NodeTreeChange &change : nodeTreeChanges) {
- // Buckets ensure that even if we have intermingled node added / removed
- // buckets, we preserve the order of the sequences
-
- for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
- switch (change.type) {
- case NodeTreeChange::Added:
- aspect->d_func()->createBackendNode(change);
- break;
- case NodeTreeChange::Removed:
- aspect->d_func()->clearBackendNode(change);
- break;
+ {
+ // scope for QTaskLogger
+ QTaskLogger logger(m_serviceLocator->systemInformation(), 4096, 0);
+
+ // Tell the NodePostConstructorInit to process any pending nodes which will add them to our list of
+ // tree changes
+ m_postConstructorInit->processNodes();
+
+ // Add and Remove Nodes
+ const QVector<NodeTreeChange> nodeTreeChanges = std::move(m_nodeTreeChanges);
+ for (const NodeTreeChange &change : nodeTreeChanges) {
+ // Buckets ensure that even if we have intermingled node added / removed
+ // buckets, we preserve the order of the sequences
+
+ for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
+ switch (change.type) {
+ case NodeTreeChange::Added:
+ aspect->d_func()->createBackendNode(change);
+ break;
+ case NodeTreeChange::Removed:
+ aspect->d_func()->clearBackendNode(change);
+ break;
+ }
}
}
- }
- // Sync node / subnode relationship changes
- const auto dirtySubNodes = m_changeArbiter->takeDirtyFrontEndSubNodes();
- if (dirtySubNodes.size())
- for (QAbstractAspect *aspect : qAsConst(m_aspects))
- QAbstractAspectPrivate::get(aspect)->syncDirtyFrontEndSubNodes(dirtySubNodes);
-
- // Sync property updates
- const auto dirtyFrontEndNodes = m_changeArbiter->takeDirtyFrontEndNodes();
- if (dirtyFrontEndNodes.size())
- for (QAbstractAspect *aspect : qAsConst(m_aspects))
- QAbstractAspectPrivate::get(aspect)->syncDirtyFrontEndNodes(dirtyFrontEndNodes);
-
- // TO DO: Having this done in the main thread actually means aspects could just
- // as simply read info out of the Frontend classes without risk of introducing
- // races. This could therefore be removed for Qt 6.
- m_changeArbiter->syncChanges();
-#if QT_CONFIG(qt3d_profile_jobs)
- changeArbiterStats.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- QThreadPooler::addJobLogStatsEntry(changeArbiterStats);
-#endif
+ // Sync node / subnode relationship changes
+ const auto dirtySubNodes = m_changeArbiter->takeDirtyFrontEndSubNodes();
+ if (dirtySubNodes.size())
+ for (QAbstractAspect *aspect : qAsConst(m_aspects))
+ QAbstractAspectPrivate::get(aspect)->syncDirtyFrontEndSubNodes(dirtySubNodes);
+
+ // Sync property updates
+ const auto dirtyFrontEndNodes = m_changeArbiter->takeDirtyFrontEndNodes();
+ if (dirtyFrontEndNodes.size())
+ for (QAbstractAspect *aspect : qAsConst(m_aspects))
+ QAbstractAspectPrivate::get(aspect)->syncDirtyFrontEndNodes(dirtyFrontEndNodes);
+
+ // TO DO: Having this done in the main thread actually means aspects could just
+ // as simply read info out of the Frontend classes without risk of introducing
+ // races. This could therefore be removed for Qt 6.
+ m_changeArbiter->syncChanges();
+ }
// For each Aspect
// Ask them to launch set of jobs for the current frame
@@ -512,8 +505,6 @@ void QAspectManager::processFrame()
#if defined(QT3D_CORE_JOB_TIMING)
qDebug() << "Jobs took" << timer.nsecsElapsed() / 1.0e6;
#endif
-
- // TODO sync backend changes to frontend
}
} // namespace Qt3DCore
diff --git a/src/core/jobs/qaspectjob_p.h b/src/core/jobs/qaspectjob_p.h
index b16c3cad2..ddad09c86 100644
--- a/src/core/jobs/qaspectjob_p.h
+++ b/src/core/jobs/qaspectjob_p.h
@@ -54,6 +54,7 @@
#include <QtCore/QWeakPointer>
#include <Qt3DCore/private/qt3dcore_global_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p_p.h>
#include <Qt3DCore/qt3dcore-config.h>
QT_BEGIN_NAMESPACE
@@ -63,47 +64,6 @@ namespace Qt3DCore {
class QAspectJob;
class QAspectManager;
-#if QT_CONFIG(qt3d_profile_jobs)
-struct FrameHeader
-{
- FrameHeader()
- : frameId(0)
- , jobCount(0)
- , frameType(WorkerJob)
- {
- }
-
- enum FrameType {
- WorkerJob = 0,
- Submission
- };
-
- quint32 frameId;
- quint16 jobCount;
- quint16 frameType; // Submission or worker job
-};
-
-union JobId
-{
- quint32 typeAndInstance[2];
- quint64 id;
-};
-
-struct JobRunStats
-{
- JobRunStats()
- {
- jobId.id = 0;
- }
-
- qint64 startTime;
- qint64 endTime;
- JobId jobId;
- // QAspectJob subclasses should properly populate the jobId
- quint64 threadId;
-};
-#endif
-
class Q_3DCORE_PRIVATE_EXPORT QAspectJobPrivate
{
public:
@@ -115,29 +75,16 @@ public:
virtual void postFrame(QAspectManager *aspectManager);
QVector<QWeakPointer<QAspectJob> > m_dependencies;
-#if QT_CONFIG(qt3d_profile_jobs)
- JobRunStats m_stats;
-#endif
+ JobId m_jobId;
};
-
} // Qt3D
-#if QT_CONFIG(qt3d_profile_jobs)
-
-#include <Qt3DCore/private/qaspectjob_p.h>
-
#define SET_JOB_RUN_STAT_TYPE(job, type, instance) \
- Qt3DCore::QAspectJobPrivate::get(job)->m_stats.jobId.typeAndInstance[0] = type; \
- Qt3DCore::QAspectJobPrivate::get(job)->m_stats.jobId.typeAndInstance[1] = instance;
-
-#else
-
-#define SET_JOB_RUN_STAT_TYPE(job, type, instance) \
- Q_UNUSED(job) \
- Q_UNUSED(type) \
- Q_UNUSED(instance)
-
-#endif
+ { \
+ auto &jobId = Qt3DCore::QAspectJobPrivate::get(job)->m_jobId; \
+ jobId.typeAndInstance[0] = type; \
+ jobId.typeAndInstance[1] = instance; \
+ }
QT_END_NAMESPACE
diff --git a/src/core/jobs/qaspectjobmanager.cpp b/src/core/jobs/qaspectjobmanager.cpp
index 91394924f..be7942359 100644
--- a/src/core/jobs/qaspectjobmanager.cpp
+++ b/src/core/jobs/qaspectjobmanager.cpp
@@ -44,7 +44,7 @@
#include <QtCore/QDebug>
#include <QtCore/QThread>
#include <QtCore/QFuture>
-
+#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DCore/private/qthreadpooler_p.h>
#include <Qt3DCore/private/task_p.h>
@@ -52,9 +52,10 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-QAspectJobManager::QAspectJobManager(QObject *parent)
+QAspectJobManager::QAspectJobManager(QAspectManager *parent)
: QAbstractAspectJobManager(parent)
, m_threadPooler(new QThreadPooler(this))
+ , m_aspectManager(parent)
{
}
@@ -69,12 +70,16 @@ void QAspectJobManager::initialize()
// Adds all Aspect Jobs to be processed for a frame
void QAspectJobManager::enqueueJobs(const QVector<QAspectJobPtr> &jobQueue)
{
+ auto systemService = m_aspectManager ? m_aspectManager->serviceLocator()->systemInformation() : nullptr;
+ if (systemService)
+ systemService->writePreviousFrameTraces();
+
// Convert QJobs to Tasks
QHash<QAspectJob *, AspectTaskRunnable *> tasksMap;
QVector<RunnableInterface *> taskList;
taskList.reserve(jobQueue.size());
for (const QAspectJobPtr &job : jobQueue) {
- AspectTaskRunnable *task = new AspectTaskRunnable();
+ AspectTaskRunnable *task = new AspectTaskRunnable(systemService);
task->m_job = job;
tasksMap.insert(job.data(), task);
@@ -99,9 +104,6 @@ void QAspectJobManager::enqueueJobs(const QVector<QAspectJobPtr> &jobQueue)
taskDepender->m_dependerCount += dependerCount;
}
-#if QT_CONFIG(qt3d_profile_jobs)
- QThreadPooler::writeFrameJobLogStats();
-#endif
m_threadPooler->mapDependables(taskList);
}
diff --git a/src/core/jobs/qaspectjobmanager_p.h b/src/core/jobs/qaspectjobmanager_p.h
index 77e535491..acbd0263e 100644
--- a/src/core/jobs/qaspectjobmanager_p.h
+++ b/src/core/jobs/qaspectjobmanager_p.h
@@ -63,12 +63,13 @@ namespace Qt3DCore {
class QThreadPooler;
class DependencyHandler;
+class QAspectManager;
class Q_3DCORE_PRIVATE_EXPORT QAspectJobManager : public QAbstractAspectJobManager
{
Q_OBJECT
public:
- explicit QAspectJobManager(QObject *parent = 0);
+ explicit QAspectJobManager(QAspectManager *parent = nullptr);
~QAspectJobManager();
void initialize() override;
@@ -81,6 +82,7 @@ public:
private:
QThreadPooler *m_threadPooler;
+ QAspectManager *m_aspectManager;
};
} // namespace Qt3DCore
diff --git a/src/core/jobs/qthreadpooler.cpp b/src/core/jobs/qthreadpooler.cpp
index 3ab321542..f5c50062a 100644
--- a/src/core/jobs/qthreadpooler.cpp
+++ b/src/core/jobs/qthreadpooler.cpp
@@ -40,27 +40,10 @@
#include "qthreadpooler_p.h"
#include <QtCore/QDebug>
-#if QT_CONFIG(qt3d_profile_jobs)
-
-#ifdef Q_OS_ANDROID
-#include <QtCore/QStandardPaths>
-#endif
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QFile>
-#include <QtCore/QThreadStorage>
-#include <QtCore/QDateTime>
-#include <QtCore/QCoreApplication>
-#endif
-
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-#if QT_CONFIG(qt3d_profile_jobs)
-QElapsedTimer QThreadPooler::m_jobsStatTimer;
-#endif
-
QThreadPooler::QThreadPooler(QObject *parent)
: QObject(parent)
, m_futureInterface(nullptr)
@@ -76,12 +59,8 @@ QThreadPooler::QThreadPooler(QObject *parent)
m_threadPool->setMaxThreadCount(maxThreadCountValue);
}
-
// Ensures that threads will never be recycled
m_threadPool->setExpiryTimeout(-1);
-#if QT_CONFIG(qt3d_profile_jobs)
- QThreadPooler::m_jobsStatTimer.start();
-#endif
}
QThreadPooler::~QThreadPooler()
@@ -194,102 +173,6 @@ int QThreadPooler::maxThreadCount() const
return m_threadPool->maxThreadCount();
}
-#if QT_CONFIG(qt3d_profile_jobs)
-
-QThreadStorage<QVector<JobRunStats> *> jobStatsCached;
-
-QVector<QVector<JobRunStats> *> localStorages;
-QVector<JobRunStats> *submissionStorage = nullptr;
-
-QMutex localStoragesMutex;
-
-// Called by the jobs
-void QThreadPooler::addJobLogStatsEntry(JobRunStats &stats)
-{
- if (!jobStatsCached.hasLocalData()) {
- auto jobVector = new QVector<JobRunStats>;
- jobStatsCached.setLocalData(jobVector);
- QMutexLocker lock(&localStoragesMutex);
- localStorages.push_back(jobVector);
- }
- jobStatsCached.localData()->push_back(stats);
-}
-
-// Called after jobs have been executed (MainThread QAspectJobManager::enqueueJobs)
-void QThreadPooler::writeFrameJobLogStats()
-{
- static QScopedPointer<QFile> traceFile;
- static quint32 frameId = 0;
- if (!traceFile) {
- const QString fileName = QStringLiteral("trace_") + QCoreApplication::applicationName() + QDateTime::currentDateTime().toString(QStringLiteral("_ddd_dd_MM_yy-hh_mm_ss_"))+ QSysInfo::productType() + QStringLiteral("_") + QSysInfo::buildAbi() + QStringLiteral(".qt3d");
-#ifdef Q_OS_ANDROID
- traceFile.reset(new QFile(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + QStringLiteral("/") + fileName));
-#else
- traceFile.reset(new QFile(fileName));
-#endif
- if (!traceFile->open(QFile::WriteOnly|QFile::Truncate))
- qCritical("Failed to open trace file");
- }
-
- // Write Aspect + Job threads
- {
- FrameHeader header;
- header.frameId = frameId;
- header.jobCount = 0;
-
- for (const QVector<JobRunStats> *storage : qAsConst(localStorages))
- header.jobCount += storage->size();
-
- traceFile->write(reinterpret_cast<char *>(&header), sizeof(FrameHeader));
-
- for (QVector<JobRunStats> *storage : qAsConst(localStorages)) {
- for (const JobRunStats &stat : *storage)
- traceFile->write(reinterpret_cast<const char *>(&stat), sizeof(JobRunStats));
- storage->clear();
- }
- }
-
- // Write submission thread
- {
- QMutexLocker lock(&localStoragesMutex);
- const int submissionJobSize = submissionStorage != nullptr ? submissionStorage->size() : 0;
- if (submissionJobSize > 0) {
- FrameHeader header;
- header.frameId = frameId;
- header.jobCount = submissionJobSize;
- header.frameType = FrameHeader::Submission;
-
- traceFile->write(reinterpret_cast<char *>(&header), sizeof(FrameHeader));
-
- for (const JobRunStats &stat : *submissionStorage)
- traceFile->write(reinterpret_cast<const char *>(&stat), sizeof(JobRunStats));
- submissionStorage->clear();
- }
- }
-
- traceFile->flush();
- ++frameId;
-}
-
-// Called from Submission thread (which can be main thread in Manual drive mode)
-void QThreadPooler::addSubmissionLogStatsEntry(JobRunStats &stats)
-{
- QMutexLocker lock(&localStoragesMutex);
- if (!jobStatsCached.hasLocalData()) {
- submissionStorage = new QVector<JobRunStats>;
- jobStatsCached.setLocalData(submissionStorage);
- }
-
- // Handle the case where submission thread is also the main thread (Scene/Manual drive modes with no RenderThread)
- if (submissionStorage == nullptr && jobStatsCached.hasLocalData())
- submissionStorage = new QVector<JobRunStats>;
-
- // When having no submission thread this can be null
- submissionStorage->push_back(stats);
-}
-
-#endif
-
} // namespace Qt3DCore
QT_END_NAMESPACE
diff --git a/src/core/jobs/qthreadpooler_p.h b/src/core/jobs/qthreadpooler_p.h
index 3e17cbd6d..1970641b8 100644
--- a/src/core/jobs/qthreadpooler_p.h
+++ b/src/core/jobs/qthreadpooler_p.h
@@ -60,10 +60,6 @@
#include <Qt3DCore/private/qaspectjob_p.h>
#include <Qt3DCore/private/task_p.h>
-#if QT_CONFIG(qt3d_profile_jobs)
-#include <QtCore/QElapsedTimer>
-#endif
-
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
@@ -81,17 +77,6 @@ public:
QFuture<void> future();
int maxThreadCount() const;
-#if QT_CONFIG(qt3d_profile_jobs)
- static QElapsedTimer m_jobsStatTimer;
-
- // Aspects + Job threads
- static void addJobLogStatsEntry(JobRunStats &stats);
- static void writeFrameJobLogStats();
-
- // Submission thread
- static void addSubmissionLogStatsEntry(JobRunStats &stats);
-
-#endif
private:
void enqueueTasks(const QVector<RunnableInterface *> &tasks);
diff --git a/src/core/jobs/task.cpp b/src/core/jobs/task.cpp
index 7c3ebf6eb..1dd5712c9 100644
--- a/src/core/jobs/task.cpp
+++ b/src/core/jobs/task.cpp
@@ -44,6 +44,7 @@
#include <QtCore/QMutexLocker>
#include <Qt3DCore/private/qthreadpooler_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p_p.h>
QT_BEGIN_NAMESPACE
@@ -55,8 +56,9 @@ RunnableInterface::~RunnableInterface()
// Aspect task
-AspectTaskRunnable::AspectTaskRunnable()
- : m_pooler(nullptr)
+AspectTaskRunnable::AspectTaskRunnable(QSystemInformationService *service)
+ : m_service(service)
+ , m_pooler(nullptr)
, m_id(0)
, m_reserved(false)
{
@@ -69,21 +71,9 @@ AspectTaskRunnable::~AspectTaskRunnable()
void AspectTaskRunnable::run()
{
if (m_job) {
-#if QT_CONFIG(qt3d_profile_jobs)
QAspectJobPrivate *jobD = QAspectJobPrivate::get(m_job.data());
- if (m_pooler) {
- jobD->m_stats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- jobD->m_stats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
- }
-#endif
+ QTaskLogger logger(m_pooler ? m_service : nullptr, jobD->m_jobId, QTaskLogger::AspectJob);
m_job->run();
-#if QT_CONFIG(qt3d_profile_jobs)
- if (m_pooler) {
- jobD->m_stats.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- // Add current job's stats to log output
- QThreadPooler::addJobLogStatsEntry(jobD->m_stats);
- }
-#endif
}
// We could have an append sub task or something in here
diff --git a/src/core/jobs/task_p.h b/src/core/jobs/task_p.h
index c81882719..ff411539f 100644
--- a/src/core/jobs/task_p.h
+++ b/src/core/jobs/task_p.h
@@ -65,6 +65,7 @@ namespace Qt3DCore {
class JobRunner;
class DependencyHandler;
class QThreadPooler;
+class QSystemInformationService;
class RunnableInterface : public QRunnable
{
@@ -92,7 +93,7 @@ public:
class AspectTaskRunnable : public RunnableInterface
{
public:
- AspectTaskRunnable();
+ AspectTaskRunnable(QSystemInformationService *service);
~AspectTaskRunnable();
void run() override;
@@ -113,6 +114,7 @@ public:
int m_dependerCount = 0;
private:
+ QSystemInformationService *m_service;
QThreadPooler *m_pooler;
int m_id; // For testing purposes for now
bool m_reserved;
diff --git a/src/core/services/nullservices_p.h b/src/core/services/nullservices_p.h
index 30dc2d543..6b2d1b029 100644
--- a/src/core/services/nullservices_p.h
+++ b/src/core/services/nullservices_p.h
@@ -54,25 +54,11 @@
#include <Qt3DCore/qt3dcore_global.h>
#include <Qt3DCore/private/qopenglinformationservice_p.h>
-#include <Qt3DCore/private/qsysteminformationservice_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-class NullSystemInformationService : public QSystemInformationService
-{
-public:
- NullSystemInformationService()
- : QSystemInformationService(QStringLiteral("Null System Information Service"))
- {}
- ~NullSystemInformationService() {}
-
- QStringList aspectNames() const final { return QStringList(); }
- int threadPoolThreadCount() const final { return 0; }
-};
-
-
class NullOpenGLInformationService : public QOpenGLInformationService
{
public:
diff --git a/src/core/services/qservicelocator.cpp b/src/core/services/qservicelocator.cpp
index bdcb4a521..5df33dae9 100644
--- a/src/core/services/qservicelocator.cpp
+++ b/src/core/services/qservicelocator.cpp
@@ -46,6 +46,7 @@
#include <Qt3DCore/private/qdownloadhelperservice_p.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
#include <Qt3DCore/private/qtickclockservice_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p.h>
QT_BEGIN_NAMESPACE
@@ -94,7 +95,7 @@ public:
QHash<int, QAbstractServiceProvider *> m_services;
- NullSystemInformationService m_nullSystemInfo;
+ QSystemInformationService m_systemInfo;
NullOpenGLInformationService m_nullOpenGLInfo;
QTickClockService m_defaultFrameAdvanceService;
QEventFilterService m_eventFilterService;
@@ -196,7 +197,7 @@ int QServiceLocator::serviceCount() const
QSystemInformationService *QServiceLocator::systemInformation()
{
Q_D(QServiceLocator);
- return static_cast<QSystemInformationService *>(d->m_services.value(SystemInformation, &d->m_nullSystemInfo));
+ return static_cast<QSystemInformationService *>(d->m_services.value(SystemInformation, &d->m_systemInfo));
}
/*
diff --git a/src/core/services/qsysteminformationservice.cpp b/src/core/services/qsysteminformationservice.cpp
index f11e0c3d1..6a8cbee04 100644
--- a/src/core/services/qsysteminformationservice.cpp
+++ b/src/core/services/qsysteminformationservice.cpp
@@ -40,10 +40,206 @@
#include "qsysteminformationservice_p.h"
#include "qsysteminformationservice_p_p.h"
+#ifdef Q_OS_ANDROID
+#include <QtCore/QStandardPaths>
+#endif
+
+#include <QtCore/QThreadPool>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFile>
+#include <QtCore/QDateTime>
+#include <QtCore/QCoreApplication>
+
QT_BEGIN_NAMESPACE
+namespace {
+
+struct FrameHeader
+{
+ FrameHeader()
+ : frameId(0)
+ , jobCount(0)
+ , frameType(WorkerJob)
+ {
+ }
+
+ enum FrameType {
+ WorkerJob = 0,
+ Submission
+ };
+
+ quint32 frameId;
+ quint16 jobCount;
+ quint16 frameType; // Submission or worker job
+};
+
+}
namespace Qt3DCore {
+QSystemInformationServicePrivate::QSystemInformationServicePrivate(const QString &description)
+ : QAbstractServiceProviderPrivate(QServiceLocator::SystemInformation, description)
+ , m_submissionStorage(nullptr)
+ , m_frameId(0)
+{
+ m_traceEnabled = qEnvironmentVariableIsSet("QT3D_TRACE_ENABLED");
+ if (m_traceEnabled)
+ m_jobsStatTimer.start();
+}
+
+QSystemInformationServicePrivate::~QSystemInformationServicePrivate() = default;
+
+QSystemInformationServicePrivate *QSystemInformationServicePrivate::get(QSystemInformationService *q)
+{
+ return q->d_func();
+}
+
+// Called by the jobs
+void QSystemInformationServicePrivate::addJobLogStatsEntry(QSystemInformationServicePrivate::JobRunStats &stats)
+{
+ if (!m_traceEnabled)
+ return;
+
+ if (!m_jobStatsCached.hasLocalData()) {
+ auto jobVector = new QVector<JobRunStats>;
+ m_jobStatsCached.setLocalData(jobVector);
+ QMutexLocker lock(&m_localStoragesMutex);
+ m_localStorages.push_back(jobVector);
+ }
+ m_jobStatsCached.localData()->push_back(stats);
+}
+
+// Called from Submission thread (which can be main thread in Manual drive mode)
+void QSystemInformationServicePrivate::addSubmissionLogStatsEntry(QSystemInformationServicePrivate::JobRunStats &stats)
+{
+ if (!m_traceEnabled)
+ return;
+
+ QMutexLocker lock(&m_localStoragesMutex);
+ if (!m_jobStatsCached.hasLocalData()) {
+ m_submissionStorage = new QVector<JobRunStats>;
+ m_jobStatsCached.setLocalData(m_submissionStorage);
+ }
+
+ // Handle the case where submission thread is also the main thread (Scene/Manual drive modes with no RenderThread)
+ if (m_submissionStorage == nullptr && m_jobStatsCached.hasLocalData())
+ m_submissionStorage = new QVector<JobRunStats>;
+
+ // When having no submission thread this can be null
+ m_submissionStorage->push_back(stats);
+}
+
+// Called after jobs have been executed (MainThread QAspectJobManager::enqueueJobs)
+void QSystemInformationServicePrivate::writeFrameJobLogStats()
+{
+ if (!m_traceEnabled)
+ return;
+
+ using JobRunStats = QSystemInformationServicePrivate::JobRunStats;
+
+ if (!m_traceFile) {
+ const QString fileName = QStringLiteral("trace_") + QCoreApplication::applicationName() + QDateTime::currentDateTime().toString(QStringLiteral("_ddd_dd_MM_yy-hh_mm_ss_"))+ QSysInfo::productType() + QStringLiteral("_") + QSysInfo::buildAbi() + QStringLiteral(".qt3d");
+#ifdef Q_OS_ANDROID
+ m_traceFile.reset(new QFile(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + QStringLiteral("/") + fileName));
+#else
+ // TODO fix for iOS
+ m_traceFile.reset(new QFile(fileName));
+#endif
+ if (!m_traceFile->open(QFile::WriteOnly|QFile::Truncate))
+ qCritical("Failed to open trace file");
+ }
+
+ // Write Aspect + Job threads
+ {
+ FrameHeader header;
+ header.frameId = m_frameId;
+ header.jobCount = 0;
+
+ for (const QVector<JobRunStats> *storage : qAsConst(m_localStorages))
+ header.jobCount += storage->size();
+
+ m_traceFile->write(reinterpret_cast<char *>(&header), sizeof(FrameHeader));
+
+ for (QVector<JobRunStats> *storage : qAsConst(m_localStorages)) {
+ for (const JobRunStats &stat : *storage)
+ m_traceFile->write(reinterpret_cast<const char *>(&stat), sizeof(JobRunStats));
+ storage->clear();
+ }
+ }
+
+ // Write submission thread
+ {
+ QMutexLocker lock(&m_localStoragesMutex);
+ const int submissionJobSize = m_submissionStorage != nullptr ? m_submissionStorage->size() : 0;
+ if (submissionJobSize > 0) {
+ FrameHeader header;
+ header.frameId = m_frameId;
+ header.jobCount = submissionJobSize;
+ header.frameType = FrameHeader::Submission;
+
+ m_traceFile->write(reinterpret_cast<char *>(&header), sizeof(FrameHeader));
+
+ for (const JobRunStats &stat : *m_submissionStorage)
+ m_traceFile->write(reinterpret_cast<const char *>(&stat), sizeof(JobRunStats));
+ m_submissionStorage->clear();
+ }
+ }
+
+ m_traceFile->flush();
+ ++m_frameId;
+}
+
+
+QTaskLogger::QTaskLogger(QSystemInformationService *service, const JobId &jobId, Type type)
+ : m_service(service && service->isTraceEnabled() ? service : nullptr)
+ , m_type(type)
+{
+ m_stats.jobId = jobId;
+ if (m_service) {
+ m_stats.startTime = QSystemInformationServicePrivate::get(m_service)->m_jobsStatTimer.nsecsElapsed();
+ m_stats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
+ }
+}
+
+QTaskLogger::QTaskLogger(QSystemInformationService *service,
+ const quint32 jobType,
+ const quint32 instance,
+ QTaskLogger::Type type)
+ : m_service(service && service->isTraceEnabled() ? service : nullptr)
+ , m_type(type)
+{
+ m_stats.jobId.typeAndInstance[0] = jobType;
+ m_stats.jobId.typeAndInstance[1] = instance;
+ if (m_service) {
+ m_stats.startTime = QSystemInformationServicePrivate::get(m_service)->m_jobsStatTimer.nsecsElapsed();
+ m_stats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
+ }
+}
+
+QTaskLogger::~QTaskLogger() {
+ if (m_service) {
+ auto dservice = QSystemInformationServicePrivate::get(m_service);
+ if (m_stats.endTime == 0L)
+ m_stats.endTime = dservice->m_jobsStatTimer.nsecsElapsed();
+ switch (m_type) {
+ case AspectJob: dservice->addJobLogStatsEntry(m_stats); break;
+ case Submission: dservice->addSubmissionLogStatsEntry(m_stats); break;
+ }
+ }
+}
+
+void QTaskLogger::end(qint64 t)
+{
+ m_stats.endTime = t > 0 || !m_service ? t : QSystemInformationServicePrivate::get(m_service)->m_jobsStatTimer.nsecsElapsed();
+}
+
+qint64 QTaskLogger::restart()
+{
+ if (m_service)
+ m_stats.startTime = QSystemInformationServicePrivate::get(m_service)->m_jobsStatTimer.nsecsElapsed();
+ return m_stats.startTime;
+}
+
+
/* !\internal
\class Qt3DCore::QSystemInformationService
\inmodule Qt3DCore
@@ -58,6 +254,12 @@ namespace Qt3DCore {
the new service. This constructor is protected so only subclasses can
instantiate a QSystemInformationService object.
*/
+
+QSystemInformationService::QSystemInformationService()
+ : QAbstractServiceProvider(*new QSystemInformationServicePrivate(QLatin1String("Default System Information Service")))
+{
+}
+
QSystemInformationService::QSystemInformationService(const QString &description)
: QAbstractServiceProvider(*new QSystemInformationServicePrivate(description))
{
@@ -71,19 +273,52 @@ QSystemInformationService::QSystemInformationService(QSystemInformationServicePr
{
}
+bool QSystemInformationService::isTraceEnabled() const
+{
+ Q_D(const QSystemInformationService);
+ return d->m_traceEnabled;
+}
+
+void QSystemInformationService::setTraceEnabled(bool traceEnabled)
+{
+ Q_D(QSystemInformationService);
+ if (d->m_traceEnabled != traceEnabled) {
+ d->m_traceEnabled = traceEnabled;
+ emit traceEnabledChanged(d->m_traceEnabled);
+ if (d->m_traceEnabled) {
+ if (!d->m_jobsStatTimer.isValid())
+ d->m_jobsStatTimer.start();
+ } else {
+ d->m_traceFile.reset();
+ }
+ }
+}
+
/*
\fn QStringList Qt3DCore::QSystemInformationService::aspectNames() const
- Subclasses should override this function and return a string list containing the
- names of all registered aspects.
+ Returns a string list containing the names of all registered aspects.
*/
+QStringList QSystemInformationService::aspectNames() const
+{
+ return {};
+}
/*
\fn int Qt3DCore::QSystemInformationService::threadPoolThreadCount() const
- Subclasses should override this function and return the number of threads in the
- Qt3D task manager's threadpool.
+ Returns the maximum number of threads in the Qt3D task manager's threadpool.
*/
+int QSystemInformationService::threadPoolThreadCount() const
+{
+ return QThreadPool::globalInstance()->maxThreadCount();
+}
+
+void QSystemInformationService::writePreviousFrameTraces()
+{
+ Q_D(QSystemInformationService);
+ d->writeFrameJobLogStats();
+}
}
diff --git a/src/core/services/qsysteminformationservice_p.h b/src/core/services/qsysteminformationservice_p.h
index a8a83701b..6fc1579bc 100644
--- a/src/core/services/qsysteminformationservice_p.h
+++ b/src/core/services/qsysteminformationservice_p.h
@@ -61,16 +61,29 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
class QSystemInformationServicePrivate;
+struct JobRunStats;
class Q_3DCORESHARED_EXPORT QSystemInformationService : public QAbstractServiceProvider
{
Q_OBJECT
+ Q_PROPERTY(bool traceEnabled READ isTraceEnabled WRITE setTraceEnabled NOTIFY traceEnabledChanged)
public:
- virtual QStringList aspectNames() const = 0;
- virtual int threadPoolThreadCount() const = 0;
+ QSystemInformationService();
+
+ bool isTraceEnabled() const;
+ void setTraceEnabled(bool traceEnabled);
+
+ QStringList aspectNames() const;
+ int threadPoolThreadCount() const;
+
+ void writePreviousFrameTraces();
+
+signals:
+ void traceEnabledChanged(bool traceEnabled);
protected:
- QSystemInformationService(const QString &description = QString());
+ Q_DECLARE_PRIVATE(QSystemInformationService)
+ QSystemInformationService(const QString &description);
QSystemInformationService(QSystemInformationServicePrivate &dd);
};
diff --git a/src/core/services/qsysteminformationservice_p_p.h b/src/core/services/qsysteminformationservice_p_p.h
index e3ce9fe49..75a6e98e7 100644
--- a/src/core/services/qsysteminformationservice_p_p.h
+++ b/src/core/services/qsysteminformationservice_p_p.h
@@ -51,21 +51,91 @@
// We mean it.
//
-#include <Qt3DCore/qt3dcore_global.h>
+#include <QtCore/QThreadStorage>
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QFile>
+#include <QtCore/QMutex>
+#include <Qt3DCore/qt3dcore_global.h>
+#include <Qt3DCore/private/qt3dcore_global_p.h>
#include <Qt3DCore/private/qabstractserviceprovider_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-class QSystemInformationServicePrivate : public QAbstractServiceProviderPrivate
+union Q_3DCORE_PRIVATE_EXPORT JobId
+{
+ JobId() : id(0L) { }
+ JobId(quint32 t, quint32 i) { typeAndInstance[0] = t; typeAndInstance[1] = i; }
+
+ quint32 typeAndInstance[2];
+ quint64 id;
+};
+
+class Q_3DCORE_PRIVATE_EXPORT QSystemInformationServicePrivate : public QAbstractServiceProviderPrivate
{
public:
- QSystemInformationServicePrivate(const QString &description)
- : QAbstractServiceProviderPrivate(QServiceLocator::SystemInformation, description)
- {}
+ struct JobRunStats
+ {
+ JobRunStats() { jobId.id = 0; startTime = 0L; endTime = 0L; }
+
+ qint64 startTime;
+ qint64 endTime;
+ JobId jobId; // QAspectJob subclasses should properly populate the jobId
+ quint64 threadId;
+ };
+
+ QSystemInformationServicePrivate(const QString &description);
+ ~QSystemInformationServicePrivate();
+
+ static QSystemInformationServicePrivate *get(QSystemInformationService *q);
+
+ // Aspects + Job threads
+ void addJobLogStatsEntry(JobRunStats &stats);
+
+ // Submission thread
+ void addSubmissionLogStatsEntry(JobRunStats &stats);
+
+ void writeFrameJobLogStats();
+
+ bool m_traceEnabled;
+
+ QElapsedTimer m_jobsStatTimer;
+ QThreadStorage<QVector<JobRunStats> *> m_jobStatsCached;
+
+ QVector<QVector<JobRunStats> *> m_localStorages;
+ QVector<JobRunStats> *m_submissionStorage;
+
+ QMutex m_localStoragesMutex;
+
+ QScopedPointer<QFile> m_traceFile;
+ quint32 m_frameId;
+
+ Q_DECLARE_PUBLIC(QSystemInformationService)
+};
+
+class Q_3DCORE_PRIVATE_EXPORT QTaskLogger {
+public:
+ enum Type {
+ AspectJob,
+ Submission
+ };
+
+ QTaskLogger(QSystemInformationService *service, const JobId &jobId, Type type);
+ QTaskLogger(QSystemInformationService *service, const quint32 jobType, const quint32 instance, Type type = Submission);
+
+ ~QTaskLogger();
+
+ void end(qint64 t = 0L);
+ qint64 restart();
+
+private:
+ QSystemInformationService *m_service;
+ QSystemInformationServicePrivate::JobRunStats m_stats;
+ Type m_type;
};
}
diff --git a/src/logic/callbackjob.cpp b/src/logic/callbackjob.cpp
index 5c04d8838..5dfc74f02 100644
--- a/src/logic/callbackjob.cpp
+++ b/src/logic/callbackjob.cpp
@@ -51,7 +51,7 @@ CallbackJob::CallbackJob()
: QAspectJob()
, m_logicManager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::Callback, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::Callback, 0)
}
void CallbackJob::setManager(Manager *manager)
diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp
index 9af2f4f38..172c4ddca 100644
--- a/src/render/jobs/calcboundingvolumejob.cpp
+++ b/src/render/jobs/calcboundingvolumejob.cpp
@@ -354,7 +354,7 @@ CalculateBoundingVolumeJob::CalculateBoundingVolumeJob()
: m_manager(nullptr)
, m_node(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::CalcBoundingVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::CalcBoundingVolume, 0)
}
void CalculateBoundingVolumeJob::run()
diff --git a/src/render/jobs/calcgeometrytrianglevolumes.cpp b/src/render/jobs/calcgeometrytrianglevolumes.cpp
index d2b12e09c..eb31a25a6 100644
--- a/src/render/jobs/calcgeometrytrianglevolumes.cpp
+++ b/src/render/jobs/calcgeometrytrianglevolumes.cpp
@@ -53,7 +53,7 @@ CalcGeometryTriangleVolumes::CalcGeometryTriangleVolumes(const Qt3DCore::QNodeId
, m_geometryRendererId(geometryRendererId)
, m_manager(manager)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::CalcTriangleVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::CalcTriangleVolume, 0)
}
void CalcGeometryTriangleVolumes::run()
diff --git a/src/render/jobs/expandboundingvolumejob.cpp b/src/render/jobs/expandboundingvolumejob.cpp
index 641a5c272..8587634cb 100644
--- a/src/render/jobs/expandboundingvolumejob.cpp
+++ b/src/render/jobs/expandboundingvolumejob.cpp
@@ -84,7 +84,7 @@ ExpandBoundingVolumeJob::ExpandBoundingVolumeJob()
: m_node(nullptr)
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::ExpandBoundingVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::ExpandBoundingVolume, 0)
}
void ExpandBoundingVolumeJob::setRoot(Entity *root)
diff --git a/src/render/jobs/filterentitybycomponentjob_p.h b/src/render/jobs/filterentitybycomponentjob_p.h
index 75e487d7f..cefcdd296 100644
--- a/src/render/jobs/filterentitybycomponentjob_p.h
+++ b/src/render/jobs/filterentitybycomponentjob_p.h
@@ -74,7 +74,7 @@ public:
: Qt3DCore::QAspectJob()
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::EntityComponentTypeFiltering, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::EntityComponentTypeFiltering, 0)
}
inline void setManager(EntityManager *manager) Q_DECL_NOTHROW { m_manager = manager; }
diff --git a/src/render/jobs/filterlayerentityjob.cpp b/src/render/jobs/filterlayerentityjob.cpp
index e206ef968..032004422 100644
--- a/src/render/jobs/filterlayerentityjob.cpp
+++ b/src/render/jobs/filterlayerentityjob.cpp
@@ -58,7 +58,7 @@ FilterLayerEntityJob::FilterLayerEntityJob()
: Qt3DCore::QAspectJob()
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LayerFiltering, layerFilterJobCounter++);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LayerFiltering, layerFilterJobCounter++)
}
diff --git a/src/render/jobs/framecleanupjob.cpp b/src/render/jobs/framecleanupjob.cpp
index 17ca60bff..fb63f005b 100644
--- a/src/render/jobs/framecleanupjob.cpp
+++ b/src/render/jobs/framecleanupjob.cpp
@@ -55,7 +55,7 @@ FrameCleanupJob::FrameCleanupJob()
: m_managers(nullptr)
, m_root(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::FrameCleanup, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::FrameCleanup, 0)
}
FrameCleanupJob::~FrameCleanupJob()
diff --git a/src/render/jobs/frustumcullingjob.cpp b/src/render/jobs/frustumcullingjob.cpp
index 0922fb0cb..e22d625df 100644
--- a/src/render/jobs/frustumcullingjob.cpp
+++ b/src/render/jobs/frustumcullingjob.cpp
@@ -58,7 +58,7 @@ FrustumCullingJob::FrustumCullingJob()
, m_manager(nullptr)
, m_active(false)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::FrustumCulling, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::FrustumCulling, 0)
}
void FrustumCullingJob::run()
diff --git a/src/render/jobs/genericlambdajob_p.h b/src/render/jobs/genericlambdajob_p.h
index 4d93f0f8d..8cf4276f6 100644
--- a/src/render/jobs/genericlambdajob_p.h
+++ b/src/render/jobs/genericlambdajob_p.h
@@ -68,7 +68,7 @@ public:
: Qt3DCore::QAspectJob()
, m_callable(callable)
{
- SET_JOB_RUN_STAT_TYPE(this, type, 0);
+ SET_JOB_RUN_STAT_TYPE(this, type, 0)
}
// QAspectJob interface
@@ -111,7 +111,7 @@ public:
: Qt3DCore::QAspectJob(*new GenericLambdaJobAndPostFramePrivate<T, U>(postFrameCallable))
, m_runCallable(runCallable)
{
- SET_JOB_RUN_STAT_TYPE(this, type, 0);
+ SET_JOB_RUN_STAT_TYPE(this, type, 0)
}
// QAspectJob interface
diff --git a/src/render/jobs/lightgatherer.cpp b/src/render/jobs/lightgatherer.cpp
index f4c8dfba8..b79976aef 100644
--- a/src/render/jobs/lightgatherer.cpp
+++ b/src/render/jobs/lightgatherer.cpp
@@ -53,7 +53,7 @@ LightGatherer::LightGatherer()
, m_manager(nullptr)
, m_environmentLight(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LightGathering, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LightGathering, 0)
}
void LightGatherer::run()
diff --git a/src/render/jobs/loadbufferjob.cpp b/src/render/jobs/loadbufferjob.cpp
index c9cbb623d..0f4feb5d4 100644
--- a/src/render/jobs/loadbufferjob.cpp
+++ b/src/render/jobs/loadbufferjob.cpp
@@ -68,7 +68,7 @@ LoadBufferJob::LoadBufferJob(const HBuffer &handle)
, m_handle(handle)
, m_nodeManagers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadBuffer, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadBuffer, 0)
}
LoadBufferJob::~LoadBufferJob()
diff --git a/src/render/jobs/loadgeometryjob.cpp b/src/render/jobs/loadgeometryjob.cpp
index 88930038a..2069336cd 100644
--- a/src/render/jobs/loadgeometryjob.cpp
+++ b/src/render/jobs/loadgeometryjob.cpp
@@ -66,7 +66,7 @@ LoadGeometryJob::LoadGeometryJob(const HGeometryRenderer &handle)
, m_handle(handle)
, m_nodeManagers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadGeometry, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadGeometry, 0)
}
LoadGeometryJob::~LoadGeometryJob()
diff --git a/src/render/jobs/loadscenejob.cpp b/src/render/jobs/loadscenejob.cpp
index f858f82e3..be855c608 100644
--- a/src/render/jobs/loadscenejob.cpp
+++ b/src/render/jobs/loadscenejob.cpp
@@ -63,7 +63,7 @@ LoadSceneJob::LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId sceneComponent)
, m_sceneComponent(sceneComponent)
, m_managers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadScene, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadScene, 0)
}
void LoadSceneJob::setData(const QByteArray &data)
diff --git a/src/render/jobs/sendbuffercapturejob.cpp b/src/render/jobs/sendbuffercapturejob.cpp
index 3fa185684..2ccb72337 100644
--- a/src/render/jobs/sendbuffercapturejob.cpp
+++ b/src/render/jobs/sendbuffercapturejob.cpp
@@ -69,7 +69,7 @@ SendBufferCaptureJob::SendBufferCaptureJob()
: Qt3DCore::QAspectJob(*new SendBufferCaptureJobPrivate)
, m_nodeManagers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendBufferCapture, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendBufferCapture, 0)
}
SendBufferCaptureJob::~SendBufferCaptureJob()
diff --git a/src/render/jobs/sendrendercapturejob.cpp b/src/render/jobs/sendrendercapturejob.cpp
index f622c347a..46b1d9449 100644
--- a/src/render/jobs/sendrendercapturejob.cpp
+++ b/src/render/jobs/sendrendercapturejob.cpp
@@ -51,7 +51,7 @@ SendRenderCaptureJob::SendRenderCaptureJob()
: Qt3DCore::QAspectJob()
, m_managers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendRenderCapture, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendRenderCapture, 0)
}
SendRenderCaptureJob::~SendRenderCaptureJob()
diff --git a/src/render/jobs/updateentitylayersjob.cpp b/src/render/jobs/updateentitylayersjob.cpp
index 2c5e38364..b8c50c179 100644
--- a/src/render/jobs/updateentitylayersjob.cpp
+++ b/src/render/jobs/updateentitylayersjob.cpp
@@ -52,7 +52,7 @@ namespace Render {
UpdateEntityLayersJob::UpdateEntityLayersJob()
: m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLayerEntity, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLayerEntity, 0)
}
diff --git a/src/render/jobs/updatemeshtrianglelistjob.cpp b/src/render/jobs/updatemeshtrianglelistjob.cpp
index 1c61d1c90..4837dcad6 100644
--- a/src/render/jobs/updatemeshtrianglelistjob.cpp
+++ b/src/render/jobs/updatemeshtrianglelistjob.cpp
@@ -60,7 +60,7 @@ namespace Render {
UpdateMeshTriangleListJob::UpdateMeshTriangleListJob()
: m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateMeshTriangleList, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateMeshTriangleList, 0)
}
UpdateMeshTriangleListJob::~UpdateMeshTriangleListJob()
diff --git a/src/render/jobs/updateshaderdatatransformjob.cpp b/src/render/jobs/updateshaderdatatransformjob.cpp
index c29a827e3..11fe91932 100644
--- a/src/render/jobs/updateshaderdatatransformjob.cpp
+++ b/src/render/jobs/updateshaderdatatransformjob.cpp
@@ -61,7 +61,7 @@ namespace Render {
UpdateShaderDataTransformJob::UpdateShaderDataTransformJob()
: m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateShaderDataTransform, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateShaderDataTransform, 0)
}
UpdateShaderDataTransformJob::~UpdateShaderDataTransformJob()
diff --git a/src/render/jobs/updateskinningpalettejob.cpp b/src/render/jobs/updateskinningpalettejob.cpp
index 0f5d3d6d6..b77707f15 100644
--- a/src/render/jobs/updateskinningpalettejob.cpp
+++ b/src/render/jobs/updateskinningpalettejob.cpp
@@ -50,7 +50,7 @@ UpdateSkinningPaletteJob::UpdateSkinningPaletteJob()
, m_nodeManagers(nullptr)
, m_root()
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateSkinningPalette, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateSkinningPalette, 0)
}
UpdateSkinningPaletteJob::~UpdateSkinningPaletteJob()
diff --git a/src/render/jobs/updatetreeenabledjob.cpp b/src/render/jobs/updatetreeenabledjob.cpp
index 5c6f2b378..22d6f6083 100644
--- a/src/render/jobs/updatetreeenabledjob.cpp
+++ b/src/render/jobs/updatetreeenabledjob.cpp
@@ -73,7 +73,7 @@ UpdateTreeEnabledJob::UpdateTreeEnabledJob()
, m_node(nullptr)
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateTreeEnabled, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateTreeEnabled, 0)
}
void UpdateTreeEnabledJob::setRoot(Entity *root)
diff --git a/src/render/jobs/updateworldtransformjob.cpp b/src/render/jobs/updateworldtransformjob.cpp
index d72c0a3a8..e3c8077f4 100644
--- a/src/render/jobs/updateworldtransformjob.cpp
+++ b/src/render/jobs/updateworldtransformjob.cpp
@@ -109,7 +109,7 @@ UpdateWorldTransformJob::UpdateWorldTransformJob()
, m_node(nullptr)
, m_manager(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateTransform, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateTransform, 0)
}
void UpdateWorldTransformJob::setRoot(Entity *root)
diff --git a/src/render/renderers/opengl/jobs/filtercompatibletechniquejob.cpp b/src/render/renderers/opengl/jobs/filtercompatibletechniquejob.cpp
index 342fd3dad..d2a01eef4 100644
--- a/src/render/renderers/opengl/jobs/filtercompatibletechniquejob.cpp
+++ b/src/render/renderers/opengl/jobs/filtercompatibletechniquejob.cpp
@@ -53,7 +53,7 @@ FilterCompatibleTechniqueJob::FilterCompatibleTechniqueJob()
: m_manager(nullptr)
, m_renderer(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::FilterCompatibleTechniques, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::FilterCompatibleTechniques, 0)
}
void FilterCompatibleTechniqueJob::setManager(TechniqueManager *manager)
diff --git a/src/render/renderers/opengl/jobs/materialparametergathererjob.cpp b/src/render/renderers/opengl/jobs/materialparametergathererjob.cpp
index 5e56e817f..e1f8aa403 100644
--- a/src/render/renderers/opengl/jobs/materialparametergathererjob.cpp
+++ b/src/render/renderers/opengl/jobs/materialparametergathererjob.cpp
@@ -63,7 +63,7 @@ MaterialParameterGathererJob::MaterialParameterGathererJob()
, m_techniqueFilter(nullptr)
, m_renderPassFilter(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::MaterialParameterGathering, materialParameterGathererCounter++);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::MaterialParameterGathering, materialParameterGathererCounter++)
}
// TechniqueFilter / RenderPassFilter
diff --git a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
index 6d6ae7853..5fc2395d3 100644
--- a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
@@ -60,7 +60,7 @@ RenderViewCommandUpdaterJob::RenderViewCommandUpdaterJob()
, m_renderer(nullptr)
, m_renderables(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderCommandUpdater, renderViewInstanceCounter++);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderCommandUpdater, renderViewInstanceCounter++)
}
void RenderViewCommandUpdaterJob::run()
diff --git a/src/render/renderers/opengl/jobs/renderviewinitializerjob.cpp b/src/render/renderers/opengl/jobs/renderviewinitializerjob.cpp
index 7bf55be40..f0f72803c 100644
--- a/src/render/renderers/opengl/jobs/renderviewinitializerjob.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewinitializerjob.cpp
@@ -65,7 +65,7 @@ RenderViewInitializerJob::RenderViewInitializerJob()
, m_index(0)
, m_renderView(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderView, renderViewInstanceCounter++);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderView, renderViewInstanceCounter++)
}
RenderViewInitializerJob::~RenderViewInitializerJob()
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index 3ab5be6cc..df2517018 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -99,6 +99,8 @@
#include <Qt3DCore/private/qeventfilterservice_p.h>
#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p.h>
+#include <Qt3DCore/private/qsysteminformationservice_p_p.h>
#if QT_CONFIG(qt3d_profile_jobs)
#include <Qt3DCore/private/aspectcommanddebugger_p.h>
@@ -752,19 +754,12 @@ void Renderer::doRender(bool swapBuffers)
// RenderQueue is complete (but that means it may be of size 0)
if (canSubmit && (queueIsComplete && !queueIsEmpty)) {
const QVector<Render::RenderView *> renderViews = m_renderQueue->nextFrameQueue();
-
-#if QT_CONFIG(qt3d_profile_jobs)
- // Save start of frame
- JobRunStats submissionStatsPart1;
- JobRunStats submissionStatsPart2;
- submissionStatsPart1.jobId.typeAndInstance[0] = JobTypes::FrameSubmissionPart1;
- submissionStatsPart1.jobId.typeAndInstance[1] = 0;
- submissionStatsPart1.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
- submissionStatsPart1.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- submissionStatsPart2.jobId.typeAndInstance[0] = JobTypes::FrameSubmissionPart2;
- submissionStatsPart2.jobId.typeAndInstance[1] = 0;
- submissionStatsPart2.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
-#endif
+ QTaskLogger submissionStatsPart1(m_services->systemInformation(),
+ {JobTypes::FrameSubmissionPart1, 0},
+ QTaskLogger::Submission);
+ QTaskLogger submissionStatsPart2(m_services->systemInformation(),
+ {JobTypes::FrameSubmissionPart2, 0},
+ QTaskLogger::Submission);
if (canRender()) {
{ // Scoped to destroy surfaceLock
@@ -797,15 +792,11 @@ void Renderer::doRender(bool swapBuffers)
m_vsyncFrameAdvanceService->proceedToNextFrame();
hasCleanedQueueAndProceeded = true;
-#if QT_CONFIG(qt3d_profile_jobs)
- if (preprocessingComplete) {
- submissionStatsPart2.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- submissionStatsPart1.endTime = submissionStatsPart2.startTime;
- }
-#endif
// Only try to submit the RenderViews if the preprocessing was successful
// This part of the submission is happening in parallel to the RV building for the next frame
if (preprocessingComplete) {
+ submissionStatsPart1.end(submissionStatsPart2.restart());
+
// 3) Submit the render commands for frame n (making sure we never reference something that could be changing)
// Render using current device state and renderer configuration
submissionData = submitRenderViews(renderViews);
@@ -823,25 +814,12 @@ void Renderer::doRender(bool swapBuffers)
// Delete all the RenderViews which will clear the allocators
// that were used for their allocation
qDeleteAll(renderViews);
-
-#if QT_CONFIG(qt3d_profile_jobs)
- if (preprocessingComplete) {
- // Save submission elapsed time
- submissionStatsPart2.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- // Note this is safe since proceedToNextFrame is the one going to trigger
- // the write to the file, and this is performed after this step
- Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(submissionStatsPart1);
- Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(submissionStatsPart2);
- Profiling::GLTimeRecorder::writeResults();
- }
-#endif
}
// If hasCleanedQueueAndProceeded isn't true this implies that something went wrong
// with the rendering and/or the renderqueue is incomplete from some reason
// or alternatively it could be complete but empty (RenderQueue of size 0)
-
if (!hasCleanedQueueAndProceeded) {
// RenderQueue was full but something bad happened when
// trying to render it and therefore proceedToNextFrame was not called
diff --git a/tests/auto/core/qservicelocator/tst_qservicelocator.cpp b/tests/auto/core/qservicelocator/tst_qservicelocator.cpp
index cde9834b4..04e6881aa 100644
--- a/tests/auto/core/qservicelocator/tst_qservicelocator.cpp
+++ b/tests/auto/core/qservicelocator/tst_qservicelocator.cpp
@@ -54,9 +54,6 @@ public:
DummySystemInfoService()
: QSystemInformationService(QStringLiteral("Dummy System Information Service"))
{}
-
- QStringList aspectNames() const final { return QStringList(); }
- int threadPoolThreadCount() const final { return 4; }
};
@@ -90,8 +87,8 @@ void tst_QServiceLocator::defaultServices()
QSystemInformationService *sysInfo = locator.systemInformation();
QVERIFY(sysInfo != nullptr);
- QVERIFY(sysInfo->description() == QStringLiteral("Null System Information Service"));
- QVERIFY(sysInfo->threadPoolThreadCount() == 0);
+ QVERIFY(sysInfo->description() == QStringLiteral("Default System Information Service"));
+ QVERIFY(sysInfo->threadPoolThreadCount() != 0);
}
void tst_QServiceLocator::addRemoveDefaultService()
@@ -105,7 +102,6 @@ void tst_QServiceLocator::addRemoveDefaultService()
// Get the service from the locator and check it works as expected
QSystemInformationService *service = locator.systemInformation();
QVERIFY(service == dummy.data());
- QVERIFY(service->threadPoolThreadCount() == 4);
// Ensure the other default services work
QOpenGLInformationService *glInfo = locator.openGLInformation();
@@ -118,7 +114,7 @@ void tst_QServiceLocator::addRemoveDefaultService()
QVERIFY(locator.serviceCount() == QServiceLocator::DefaultServiceCount);
// Check the dummy service still exists
- QVERIFY(dummy->threadPoolThreadCount() == 4);
+ QVERIFY(!dummy.isNull());
}
void tst_QServiceLocator::addRemoveUserService()
@@ -138,8 +134,8 @@ void tst_QServiceLocator::addRemoveUserService()
// Ensure the default services work
QSystemInformationService *sysInfo = locator.systemInformation();
QVERIFY(sysInfo != nullptr);
- QVERIFY(sysInfo->description() == QStringLiteral("Null System Information Service"));
- QVERIFY(sysInfo->threadPoolThreadCount() == 0);
+ QVERIFY(sysInfo->description() == QStringLiteral("Default System Information Service"));
+ QVERIFY(sysInfo->threadPoolThreadCount() != 0);
// Remove custom service
locator.unregisterServiceProvider(dummy->type());
diff --git a/tests/auto/core/threadpooler/tst_threadpooler.cpp b/tests/auto/core/threadpooler/tst_threadpooler.cpp
index cfe3480ee..289f0b103 100644
--- a/tests/auto/core/threadpooler/tst_threadpooler.cpp
+++ b/tests/auto/core/threadpooler/tst_threadpooler.cpp
@@ -182,7 +182,7 @@ void massTestFunction(QVector3D *data)
void tst_ThreadPooler::initTestCase()
{
- m_jobManager = new JobManager(this);
+ m_jobManager = new JobManager(nullptr);
}
void tst_ThreadPooler::cleanupTestCase()