summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--src/plugins/renderers/opengl/debug/imguirenderer.cpp5
-rw-r--r--src/plugins/renderers/opengl/renderer/renderer.cpp28
-rw-r--r--src/plugins/renderers/opengl/renderer/renderer_p.h2
-rw-r--r--src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp16
-rw-r--r--src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h2
-rw-r--r--src/render/jobs/genericlambdajob_p.h8
-rw-r--r--tests/auto/core/qscheduler/tst_qscheduler.cpp2
14 files changed, 102 insertions, 32 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;
diff --git a/src/plugins/renderers/opengl/debug/imguirenderer.cpp b/src/plugins/renderers/opengl/debug/imguirenderer.cpp
index 449ec65b0..687f5e4fc 100644
--- a/src/plugins/renderers/opengl/debug/imguirenderer.cpp
+++ b/src/plugins/renderers/opengl/debug/imguirenderer.cpp
@@ -289,7 +289,10 @@ void ImGuiRenderer::renderDebugOverlay(const QVector<RenderView *> &renderViews,
if (ImGui::Button("FrameGraph Paths##1"))
QMetaObject::invokeMethod(m_renderer->services()->systemInformation(), "dumpCommand",
Qt::QueuedConnection, Q_ARG(QString, QLatin1String("render framepaths")));
-
+ ImGui::SameLine();
+ if (ImGui::Button("JobsGraph##1"))
+ QMetaObject::invokeMethod(m_renderer->services()->systemInformation(), "dumpCommand",
+ Qt::QueuedConnection, Q_ARG(QString, QLatin1String("dump jobs")));
ImGui::End();
if (m_showGLInfoWindow)
diff --git a/src/plugins/renderers/opengl/renderer/renderer.cpp b/src/plugins/renderers/opengl/renderer/renderer.cpp
index e385a264e..ddff21a96 100644
--- a/src/plugins/renderers/opengl/renderer/renderer.cpp
+++ b/src/plugins/renderers/opengl/renderer/renderer.cpp
@@ -266,20 +266,20 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_lightGathererJob(Render::LightGathererPtr::create())
, m_renderableEntityFilterJob(Render::RenderableEntityFilterPtr::create())
, m_computableEntityFilterJob(Render::ComputableEntityFilterPtr::create())
- , m_bufferGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
- , m_vaoGathererJob(SynchronizerJobPtr::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
- , m_textureGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
- , m_sendSetFenceHandlesToFrontendJob(SynchronizerJobPtr::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
- , m_introspectShaderJob(SynchronizerPostFramePtr::create([this] { reloadDirtyShaders(); },
- [this] (Qt3DCore::QAspectManager *m) { sendShaderChangesToFrontend(m); },
- JobTypes::DirtyShaderGathering))
- , m_syncLoadingJobs(SynchronizerJobPtr::create([] {}, JobTypes::SyncLoadingJobs))
- , m_cacheRenderableEntitiesJob(SynchronizerJobPtr::create(SyncRenderableEntities(m_renderableEntityFilterJob, &m_cache),
- JobTypes::EntityComponentTypeFiltering))
- , m_cacheComputableEntitiesJob(SynchronizerJobPtr::create(SyncComputableEntities(m_computableEntityFilterJob, &m_cache),
- JobTypes::EntityComponentTypeFiltering))
- , m_cacheLightsJob(SynchronizerJobPtr::create(SyncLightsGatherer(m_lightGathererJob, &m_cache),
- JobTypes::EntityComponentTypeFiltering))
+ , m_bufferGathererJob(CreateSynchronizerJobPtr([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
+ , m_vaoGathererJob(CreateSynchronizerJobPtr([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
+ , m_textureGathererJob(CreateSynchronizerJobPtr([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
+ , m_sendSetFenceHandlesToFrontendJob(CreateSynchronizerJobPtr([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
+ , m_introspectShaderJob(CreateSynchronizerPostFramePtr([this] { reloadDirtyShaders(); },
+ [this] (Qt3DCore::QAspectManager *m) { sendShaderChangesToFrontend(m); },
+ JobTypes::DirtyShaderGathering))
+ , m_syncLoadingJobs(CreateSynchronizerJobPtr([] {}, JobTypes::SyncLoadingJobs))
+ , m_cacheRenderableEntitiesJob(CreateSynchronizerJobPtr(SyncRenderableEntities(m_renderableEntityFilterJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
+ , m_cacheComputableEntitiesJob(CreateSynchronizerJobPtr(SyncComputableEntities(m_computableEntityFilterJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
+ , m_cacheLightsJob(CreateSynchronizerJobPtr(SyncLightsGatherer(m_lightGathererJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
, m_ownedContext(false)
, m_offscreenHelper(nullptr)
, m_glResourceManagers(nullptr)
diff --git a/src/plugins/renderers/opengl/renderer/renderer_p.h b/src/plugins/renderers/opengl/renderer/renderer_p.h
index aa3b26961..cf76e1b8a 100644
--- a/src/plugins/renderers/opengl/renderer/renderer_p.h
+++ b/src/plugins/renderers/opengl/renderer/renderer_p.h
@@ -165,6 +165,8 @@ using RenderableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::Geometry
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
using SynchronizerPostFramePtr = GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>>;
+#define CreateSynchronizerPostFramePtr(lambda, postlambda, type) \
+ SynchronizerPostFramePtr::create(lambda, postlambda, type, #type)
namespace Debug {
class ImGuiRenderer;
diff --git a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp
index 1e16209c6..a80fbe445 100644
--- a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp
+++ b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp
@@ -463,8 +463,8 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende
, m_renderViewJob(RenderViewInitializerJobPtr::create())
, m_filterEntityByLayerJob()
, m_frustumCullingJob(new Render::FrustumCullingJob())
- , m_syncPreFrustumCullingJob(SynchronizerJobPtr::create(SyncPreFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling))
- , m_setClearDrawBufferIndexJob(SynchronizerJobPtr::create(SetClearDrawBufferIndex(m_renderViewJob), JobTypes::ClearBufferDrawIndex))
+ , m_syncPreFrustumCullingJob(CreateSynchronizerJobPtr(SyncPreFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling))
+ , m_setClearDrawBufferIndexJob(CreateSynchronizerJobPtr(SetClearDrawBufferIndex(m_renderViewJob), JobTypes::ClearBufferDrawIndex))
, m_syncFilterEntityByLayerJob()
, m_filterProximityJob(Render::FilterProximityDistanceJobPtr::create())
{
@@ -558,7 +558,7 @@ void RenderViewBuilder::prepareJobs()
auto renderViewCommandBuilder = Render::OpenGL::RenderViewCommandBuilderJobPtr::create();
m_renderViewCommandBuilderJobs.push_back(renderViewCommandBuilder);
}
- m_syncRenderViewPreCommandBuildingJob = SynchronizerJobPtr::create(SyncPreCommandBuilding(m_renderViewJob,
+ m_syncRenderViewPreCommandBuildingJob = CreateSynchronizerJobPtr(SyncPreCommandBuilding(m_renderViewJob,
m_renderViewCommandBuilderJobs,
m_renderer,
m_leafNode),
@@ -593,7 +593,7 @@ void RenderViewBuilder::prepareJobs()
materialGatherer->setHandles(materialHandles.mid(i * elementsPerJob, elementsPerJob));
m_materialGathererJobs.push_back(materialGatherer);
}
- m_syncMaterialGathererJob = SynchronizerJobPtr::create(SyncMaterialParameterGatherer(m_materialGathererJobs,
+ m_syncMaterialGathererJob = CreateSynchronizerJobPtr(SyncMaterialParameterGatherer(m_materialGathererJobs,
m_renderer,
m_leafNode),
JobTypes::SyncMaterialGatherer);
@@ -602,13 +602,13 @@ void RenderViewBuilder::prepareJobs()
if (m_layerCacheNeedsToBeRebuilt) {
m_filterEntityByLayerJob = Render::FilterLayerEntityJobPtr::create();
m_filterEntityByLayerJob->setManager(m_renderer->nodeManagers());
- m_syncFilterEntityByLayerJob = SynchronizerJobPtr::create(SyncFilterEntityByLayer(m_filterEntityByLayerJob,
+ m_syncFilterEntityByLayerJob = CreateSynchronizerJobPtr(SyncFilterEntityByLayer(m_filterEntityByLayerJob,
m_renderer,
m_leafNode),
JobTypes::SyncFilterEntityByLayer);
}
- m_syncRenderViewPreCommandUpdateJob = SynchronizerJobPtr::create(SyncRenderViewPreCommandUpdate(m_renderViewJob,
+ m_syncRenderViewPreCommandUpdateJob = CreateSynchronizerJobPtr(SyncRenderViewPreCommandUpdate(m_renderViewJob,
m_frustumCullingJob,
m_filterProximityJob,
m_materialGathererJobs,
@@ -619,12 +619,12 @@ void RenderViewBuilder::prepareJobs()
m_renderCommandCacheNeedsToBeRebuilt),
JobTypes::SyncRenderViewPreCommandUpdate);
- m_syncRenderViewPostCommandUpdateJob = SynchronizerJobPtr::create(SyncRenderViewPostCommandUpdate(m_renderViewJob,
+ m_syncRenderViewPostCommandUpdateJob = CreateSynchronizerJobPtr(SyncRenderViewPostCommandUpdate(m_renderViewJob,
m_renderViewCommandUpdaterJobs,
m_renderer),
JobTypes::SyncRenderViewPostCommandUpdate);
- m_syncRenderViewPostInitializationJob = SynchronizerJobPtr::create(SyncRenderViewPostInitialization(m_renderViewJob,
+ m_syncRenderViewPostInitializationJob = CreateSynchronizerJobPtr(SyncRenderViewPostInitialization(m_renderViewJob,
m_frustumCullingJob,
m_filterEntityByLayerJob,
m_filterProximityJob,
diff --git a/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h b/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h
index 98202670e..54fc98352 100644
--- a/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h
+++ b/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h
@@ -75,6 +75,8 @@ namespace OpenGL {
class Renderer;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
+#define CreateSynchronizerJobPtr(lambda, type) \
+ SynchronizerJobPtr::create(lambda, type, #type)
class Q_AUTOTEST_EXPORT RenderViewBuilder
{
diff --git a/src/render/jobs/genericlambdajob_p.h b/src/render/jobs/genericlambdajob_p.h
index 8cf4276f6..994cd3a14 100644
--- a/src/render/jobs/genericlambdajob_p.h
+++ b/src/render/jobs/genericlambdajob_p.h
@@ -64,11 +64,11 @@ template<typename T>
class GenericLambdaJob : public Qt3DCore::QAspectJob
{
public:
- explicit GenericLambdaJob(T callable, JobTypes::JobType type = JobTypes::GenericLambda)
+ explicit GenericLambdaJob(T callable, JobTypes::JobType type = JobTypes::GenericLambda, const char *name = "GenericLambda")
: Qt3DCore::QAspectJob()
, m_callable(callable)
{
- SET_JOB_RUN_STAT_TYPE(this, type, 0)
+ SET_JOB_RUN_STAT_TYPE_AND_NAME(this, type, name, 0)
}
// QAspectJob interface
@@ -107,11 +107,11 @@ template<typename T, typename U>
class GenericLambdaJobAndPostFrame : public Qt3DCore::QAspectJob
{
public:
- explicit GenericLambdaJobAndPostFrame(T runCallable, U postFrameCallable, JobTypes::JobType type = JobTypes::GenericLambda)
+ explicit GenericLambdaJobAndPostFrame(T runCallable, U postFrameCallable, JobTypes::JobType type = JobTypes::GenericLambda, const char *name = "GenericLambda")
: Qt3DCore::QAspectJob(*new GenericLambdaJobAndPostFramePrivate<T, U>(postFrameCallable))
, m_runCallable(runCallable)
{
- SET_JOB_RUN_STAT_TYPE(this, type, 0)
+ SET_JOB_RUN_STAT_TYPE_AND_NAME(this, type, name, 0)
}
// QAspectJob interface
diff --git a/tests/auto/core/qscheduler/tst_qscheduler.cpp b/tests/auto/core/qscheduler/tst_qscheduler.cpp
index d1afb5aac..5d858a77a 100644
--- a/tests/auto/core/qscheduler/tst_qscheduler.cpp
+++ b/tests/auto/core/qscheduler/tst_qscheduler.cpp
@@ -181,7 +181,7 @@ private Q_SLOTS:
QVERIFY(!second->postFrameCalled());
// WHEN
- const int count = scheduler.scheduleAndWaitForFrameAspectJobs(0);
+ const int count = scheduler.scheduleAndWaitForFrameAspectJobs(0, false);
// THEN
QCOMPARE(count, 2);