summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvenn-Arne Dragly <s@dragly.com>2019-02-27 09:51:33 +0100
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2019-03-21 12:58:25 +0000
commit4b0237eb7891dacf5105e1e4ce4a5b29fc762509 (patch)
tree492435b5f241454e4946c93fbee01ca3101692b1
parent4fad7f872d4582095b3bf23d18692059b577ba38 (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.cpp2
-rw-r--r--src/runtime/dragon/dragonbackendnode.cpp7
-rw-r--r--src/runtime/dragon/dragonbackendnode_p.h2
-rw-r--r--src/runtime/dragon/dragonentity.cpp4
-rw-r--r--src/runtime/dragon/dragonscene2d.cpp2
-rw-r--r--src/runtime/dragon/dragontrackingchangescontainer_p.h112
-rw-r--r--src/runtime/dragon/framegraph/dragonframegraphnode.cpp4
-rw-r--r--src/runtime/dragon/jobs/dragonboundingvolumejobs.cpp15
-rw-r--r--src/runtime/dragon/jobs/dragonjobs_common_p.h124
-rw-r--r--src/runtime/dragon/jobs/dragontexturejobs.cpp6
-rw-r--r--src/runtime/dragon/jobs/dragontransformjobs.cpp9
-rw-r--r--src/runtime/dragon/jobs/dragontreejobs_p.h24
-rw-r--r--src/runtime/dragon/renderer/dragondraw.cpp2
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()];