summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2020-02-13 17:14:49 +0000
committerMike Krus <mike.krus@kdab.com>2020-02-14 11:00:11 +0000
commit90d5218564ceff5b4479c2679a1914227299b168 (patch)
tree1aa005074fcbbba7356a5768299c1db935e10d88 /src/core
parentd967a6369c967d9a1c7f740cfc5c962b8664c9eb (diff)
Add ability to dump job graph to dot file
Can be triggered from the overlay API and using sending a "dump jobs" command to the aspect engine. Gets saved in the current working directory. Change-Id: I19fc94a1215187c1d7eb9d1f3b13b968939cc917 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/aspects/qaspectengine.cpp4
-rw-r--r--src/core/aspects/qaspectmanager.cpp9
-rw-r--r--src/core/aspects/qaspectmanager_p.h2
-rw-r--r--src/core/jobs/qaspectjob.cpp1
-rw-r--r--src/core/jobs/qaspectjob_p.h14
-rw-r--r--src/core/qscheduler.cpp39
-rw-r--r--src/core/qscheduler_p.h2
7 files changed, 67 insertions, 4 deletions
diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp
index d28306197..e52435eed 100644
--- a/src/core/aspects/qaspectengine.cpp
+++ b/src/core/aspects/qaspectengine.cpp
@@ -412,6 +412,10 @@ QVariant QAspectEngine::executeCommand(const QString &command)
const QStringList names = d->m_aspectManager->serviceLocator()->systemInformation()->aspectNames();
return names.join(QLatin1String("\n"));
}
+ if (command == QLatin1String("dump jobs")) {
+ d->m_aspectManager->dumpJobsOnNextFrame();
+ return QLatin1String("Dump in next frame in working directory");
+ }
QStringList args = command.split(QLatin1Char(' '));
QString aspectName = args.takeFirst();
diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp
index f0dc366b2..66475c615 100644
--- a/src/core/aspects/qaspectmanager.cpp
+++ b/src/core/aspects/qaspectmanager.cpp
@@ -128,6 +128,7 @@ QAspectManager::QAspectManager(QAspectEngine *parent)
, m_simulationAnimation(nullptr)
#endif
, m_jobsInLastFrame(0)
+ , m_dumpJobs(false)
{
qRegisterMetaType<QSurface *>("QSurface*");
qCDebug(Aspects) << Q_FUNC_INFO;
@@ -434,6 +435,11 @@ QVector<QNode *> QAspectManager::lookupNodes(const QVector<QNodeId> &ids) const
return d->m_scene ? d->m_scene->lookupNodes(ids) : QVector<QNode *>{};
}
+void QAspectManager::dumpJobsOnNextFrame()
+{
+ m_dumpJobs = true;
+}
+
#if !QT_CONFIG(animation)
/*!
\internal
@@ -537,7 +543,8 @@ void QAspectManager::processFrame()
// For each Aspect
// Ask them to launch set of jobs for the current frame
// Updates matrices, bounding volumes, render bins ...
- m_jobsInLastFrame = m_scheduler->scheduleAndWaitForFrameAspectJobs(t);
+ m_jobsInLastFrame = m_scheduler->scheduleAndWaitForFrameAspectJobs(t, m_dumpJobs);
+ m_dumpJobs = false;
// Tell the aspect the frame is complete (except rendering)
for (QAbstractAspect *aspect : qAsConst(m_aspects))
diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h
index 2038e0822..e3d978ee2 100644
--- a/src/core/aspects/qaspectmanager_p.h
+++ b/src/core/aspects/qaspectmanager_p.h
@@ -116,6 +116,7 @@ public:
QVector<QNode *> lookupNodes(const QVector<QNodeId> &ids) const;
int jobsInLastFrame() const { return m_jobsInLastFrame; }
+ void dumpJobsOnNextFrame();
private:
#if !QT_CONFIG(animation)
@@ -140,6 +141,7 @@ private:
RequestFrameAnimation *m_simulationAnimation;
#endif
int m_jobsInLastFrame;
+ bool m_dumpJobs;
};
} // namespace Qt3DCore
diff --git a/src/core/jobs/qaspectjob.cpp b/src/core/jobs/qaspectjob.cpp
index 44efc2c0b..0a2ee9841 100644
--- a/src/core/jobs/qaspectjob.cpp
+++ b/src/core/jobs/qaspectjob.cpp
@@ -56,6 +56,7 @@ bool isDependencyNull(const QWeakPointer<QAspectJob> &dep)
} // anonymous
QAspectJobPrivate::QAspectJobPrivate()
+ : m_jobName(QLatin1String("UnknowJob"))
{
}
diff --git a/src/core/jobs/qaspectjob_p.h b/src/core/jobs/qaspectjob_p.h
index 5b72e64ee..63a2cc572 100644
--- a/src/core/jobs/qaspectjob_p.h
+++ b/src/core/jobs/qaspectjob_p.h
@@ -77,14 +77,26 @@ public:
QVector<QWeakPointer<QAspectJob> > m_dependencies;
JobId m_jobId;
+ QString m_jobName;
};
} // Qt3D
#define SET_JOB_RUN_STAT_TYPE(job, type, instance) \
{ \
- auto &jobId = Qt3DCore::QAspectJobPrivate::get(job)->m_jobId; \
+ auto djob = Qt3DCore::QAspectJobPrivate::get(job); \
+ auto &jobId = djob->m_jobId; \
jobId.typeAndInstance[0] = type; \
jobId.typeAndInstance[1] = instance; \
+ djob->m_jobName = QLatin1String(#type); \
+ }
+
+#define SET_JOB_RUN_STAT_TYPE_AND_NAME(job, type, name, instance) \
+ { \
+ auto djob = Qt3DCore::QAspectJobPrivate::get(job); \
+ auto &jobId = djob->m_jobId; \
+ jobId.typeAndInstance[0] = type; \
+ jobId.typeAndInstance[1] = instance; \
+ djob->m_jobName = QLatin1String(name); \
}
QT_END_NAMESPACE
diff --git a/src/core/qscheduler.cpp b/src/core/qscheduler.cpp
index 9ff8a54f3..872b3ccd6 100644
--- a/src/core/qscheduler.cpp
+++ b/src/core/qscheduler.cpp
@@ -46,8 +46,42 @@
#include <Qt3DCore/private/qaspectjob_p.h>
#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDateTime>
+#include <QtCore/QRegularExpression>
+
QT_BEGIN_NAMESPACE
+namespace {
+
+// Creates a graphviz dot file. To view online: https://dreampuf.github.io/GraphvizOnline/
+void dumpJobs(QVector<Qt3DCore::QAspectJobPtr> jobs) {
+ const QString fileName = QStringLiteral("qt3djobs_") + QCoreApplication::applicationName() +
+ QDateTime::currentDateTime().toString(QStringLiteral("_yyMMdd-hhmmss")) + QStringLiteral(".dot");
+
+ QFile f(fileName);
+ if (!f.open(QFile::WriteOnly))
+ return;
+
+ auto formatJob = [](Qt3DCore::QAspectJob *job) -> QString {
+ auto jobId = Qt3DCore::QAspectJobPrivate::get(job)->m_jobId;
+ auto type = Qt3DCore::QAspectJobPrivate::get(job)->m_jobName.replace(QRegularExpression(QLatin1String("(^.*::)")), QLatin1String(""));
+ return QString(QLatin1String("\"%1_%2\"")).arg(type).arg(jobId.typeAndInstance[1]);
+ };
+
+ QTextStream stream(&f);
+ stream << "digraph qt3d_jobs {" << Qt::endl;
+ for (const auto &job: jobs) {
+ auto dependencies = job->dependencies();
+ for (const auto &dependency: dependencies)
+ stream << QLatin1String("\t") << formatJob(job.data()) << QLatin1String(" -> ") << formatJob(dependency.toStrongRef().data()) << Qt::endl;
+ }
+
+ stream << "}" << Qt::endl;
+}
+
+}
+
namespace Qt3DCore {
QScheduler::QScheduler(QObject *parent)
@@ -70,7 +104,7 @@ QAspectManager *QScheduler::aspectManager() const
return m_aspectManager;
}
-int QScheduler::scheduleAndWaitForFrameAspectJobs(qint64 time)
+int QScheduler::scheduleAndWaitForFrameAspectJobs(qint64 time, bool dumpJobs)
{
QVector<QAspectJobPtr> jobQueue;
@@ -86,6 +120,9 @@ int QScheduler::scheduleAndWaitForFrameAspectJobs(qint64 time)
jobQueue << aspectJobs;
}
+ if (dumpJobs)
+ ::dumpJobs(jobQueue);
+
m_aspectManager->jobManager()->enqueueJobs(jobQueue);
// Do any other work here that the aspect thread can usefully be doing
diff --git a/src/core/qscheduler_p.h b/src/core/qscheduler_p.h
index 92e8e04fb..a781e1cbb 100644
--- a/src/core/qscheduler_p.h
+++ b/src/core/qscheduler_p.h
@@ -70,7 +70,7 @@ public:
void setAspectManager(QAspectManager *aspectManager);
QAspectManager *aspectManager() const;
- virtual int scheduleAndWaitForFrameAspectJobs(qint64 time);
+ virtual int scheduleAndWaitForFrameAspectJobs(qint64 time, bool dumpJobs);
private:
QAspectManager *m_aspectManager;