1 | // Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qscheduler_p.h" |
5 | |
6 | #include <Qt3DCore/qabstractaspect.h> |
7 | |
8 | #include <Qt3DCore/private/qabstractaspect_p.h> |
9 | #include <Qt3DCore/private/qaspectmanager_p.h> |
10 | #include <Qt3DCore/private/qaspectjob_p.h> |
11 | #include <Qt3DCore/private/qabstractaspectjobmanager_p.h> |
12 | #include <Qt3DCore/private/vector_helper_p.h> |
13 | |
14 | #include <QtCore/QCoreApplication> |
15 | #include <QtCore/QDateTime> |
16 | #include <QtCore/QRegularExpression> |
17 | |
18 | QT_BEGIN_NAMESPACE |
19 | |
20 | namespace { |
21 | |
22 | // Creates a graphviz dot file. To view online: https://dreampuf.github.io/GraphvizOnline/ |
23 | void dumpJobs(const std::vector<Qt3DCore::QAspectJobPtr> &jobs) { |
24 | const QString fileName = QStringLiteral("qt3djobs_") + QCoreApplication::applicationName() + |
25 | QDateTime::currentDateTime().toString(QStringLiteral("_yyMMdd-hhmmss")) + QStringLiteral( ".dot"); |
26 | |
27 | QFile f(fileName); |
28 | if (!f.open(flags: QFile::WriteOnly)) |
29 | return; |
30 | |
31 | auto formatJob = [](Qt3DCore::QAspectJob *job) -> QString { |
32 | auto jobId = Qt3DCore::QAspectJobPrivate::get(job)->m_jobId; |
33 | auto type = Qt3DCore::QAspectJobPrivate::get(job)->m_jobName.replace(re: QRegularExpression(QLatin1String("(^.*::)")), after: QLatin1String( "")); |
34 | return QString(QLatin1String("\"%1_%2\"")).arg(a: type).arg(a: jobId.typeAndInstance[1]); |
35 | }; |
36 | |
37 | QTextStream stream(&f); |
38 | stream << "digraph qt3d_jobs {"<< Qt::endl; |
39 | |
40 | for (const auto &job: jobs) { |
41 | if (!Qt3DCore::QAspectJobPrivate::get(job: job.data())->isRequired()) |
42 | stream << QLatin1String("\t") << formatJob(job.data()) << QLatin1String( " [style=dotted]") << Qt::endl; |
43 | } |
44 | |
45 | for (const auto &job: jobs) { |
46 | auto dependencies = job->dependencies(); |
47 | for (const auto &dependency: dependencies) |
48 | stream << QLatin1String("\t") << formatJob(dependency.toStrongRef().data()) << QLatin1String( " -> ") << formatJob(job.data()) << Qt::endl; |
49 | } |
50 | |
51 | stream << "}"<< Qt::endl; |
52 | } |
53 | |
54 | } |
55 | |
56 | namespace Qt3DCore { |
57 | |
58 | QScheduler::QScheduler(QObject *parent) |
59 | : QObject(parent) |
60 | , m_aspectManager(nullptr) |
61 | { |
62 | } |
63 | |
64 | QScheduler::~QScheduler() |
65 | { |
66 | } |
67 | |
68 | void QScheduler::setAspectManager(QAspectManager *aspectManager) |
69 | { |
70 | m_aspectManager = aspectManager; |
71 | } |
72 | |
73 | QAspectManager *QScheduler::aspectManager() const |
74 | { |
75 | return m_aspectManager; |
76 | } |
77 | |
78 | int QScheduler::scheduleAndWaitForFrameAspectJobs(qint64 time, bool dumpJobs) |
79 | { |
80 | std::vector<QAspectJobPtr> jobQueue; |
81 | |
82 | // TODO: Allow clocks with custom scale factors and independent control |
83 | // over running / paused / stopped status |
84 | // TODO: Advance all clocks registered with the engine |
85 | |
86 | // TODO: Set up dependencies between jobs as needed |
87 | // For now just queue them up as they are |
88 | const QList<QAbstractAspect *> &aspects = m_aspectManager->aspects(); |
89 | for (QAbstractAspect *aspect : aspects) { |
90 | std::vector<QAspectJobPtr> aspectJobs = QAbstractAspectPrivate::get(aspect)->jobsToExecute(time); |
91 | Qt3DCore::moveAtEnd(destination&: jobQueue, source: std::move(aspectJobs)); |
92 | } |
93 | |
94 | if (jobQueue.empty()) |
95 | return 0; |
96 | |
97 | if (dumpJobs) |
98 | ::dumpJobs(jobs: jobQueue); |
99 | |
100 | m_aspectManager->jobManager()->enqueueJobs(jobQueue); |
101 | |
102 | // Do any other work here that the aspect thread can usefully be doing |
103 | // whilst the threadpool works its way through the jobs |
104 | |
105 | const int totalJobs = m_aspectManager->jobManager()->waitForAllJobs(); |
106 | |
107 | { |
108 | QTaskLogger logger(m_aspectManager->serviceLocator()->systemInformation(), 4097, 0, QTaskLogger::AspectJob); |
109 | |
110 | for (auto &job : std::as_const(t&: jobQueue)) |
111 | job->postFrame(aspectEngine: m_aspectManager->engine()); |
112 | |
113 | for (QAbstractAspect *aspect : aspects) |
114 | aspect->jobsDone(); |
115 | } |
116 | |
117 | return totalJobs; |
118 | } |
119 | |
120 | } // namespace Qt3DCore |
121 | |
122 | QT_END_NAMESPACE |
123 | |
124 | #include "moc_qscheduler_p.cpp" |
125 |