/**************************************************************************** ** ** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class TestAspect : public Qt3DRender::QRenderAspect { Q_OBJECT public: TestAspect(bool withWindow = false) : Qt3DRender::QRenderAspect(QRenderAspect::Synchronous) , m_jobManager(new Qt3DCore::QAspectJobManager()) { Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data(); if (!withWindow) { d_func()->m_renderer->createAllocators(m_jobManager.data()); } else { m_window.reset(new QWindow()); m_window->resize(1024, 768); QSurfaceFormat format; if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { format.setVersion(4, 3); format.setProfile(QSurfaceFormat::CoreProfile); } format.setDepthBufferSize( 24 ); format.setSamples( 4 ); format.setStencilBufferSize(8); m_window->setFormat(format); m_window->create(); QRenderAspect::onRegistered(); } } QVector worldTransformJob() { d_func()->m_worldTransformJob->setRoot(d_func()->m_renderer->sceneRoot()); return QVector() << d_func()->m_worldTransformJob; } QVector updateBoundingJob() { d_func()->m_updateBoundingVolumeJob->setRoot(d_func()->m_renderer->sceneRoot()); return QVector() << d_func()->m_updateBoundingVolumeJob; } QVector calculateBoundingVolumeJob() { d_func()->m_calculateBoundingVolumeJob->setRoot(d_func()->m_renderer->sceneRoot()); return QVector() << d_func()->m_calculateBoundingVolumeJob; } QVector framePreparationJob() { d_func()->m_framePreparationJob->setRoot(d_func()->m_renderer->sceneRoot()); return QVector() << d_func()->m_framePreparationJob; } QVector frameCleanupJob() { d_func()->m_cleanupJob->setRoot(d_func()->m_renderer->sceneRoot()); return QVector() << d_func()->m_cleanupJob; } QVector renderBinJobs() { return d_func()->m_renderer->renderBinJobs(); } void onRootEntityChanged(Qt3DCore::QEntity *root) { if (!m_window) { Qt3DCore::QNodeVisitor visitor; visitor.traverse(root, this, &TestAspect::visitNode); static_cast(d_func()->m_renderer)->m_renderSceneRoot = d_func()->m_renderer->nodeManagers() ->lookupResource(root->id()); } } void visitNode(Qt3DCore::QNode *node) { d_func()->createBackendNode(node); } private: QScopedPointer m_jobManager; QScopedPointer m_window; }; Qt3DCore::QEntity *loadFromQML(const QUrl &source) { QQmlEngine qmlEngine; QQmlComponent *component = new QQmlComponent(&qmlEngine, source); while (component->isLoading()) QThread::usleep(250); QObject *rootObj = component->create(); return qobject_cast(rootObj); } Qt3DCore::QEntity *buildBigScene() { Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); // Camera Qt3DRender::QCamera *cameraEntity = new Qt3DRender::QCamera(root); cameraEntity->setObjectName(QStringLiteral("cameraEntity")); cameraEntity->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f); cameraEntity->setPosition(QVector3D(0, -250.0f, -50.0f)); cameraEntity->setUpVector(QVector3D(0, 1, 0)); cameraEntity->setViewCenter(QVector3D(0, 0, 0)); // FrameGraph Qt3DRender::QRenderSettings* renderSettings = new Qt3DRender::QRenderSettings(); Qt3DRender::QForwardRenderer *forwardRenderer = new Qt3DRender::QForwardRenderer(); forwardRenderer->setCamera(cameraEntity); forwardRenderer->setClearColor(Qt::black); renderSettings->setActiveFrameGraph(forwardRenderer); root->addComponent(renderSettings); const float radius = 100.0f; const int max = 1000; const float det = 1.0f / max; // Scene for (int i = 0; i < max; i++) { Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(); Qt3DRender::QCylinderMesh *mesh = new Qt3DRender::QCylinderMesh(); Qt3DRender::QPhongMaterial *material = new Qt3DRender::QPhongMaterial(); mesh->setRings(50.0f); mesh->setSlices(30.0f); mesh->setRadius(2.5f); mesh->setLength(5.0f); const float angle = M_PI * 2.0f * i * det * 10.; material->setDiffuse(QColor(qFabs(qCos(angle)) * 255, 204, 75)); material->setAmbient(Qt::black); material->setSpecular(Qt::white); material->setShininess(150.0f); QMatrix4x4 m; m.translate(QVector3D(radius * qCos(angle), 200.* i * det, radius * qSin(angle))); m.rotate(30.0f * i, QVector3D(1.0f, 0.0f, 0.0f)); m.rotate(45.0f * i, QVector3D(0.0f, 0.0f, 1.0f)); transform->setMatrix(m); e->addComponent(transform); e->addComponent(mesh); e->addComponent(material); e->setParent(root); } return root; } class tst_benchJobs : public QObject { Q_OBJECT private: Qt3DCore::QEntity *m_bigSceneRoot; public: tst_benchJobs() : m_bigSceneRoot(buildBigScene()) {} private Q_SLOTS: void updateTransformJob_data() { QTest::addColumn("rootEntity"); QTest::newRow("bigscene") << m_bigSceneRoot; } void updateTransformJob() { // GIVEN QFETCH(Qt3DCore::QEntity*, rootEntity); TestAspect aspect; Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast(rootEntity), QVector()); // WHEN QVector jobs = aspect.worldTransformJob(); QBENCHMARK { Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->enqueueJobs(jobs); Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->waitForAllJobs(); } } void updateBoundingJob_data() { QTest::addColumn("rootEntity"); QTest::newRow("bigscene") << m_bigSceneRoot; } void updateBoundingJob() { // GIVEN QFETCH(Qt3DCore::QEntity*, rootEntity); TestAspect aspect; Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast(rootEntity), QVector()); // WHEN QVector jobs = aspect.updateBoundingJob(); QBENCHMARK { Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->enqueueJobs(jobs); Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->waitForAllJobs(); } } void calculateBoundingVolumeJob_data() { QTest::addColumn("rootEntity"); QTest::newRow("bigscene") << m_bigSceneRoot; } void calculateBoundingVolumeJob() { // GIVEN QFETCH(Qt3DCore::QEntity*, rootEntity); TestAspect aspect; Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast(rootEntity), QVector()); // WHEN QVector jobs = aspect.calculateBoundingVolumeJob(); QBENCHMARK { Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->enqueueJobs(jobs); Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->waitForAllJobs(); } } void framePreparationJob_data() { QTest::addColumn("rootEntity"); QTest::newRow("bigscene") << m_bigSceneRoot; } void framePreparationJob() { // GIVEN QFETCH(Qt3DCore::QEntity*, rootEntity); TestAspect aspect; Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast(rootEntity), QVector()); // WHEN QVector jobs = aspect.framePreparationJob(); QBENCHMARK { Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->enqueueJobs(jobs); Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->waitForAllJobs(); } } void frameCleanupJob_data() { QTest::addColumn("rootEntity"); QTest::newRow("bigscene") << m_bigSceneRoot; } void frameCleanupJob() { // GIVEN QFETCH(Qt3DCore::QEntity*, rootEntity); TestAspect aspect; Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast(rootEntity), QVector()); // WHEN QVector jobs = aspect.frameCleanupJob(); QBENCHMARK { Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->enqueueJobs(jobs); Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->waitForAllJobs(); } } /* Note: The renderer still needs to be simplified to run these jobs void renderBinJobs_data() { QTest::addColumn("rootEntity"); QTest::newRow("bigscene") << m_bigSceneRoot; } void renderBinJobs() { // GIVEN QFETCH(Qt3DCore::QEntity*, rootEntity); QScopedPointer aspectThread(new QThread); TestAspect aspect(true); aspect.moveToThread(aspectThread.data()); qDebug() << 1; Qt3DCore::QAbstractAspectPrivate::get(&aspect)->registerAspect(qobject_cast(rootEntity)); qDebug() << 2; // WHEN QVector jobs = aspect.renderBinJobs(); qDebug() << 3; QBENCHMARK { qDebug() << 4; Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->enqueueJobs(jobs); Qt3DCore::QAbstractAspectPrivate::get(&aspect)->jobManager()->waitForAllJobs(); } } */ }; QTEST_MAIN(tst_benchJobs) #include "tst_bench_jobs.moc"