diff options
author | Svenn-Arne Dragly <s@dragly.com> | 2019-02-27 09:51:33 +0100 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2019-03-21 12:58:25 +0000 |
commit | 4b0237eb7891dacf5105e1e4ce4a5b29fc762509 (patch) | |
tree | 492435b5f241454e4946c93fbee01ca3101692b1 | |
parent | 4fad7f872d4582095b3bf23d18692059b577ba38 (diff) |
Dragon: Make changes ordered in TrackingChangesContainer
This makes sure that all changes happen in the right order,
in case the same node has been created, modified, and/or removed since
the previous frame. Previously, we only had a list of created, modified,
and removed nodes, leading to cases where we could not know if we should
create before removal or the other way around.
Further, this change removes the DirtyInfo class and replaces it with a
simple enum.
Change-Id: If23ff583c685996caca87e2f0a9d0d4c7b1543c2
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r-- | src/runtime/dragon/dragonactivatedsurface.cpp | 2 | ||||
-rw-r--r-- | src/runtime/dragon/dragonbackendnode.cpp | 7 | ||||
-rw-r--r-- | src/runtime/dragon/dragonbackendnode_p.h | 2 | ||||
-rw-r--r-- | src/runtime/dragon/dragonentity.cpp | 4 | ||||
-rw-r--r-- | src/runtime/dragon/dragonscene2d.cpp | 2 | ||||
-rw-r--r-- | src/runtime/dragon/dragontrackingchangescontainer_p.h | 112 | ||||
-rw-r--r-- | src/runtime/dragon/framegraph/dragonframegraphnode.cpp | 4 | ||||
-rw-r--r-- | src/runtime/dragon/jobs/dragonboundingvolumejobs.cpp | 15 | ||||
-rw-r--r-- | src/runtime/dragon/jobs/dragonjobs_common_p.h | 124 | ||||
-rw-r--r-- | src/runtime/dragon/jobs/dragontexturejobs.cpp | 6 | ||||
-rw-r--r-- | src/runtime/dragon/jobs/dragontransformjobs.cpp | 9 | ||||
-rw-r--r-- | src/runtime/dragon/jobs/dragontreejobs_p.h | 24 | ||||
-rw-r--r-- | src/runtime/dragon/renderer/dragondraw.cpp | 2 |
13 files changed, 178 insertions, 135 deletions
diff --git a/src/runtime/dragon/dragonactivatedsurface.cpp b/src/runtime/dragon/dragonactivatedsurface.cpp index 9699c5c..42c86ea 100644 --- a/src/runtime/dragon/dragonactivatedsurface.cpp +++ b/src/runtime/dragon/dragonactivatedsurface.cpp @@ -526,7 +526,7 @@ Immutable<GLVertexArrayObject> ActivatedSurface::createVertexArrayObject( const auto attributeType = attributeTypeToGLBufferType(attribute->attributeType()); // Index Attribute - bool attributeWasDirty = attributes.dirtyOrNew().contains(attributeId); + bool attributeWasDirty = attributes.hasDirtyOrCreated(attributeId); // TODO fix this by checking in which cases we need a real update bool geometryDirtyOrSomething = true; diff --git a/src/runtime/dragon/dragonbackendnode.cpp b/src/runtime/dragon/dragonbackendnode.cpp index fe00d75..f3b9721 100644 --- a/src/runtime/dragon/dragonbackendnode.cpp +++ b/src/runtime/dragon/dragonbackendnode.cpp @@ -48,14 +48,13 @@ void BackendNode::setManager(AbstractContainer *manager) void BackendNode::markDirty() { - Q_ASSERT(m_manager != nullptr); - m_manager->markDirty(m_peerId); + markDirty(Change::DirtyInfo::Other); } -void BackendNode::markDirty(const Immutable<AbstractContainer::DirtyInfo> &dirtyInfo) +void BackendNode::markDirty(Change::DirtyInfo info) { Q_ASSERT(m_manager != nullptr); - m_manager->markDirty(m_peerId, dirtyInfo); + m_manager->markDirty(m_peerId, info); } Qt3DCore::QNodeId BackendNode::peerId() const diff --git a/src/runtime/dragon/dragonbackendnode_p.h b/src/runtime/dragon/dragonbackendnode_p.h index aa0be0b..31de54a 100644 --- a/src/runtime/dragon/dragonbackendnode_p.h +++ b/src/runtime/dragon/dragonbackendnode_p.h @@ -68,7 +68,7 @@ public: // TODO consider removing, this is a bit hacky // TODO perhaps we could just use the fact that we changed? void markDirty(); - void markDirty(const Immutable<AbstractContainer::DirtyInfo> &dirtyInfo); + void markDirty(Change::DirtyInfo info); Qt3DCore::QNodeId peerId() const; // TODO consider making private and protected by befriending DragonNodeFunctor and diff --git a/src/runtime/dragon/dragonentity.cpp b/src/runtime/dragon/dragonentity.cpp index ad38490..125e66c 100644 --- a/src/runtime/dragon/dragonentity.cpp +++ b/src/runtime/dragon/dragonentity.cpp @@ -99,7 +99,7 @@ void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) if (change->metaObject()->inherits(&QEntity::staticMetaObject)) { if (!m_childEntityIds.contains(change->addedNodeId())) { m_childEntityIds.push_back(change->addedNodeId()); - markDirty(DirtyTreeInfo{}); + markDirty(Change::DirtyInfo::Tree); } } break; @@ -109,7 +109,7 @@ void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QPropertyNodeRemovedChangePtr change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); if (change->metaObject()->inherits(&QEntity::staticMetaObject)) { m_childEntityIds.removeAll(change->removedNodeId()); - markDirty(DirtyTreeInfo{}); + markDirty(Change::DirtyInfo::Tree); } break; } diff --git a/src/runtime/dragon/dragonscene2d.cpp b/src/runtime/dragon/dragonscene2d.cpp index b65cf16..57e201f 100644 --- a/src/runtime/dragon/dragonscene2d.cpp +++ b/src/runtime/dragon/dragonscene2d.cpp @@ -378,7 +378,7 @@ ValueContainer<Scene2DState> updateScene2Ds(ValueContainer<Scene2DState> scene2d continue; } - if (outputs.dirty().contains(scene2d.m_data->m_outputId)) { + if (outputs.changes().contains(Change{Change::Action::Modified, scene2d.m_data->m_outputId})) { RenderTargetOutput output = *outputs[scene2d.m_data->m_outputId]; Attachment attachment; attachment.m_name = output.name; diff --git a/src/runtime/dragon/dragontrackingchangescontainer_p.h b/src/runtime/dragon/dragontrackingchangescontainer_p.h index 7128f12..c4df989 100644 --- a/src/runtime/dragon/dragontrackingchangescontainer_p.h +++ b/src/runtime/dragon/dragontrackingchangescontainer_p.h @@ -49,19 +49,56 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Dragon { +struct Change +{ + enum class Action + { + Created, + Modified, + Removed + }; + + enum class DirtyInfo + { + Other, + Tree + }; + + Change() = default; + + Change(Action action_, Qt3DCore::QNodeId id_) + : action(action_) + , id(id_) + , info(DirtyInfo::Other) + { + } + + Change(Action action_, Qt3DCore::QNodeId id_, DirtyInfo info_) + : action(action_) + , id(id_) + , info(info_) + { + Q_ASSERT_X(action == Action::Modified, "Dragon::Change", + "ERROR: DirtyInfo provided for non-dirty change"); + } + + Action action = Action::Created; + Qt3DCore::QNodeId id; + DirtyInfo info = DirtyInfo::Other; +}; + +inline bool operator ==(const Change &a, const Change &b) +{ + return a.action == b.action && a.id == b.id; +}; + // TODO consider if this is really needed class AbstractContainer { public: - class DirtyInfo { - public: - DirtyInfo() = default; - virtual ~DirtyInfo() = default; - }; - virtual ~AbstractContainer() {} virtual void markDirty(const Qt3DCore::QNodeId &id) = 0; - virtual void markDirty(const Qt3DCore::QNodeId &id, const Immutable<DirtyInfo> &dirtyInfo) = 0; + virtual void markDirty(const Qt3DCore::QNodeId &id, Change::DirtyInfo info) = 0; }; // TODO make sure creating and removing is counted properly - consider adding a changelist instead @@ -79,17 +116,12 @@ public: void markDirty(const Key &id) override { - // If m_dirty already contains id, don't replace it. Otherwise there - // is a risk to override DirtyTreeInfo{} with DirtyInfo{} - if (m_dirty.contains(id)) - return; - - m_dirty.insert(id, DirtyInfo{}); + m_changes.push_back(Change{Change::Action::Modified, id, Change::DirtyInfo::Other}); } - void markDirty(const Key &id, const Immutable<DirtyInfo> &dirtyInfo) override + void markDirty(const Key &id, Change::DirtyInfo info) override { - m_dirty.insert(id, dirtyInfo); + m_changes.push_back(Change{Change::Action::Modified, id, info}); } QList<Key> keys() const @@ -116,7 +148,7 @@ public: T& operator[](const Key &key) { if (!m_container.contains(key)) - m_created.push_back(key); + m_changes.push_back(Change{Change::Action::Created, key}); return m_container[key]; } @@ -140,37 +172,34 @@ public: return m_container.end(); } - QVector<Key> created() const + bool anythingDirty() const { - return m_created; + return !m_changes.isEmpty(); } - QVector<Key> removed() const + bool hasCreated(const Key &key) const { - return m_removed; + return m_changes.contains(Change{Change::Action::Created, key}); } - QSet<Key> dirty() const + bool hasDirty(const Key &key) const { - return m_dirty.keys().toSet(); + return m_changes.contains(Change{Change::Action::Modified, key}); } - // TODO reconsider the use of QList... - QList<Key> dirtyOrNew() const + bool hasRemoved(const Key &key) const { - return m_dirty.keys() + m_created.toList(); + return m_changes.contains(Change{Change::Action::Removed, key}); } - bool anythingDirty() const + bool hasDirtyOrCreated(const Key &key) const { - return !m_dirty.isEmpty() - || !m_created.isEmpty() - || !m_removed.isEmpty(); + return hasDirty(key) || hasCreated(key); } void insert(const Key & key, T value) { - m_created.push_back(key); + m_changes.push_back(Change{Change::Action::Created, key}); m_container.insert(key, value); } @@ -182,7 +211,7 @@ public: T take(const Key & key) { - m_removed.push_back(key); + m_changes.push_back(Change{Change::Action::Removed, key}); return m_container.take(key); } @@ -198,28 +227,25 @@ public: void reset() { - m_created.clear(); - m_removed.clear(); - m_dirty.clear(); + m_changes.clear(); } - void clear() + QVector<Change> changes() const { - m_removed = m_removed + m_container.keys(); - m_container.clear(); + return m_changes; } - // TODO rename to dirty - const QHash<Key, Immutable<DirtyInfo>> &dirtyInfo() + void clear() { - return m_dirty; + for (const auto &key : m_container.keys()) { + m_changes.push_back(Change{Change::Action::Removed, key}); + } + m_container.clear(); } private: DataContainer m_container; - QHash<Key, Immutable<DirtyInfo>> m_dirty; - QVector<Key> m_created; - QVector<Key> m_removed; + QVector<Change> m_changes; }; template<typename T, typename Key> diff --git a/src/runtime/dragon/framegraph/dragonframegraphnode.cpp b/src/runtime/dragon/framegraph/dragonframegraphnode.cpp index 09dd558..932c127 100644 --- a/src/runtime/dragon/framegraph/dragonframegraphnode.cpp +++ b/src/runtime/dragon/framegraph/dragonframegraphnode.cpp @@ -95,7 +95,7 @@ void FrameGraphNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Qt3DCore::QPropertyNodeAddedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e); if (change->metaObject()->inherits(&QFrameGraphNode::staticMetaObject)) { if (!m_childFrameGraphNodeIds.contains(change->addedNodeId())) { - markDirty(DirtyTreeInfo{}); + markDirty(Change::DirtyInfo::Tree); m_childFrameGraphNodeIds.append(change->addedNodeId()); } } @@ -106,7 +106,7 @@ void FrameGraphNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Qt3DCore::QPropertyNodeRemovedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e); if (change->metaObject()->inherits(&QFrameGraphNode::staticMetaObject)) { m_childFrameGraphNodeIds.removeAll(change->removedNodeId()); - markDirty(DirtyTreeInfo{}); + markDirty(Change::DirtyInfo::Tree); } break; } diff --git a/src/runtime/dragon/jobs/dragonboundingvolumejobs.cpp b/src/runtime/dragon/jobs/dragonboundingvolumejobs.cpp index 2b96f3b..0106151 100644 --- a/src/runtime/dragon/jobs/dragonboundingvolumejobs.cpp +++ b/src/runtime/dragon/jobs/dragonboundingvolumejobs.cpp @@ -195,7 +195,8 @@ LocalBoundingVolumes calculateLocalBoundingVolumes(LocalBoundingVolumes localBou // TODO consider using an Optional here LocalBoundingVolumeResult result = *localBoundingVolumes[id]; - bool entityDirty = entities.dirtyOrNew().contains(id); + bool entityDirty = entities.changes().contains(Change{Change::Action::Created, id}) || + entities.changes().contains(Change{Change::Action::Modified, id}); if (entityDirty) { // TODO make all these asserts part of the [] operator Q_ASSERT(entities.contains(id)); @@ -213,7 +214,7 @@ LocalBoundingVolumes calculateLocalBoundingVolumes(LocalBoundingVolumes localBou // Geometry renderer is dirty if the entity is new, or if the geometry renderer itself changed // TODO repeated pattern - can we generalize this somehow? - bool geometryRendererDirty = entityDirty || geometryRenderers.dirtyOrNew().contains(result.geometryRendererId); + bool geometryRendererDirty = entityDirty || geometryRenderers.hasDirtyOrCreated(result.geometryRendererId); if (geometryRendererDirty) { Q_ASSERT(geometryRenderers.contains(result.geometryRendererId)); const auto &geometryRenderer = geometryRenderers[result.geometryRendererId]; @@ -229,7 +230,7 @@ LocalBoundingVolumes calculateLocalBoundingVolumes(LocalBoundingVolumes localBou return result; // TODO what if we have a geometry factory? - bool geometryDirty = geometryRendererDirty || geometries.dirtyOrNew().contains(result.geometryId); + bool geometryDirty = geometryRendererDirty || geometries.hasDirtyOrCreated(result.geometryId); if (geometryDirty) { result.positionAttributeId = QNodeId(); // Reset the ID in case it was set previously result.indexAttributeId = QNodeId(); @@ -269,7 +270,7 @@ LocalBoundingVolumes calculateLocalBoundingVolumes(LocalBoundingVolumes localBou return result; } - bool positionAttributeDirty = geometryDirty || attributes.dirtyOrNew().contains(result.positionAttributeId); + bool positionAttributeDirty = geometryDirty || attributes.hasDirtyOrCreated(result.positionAttributeId); if (positionAttributeDirty) { Q_ASSERT(attributes.contains(result.positionAttributeId)); result.positionAttribute = attributes[result.positionAttributeId]; @@ -288,7 +289,7 @@ LocalBoundingVolumes calculateLocalBoundingVolumes(LocalBoundingVolumes localBou return result; } - bool indexAttributeDirty = geometryDirty || attributes.dirtyOrNew().contains(result.indexAttributeId); + bool indexAttributeDirty = geometryDirty || attributes.hasDirtyOrCreated(result.indexAttributeId); if (indexAttributeDirty) { Q_ASSERT(attributes.contains(result.indexAttributeId)); result.indexAttribute = attributes[result.indexAttributeId]; @@ -310,12 +311,12 @@ LocalBoundingVolumes calculateLocalBoundingVolumes(LocalBoundingVolumes localBou return 0; }(); - bool indexBufferDirty = indexAttributeDirty || buffers.dirtyOrNew().contains(result.indexBufferId); + bool indexBufferDirty = indexAttributeDirty || buffers.hasDirtyOrCreated(result.indexBufferId); if (indexBufferDirty) { result.indexBuffer = buffers[result.indexBufferId]; } - bool positionBufferDirty = positionAttributeDirty || buffers.dirtyOrNew().contains(result.positionBufferId); + bool positionBufferDirty = positionAttributeDirty || buffers.hasDirtyOrCreated(result.positionBufferId); if (indexBufferDirty) { result.positionBuffer = buffers[result.positionBufferId]; } diff --git a/src/runtime/dragon/jobs/dragonjobs_common_p.h b/src/runtime/dragon/jobs/dragonjobs_common_p.h index bc6e9f0..c32f21e 100644 --- a/src/runtime/dragon/jobs/dragonjobs_common_p.h +++ b/src/runtime/dragon/jobs/dragonjobs_common_p.h @@ -55,11 +55,14 @@ namespace Dragon { template<typename Target, typename Reference> Target synchronizeKeys(Target target, const Reference &reference) { - for (const auto &key : reference.created()) { - target[key]; - } - for (const auto &key : reference.removed()) { - target.remove(key); + const auto &changes = reference.changes(); + for (const auto &change : changes) { + const auto &key = change.id; + if (change.action == Change::Action::Created) { + target[key]; + } else if (change.action == Change::Action::Removed) { + target.remove(key); + } } return target; } @@ -67,14 +70,17 @@ Target synchronizeKeys(Target target, const Reference &reference) template<typename Target, typename Reference, typename Callback> Target synchronizeKeys(Target target, const Reference &reference, Callback callback) { - for (const auto &key : reference.dirtyOrNew()) { - if (target.contains(key)) - target.markDirty(key); - const auto &item = reference[key]; - target.insert(key, callback(key, item)); - } - for (const auto &key : reference.removed()) { - target.remove(key); + const auto &changes = reference.changes(); + for (const auto &change : changes) { + const auto &key = change.id; + if (change.action == Change::Action::Created || change.action == Change::Action::Modified) { + if (target.contains(key)) + target.markDirty(key); + const auto &item = reference[key]; + target.insert(key, callback(key, item)); + } else if (change.action == Change::Action::Removed) { + target.remove(key); + } } return target; } @@ -82,13 +88,15 @@ Target synchronizeKeys(Target target, const Reference &reference, Callback callb template<typename Target, typename Reference, typename Callback> Target synchronizeNew(Target target, const Reference &reference, Callback callback) { - for (const auto &key : reference.created()) { -// Q_ASSERT(!target.contains(key)); - const auto &item = reference[key]; - target.insert(key, callback(key, item)); - } - for (const auto &key : reference.removed()) { - target.remove(key); + const auto &changes = reference.changes(); + for (const auto &change : changes) { + const auto &key = change.id; + if (change.action == Change::Action::Created) { + const auto &item = reference[key]; + target.insert(key, callback(key, item)); + } else if (change.action == Change::Action::Removed) { + target.remove(key); + } } return target; } @@ -96,13 +104,16 @@ Target synchronizeNew(Target target, const Reference &reference, Callback callba template<typename Target, typename Reference, typename Callback> Target synchronizeDirty(Target target, const Reference &reference, Callback callback) { - for (const auto &key : reference.dirty()) { - Q_ASSERT(target.contains(key)); - const auto &sourceItem = reference[key]; - target[key] = callback(key, std::move(target[key]), sourceItem); - } - for (const auto &key : reference.removed()) { - target.remove(key); + const auto &changes = reference.changes(); + for (const auto &change : changes) { + const auto &key = change.id; + if (change.action == Change::Action::Modified) { + Q_ASSERT(target.contains(key)); + const auto &sourceItem = reference[key]; + target[key] = callback(key, std::move(target[key]), sourceItem); + } else if (change.action == Change::Action::Removed) { + target.remove(key); + } } return target; } @@ -119,25 +130,27 @@ Target synchronizeKeys(Target target, Compare compare, CreateFunction create) { - for (const auto &id : reference.dirtyOrNew()) { - if (target.contains(id)) - target.markDirty(id); - - const auto &item = reference[id]; - bool foundExisting = false; - for (const auto &cached : target) { - if (compare(*cached, item)) { - target[id] = cached; - foundExisting = true; - break; + const auto &changes = reference.changes(); + for (const auto &change : changes) { + const auto &id = change.id; + if (change.action == Change::Action::Modified || change.action == Change::Action::Created) { + if (target.contains(id)) + target.markDirty(id); + + const auto &item = reference[id]; + bool foundExisting = false; + for (const auto &cached : target) { + if (compare(*cached, item)) { + target[id] = cached; + foundExisting = true; + break; + } } + if (!foundExisting) + target[id] = create(id, *item); + } else if (change.action == Change::Action::Removed) { + target.remove(id); } - if (!foundExisting) - target[id] = create(id, *item); - } - // Remove unused - for (const auto &key : reference.removed()) { - target.remove(key); } return target; } @@ -148,8 +161,12 @@ Target synchronizeNew(Target target, Compare compare, CreateFunction create) { - for (const auto &id : reference.created()) { -// Q_ASSERT(!target.contains(id)); // this is a bit strict + const auto &changes = reference.changes(); + for (const auto &change : changes) { + const auto &id = change.id; + if (change.action != Change::Action::Created) + continue; + const auto &item = reference[id]; bool foundExisting = false; for (const auto &cached : target) { @@ -171,7 +188,12 @@ Target synchronizeDirty(Target target, Compare compare, CreateFunction create) { - for (const auto &id : reference.dirty()) { + const auto &changes = reference.changes(); + for (const auto &change : changes) { + const auto &id = change.id; + if (change.action != Change::Action::Modified) + continue; + Q_ASSERT(target.contains(id)); // this is a bit strict target.markDirty(id); const auto &item = reference[id]; @@ -192,15 +214,17 @@ Target synchronizeDirty(Target target, template<typename Target, typename Reference, typename Callback> Target rebuildAll(Target target, const Reference &reference, Callback callback) { + for (const auto &change : reference.changes()) { + const auto &key = change.id; + if (change.action == Change::Action::Removed) + target.remove(key); + } for (const auto &key : reference.keys()) { // if (target.contains(key)) const auto &item = reference[key]; target[key] = callback(key, item); target.markDirty(key); } - for (const auto &key : reference.removed()) { - target.remove(key); - } return target; } diff --git a/src/runtime/dragon/jobs/dragontexturejobs.cpp b/src/runtime/dragon/jobs/dragontexturejobs.cpp index ba4e3df..6ba6c5f 100644 --- a/src/runtime/dragon/jobs/dragontexturejobs.cpp +++ b/src/runtime/dragon/jobs/dragontexturejobs.cpp @@ -108,11 +108,13 @@ LoadedTextures loadTextures(LoadedTextures loadedTextures, const ValueContainer< // TODO this is not the cleanest approach to finding dirty texture images that affect our // texture. Consider storing a hash of textures using different images, or implementing // more sophisticated dependency tracking between different types of nodes. - const auto &dirtyOrNewImages = loadedImages.dirtyOrNew(); + const auto &changes = loadedImages.changes(); for (const auto &textureId : loadedTextures.keys()) { const auto loadedTextureImages = loadedTextures[textureId]->images; for (const auto &loadedTextureImage : loadedTextureImages) { - if (dirtyOrNewImages.contains(loadedTextureImage->image->peerId())) { + const QNodeId textureImageId = loadedTextureImage->image->peerId(); + if (changes.contains(Change{Change::Action::Modified, textureImageId}) || + changes.contains(Change{Change::Action::Created, textureImageId})) { loadedTextures[textureId] = generateTexture(textureId, textures[textureId]); loadedTextures.markDirty(textureId); } diff --git a/src/runtime/dragon/jobs/dragontransformjobs.cpp b/src/runtime/dragon/jobs/dragontransformjobs.cpp index 6d15796..921baae 100644 --- a/src/runtime/dragon/jobs/dragontransformjobs.cpp +++ b/src/runtime/dragon/jobs/dragontransformjobs.cpp @@ -62,9 +62,6 @@ ValueContainer<Matrix4x4> calculateWorldTransforms(ValueContainer<Matrix4x4> wor bool dirty = false; }; - const auto &dirtyTransforms = transforms.dirtyOrNew(); - const auto &dirtyEntities = entities.dirtyOrNew(); - // If entities are dirty, a transform component may have changed and we set the entire tree to // be recalculated. Note that this could be optimized. bool rootDirty = entities.anythingDirty(); @@ -74,7 +71,7 @@ ValueContainer<Matrix4x4> calculateWorldTransforms(ValueContainer<Matrix4x4> wor worldTransforms[rootEntityId] = Matrix4x4{}; } else { const auto &transform = transforms[rootEntity->m_transformComponent]; - if (transforms.dirty().contains(rootEntity->m_transformComponent)) + if (transforms.hasDirty(rootEntity->m_transformComponent)) rootDirty = true; worldTransforms[rootEntityId] = transform->m_transformMatrix; } @@ -99,10 +96,10 @@ ValueContainer<Matrix4x4> calculateWorldTransforms(ValueContainer<Matrix4x4> wor for (auto it = children.rbegin(); it != children.rend(); ++it) { const auto &childId = *it; const auto &childEntity = entities[childId]; - bool childDirty = currentDirty || dirtyEntities.contains(childId); + bool childDirty = currentDirty || entities.hasDirtyOrCreated(childId); if (!childEntity->m_transformComponent.isNull()) { const auto &transform = transforms[childEntity->m_transformComponent]; - childDirty |= dirtyTransforms.contains(childEntity->m_transformComponent); + childDirty |= transforms.hasDirtyOrCreated(childEntity->m_transformComponent); if (childDirty) worldTransforms[childId] = currentWorldTransform * transform->m_transformMatrix; } else { diff --git a/src/runtime/dragon/jobs/dragontreejobs_p.h b/src/runtime/dragon/jobs/dragontreejobs_p.h index 9dd4955..bcc6246 100644 --- a/src/runtime/dragon/jobs/dragontreejobs_p.h +++ b/src/runtime/dragon/jobs/dragontreejobs_p.h @@ -82,11 +82,6 @@ struct TreeInfo Key rootNode; }; -class DirtyTreeInfo : public AbstractContainer::DirtyInfo -{ -public: -}; - template<typename T> TreeInfo generateInheritanceTable(TreeInfo inheritanceTable, T nodes, Qt3DCore::QNodeId rootEntityId) { @@ -95,19 +90,16 @@ TreeInfo generateInheritanceTable(TreeInfo inheritanceTable, T nodes, Qt3DCore:: if (!nodes.anythingDirty()) return inheritanceTable; - if (nodes.created().isEmpty()) { - const auto &dirtyInfos = nodes.dirtyInfo(); - bool dirtyTreeStuff = false; - for (const auto &id : dirtyInfos.keys()) { - const Immutable<AbstractContainer::DirtyInfo> &dirtyInfo = dirtyInfos[id]; - if (dirtyInfo.can_convert<DirtyTreeInfo>()) { - dirtyTreeStuff = true; - } + const auto &changes = nodes.changes(); + bool dirtyTree = false; + for (const auto &change : changes) { + if (change.action != Change::Action::Modified || change.info == Change::DirtyInfo::Tree) { + dirtyTree = true; + break; } - - if (!dirtyTreeStuff) - return inheritanceTable; } + if (!dirtyTree) + return inheritanceTable; // Clear old data inheritanceTable.leafNodes.clear(); diff --git a/src/runtime/dragon/renderer/dragondraw.cpp b/src/runtime/dragon/renderer/dragondraw.cpp index 91057fe..983f892 100644 --- a/src/runtime/dragon/renderer/dragondraw.cpp +++ b/src/runtime/dragon/renderer/dragondraw.cpp @@ -500,6 +500,8 @@ bool draw(const ActivatedSurface &activatedSurface, // TODO consider emulated VAO vao->m_vao->bind(); + + Q_ASSERT(glShader->shaderProgram != nullptr); glShader->shaderProgram->bind(); const auto &worldTransform = worldTransforms[command.m_entity->peerId()]; |