summaryrefslogtreecommitdiffstats
path: root/src/render
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2019-04-25 15:27:11 +0200
committerPaul Lemire <paul.lemire@kdab.com>2019-04-26 07:14:12 +0200
commit06f41f15abaacc9f6f7acb8e51d2cfb68705a924 (patch)
tree210403f4bb9872940f8db4ab656238e9f14e1b98 /src/render
parent9b140ccba930f159443a70a81eb1d2585b6070f9 (diff)
parentfed848f7dcff99cf5adb3b7b45190826b3dcf898 (diff)
Merge remote-tracking branch 5.12 into 5.13
Diffstat (limited to 'src/render')
-rw-r--r--src/render/backend/abstractrenderer_p.h2
-rw-r--r--src/render/backend/entity.cpp74
-rw-r--r--src/render/backend/entity_p.h6
-rw-r--r--src/render/backend/managers.cpp6
-rw-r--r--src/render/configure.json4
-rw-r--r--src/render/framegraph/framegraphnode.cpp52
-rw-r--r--src/render/framegraph/framegraphnode_p.h4
-rw-r--r--src/render/framegraph/qframegraphnode.cpp16
-rw-r--r--src/render/framegraph/qframegraphnode.h3
-rw-r--r--src/render/jobs/framecleanupjob.cpp3
-rw-r--r--src/render/jobs/job_common_p.h1
-rw-r--r--src/render/jobs/jobs.pri2
-rw-r--r--src/render/jobs/raycastingjob.cpp7
-rw-r--r--src/render/jobs/updateentityhierarchyjob.cpp80
-rw-r--r--src/render/jobs/updateentityhierarchyjob_p.h91
-rw-r--r--src/render/jobs/updateentitylayersjob_p.h2
-rw-r--r--src/render/jobs/updatelevelofdetailjob.cpp5
-rw-r--r--src/render/jobs/updateskinningpalettejob.cpp5
-rw-r--r--src/render/lights/light.cpp5
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp26
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h2
-rw-r--r--src/render/renderers/opengl/renderer/renderercache_p.h5
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder.cpp206
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder_p.h16
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;
};