diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2019-04-25 15:27:11 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2019-04-26 07:14:12 +0200 |
commit | 06f41f15abaacc9f6f7acb8e51d2cfb68705a924 (patch) | |
tree | 210403f4bb9872940f8db4ab656238e9f14e1b98 /src/render | |
parent | 9b140ccba930f159443a70a81eb1d2585b6070f9 (diff) | |
parent | fed848f7dcff99cf5adb3b7b45190826b3dcf898 (diff) |
Merge remote-tracking branch 5.12 into 5.13
Change-Id: I42affdd02bddb5205b9f2455f0c5e5efbd414dd8
Diffstat (limited to 'src/render')
24 files changed, 498 insertions, 125 deletions
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h index ed6a06754..69e71dece 100644 --- a/src/render/backend/abstractrenderer_p.h +++ b/src/render/backend/abstractrenderer_p.h @@ -114,6 +114,8 @@ public: JointDirty = 1 << 11, LayersDirty = 1 << 12, TechniquesDirty = 1 << 13, + EntityHierarchyDirty= 1 << 14, + LightsDirty = 1 << 15, AllDirty = 0xffffff }; Q_DECLARE_FLAGS(BackendNodeDirtySet, BackendNodeDirtyFlag) diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index 8d03cd75f..d8d04aef1 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -65,8 +65,6 @@ #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qtransform.h> #include <Qt3DCore/private/qentity_p.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qnodecreatedchange.h> #include <QMatrix4x4> @@ -95,14 +93,13 @@ Entity::~Entity() void Entity::cleanup() { if (m_nodeManagers != nullptr) { - Entity *parentEntity = parent(); - if (parentEntity != nullptr) - parentEntity->removeChildHandle(m_handle); m_nodeManagers->worldMatrixManager()->releaseResource(peerId()); - qCDebug(Render::RenderNodes) << Q_FUNC_INFO; - } + if (!m_parentEntityId.isNull()) + markDirty(AbstractRenderer::EntityHierarchyDirty); + + m_parentEntityId = Qt3DCore::QNodeId(); m_worldTransform = HMatrix(); // Release all component will have to perform their own release when they receive the // NodeDeleted notification @@ -132,12 +129,8 @@ void Entity::cleanup() void Entity::setParentHandle(HEntity parentHandle) { Q_ASSERT(m_nodeManagers); - // Remove ourselves from previous parent children list - Entity *parent = m_nodeManagers->renderNodesManager()->data(parentHandle); - if (parent != nullptr && parent->m_childrenHandles.contains(m_handle)) - parent->m_childrenHandles.removeAll(m_handle); m_parentHandle = parentHandle; - parent = m_nodeManagers->renderNodesManager()->data(parentHandle); + auto parent = m_nodeManagers->renderNodesManager()->data(parentHandle); if (parent != nullptr && !parent->m_childrenHandles.contains(m_handle)) parent->m_childrenHandles.append(m_handle); } @@ -159,8 +152,8 @@ void Entity::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) // Note this is *not* the parentId as that is the ID of the parent QNode, which is not // necessarily the same as the parent QEntity (which may be further up the tree). - const QNodeId parentEntityId = data.parentEntityId; - qCDebug(Render::RenderNodes) << "Creating Entity id =" << peerId() << "parentId =" << parentEntityId; + m_parentEntityId = data.parentEntityId; + qCDebug(Render::RenderNodes) << "Creating Entity id =" << peerId() << "parentId =" << m_parentEntityId; // TODO: Store string id instead and only in debug mode //m_objectName = peer->objectName(); @@ -187,10 +180,7 @@ void Entity::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) for (const auto &idAndType : qAsConst(data.componentIdsAndTypes)) addComponent(idAndType); - if (!parentEntityId.isNull()) - setParentHandle(m_nodeManagers->renderNodesManager()->lookupHandle(parentEntityId)); - else - qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "No parent entity found for Entity" << peerId(); + markDirty(AbstractRenderer::EntityHierarchyDirty); } void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) @@ -214,30 +204,21 @@ void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) break; } - case PropertyValueAdded: { - QPropertyNodeAddedChangePtr change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->metaObject()->inherits(&QEntity::staticMetaObject)) { - appendChildHandle(m_nodeManagers->renderNodesManager()->lookupHandle(change->addedNodeId())); - markDirty(AbstractRenderer::AllDirty); - } - break; - } - - case PropertyValueRemoved: { - QPropertyNodeRemovedChangePtr change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->metaObject()->inherits(&QEntity::staticMetaObject)) { - removeChildHandle(m_nodeManagers->renderNodesManager()->lookupHandle(change->removedNodeId())); - markDirty(AbstractRenderer::AllDirty); - } - break; - } - case PropertyUpdated: { QPropertyUpdatedChangePtr change = qSharedPointerCast<QPropertyUpdatedChange>(e); if (change->propertyName() == QByteArrayLiteral("enabled")) { // We only mark as dirty the renderer markDirty(AbstractRenderer::EntityEnabledDirty); // We let QBackendNode::sceneChangeEvent change the enabled property + } else if (change->propertyName() == QByteArrayLiteral("parentEntityUpdated")) { + auto newParent = change->value().value<Qt3DCore::QNodeId>(); + qCDebug(Render::RenderNodes) << "Setting parent for " << peerId() << ", new parentId =" << newParent; + if (m_parentEntityId != newParent) { + m_parentEntityId = newParent; + // TODO: change to EventHierarchyDirty and update renderer to + // ensure all jobs are run that depend on Entity hierarchy. + markDirty(AbstractRenderer::AllDirty); + } } break; @@ -265,6 +246,27 @@ Entity *Entity::parent() const return m_nodeManagers->renderNodesManager()->data(m_parentHandle); } + +// clearEntityHierarchy and rebuildEntityHierarchy should only be called +// from UpdateEntityHierarchyJob to update the entity hierarchy for the +// entire scene at once +void Entity::clearEntityHierarchy() +{ + m_childrenHandles.clear(); + m_parentHandle = HEntity(); +} + +// clearEntityHierarchy and rebuildEntityHierarchy should only be called +// from UpdateEntityHierarchyJob to update the entity hierarchy for the +// entire scene at once +void Entity::rebuildEntityHierarchy() +{ + if (!m_parentEntityId.isNull()) + setParentHandle(m_nodeManagers->renderNodesManager()->lookupHandle(m_parentEntityId)); + else + qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "No parent entity found for Entity" << peerId(); +} + void Entity::appendChildHandle(HEntity childHandle) { if (!m_childrenHandles.contains(childHandle)) { diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h index 149ac1143..c170fd42d 100644 --- a/src/render/backend/entity_p.h +++ b/src/render/backend/entity_p.h @@ -97,6 +97,10 @@ public: HEntity handle() const { return m_handle; } Entity *parent() const; HEntity parentHandle() const { return m_parentHandle; } + Qt3DCore::QNodeId parentEntityId() const { return m_parentEntityId; } + + void clearEntityHierarchy(); + void rebuildEntityHierarchy(); void appendChildHandle(HEntity childHandle); void removeChildHandle(HEntity childHandle) { m_childrenHandles.removeOne(childHandle); } @@ -181,6 +185,8 @@ private: HEntity m_parentHandle; QVector<HEntity > m_childrenHandles; + Qt3DCore::QNodeId m_parentEntityId; + HMatrix m_worldTransform; QSharedPointer<Sphere> m_localBoundingVolume; QSharedPointer<Sphere> m_worldBoundingVolume; diff --git a/src/render/backend/managers.cpp b/src/render/backend/managers.cpp index 3b1f8e910..26fd68600 100644 --- a/src/render/backend/managers.cpp +++ b/src/render/backend/managers.cpp @@ -72,7 +72,11 @@ FrameGraphNode* FrameGraphManager::lookupNode(Qt3DCore::QNodeId id) const void FrameGraphManager::releaseNode(Qt3DCore::QNodeId id) { - delete m_nodes.take(id); + auto node = m_nodes.take(id); + if (node) { + node->cleanup(); + delete node; + } } void SkeletonManager::addDirtySkeleton(DirtyFlag dirtyFlag, HSkeleton skeletonHandle) diff --git a/src/render/configure.json b/src/render/configure.json index ee5002707..02a6e3747 100644 --- a/src/render/configure.json +++ b/src/render/configure.json @@ -1,5 +1,9 @@ { "module": "3drender", + "depends": [ + "3dcore" + ], + "condition": "module.3dcore", "testDir": "./config.tests", "commandline": { diff --git a/src/render/framegraph/framegraphnode.cpp b/src/render/framegraph/framegraphnode.cpp index 562548e46..41a94f0e3 100644 --- a/src/render/framegraph/framegraphnode.cpp +++ b/src/render/framegraph/framegraphnode.cpp @@ -40,9 +40,8 @@ #include "framegraphnode_p.h" #include <Qt3DRender/private/renderer_p.h> #include <Qt3DRender/private/nodemanagers_p.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> +#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -101,28 +100,6 @@ void FrameGraphNode::setParentId(Qt3DCore::QNodeId parentId) } } -void FrameGraphNode::appendChildId(Qt3DCore::QNodeId childId) -{ - if (!m_childrenIds.contains(childId)) { - FrameGraphNode *child = m_manager->lookupNode(childId); - if (child != nullptr) { - m_childrenIds.append(childId); - child->m_parentId = peerId(); - } - } -} - -void FrameGraphNode::removeChildId(Qt3DCore::QNodeId childId) -{ - if (m_childrenIds.contains(childId)) { - FrameGraphNode *child = m_manager->lookupNode(childId); - if (child != nullptr) { - child->m_parentId = Qt3DCore::QNodeId(); - } - m_childrenIds.removeAll(childId); - } -} - Qt3DCore::QNodeId FrameGraphNode::parentId() const { return m_parentId; @@ -155,28 +132,15 @@ void FrameGraphNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { switch (e->type()) { - case Qt3DCore::PropertyValueAdded: { - Qt3DCore::QPropertyNodeAddedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e); - if (change->metaObject()->inherits(&QFrameGraphNode::staticMetaObject)) { - appendChildId(change->addedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } - break; - } - - case Qt3DCore::PropertyValueRemoved: { - Qt3DCore::QPropertyNodeRemovedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e); - if (change->metaObject()->inherits(&QFrameGraphNode::staticMetaObject)) { - removeChildId(change->removedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } - break; - } case Qt3DCore::PropertyUpdated: { Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) { d_func()->m_enabled = propertyChange->value().toBool(); markDirty(AbstractRenderer::FrameGraphDirty); + } else if (propertyChange->propertyName() == QByteArrayLiteral("parentFrameGraphUpdated")) { + auto newParent = propertyChange->value().value<Qt3DCore::QNodeId>(); + setParentId(newParent); + markDirty(AbstractRenderer::AllDirty); } break; } @@ -185,6 +149,12 @@ void FrameGraphNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) } } +void FrameGraphNode::cleanup() +{ + setParentId({}); +} + + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/framegraph/framegraphnode_p.h b/src/render/framegraph/framegraphnode_p.h index 87d5c79e8..6aa3b3d6d 100644 --- a/src/render/framegraph/framegraphnode_p.h +++ b/src/render/framegraph/framegraphnode_p.h @@ -111,8 +111,6 @@ public: FrameGraphManager *manager() const; void setParentId(Qt3DCore::QNodeId parentId); - void appendChildId(Qt3DCore::QNodeId childHandle); - void removeChildId(Qt3DCore::QNodeId childHandle); Qt3DCore::QNodeId parentId() const; QVector<Qt3DCore::QNodeId> childrenIds() const; @@ -120,6 +118,8 @@ public: FrameGraphNode *parent() const; QVector<FrameGraphNode *> children() const; + void cleanup(); + void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; protected: diff --git a/src/render/framegraph/qframegraphnode.cpp b/src/render/framegraph/qframegraphnode.cpp index 9acfd1209..d52b728a8 100644 --- a/src/render/framegraph/qframegraphnode.cpp +++ b/src/render/framegraph/qframegraphnode.cpp @@ -40,6 +40,7 @@ #include "qframegraphnode.h" #include "qframegraphnode_p.h" #include <Qt3DRender/qframegraphnodecreatedchange.h> +#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/QNode> @@ -248,9 +249,24 @@ QFrameGraphNode::QFrameGraphNode(QFrameGraphNodePrivate &dd, QNode *parent) Qt3DCore::QNodeCreatedChangeBasePtr QFrameGraphNode::createNodeCreationChange() const { + // connect to the parentChanged signal here rather than constructor because + // until now there's no backend node to notify when parent changes + connect(this, &QNode::parentChanged, this, &QFrameGraphNode::onParentChanged); + return QFrameGraphNodeCreatedChangeBasePtr::create(this); } +void QFrameGraphNode::onParentChanged(QObject *) +{ + const auto parentID = parentFrameGraphNode() ? parentFrameGraphNode()->id() : Qt3DCore::QNodeId(); + auto parentChange = Qt3DCore::QPropertyUpdatedChangePtr::create(id()); + parentChange->setPropertyName("parentFrameGraphUpdated"); + parentChange->setValue(QVariant::fromValue(parentID)); + const bool blocked = blockNotifications(false); + notifyObservers(parentChange); + blockNotifications(blocked); +} + } // namespace Qt3DRender QT_END_NAMESPACE diff --git a/src/render/framegraph/qframegraphnode.h b/src/render/framegraph/qframegraphnode.h index 9b08c98d3..826f01a1e 100644 --- a/src/render/framegraph/qframegraphnode.h +++ b/src/render/framegraph/qframegraphnode.h @@ -63,6 +63,9 @@ protected: explicit QFrameGraphNode(QFrameGraphNodePrivate &dd, Qt3DCore::QNode *parent = nullptr); Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override; +private Q_SLOTS: + void onParentChanged(QObject *); + private: Q_DECLARE_PRIVATE(QFrameGraphNode) }; diff --git a/src/render/jobs/framecleanupjob.cpp b/src/render/jobs/framecleanupjob.cpp index 3105f547c..7ebe31531 100644 --- a/src/render/jobs/framecleanupjob.cpp +++ b/src/render/jobs/framecleanupjob.cpp @@ -91,11 +91,12 @@ void FrameCleanupJob::updateBoundingVolumesDebug(Entity *node) debugBV->setRadius(s.radius()); debugBV->setCenter(s.center()); } -#endif + const auto children = node->children(); for (Entity *c : children) updateBoundingVolumesDebug(c); +#endif } void FrameCleanupJob::setManagers(NodeManagers *managers) diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h index e776d452d..99bf99195 100644 --- a/src/render/jobs/job_common_p.h +++ b/src/render/jobs/job_common_p.h @@ -109,6 +109,7 @@ namespace JobTypes { UpdateLayerEntity, SendTextureChangesToFrontend, SendSetFenceHandlesToFrontend, + UpdateEntityHierarchy, }; } // JobTypes diff --git a/src/render/jobs/jobs.pri b/src/render/jobs/jobs.pri index 472531681..0c326c0b5 100644 --- a/src/render/jobs/jobs.pri +++ b/src/render/jobs/jobs.pri @@ -31,6 +31,7 @@ HEADERS += \ $$PWD/filterproximitydistancejob_p.h \ $$PWD/abstractpickingjob_p.h \ $$PWD/raycastingjob_p.h \ + $$PWD/updateentityhierarchyjob_p.h \ $$PWD/updateentitylayersjob_p.h SOURCES += \ @@ -61,5 +62,6 @@ SOURCES += \ $$PWD/filterproximitydistancejob.cpp \ $$PWD/abstractpickingjob.cpp \ $$PWD/raycastingjob.cpp \ + $$PWD/updateentityhierarchyjob.cpp \ $$PWD/updateentitylayersjob.cpp diff --git a/src/render/jobs/raycastingjob.cpp b/src/render/jobs/raycastingjob.cpp index 70c7ac374..887f203bf 100644 --- a/src/render/jobs/raycastingjob.cpp +++ b/src/render/jobs/raycastingjob.cpp @@ -164,8 +164,11 @@ bool RayCastingJob::runHelper() rays.back().transform(*pair.first->worldTransform()); break; case QAbstractRayCasterPrivate::ScreenScapeRayCaster: - for (const PickingUtils::ViewportCameraAreaDetails &vca : vcaDetails) - rays << rayForViewportAndCamera(vca, nullptr, pair.second->position()); + for (const PickingUtils::ViewportCameraAreaDetails &vca : vcaDetails) { + auto ray = rayForViewportAndCamera(vca, nullptr, pair.second->position()); + if (ray.isValid()) + rays << ray; + } break; default: Q_UNREACHABLE(); diff --git a/src/render/jobs/updateentityhierarchyjob.cpp b/src/render/jobs/updateentityhierarchyjob.cpp new file mode 100644 index 000000000..7c18514bb --- /dev/null +++ b/src/render/jobs/updateentityhierarchyjob.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "updateentityhierarchyjob_p.h" +#include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DRender/private/entity_p.h> +#include <Qt3DRender/private/job_common_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +namespace Render { + +UpdateEntityHierarchyJob::UpdateEntityHierarchyJob() + : m_manager(nullptr) +{ + SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateEntityHierarchy, 0); +} + +void UpdateEntityHierarchyJob::run() +{ + Q_ASSERT(m_manager); + EntityManager *entityManager = m_manager->renderNodesManager(); + + const QVector<HEntity> handles = entityManager->activeHandles(); + + // Clear the parents and children + for (const HEntity &handle : handles) { + Entity *entity = entityManager->data(handle); + entity->clearEntityHierarchy(); + } + for (const HEntity &handle : handles) { + Entity *entity = entityManager->data(handle); + entity->rebuildEntityHierarchy(); + } +} + +} // Render + +} // Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/jobs/updateentityhierarchyjob_p.h b/src/render/jobs/updateentityhierarchyjob_p.h new file mode 100644 index 000000000..fd2b13631 --- /dev/null +++ b/src/render/jobs/updateentityhierarchyjob_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QT3DRENDER_RENDER_UPDATEENTITYHIERARCHYJOB_P_H +#define QT3DRENDER_RENDER_UPDATEENTITYHIERARCHYJOB_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DRender/private/qt3drender_global_p.h> +#include <Qt3DCore/qaspectjob.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +namespace Render { + +class Entity; +class NodeManagers; + +class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateEntityHierarchyJob: public Qt3DCore::QAspectJob +{ +public: + UpdateEntityHierarchyJob(); + + inline void setManager(NodeManagers *manager) { m_manager = manager; } + inline NodeManagers *manager() const { return m_manager; } + + // QAspectJob interface + void run() final; + +private: + NodeManagers *m_manager; +}; + + +using UpdateEntityHierarchyJobPtr = QSharedPointer<UpdateEntityHierarchyJob>; + +} // Render + +} // Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_UPDATEENTITYHIERARCHYJOB_P_H diff --git a/src/render/jobs/updateentitylayersjob_p.h b/src/render/jobs/updateentitylayersjob_p.h index 13cc2fc4c..5d36042c4 100644 --- a/src/render/jobs/updateentitylayersjob_p.h +++ b/src/render/jobs/updateentitylayersjob_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. diff --git a/src/render/jobs/updatelevelofdetailjob.cpp b/src/render/jobs/updatelevelofdetailjob.cpp index 141d65c22..e4b651949 100644 --- a/src/render/jobs/updatelevelofdetailjob.cpp +++ b/src/render/jobs/updatelevelofdetailjob.cpp @@ -93,6 +93,11 @@ void UpdateLevelOfDetailJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot) void UpdateLevelOfDetailJob::run() { Q_ASSERT(m_frameGraphRoot && m_root && m_manager); + + // short-circuit if no LoDs exist + if (m_manager->levelOfDetailManager()->count() == 0) + return; + updateEntityLod(m_root); } diff --git a/src/render/jobs/updateskinningpalettejob.cpp b/src/render/jobs/updateskinningpalettejob.cpp index 30ffafa53..1ee9101f9 100644 --- a/src/render/jobs/updateskinningpalettejob.cpp +++ b/src/render/jobs/updateskinningpalettejob.cpp @@ -59,6 +59,10 @@ UpdateSkinningPaletteJob::~UpdateSkinningPaletteJob() void UpdateSkinningPaletteJob::run() { + auto armatureManager = m_nodeManagers->armatureManager(); + if (armatureManager->count() == 0) + return; + // TODO: Decompose this job across several jobs, say one per skeleton so // that it can be done in parallel @@ -78,7 +82,6 @@ void UpdateSkinningPaletteJob::run() findDirtyArmatures(m_root, dirtyArmatures); // Update the skeleton for each dirty armature - auto armatureManager = m_nodeManagers->armatureManager(); auto skeletonManager = m_nodeManagers->skeletonManager(); for (const auto &armatureHandle : qAsConst(dirtyArmatures)) { auto armature = armatureManager->data(armatureHandle); diff --git a/src/render/lights/light.cpp b/src/render/lights/light.cpp index 1e1855349..e8474b728 100644 --- a/src/render/lights/light.cpp +++ b/src/render/lights/light.cpp @@ -63,6 +63,9 @@ void Light::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractLightData>>(change); const auto &data = typedChange->data; m_shaderDataId = data.shaderDataId; + + Q_ASSERT(m_renderer); + BackendNode::markDirty(AbstractRenderer::LightsDirty); } RenderLightFunctor::RenderLightFunctor(AbstractRenderer *renderer, NodeManagers *managers) @@ -85,6 +88,8 @@ Qt3DCore::QBackendNode *RenderLightFunctor::get(Qt3DCore::QNodeId id) const void RenderLightFunctor::destroy(Qt3DCore::QNodeId id) const { + Light *backend = m_managers->lightManager()->getOrCreateResource(id); + m_renderer->markDirty(AbstractRenderer::LightsDirty, backend); m_managers->lightManager()->releaseResource(id); } diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index 746ca514f..e7fa4615c 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -200,6 +200,7 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend)) , m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering)) , m_syncTextureLoadingJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncTextureLoading)) + , m_updateEntityHierarchyJob(Render::UpdateEntityHierarchyJobPtr::create()) , m_ownedContext(false) , m_offscreenHelper(nullptr) #if QT_CONFIG(qt3d_profile_jobs) @@ -212,6 +213,9 @@ Renderer::Renderer(QRenderAspect::RenderType type) if (m_renderThread) m_renderThread->waitForStart(); + m_worldTransformJob->addDependency(m_updateEntityHierarchyJob); + m_updateEntityLayersJob->addDependency(m_updateEntityHierarchyJob); + // Create jobs to update transforms and bounding volumes // We can only update bounding volumes once all world transforms are known m_updateWorldBoundingVolumeJob->addDependency(m_worldTransformJob); @@ -301,6 +305,7 @@ void Renderer::setNodeManagers(NodeManagers *managers) m_updateMeshTriangleListJob->setManagers(m_nodesManager); m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager()); m_updateEntityLayersJob->setManager(m_nodesManager); + m_updateEntityHierarchyJob->setManager(m_nodesManager); } void Renderer::setServices(QServiceLocator *services) @@ -1783,14 +1788,17 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() // Add jobs const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty; - if (entitiesEnabledDirty) { + const bool entityHierarchyNeedsToBeRebuilt = dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty; + if (entitiesEnabledDirty || entityHierarchyNeedsToBeRebuilt) { renderBinJobs.push_back(m_updateTreeEnabledJob); // This dependency is added here because we clear all dependencies // at the start of this function. m_calculateBoundingVolumeJob->addDependency(m_updateTreeEnabledJob); + m_calculateBoundingVolumeJob->addDependency(m_updateEntityHierarchyJob); } - if (dirtyBitsForFrame & AbstractRenderer::TransformDirty) { + if (dirtyBitsForFrame & AbstractRenderer::TransformDirty || + dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty) { renderBinJobs.push_back(m_worldTransformJob); renderBinJobs.push_back(m_updateWorldBoundingVolumeJob); renderBinJobs.push_back(m_updateShaderDataTransformJob); @@ -1803,6 +1811,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() } if (dirtyBitsForFrame & AbstractRenderer::GeometryDirty || + dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty || dirtyBitsForFrame & AbstractRenderer::TransformDirty) { renderBinJobs.push_back(m_expandBoundingVolumeJob); } @@ -1829,10 +1838,17 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() // Layer cache is dependent on layers, layer filters (hence FG structure // changes) and the enabled flag on entities const bool frameGraphDirty = dirtyBitsForFrame & AbstractRenderer::FrameGraphDirty; - const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty; + const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty || entityHierarchyNeedsToBeRebuilt; const bool layersCacheNeedsToBeRebuilt = layersDirty || entitiesEnabledDirty || frameGraphDirty; const bool materialDirty = dirtyBitsForFrame & AbstractRenderer::MaterialDirty; const bool materialCacheNeedsToBeRebuilt = materialDirty || frameGraphDirty; + const bool lightsDirty = dirtyBitsForFrame & AbstractRenderer::LightsDirty; + const bool computeableDirty = dirtyBitsForFrame & AbstractRenderer::ComputeDirty; + const bool renderableDirty = dirtyBitsForFrame & AbstractRenderer::GeometryDirty; + + // Rebuild Entity Hierarchy if dirty + if (entityHierarchyNeedsToBeRebuilt) + renderBinJobs.push_back(m_updateEntityHierarchyJob); // Rebuild Entity Layers list if layers are dirty if (layersDirty) @@ -1860,6 +1876,10 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() RenderViewBuilder builder(fgLeaves.at(i), i, this); builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt); builder.setMaterialGathererCacheNeedsToBeRebuilt(materialCacheNeedsToBeRebuilt); + builder.setRenderableCacheNeedsToBeRebuilt(renderableDirty); + builder.setComputableCacheNeedsToBeRebuilt(computeableDirty); + builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty); + builder.prepareJobs(); renderBinJobs.append(builder.buildJobHierachy()); } diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h index 97bd4f73e..5b5f5c4f4 100644 --- a/src/render/renderers/opengl/renderer/renderer_p.h +++ b/src/render/renderers/opengl/renderer/renderer_p.h @@ -78,6 +78,7 @@ #include <Qt3DRender/private/filtercompatibletechniquejob_p.h> #include <Qt3DRender/private/updateskinningpalettejob_p.h> #include <Qt3DRender/private/updateentitylayersjob_p.h> +#include <Qt3DRender/private/updateentityhierarchyjob_p.h> #include <Qt3DRender/private/renderercache_p.h> #include <Qt3DRender/private/texture_p.h> #include <Qt3DRender/private/glfence_p.h> @@ -367,6 +368,7 @@ private: UpdateMeshTriangleListJobPtr m_updateMeshTriangleListJob; FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob; UpdateEntityLayersJobPtr m_updateEntityLayersJob; + UpdateEntityHierarchyJobPtr m_updateEntityHierarchyJob; QVector<Qt3DCore::QNodeId> m_pendingRenderCaptureSendRequests; diff --git a/src/render/renderers/opengl/renderer/renderercache_p.h b/src/render/renderers/opengl/renderer/renderercache_p.h index 2aa50d131..0e9c5d3cd 100644 --- a/src/render/renderers/opengl/renderer/renderercache_p.h +++ b/src/render/renderers/opengl/renderer/renderercache_p.h @@ -55,6 +55,7 @@ #include <Qt3DRender/private/entity_p.h> #include <Qt3DRender/private/renderviewjobutils_p.h> +#include <Qt3DRender/private/lightsource_p.h> QT_BEGIN_NAMESPACE @@ -68,6 +69,10 @@ struct RendererCache { QVector<Entity *> filterEntitiesByLayer; MaterialParameterGathererData materialParameterGatherer; + QVector<LightSource> gatheredLights; + QVector<Entity *> renderableEntities; + QVector<Entity *> computeEntities; + EnvironmentLight* environmentLight; }; QHash<FrameGraphNode *, LeafNodeData> leafNodeCache; diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp index d3d2d2dc4..83fab301a 100644 --- a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp +++ b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp @@ -177,9 +177,6 @@ public: explicit SyncRenderCommandBuilding(const RenderViewInitializerJobPtr &renderViewJob, const FrustumCullingJobPtr &frustumCullingJob, const FilterProximityDistanceJobPtr &filterProximityJob, - const LightGathererPtr &lightGathererJob, - const RenderableEntityFilterPtr &renderableEntityFilterJob, - const ComputableEntityFilterPtr &computableEntityFilterJob, const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs, const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs, Renderer *renderer, @@ -187,9 +184,6 @@ public: : m_renderViewJob(renderViewJob) , m_frustumCullingJob(frustumCullingJob) , m_filterProximityJob(filterProximityJob) - , m_lightGathererJob(lightGathererJob) - , m_renderableEntityFilterJob(renderableEntityFilterJob) - , m_computableEntityFilterJob(computableEntityFilterJob) , m_materialGathererJobs(materialGathererJobs) , m_renderViewBuilderJobs(renderViewBuilderJobs) , m_renderer(renderer) @@ -203,28 +197,27 @@ public: RenderView *rv = m_renderViewJob->renderView(); if (!rv->noDraw()) { - rv->setEnvironmentLight(m_lightGathererJob->takeEnvironmentLight()); - - // We sort the vector so that the removal can then be performed linearly - QVector<Entity *> renderableEntities; const bool isDraw = !rv->isCompute(); + QMutexLocker lock(m_renderer->cache()->mutex()); + const auto& cacheData = m_renderer->cache()->leafNodeCache.value(m_leafNode); + if (isDraw) - renderableEntities = std::move(m_renderableEntityFilterJob->filteredEntities()); + renderableEntities = cacheData.renderableEntities; else - renderableEntities = std::move(m_computableEntityFilterJob->filteredEntities()); + renderableEntities = cacheData.computeEntities; - // Filter out entities that weren't selected by the layer filters - std::sort(renderableEntities.begin(), renderableEntities.end()); + const QVector<Entity *> filteredEntities = cacheData.filterEntitiesByLayer; + QVector<LightSource> lightSources = cacheData.gatheredLights; + rv->setEnvironmentLight(cacheData.environmentLight); - QMutexLocker lock(m_renderer->cache()->mutex()); - const QVector<Entity *> filteredEntities = m_renderer->cache()->leafNodeCache.value(m_leafNode).filterEntitiesByLayer; lock.unlock(); + + // Filter out entities that weren't selected by the layer filters // Remove all entities from the compute and renderable vectors that aren't in the filtered layer vector renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, filteredEntities); // Set the light sources, with layer filters applied. - QVector<LightSource> lightSources = m_lightGathererJob->lights(); for (int i = 0; i < lightSources.count(); ++i) { if (!filteredEntities.contains(lightSources[i].entity)) lightSources.removeAt(i--); @@ -260,9 +253,6 @@ private: RenderViewInitializerJobPtr m_renderViewJob; FrustumCullingJobPtr m_frustumCullingJob; FilterProximityDistanceJobPtr m_filterProximityJob; - LightGathererPtr m_lightGathererJob; - RenderableEntityFilterPtr m_renderableEntityFilterJob; - ComputableEntityFilterPtr m_computableEntityFilterJob; QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs; QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs; Renderer *m_renderer; @@ -345,6 +335,84 @@ private: FrameGraphNode *m_leafNode; }; +class SyncLightsGatherer +{ +public: + explicit SyncLightsGatherer(LightGathererPtr gatherJob, + Renderer *renderer, + FrameGraphNode *leafNode) + : m_gatherJob(gatherJob) + , m_renderer(renderer) + , m_leafNode(leafNode) + { + } + + void operator()() + { + QMutexLocker lock(m_renderer->cache()->mutex()); + RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode]; + dataCacheForLeaf.gatheredLights = m_gatherJob->lights(); + dataCacheForLeaf.environmentLight = m_gatherJob->takeEnvironmentLight(); + } + +private: + LightGathererPtr m_gatherJob; + Renderer *m_renderer; + FrameGraphNode *m_leafNode; +}; + +class SyncRenderableEntities +{ +public: + explicit SyncRenderableEntities(RenderableEntityFilterPtr gatherJob, + Renderer *renderer, + FrameGraphNode *leafNode) + : m_gatherJob(gatherJob) + , m_renderer(renderer) + , m_leafNode(leafNode) + { + } + + void operator()() + { + QMutexLocker lock(m_renderer->cache()->mutex()); + RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode]; + dataCacheForLeaf.renderableEntities = m_gatherJob->filteredEntities(); + std::sort(dataCacheForLeaf.renderableEntities.begin(), dataCacheForLeaf.renderableEntities.end()); + } + +private: + RenderableEntityFilterPtr m_gatherJob; + Renderer *m_renderer; + FrameGraphNode *m_leafNode; +}; + +class SyncComputableEntities +{ +public: + explicit SyncComputableEntities(ComputableEntityFilterPtr gatherJob, + Renderer *renderer, + FrameGraphNode *leafNode) + : m_gatherJob(gatherJob) + , m_renderer(renderer) + , m_leafNode(leafNode) + { + } + + void operator()() + { + QMutexLocker lock(m_renderer->cache()->mutex()); + RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode]; + dataCacheForLeaf.computeEntities = m_gatherJob->filteredEntities(); + std::sort(dataCacheForLeaf.computeEntities.begin(), dataCacheForLeaf.computeEntities.end()); + } + +private: + ComputableEntityFilterPtr m_gatherJob; + Renderer *m_renderer; + FrameGraphNode *m_leafNode; +}; + } // anonymous RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int renderViewIndex, Renderer *renderer) @@ -353,11 +421,11 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende , m_renderer(renderer) , m_layerCacheNeedsToBeRebuilt(false) , m_materialGathererCacheNeedsToBeRebuilt(false) + , m_lightsCacheNeedsToBeRebuilt(false) + , m_renderableCacheNeedsToBeRebuilt(false) + , m_computableCacheNeedsToBeRebuilt(false) , m_renderViewJob(RenderViewInitializerJobPtr::create()) , m_filterEntityByLayerJob() - , m_lightGathererJob(Render::LightGathererPtr::create()) - , m_renderableEntityFilterJob(RenderableEntityFilterPtr::create()) - , m_computableEntityFilterJob(ComputableEntityFilterPtr::create()) , m_frustumCullingJob(new Render::FrustumCullingJob()) , m_syncFrustumCullingJob(SynchronizerJobPtr::create(SyncFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling)) , m_setClearDrawBufferIndexJob(SynchronizerJobPtr::create(SetClearDrawBufferIndex(m_renderViewJob), JobTypes::ClearBufferDrawIndex)) @@ -451,10 +519,37 @@ void RenderViewBuilder::prepareJobs() // Init what we can here EntityManager *entityManager = m_renderer->nodeManagers()->renderNodesManager(); m_filterProximityJob->setManager(m_renderer->nodeManagers()); - m_renderableEntityFilterJob->setManager(entityManager); - m_computableEntityFilterJob->setManager(entityManager); m_frustumCullingJob->setRoot(m_renderer->sceneRoot()); - m_lightGathererJob->setManager(entityManager); + + if (m_lightsCacheNeedsToBeRebuilt) { + m_lightGathererJob = Render::LightGathererPtr::create(); + m_lightGathererJob->setManager(entityManager); + + m_cacheLightsJob = SynchronizerJobPtr::create(SyncLightsGatherer(m_lightGathererJob, m_renderer, m_leafNode), + JobTypes::EntityComponentTypeFiltering); + m_cacheLightsJob->addDependency(m_lightGathererJob); + } + + if (m_renderableCacheNeedsToBeRebuilt) { + m_renderableEntityFilterJob = RenderableEntityFilterPtr::create(); + m_renderableEntityFilterJob->setManager(entityManager); + + m_cacheRenderableEntitiesJob = SynchronizerJobPtr::create( + SyncRenderableEntities(m_renderableEntityFilterJob, m_renderer, m_leafNode), + JobTypes::EntityComponentTypeFiltering); + m_cacheRenderableEntitiesJob->addDependency(m_renderableEntityFilterJob); + } + + if (m_computableCacheNeedsToBeRebuilt) { + m_computableEntityFilterJob = ComputableEntityFilterPtr::create(); + m_computableEntityFilterJob->setManager(entityManager); + + m_cacheComputableEntitiesJob = SynchronizerJobPtr::create( + SyncComputableEntities(m_computableEntityFilterJob, m_renderer, m_leafNode), + JobTypes::EntityComponentTypeFiltering); + m_cacheComputableEntitiesJob->addDependency(m_computableEntityFilterJob); + } + m_renderViewJob->setRenderer(m_renderer); m_renderViewJob->setFrameGraphLeafNode(m_leafNode); m_renderViewJob->setSubmitOrderIndex(m_renderViewIndex); @@ -502,9 +597,6 @@ void RenderViewBuilder::prepareJobs() m_syncRenderCommandBuildingJob = SynchronizerJobPtr::create(SyncRenderCommandBuilding(m_renderViewJob, m_frustumCullingJob, m_filterProximityJob, - m_lightGathererJob, - m_renderableEntityFilterJob, - m_computableEntityFilterJob, m_materialGathererJobs, m_renderViewBuilderJobs, m_renderer, @@ -523,7 +615,6 @@ void RenderViewBuilder::prepareJobs() m_materialGathererJobs, m_renderViewBuilderJobs), JobTypes::SyncRenderViewInitialization); - } QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const @@ -553,10 +644,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const m_filterProximityJob->addDependency(m_syncRenderViewInitializationJob); m_syncRenderCommandBuildingJob->addDependency(m_syncRenderViewInitializationJob); - m_syncRenderCommandBuildingJob->addDependency(m_renderableEntityFilterJob); - m_syncRenderCommandBuildingJob->addDependency(m_computableEntityFilterJob); m_syncRenderCommandBuildingJob->addDependency(m_filterProximityJob); - m_syncRenderCommandBuildingJob->addDependency(m_lightGathererJob); m_syncRenderCommandBuildingJob->addDependency(m_frustumCullingJob); // Ensure the RenderThread won't be able to process dirtyResources @@ -575,11 +663,25 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const // Add jobs jobs.push_back(m_renderViewJob); // Step 1 - jobs.push_back(m_renderableEntityFilterJob); // Step 1 - jobs.push_back(m_lightGathererJob); // Step 1 - // Note: do it only if OpenGL 4.3+ available - jobs.push_back(m_computableEntityFilterJob); // Step 1 + if (m_lightsCacheNeedsToBeRebuilt) { + jobs.push_back(m_lightGathererJob); // Step 1 + jobs.push_back(m_cacheLightsJob); + m_syncRenderCommandBuildingJob->addDependency(m_cacheLightsJob); + } + + if (m_renderableCacheNeedsToBeRebuilt) { + jobs.push_back(m_renderableEntityFilterJob); // Step 1 + jobs.push_back(m_cacheRenderableEntitiesJob); + m_syncRenderCommandBuildingJob->addDependency(m_cacheRenderableEntitiesJob); + } + + if (m_computableCacheNeedsToBeRebuilt) { + // Note: do it only if OpenGL 4.3+ available + jobs.push_back(m_computableEntityFilterJob); // Step 1 + jobs.push_back(m_cacheComputableEntitiesJob); + m_syncRenderCommandBuildingJob->addDependency(m_cacheComputableEntitiesJob); + } jobs.push_back(m_syncRenderViewInitializationJob); // Step 2 @@ -652,6 +754,36 @@ bool RenderViewBuilder::materialGathererCacheNeedsToBeRebuilt() const return m_materialGathererCacheNeedsToBeRebuilt; } +void RenderViewBuilder::setRenderableCacheNeedsToBeRebuilt(bool needsToBeRebuilt) +{ + m_renderableCacheNeedsToBeRebuilt = needsToBeRebuilt; +} + +bool RenderViewBuilder::renderableCacheNeedsToBeRebuilt() const +{ + return m_renderableCacheNeedsToBeRebuilt; +} + +void RenderViewBuilder::setComputableCacheNeedsToBeRebuilt(bool needsToBeRebuilt) +{ + m_computableCacheNeedsToBeRebuilt = needsToBeRebuilt; +} + +bool RenderViewBuilder::computableCacheNeedsToBeRebuilt() const +{ + return m_computableCacheNeedsToBeRebuilt; +} + +void RenderViewBuilder::setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt) +{ + m_lightsCacheNeedsToBeRebuilt = needsToBeRebuilt; +} + +bool RenderViewBuilder::lightGathererCacheNeedsToBeRebuilt() const +{ + return m_lightsCacheNeedsToBeRebuilt; +} + int RenderViewBuilder::optimalJobCount() { return RenderViewBuilder::m_optimalParallelJobCount; diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h index 818313500..e223a5f1e 100644 --- a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h +++ b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h @@ -109,6 +109,15 @@ public: void setMaterialGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt); bool materialGathererCacheNeedsToBeRebuilt() const; + void setRenderableCacheNeedsToBeRebuilt(bool needsToBeRebuilt); + bool renderableCacheNeedsToBeRebuilt() const; + + void setComputableCacheNeedsToBeRebuilt(bool needsToBeRebuilt); + bool computableCacheNeedsToBeRebuilt() const; + + void setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt); + bool lightGathererCacheNeedsToBeRebuilt() const; + static int optimalJobCount(); static QVector<Entity *> entitiesInSubset(const QVector<Entity *> &entities, const QVector<Entity *> &subset); @@ -118,6 +127,9 @@ private: Renderer *m_renderer; bool m_layerCacheNeedsToBeRebuilt; bool m_materialGathererCacheNeedsToBeRebuilt; + bool m_lightsCacheNeedsToBeRebuilt; + bool m_renderableCacheNeedsToBeRebuilt; + bool m_computableCacheNeedsToBeRebuilt; RenderViewInitializerJobPtr m_renderViewJob; FilterLayerEntityJobPtr m_filterEntityByLayerJob; @@ -137,6 +149,10 @@ private: SynchronizerJobPtr m_syncMaterialGathererJob; FilterProximityDistanceJobPtr m_filterProximityJob; + SynchronizerJobPtr m_cacheRenderableEntitiesJob; + SynchronizerJobPtr m_cacheComputableEntitiesJob; + SynchronizerJobPtr m_cacheLightsJob; + static const int m_optimalParallelJobCount; }; |