diff options
Diffstat (limited to 'src/render')
118 files changed, 1193 insertions, 1792 deletions
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h index 6e6f4898c..006919512 100644 --- a/src/render/backend/abstractrenderer_p.h +++ b/src/render/backend/abstractrenderer_p.h @@ -67,7 +67,6 @@ class QSize; namespace Qt3DCore { class QAbstractFrameAdvanceService; -class QBackendNodeFactory; class QEventFilterService; class QAbstractAspectJobManager; class QServiceLocator; @@ -114,7 +113,6 @@ public: JointDirty = 1 << 11, LayersDirty = 1 << 12, TechniquesDirty = 1 << 13, - EntityHierarchyDirty= 1 << 14, LightsDirty = 1 << 15, AllDirty = 0xffffff }; @@ -162,7 +160,7 @@ public: virtual Qt3DCore::QAspectJobPtr syncLoadingJobs() = 0; virtual Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() = 0; - virtual void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Entity *root) = 0; + virtual void setSceneRoot(Entity *root) = 0; virtual Entity *sceneRoot() const = 0; virtual FrameGraphNode *frameGraphRoot() const = 0; diff --git a/src/render/backend/backendnode.cpp b/src/render/backend/backendnode.cpp index 0dc8da237..188e017e6 100644 --- a/src/render/backend/backendnode.cpp +++ b/src/render/backend/backendnode.cpp @@ -41,6 +41,7 @@ #include <private/renderer_p.h> #include <private/resourceaccessor_p.h> #include <private/nodemanagers_p.h> +#include <Qt3DCore/private/qbackendnode_p.h> QT_BEGIN_NAMESPACE @@ -81,6 +82,13 @@ QSharedPointer<RenderBackendResourceAccessor> BackendNode::resourceAccessor() return r->nodeManagers()->resourceAccessor(); } +void BackendNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) +{ + Q_UNUSED(firstTime); + + d_ptr->setEnabled(frontEnd->isEnabled()); +} + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/backend/backendnode_p.h b/src/render/backend/backendnode_p.h index f94033c1a..167cb87f2 100644 --- a/src/render/backend/backendnode_p.h +++ b/src/render/backend/backendnode_p.h @@ -70,6 +70,8 @@ public: BackendNode(Qt3DCore::QBackendNode::Mode mode = ReadOnly); ~BackendNode(); + virtual void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime); + void setRenderer(AbstractRenderer *renderer); AbstractRenderer *renderer() const; diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index bf128b508..8be58dd46 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -95,11 +95,19 @@ void Entity::cleanup() if (m_nodeManagers != nullptr) { m_nodeManagers->worldMatrixManager()->releaseResource(peerId()); qCDebug(Render::RenderNodes) << Q_FUNC_INFO; + + removeFromParentChildHandles(); + + for (auto &childHandle : qAsConst(m_childrenHandles)) { + auto child = m_nodeManagers->renderNodesManager()->data(childHandle); + // children should always exist and have this as parent + // if they were destroyed, they would have removed themselves from our m_childrenHandles + Q_ASSERT(child); + Q_ASSERT(child->m_parentHandle == m_handle); + child->m_parentHandle = {}; + } } - 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 @@ -122,6 +130,7 @@ void Entity::cleanup() m_localBoundingVolume.reset(); m_worldBoundingVolume.reset(); m_worldBoundingVolumeWithChildren.reset(); + m_parentHandle = {}; m_boundingDirty = false; QBackendNode::setEnabled(false); } @@ -129,6 +138,12 @@ void Entity::cleanup() void Entity::setParentHandle(HEntity parentHandle) { Q_ASSERT(m_nodeManagers); + + if (parentHandle == m_parentHandle) + return; + + removeFromParentChildHandles(); + m_parentHandle = parentHandle; auto parent = m_nodeManagers->renderNodesManager()->data(parentHandle); if (parent != nullptr && !parent->m_childrenHandles.contains(m_handle)) @@ -145,44 +160,6 @@ void Entity::setHandle(HEntity handle) m_handle = handle; } -void Entity::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<QNodeCreatedChange<Qt3DCore::QEntityData>>(change); - const auto &data = typedChange->data; - - // 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). - 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(); - m_worldTransform = m_nodeManagers->worldMatrixManager()->getOrAcquireHandle(peerId()); - - // TODO: Suboptimal -> Maybe have a Hash<QComponent, QEntityList> instead - m_transformComponent = QNodeId(); - m_materialComponent = QNodeId(); - m_cameraComponent = QNodeId(); - m_geometryRendererComponent = QNodeId(); - m_objectPickerComponent = QNodeId(); - m_boundingVolumeDebugComponent = QNodeId(); - m_computeComponent = QNodeId(); - m_layerComponents.clear(); - m_levelOfDetailComponents.clear(); - m_rayCasterComponents.clear(); - m_shaderDataComponents.clear(); - m_lightComponents.clear(); - m_environmentLightComponents.clear(); - m_localBoundingVolume = QSharedPointer<Sphere>::create(peerId()); - m_worldBoundingVolume = QSharedPointer<Sphere>::create(peerId()); - m_worldBoundingVolumeWithChildren = QSharedPointer<Sphere>::create(peerId()); - - for (const auto &idAndType : qAsConst(data.componentIdsAndTypes)) - addComponent(idAndType); - - markDirty(AbstractRenderer::EntityHierarchyDirty); -} - void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { switch (e->type()) { @@ -192,7 +169,6 @@ void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) const auto componentIdAndType = QNodeIdTypePair(change->componentId(), change->componentMetaObject()); addComponent(componentIdAndType); qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "Component Added. Id =" << change->componentId(); - markDirty(AbstractRenderer::AllDirty); break; } @@ -200,27 +176,6 @@ void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QComponentRemovedChangePtr change = qSharedPointerCast<QComponentRemovedChange>(e); removeComponent(change->componentId()); qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "Component Removed. Id =" << change->componentId(); - 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; } @@ -230,6 +185,62 @@ void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) BackendNode::sceneChangeEvent(e); } +void Entity::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) +{ + const Qt3DCore::QEntity *node = qobject_cast<const Qt3DCore::QEntity *>(frontEnd); + if (!node) + return; + + if (this->isEnabled() != node->isEnabled()) { + markDirty(AbstractRenderer::EntityEnabledDirty); + // We let QBackendNode::syncFromFrontEnd change the enabled property + } + + const auto parentID = node->parentEntity() ? node->parentEntity()->id() : Qt3DCore::QNodeId(); + auto parentHandle = m_nodeManagers->renderNodesManager()->lookupHandle(parentID); + + // All entity creation is done from top-down and always during the same frame, so + // we if we have a valid parent node, we should always be able to resolve the + // backend parent at this time + Q_ASSERT(!node->parentEntity() || (!parentHandle.isNull() && m_nodeManagers->renderNodesManager()->data(parentHandle))); + + if (parentHandle != m_parentHandle) { + markDirty(AbstractRenderer::AllDirty); + } + + setParentHandle(parentHandle); + + if (firstTime) { + m_worldTransform = m_nodeManagers->worldMatrixManager()->getOrAcquireHandle(peerId()); + + // TODO: Suboptimal -> Maybe have a Hash<QComponent, QEntityList> instead + m_transformComponent = QNodeId(); + m_materialComponent = QNodeId(); + m_cameraComponent = QNodeId(); + m_geometryRendererComponent = QNodeId(); + m_objectPickerComponent = QNodeId(); + m_boundingVolumeDebugComponent = QNodeId(); + m_computeComponent = QNodeId(); + m_layerComponents.clear(); + m_levelOfDetailComponents.clear(); + m_rayCasterComponents.clear(); + m_shaderDataComponents.clear(); + m_lightComponents.clear(); + m_environmentLightComponents.clear(); + m_localBoundingVolume = QSharedPointer<Sphere>::create(peerId()); + m_worldBoundingVolume = QSharedPointer<Sphere>::create(peerId()); + m_worldBoundingVolumeWithChildren = QSharedPointer<Sphere>::create(peerId()); + + const QComponentVector &components = node->components(); + for (QComponent *c : components) { + const auto idAndType = QNodeIdTypePair(c->id(), QNodePrivate::findStaticMetaObject(c->metaObject())); + addComponent(idAndType); + } + } + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); +} + void Entity::dump() const { static int depth = 0; @@ -246,25 +257,12 @@ 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() +void Entity::removeFromParentChildHandles() { - 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(); + // remove ourself from our parent's list of children. + auto p = parent(); + if (p) + p->removeChildHandle(m_handle); } void Entity::appendChildHandle(HEntity childHandle) @@ -358,6 +356,7 @@ void Entity::addComponent(Qt3DCore::QNodeIdTypePair idAndType) } else if (type->inherits(&QArmature::staticMetaObject)) { m_armatureComponent = id; } + markDirty(AbstractRenderer::AllDirty); } void Entity::removeComponent(Qt3DCore::QNodeId nodeId) @@ -392,6 +391,7 @@ void Entity::removeComponent(Qt3DCore::QNodeId nodeId) } else if (m_armatureComponent == nodeId) { m_armatureComponent = QNodeId(); } + markDirty(AbstractRenderer::AllDirty); } bool Entity::isBoundingVolumeDirty() const diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h index b4c9541f2..403f5568c 100644 --- a/src/render/backend/entity_p.h +++ b/src/render/backend/entity_p.h @@ -90,6 +90,7 @@ public: void setParentHandle(HEntity parentHandle); void setNodeManagers(NodeManagers *manager); void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void dump() const; @@ -97,11 +98,8 @@ 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 removeFromParentChildHandles(); void appendChildHandle(HEntity childHandle); void removeChildHandle(HEntity childHandle) { m_childrenHandles.removeOne(childHandle); } QVector<HEntity> childrenHandles() const { return m_childrenHandles; } @@ -178,17 +176,12 @@ public: return containsComponentsOfType<T>() && containsComponentsOfType<Ts, Ts2...>(); } - private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - NodeManagers *m_nodeManagers; HEntity m_handle; HEntity m_parentHandle; QVector<HEntity > m_childrenHandles; - Qt3DCore::QNodeId m_parentEntityId; - HMatrix m_worldTransform; QSharedPointer<Sphere> m_localBoundingVolume; QSharedPointer<Sphere> m_worldBoundingVolume; @@ -306,7 +299,7 @@ ENTITY_COMPONENT_LIST_TEMPLATE_SPECIALIZATION(ShaderData, HShaderData) ENTITY_COMPONENT_LIST_TEMPLATE_SPECIALIZATION(Light, HLight) ENTITY_COMPONENT_LIST_TEMPLATE_SPECIALIZATION(EnvironmentLight, HEnvironmentLight) -class RenderEntityFunctor : public Qt3DCore::QBackendNodeMapper +class Q_AUTOTEST_EXPORT RenderEntityFunctor : public Qt3DCore::QBackendNodeMapper { public: explicit RenderEntityFunctor(AbstractRenderer *renderer, NodeManagers *manager); diff --git a/src/render/backend/transform.cpp b/src/render/backend/transform.cpp index 390ed4f05..6659657fa 100644 --- a/src/render/backend/transform.cpp +++ b/src/render/backend/transform.cpp @@ -68,17 +68,6 @@ void Transform::cleanup() QBackendNode::setEnabled(false); } -void Transform::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QTransformData>>(change); - const auto &data = typedChange->data; - m_rotation = data.rotation; - m_scale = data.scale; - m_translation = data.translation; - updateMatrix(); - markDirty(AbstractRenderer::TransformDirty); -} - Matrix4x4 Transform::transformMatrix() const { return m_transformMatrix; @@ -99,6 +88,7 @@ QVector3D Transform::translation() const return m_translation; } +// TODOSYNC remove once we've found a way to propagate animation changes void Transform::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { // TODO: Flag the matrix as dirty and update all matrices batched in a job @@ -120,6 +110,27 @@ void Transform::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) BackendNode::sceneChangeEvent(e); } +void Transform::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) +{ + const Qt3DCore::QTransform *transform = qobject_cast<const Qt3DCore::QTransform *>(frontEnd); + if (!transform) + return; + + bool dirty = m_rotation != transform->rotation(); + m_rotation = transform->rotation(); + dirty |= m_scale != transform->scale3D(); + m_scale = transform->scale3D(); + dirty |= m_translation != transform->translation(); + m_translation = transform->translation(); + + if (dirty || firstTime) { + updateMatrix(); + markDirty(AbstractRenderer::TransformDirty); + } + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); +} + void Transform::notifyWorldTransformChanged(const Matrix4x4 &worldMatrix) { auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); diff --git a/src/render/backend/transform_p.h b/src/render/backend/transform_p.h index e3bcad317..50857ac94 100644 --- a/src/render/backend/transform_p.h +++ b/src/render/backend/transform_p.h @@ -77,12 +77,11 @@ public: QVector3D translation() const; void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final; void notifyWorldTransformChanged(const Matrix4x4 &worldMatrix); private: void updateMatrix(); - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Matrix4x4 m_transformMatrix; QQuaternion m_rotation; QVector3D m_scale; diff --git a/src/render/framegraph/blitframebuffer.cpp b/src/render/framegraph/blitframebuffer.cpp index 342594baf..c45d3fdbc 100644 --- a/src/render/framegraph/blitframebuffer.cpp +++ b/src/render/framegraph/blitframebuffer.cpp @@ -60,48 +60,44 @@ BlitFramebuffer::BlitFramebuffer() { } -void BlitFramebuffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void BlitFramebuffer::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("sourceRenderTarget")) { - m_sourceRenderTargetId = propertyChange->value().value<QNodeId>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("destinationRenderTarget")) { - m_destinationRenderTargetId = propertyChange->value().value<QNodeId>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("sourceRect")) { - m_sourceRect = propertyChange->value().toRect(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("destinationRect")) { - m_destinationRect = propertyChange->value().toRect(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("sourceAttachmentPoint")) { - m_sourceAttachmentPoint = propertyChange->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("destinationAttachmentPoint")) { - m_destinationAttachmentPoint = propertyChange->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("interpolationMethod")) { - m_interpolationMethod = propertyChange->value().value<QBlitFramebuffer::InterpolationMethod>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } - } - FrameGraphNode::sceneChangeEvent(e); -} + const QBlitFramebuffer *node = qobject_cast<const QBlitFramebuffer *>(frontEnd); + if (!node) + return; -void BlitFramebuffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QBlitFramebufferData> >(change); - const auto &data = typedChange->data; - m_sourceRect = data.m_sourceRect; - m_destinationRect = data.m_destinationRect; - m_sourceRenderTargetId = data.m_sourceRenderTargetId; - m_destinationRenderTargetId = data.m_destinationRenderTargetId; - m_sourceAttachmentPoint = data.m_sourceAttachmentPoint; - m_destinationAttachmentPoint = data.m_destinationAttachmentPoint; - m_interpolationMethod = data.m_interpolationMethod; + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + if (node->sourceRect().toRect() != m_sourceRect) { + m_sourceRect = node->sourceRect().toRect(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + if (node->destinationRect().toRect() != m_destinationRect) { + m_destinationRect = node->destinationRect().toRect(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + if (node->sourceAttachmentPoint() != m_sourceAttachmentPoint) { + m_sourceAttachmentPoint = node->sourceAttachmentPoint(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + if (node->destinationAttachmentPoint() != m_destinationAttachmentPoint) { + m_destinationAttachmentPoint = node->destinationAttachmentPoint(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + if (node->interpolationMethod() != m_interpolationMethod) { + m_interpolationMethod = node->interpolationMethod(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + const QNodeId destinationNodeId = qIdForNode(node->destination()); + if (destinationNodeId != m_destinationRenderTargetId) { + m_destinationRenderTargetId = destinationNodeId; + markDirty(AbstractRenderer::FrameGraphDirty); + } + const QNodeId sourceNodeId = qIdForNode(node->source()); + if (sourceNodeId != m_sourceRenderTargetId) { + m_sourceRenderTargetId = sourceNodeId; + markDirty(AbstractRenderer::FrameGraphDirty); + } } Qt3DRender::QRenderTargetOutput::AttachmentPoint BlitFramebuffer::destinationAttachmentPoint() const diff --git a/src/render/framegraph/blitframebuffer_p.h b/src/render/framegraph/blitframebuffer_p.h index 796c223ca..fa9ddacd9 100644 --- a/src/render/framegraph/blitframebuffer_p.h +++ b/src/render/framegraph/blitframebuffer_p.h @@ -65,7 +65,7 @@ class Q_AUTOTEST_EXPORT BlitFramebuffer : public FrameGraphNode public: BlitFramebuffer(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Qt3DCore::QNodeId sourceRenderTargetId() const; @@ -82,8 +82,6 @@ public: QBlitFramebuffer::InterpolationMethod interpolationMethod() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_sourceRenderTargetId; Qt3DCore::QNodeId m_destinationRenderTargetId; QRect m_sourceRect; diff --git a/src/render/framegraph/cameraselectornode.cpp b/src/render/framegraph/cameraselectornode.cpp index 357611c7c..482429b00 100644 --- a/src/render/framegraph/cameraselectornode.cpp +++ b/src/render/framegraph/cameraselectornode.cpp @@ -57,25 +57,19 @@ CameraSelector::CameraSelector() { } -void CameraSelector::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void CameraSelector::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QCameraSelectorData>>(change); - const auto &data = typedChange->data; - m_cameraUuid = data.cameraId; -} + const QCameraSelector *node = qobject_cast<const QCameraSelector *>(frontEnd); + if (!node) + return; -void CameraSelector::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - qCDebug(Render::Framegraph) << Q_FUNC_INFO; - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("camera")) { - m_cameraUuid = propertyChange->value().value<QNodeId>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + const QNodeId cameraId = qIdForNode(node->camera()); + if (m_cameraUuid != cameraId) { + m_cameraUuid = cameraId; + markDirty(AbstractRenderer::FrameGraphDirty); } - FrameGraphNode::sceneChangeEvent(e); } QNodeId CameraSelector::cameraUuid() const diff --git a/src/render/framegraph/cameraselectornode_p.h b/src/render/framegraph/cameraselectornode_p.h index 0e532d68f..dd7e050d0 100644 --- a/src/render/framegraph/cameraselectornode_p.h +++ b/src/render/framegraph/cameraselectornode_p.h @@ -69,12 +69,11 @@ class CameraSelector : public FrameGraphNode public: CameraSelector(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; Qt3DCore::QNodeId cameraUuid() const; -private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; +private: Qt3DCore::QNodeId m_cameraUuid; }; diff --git a/src/render/framegraph/clearbuffers.cpp b/src/render/framegraph/clearbuffers.cpp index ab6225a4b..98de30906 100644 --- a/src/render/framegraph/clearbuffers.cpp +++ b/src/render/framegraph/clearbuffers.cpp @@ -61,42 +61,40 @@ ClearBuffers::ClearBuffers() { } -void ClearBuffers::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void ClearBuffers::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QClearBuffersData>>(change); - const auto &data = typedChange->data; - m_type = data.buffersType; - m_clearColorAsColor = data.clearColor; - m_clearColor = vec4dFromColor(m_clearColorAsColor); - m_clearDepthValue = data.clearDepthValue; - m_clearStencilValue = data.clearStencilValue; - m_colorBufferId = data.bufferId; -} + const QClearBuffers *node = qobject_cast<const QClearBuffers *>(frontEnd); + if (!node) + return; -void ClearBuffers::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("buffers")) { - m_type = static_cast<QClearBuffers::BufferType>(propertyChange->value().toInt()); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("clearColor")) { - m_clearColorAsColor = propertyChange->value().value<QColor>(); - m_clearColor = vec4dFromColor(m_clearColorAsColor); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("clearDepthValue")) { - m_clearDepthValue = propertyChange->value().toFloat(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("clearStencilValue")) { - m_clearStencilValue = propertyChange->value().toInt(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("colorBuffer")) { - m_colorBufferId = propertyChange->value().value<QNodeId>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + if (m_clearColorAsColor != node->clearColor()) { + m_clearColorAsColor = node->clearColor(); + m_clearColor = vec4dFromColor(node->clearColor()); + markDirty(AbstractRenderer::FrameGraphDirty); + } + + if (m_clearDepthValue != node->clearDepthValue()) { + m_clearDepthValue = node->clearDepthValue(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + + if (m_clearStencilValue != node->clearStencilValue()) { + m_clearStencilValue = node->clearStencilValue(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + + const QNodeId colorBufferId = qIdForNode(node->colorBuffer()); + if (m_colorBufferId != colorBufferId) { + m_colorBufferId = colorBufferId; + markDirty(AbstractRenderer::FrameGraphDirty); + } + + if (m_type != node->buffers()) { + m_type = node->buffers(); + markDirty(AbstractRenderer::FrameGraphDirty); } - FrameGraphNode::sceneChangeEvent(e); } QClearBuffers::BufferType ClearBuffers::type() const diff --git a/src/render/framegraph/clearbuffers_p.h b/src/render/framegraph/clearbuffers_p.h index e3c56c165..ca55d2a98 100644 --- a/src/render/framegraph/clearbuffers_p.h +++ b/src/render/framegraph/clearbuffers_p.h @@ -67,8 +67,6 @@ class ClearBuffers : public FrameGraphNode public: ClearBuffers(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; - QClearBuffers::BufferType type() const; float clearDepthValue() const; int clearStencilValue() const; @@ -85,10 +83,9 @@ public: QColor clearColorAsColor() const; bool clearsAllColorBuffers() const; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QClearBuffers::BufferType m_type; QVector4D m_clearColor; QColor m_clearColorAsColor; diff --git a/src/render/framegraph/dispatchcompute.cpp b/src/render/framegraph/dispatchcompute.cpp index f7e9dcff4..5eae75bc6 100644 --- a/src/render/framegraph/dispatchcompute.cpp +++ b/src/render/framegraph/dispatchcompute.cpp @@ -66,32 +66,26 @@ void DispatchCompute::cleanup() m_workGroups[2] = 1; } -void DispatchCompute::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void DispatchCompute::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QDispatchComputeData>>(change); - const auto &data = typedChange->data; - m_workGroups[0] = data.workGroupX; - m_workGroups[1] = data.workGroupY; - m_workGroups[2] = data.workGroupZ; -} + const QDispatchCompute *node = qobject_cast<const QDispatchCompute *>(frontEnd); + if (!node) + return; -void DispatchCompute::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("workGroupX")) { - m_workGroups[0] = propertyChange->value().toInt(); - markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("workGroupY")) { - m_workGroups[1] = propertyChange->value().toInt(); - markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("workGroupZ")) { - m_workGroups[2] = propertyChange->value().toInt(); - markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty); - } + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + if (m_workGroups[0] != node->workGroupX()) { + m_workGroups[0] = node->workGroupX(); + markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty); + } + if (m_workGroups[1] != node->workGroupY()) { + m_workGroups[1] = node->workGroupY(); + markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty); + } + if (m_workGroups[2] != node->workGroupZ()) { + m_workGroups[2] = node->workGroupZ(); + markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty); } - FrameGraphNode::sceneChangeEvent(e); } } // Render diff --git a/src/render/framegraph/dispatchcompute_p.h b/src/render/framegraph/dispatchcompute_p.h index aa88a35c5..24a641938 100644 --- a/src/render/framegraph/dispatchcompute_p.h +++ b/src/render/framegraph/dispatchcompute_p.h @@ -68,13 +68,13 @@ public: void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; inline int x() const Q_DECL_NOTHROW { return m_workGroups[0]; } inline int y() const Q_DECL_NOTHROW { return m_workGroups[1]; } inline int z() const Q_DECL_NOTHROW { return m_workGroups[2]; } + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; + private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; int m_workGroups[3]; }; diff --git a/src/render/framegraph/framegraphnode.cpp b/src/render/framegraph/framegraphnode.cpp index 458d96d4b..93531fd7d 100644 --- a/src/render/framegraph/framegraphnode.cpp +++ b/src/render/framegraph/framegraphnode.cpp @@ -66,14 +66,6 @@ FrameGraphNode::~FrameGraphNode() { } -void FrameGraphNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - // Set up the parent child relationship and enabled state - const auto creationChange = qSharedPointerCast<QFrameGraphNodeCreatedChangeBase>(change); - setParentId(creationChange->parentFrameGraphNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); -} - void FrameGraphNode::setFrameGraphManager(FrameGraphManager *manager) { if (m_manager != manager) @@ -129,34 +121,33 @@ QVector<FrameGraphNode *> FrameGraphNode::children() const return children; } -void FrameGraphNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void FrameGraphNode::cleanup() { - switch (e->type()) { - - 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; - } - default: - markDirty(AbstractRenderer::AllDirty); - break; - } + setParentId({}); } -void FrameGraphNode::cleanup() +void FrameGraphNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - setParentId({}); + const QFrameGraphNode *node = qobject_cast<const QFrameGraphNode *>(frontEnd); + + const auto parentId = Qt3DCore::qIdForNode(node->parentFrameGraphNode()); + if (parentId != m_parentId) { + setParentId(parentId); + // TO DO: Check if FrameGraphDirty wouldn't be enough here + markDirty(AbstractRenderer::AllDirty); + } + + if (node->isEnabled() != d_func()->m_enabled) { + d_func()->m_enabled = node->isEnabled(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + + if (firstTime) + markDirty(AbstractRenderer::FrameGraphDirty); } + } // namespace Render } // namespace Qt3DRender diff --git a/src/render/framegraph/framegraphnode_p.h b/src/render/framegraph/framegraphnode_p.h index 3edd4f57d..846dc8060 100644 --- a/src/render/framegraph/framegraphnode_p.h +++ b/src/render/framegraph/framegraphnode_p.h @@ -121,11 +121,10 @@ public: void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; protected: FrameGraphNode(FrameGraphNodeType nodeType, QBackendNode::Mode mode = QBackendNode::ReadOnly); - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override; private: FrameGraphNodeType m_nodeType; diff --git a/src/render/framegraph/layerfilternode.cpp b/src/render/framegraph/layerfilternode.cpp index f9881be0d..5c53fa681 100644 --- a/src/render/framegraph/layerfilternode.cpp +++ b/src/render/framegraph/layerfilternode.cpp @@ -43,6 +43,7 @@ #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qpropertynoderemovedchange.h> +#include <algorithm> QT_BEGIN_NAMESPACE @@ -57,48 +58,25 @@ LayerFilterNode::LayerFilterNode() { } -void LayerFilterNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void LayerFilterNode::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLayerFilterData>>(change); - const auto &data = typedChange->data; - setLayerIds(data.layerIds); - m_filterMode = data.filterMode; -} + const QLayerFilter *node = qobject_cast<const QLayerFilter *>(frontEnd); + if (!node) + return; -void LayerFilterNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("layer")) - m_layerIds.append(change->addedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::LayersDirty); - break; - } + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("layer")) - m_layerIds.removeOne(change->removedNodeId()); + if (m_filterMode != node->filterMode()) { + m_filterMode = node->filterMode(); markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::LayersDirty); - break; } - case PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("filterMode")) { - m_filterMode = static_cast<QLayerFilter::FilterMode>(change->value().value<int>()); - markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::LayersDirty); - break; - } - } - - default: - break; + auto layerIds = qIdsForNodes(node->layers()); + std::sort(std::begin(layerIds), std::end(layerIds)); + if (m_layerIds != layerIds) { + m_layerIds = layerIds; + markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::LayersDirty); } - - FrameGraphNode::sceneChangeEvent(e); } QNodeIdVector LayerFilterNode::layerIds() const diff --git a/src/render/framegraph/layerfilternode_p.h b/src/render/framegraph/layerfilternode_p.h index 18ba4ee7a..27cdc49d3 100644 --- a/src/render/framegraph/layerfilternode_p.h +++ b/src/render/framegraph/layerfilternode_p.h @@ -53,6 +53,7 @@ #include <Qt3DRender/private/framegraphnode_p.h> #include <Qt3DRender/QLayerFilter> +#include <Qt3DRender/QLayer> #include <QStringList> QT_BEGIN_NAMESPACE @@ -68,15 +69,14 @@ class LayerFilterNode : public FrameGraphNode public: LayerFilterNode(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; + Qt3DCore::QNodeIdVector layerIds() const; void setLayerIds(const Qt3DCore::QNodeIdVector &list); QLayerFilter::FilterMode filterMode() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeIdVector m_layerIds; QLayerFilter::FilterMode m_filterMode; }; diff --git a/src/render/framegraph/memorybarrier.cpp b/src/render/framegraph/memorybarrier.cpp index 59b3071ab..6bfaedda7 100644 --- a/src/render/framegraph/memorybarrier.cpp +++ b/src/render/framegraph/memorybarrier.cpp @@ -62,24 +62,18 @@ QMemoryBarrier::Operations MemoryBarrier::waitOperations() const return m_waitOperations; } -void MemoryBarrier::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void MemoryBarrier::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("waitOperations")) { - m_waitOperations = propertyChange->value().value<QMemoryBarrier::Operations>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } - } - FrameGraphNode::sceneChangeEvent(e); -} + const QMemoryBarrier *node = qobject_cast<const QMemoryBarrier *>(frontEnd); + if (!node) + return; -void MemoryBarrier::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QMemoryBarrierData>>(change); - const QMemoryBarrierData &data = typedChange->data; - m_waitOperations = data.waitOperations; + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + if (node->waitOperations() != m_waitOperations) { + m_waitOperations = node->waitOperations(); + markDirty(AbstractRenderer::FrameGraphDirty); + } } } // Render diff --git a/src/render/framegraph/memorybarrier_p.h b/src/render/framegraph/memorybarrier_p.h index e0fd3e9cd..ce545cd09 100644 --- a/src/render/framegraph/memorybarrier_p.h +++ b/src/render/framegraph/memorybarrier_p.h @@ -67,10 +67,9 @@ public: ~MemoryBarrier(); QMemoryBarrier::Operations waitOperations() const; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; QMemoryBarrier::Operations m_waitOperations; }; diff --git a/src/render/framegraph/proximityfilter.cpp b/src/render/framegraph/proximityfilter.cpp index cdfd7e51e..593e541bc 100644 --- a/src/render/framegraph/proximityfilter.cpp +++ b/src/render/framegraph/proximityfilter.cpp @@ -53,29 +53,24 @@ ProximityFilter::ProximityFilter() { } -void ProximityFilter::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void ProximityFilter::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QProximityFilterData>>(change); - const QProximityFilterData &data = typedChange->data; - m_entityId = data.entityId; - m_distanceThreshold = data.distanceThreshold; -} + const QProximityFilter *node = qobject_cast<const QProximityFilter *>(frontEnd); + if (!node) + return; -void ProximityFilter::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - qCDebug(Render::Framegraph) << Q_FUNC_INFO; - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("entity")) { - m_entityId = propertyChange->value().value<Qt3DCore::QNodeId>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("distanceThreshold")) { - m_distanceThreshold = propertyChange->value().toFloat(); - markDirty(AbstractRenderer::FrameGraphDirty); - } + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + const auto entityId = Qt3DCore::qIdForNode(node->entity()); + if (entityId != m_entityId) { + m_entityId = entityId; + markDirty(AbstractRenderer::FrameGraphDirty); + } + + if (node->distanceThreshold() != m_distanceThreshold) { + m_distanceThreshold = node->distanceThreshold(); + markDirty(AbstractRenderer::FrameGraphDirty); } - FrameGraphNode::sceneChangeEvent(e); } } // namespace Render diff --git a/src/render/framegraph/proximityfilter_p.h b/src/render/framegraph/proximityfilter_p.h index e57b53dea..5c2f7ad66 100644 --- a/src/render/framegraph/proximityfilter_p.h +++ b/src/render/framegraph/proximityfilter_p.h @@ -64,7 +64,7 @@ class Q_AUTOTEST_EXPORT ProximityFilter : public FrameGraphNode public: ProximityFilter(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; float distanceThreshold() const { return m_distanceThreshold; } Qt3DCore::QNodeId entityId() const { return m_entityId; } @@ -76,8 +76,6 @@ public: #endif private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - float m_distanceThreshold; Qt3DCore::QNodeId m_entityId; }; diff --git a/src/render/framegraph/qblitframebuffer.cpp b/src/render/framegraph/qblitframebuffer.cpp index d0e1bdbf3..bf9e547cb 100644 --- a/src/render/framegraph/qblitframebuffer.cpp +++ b/src/render/framegraph/qblitframebuffer.cpp @@ -364,6 +364,7 @@ void QBlitFramebuffer::setDestination(QRenderTarget *destination) } } +// TO DO Qt6: convert QRectF to QRect /*! Sets the source rectangle to \a inputRect. The coordinates are assumed to follow the normal Qt coordinate system, meaning Y runs from top to bottom. diff --git a/src/render/framegraph/qframegraphnode.cpp b/src/render/framegraph/qframegraphnode.cpp index d52b728a8..1ef81a081 100644 --- a/src/render/framegraph/qframegraphnode.cpp +++ b/src/render/framegraph/qframegraphnode.cpp @@ -258,13 +258,9 @@ Qt3DCore::QNodeCreatedChangeBasePtr QFrameGraphNode::createNodeCreationChange() 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); + // Direct sync update request + Q_D(QFrameGraphNode); + d->update(); } } // namespace Qt3DRender diff --git a/src/render/framegraph/qlayerfilter.cpp b/src/render/framegraph/qlayerfilter.cpp index 04ebca572..8b0dd5669 100644 --- a/src/render/framegraph/qlayerfilter.cpp +++ b/src/render/framegraph/qlayerfilter.cpp @@ -206,11 +206,7 @@ void QLayerFilter::addLayer(QLayer *layer) if (!layer->parent()) layer->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), layer); - change->setPropertyName("layer"); - d->notifyObservers(change); - } + d->update(); } } @@ -221,11 +217,7 @@ void QLayerFilter::removeLayer(QLayer *layer) { Q_ASSERT(layer); Q_D(QLayerFilter); - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), layer); - change->setPropertyName("layer"); - d->notifyObservers(change); - } + d->update(); d->m_layers.removeOne(layer); // Remove bookkeeping connection d->unregisterDestructionHelper(layer); diff --git a/src/render/framegraph/qrendercapture.cpp b/src/render/framegraph/qrendercapture.cpp index 21eee51f6..cc74553b2 100644 --- a/src/render/framegraph/qrendercapture.cpp +++ b/src/render/framegraph/qrendercapture.cpp @@ -330,11 +330,9 @@ QRenderCaptureReply *QRenderCapture::requestCapture(int captureId) d->replyDestroyed(reply); }); - Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(id())); - change->setPropertyName(QByteArrayLiteral("renderCaptureRequest")); const QRenderCaptureRequest request = { captureId, QRect() }; - change->setValue(QVariant::fromValue(request)); - d->notifyObservers(change); + d->m_pendingRequests.push_back(request); + d->update(); return reply; } @@ -355,11 +353,9 @@ QRenderCaptureReply *QRenderCapture::requestCapture(const QRect &rect) d->replyDestroyed(reply); }); - Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(id())); - change->setPropertyName(QByteArrayLiteral("renderCaptureRequest")); const QRenderCaptureRequest request = { captureId, rect }; - change->setValue(QVariant::fromValue(request)); - d->notifyObservers(change); + d->m_pendingRequests.push_back(request); + d->update(); captureId++; diff --git a/src/render/framegraph/qrendercapture_p.h b/src/render/framegraph/qrendercapture_p.h index 4e509cc59..3dec4d280 100644 --- a/src/render/framegraph/qrendercapture_p.h +++ b/src/render/framegraph/qrendercapture_p.h @@ -57,6 +57,12 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +struct QRenderCaptureRequest +{ + int captureId; + QRect rect; +}; + class QRenderCapturePrivate : public QFrameGraphNodePrivate { public: @@ -64,6 +70,7 @@ public: ~QRenderCapturePrivate(); QVector<QRenderCaptureReply *> m_waitingReplies; QMutex m_mutex; + mutable QVector<QRenderCaptureRequest> m_pendingRequests; QRenderCaptureReply *createReply(int captureId); QRenderCaptureReply *takeReply(int captureId); @@ -82,6 +89,7 @@ public: int m_captureId; bool m_complete; + Q_DECLARE_PUBLIC(QRenderCaptureReply) }; @@ -100,12 +108,6 @@ struct RenderCaptureData typedef QSharedPointer<RenderCaptureData> RenderCaptureDataPtr; -struct QRenderCaptureRequest -{ - int captureId; - QRect rect; -}; - } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/framegraph/qrenderpassfilter.cpp b/src/render/framegraph/qrenderpassfilter.cpp index 56c229d9c..4ef7e6d2d 100644 --- a/src/render/framegraph/qrenderpassfilter.cpp +++ b/src/render/framegraph/qrenderpassfilter.cpp @@ -142,11 +142,7 @@ void QRenderPassFilter::addMatch(QFilterKey *filterKey) if (!filterKey->parent()) filterKey->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), filterKey); - change->setPropertyName("match"); - d->notifyObservers(change); - } + d->update(); } } @@ -158,11 +154,7 @@ void QRenderPassFilter::removeMatch(QFilterKey *filterKey) Q_ASSERT(filterKey); Q_D(QRenderPassFilter); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), filterKey); - change->setPropertyName("match"); - d->notifyObservers(change); - } + d->update(); d->m_matchList.removeOne(filterKey); // Remove bookkeeping connection d->unregisterDestructionHelper(filterKey); @@ -188,11 +180,7 @@ void QRenderPassFilter::addParameter(QParameter *parameter) if (!parameter->parent()) parameter->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); } } @@ -204,11 +192,7 @@ void QRenderPassFilter::removeParameter(QParameter *parameter) Q_ASSERT(parameter); Q_D(QRenderPassFilter); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); diff --git a/src/render/framegraph/qrenderstateset.cpp b/src/render/framegraph/qrenderstateset.cpp index 6f70456ab..d558a939e 100644 --- a/src/render/framegraph/qrenderstateset.cpp +++ b/src/render/framegraph/qrenderstateset.cpp @@ -194,11 +194,7 @@ void QRenderStateSet::addRenderState(QRenderState *state) if (!state->parent()) state->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), state); - change->setPropertyName("renderState"); - d->notifyObservers(change); - } + d->update(); } } @@ -210,11 +206,7 @@ void QRenderStateSet::removeRenderState(QRenderState *state) Q_ASSERT(state); Q_D(QRenderStateSet); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), state); - change->setPropertyName("renderState"); - d->notifyObservers(change); - } + d->update(); d->m_renderStates.removeOne(state); // Remove bookkeeping connection d->unregisterDestructionHelper(state); diff --git a/src/render/framegraph/qrendersurfaceselector.cpp b/src/render/framegraph/qrendersurfaceselector.cpp index 848d86f53..765aa1824 100644 --- a/src/render/framegraph/qrendersurfaceselector.cpp +++ b/src/render/framegraph/qrendersurfaceselector.cpp @@ -253,24 +253,10 @@ void QRenderSurfaceSelector::setSurface(QObject *surfaceObject) if (window) { d->m_widthConn = QObject::connect(window, &QWindow::widthChanged, [=] (int width) { - if (d->m_changeArbiter != nullptr) { - Qt3DCore::QPropertyUpdatedChangePtr change( - new Qt3DCore::QPropertyUpdatedChange(id())); - - change->setPropertyName("width"); - change->setValue(QVariant::fromValue(width)); - d->notifyObservers(change); - } + d->update(); }); d->m_heightConn = QObject::connect(window, &QWindow::heightChanged, [=] (int height) { - if (d->m_changeArbiter != nullptr) { - Qt3DCore::QPropertyUpdatedChangePtr change( - new Qt3DCore::QPropertyUpdatedChange(id())); - - change->setPropertyName("height"); - change->setValue(QVariant::fromValue(height)); - d->notifyObservers(change); - } + d->update(); }); d->m_screenConn = QObject::connect(window, &QWindow::screenChanged, [=] (QScreen *screen) { if (screen && surfacePixelRatio() != screen->devicePixelRatio()) diff --git a/src/render/framegraph/qrendertargetselector.cpp b/src/render/framegraph/qrendertargetselector.cpp index 1b4afc7e6..f4d95d507 100644 --- a/src/render/framegraph/qrendertargetselector.cpp +++ b/src/render/framegraph/qrendertargetselector.cpp @@ -153,13 +153,7 @@ void QRenderTargetSelector::setOutputs(const QVector<QRenderTargetOutput::Attach Q_D(QRenderTargetSelector); if (buffers != d->m_outputs) { d->m_outputs = buffers; - - if (d->m_changeArbiter) { - auto change = QPropertyUpdatedChangePtr::create(d->m_id); - change->setPropertyName("outputs"); - change->setValue(QVariant::fromValue(d->m_outputs)); - d->notifyObservers(change); - } + d->update(); } } diff --git a/src/render/framegraph/qsortpolicy.cpp b/src/render/framegraph/qsortpolicy.cpp index 6f852afbd..c8e3d23c5 100644 --- a/src/render/framegraph/qsortpolicy.cpp +++ b/src/render/framegraph/qsortpolicy.cpp @@ -178,7 +178,10 @@ void QSortPolicy::setSortTypes(const QVector<SortType> &sortTypes) if (sortTypes != d->m_sortTypes) { d->m_sortTypes = sortTypes; emit sortTypesChanged(sortTypes); + + const bool wasBlocked = blockNotifications(true); emit sortTypesChanged(sortTypesInt()); + blockNotifications(wasBlocked); } } diff --git a/src/render/framegraph/qtechniquefilter.cpp b/src/render/framegraph/qtechniquefilter.cpp index 404ad6991..28b151fc7 100644 --- a/src/render/framegraph/qtechniquefilter.cpp +++ b/src/render/framegraph/qtechniquefilter.cpp @@ -147,11 +147,7 @@ void QTechniqueFilter::addMatch(QFilterKey *filterKey) if (!filterKey->parent()) filterKey->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), filterKey); - change->setPropertyName("matchAll"); - d->notifyObservers(change); - } + d->update(); } } @@ -162,11 +158,7 @@ void QTechniqueFilter::removeMatch(QFilterKey *filterKey) { Q_ASSERT(filterKey); Q_D(QTechniqueFilter); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), filterKey); - change->setPropertyName("matchAll"); - d->notifyObservers(change); - } + d->update(); d->m_matchList.removeOne(filterKey); // Remove bookkeeping connection d->unregisterDestructionHelper(filterKey); @@ -192,11 +184,7 @@ void QTechniqueFilter::addParameter(QParameter *parameter) if (!parameter->parent()) parameter->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); } } @@ -207,11 +195,7 @@ void QTechniqueFilter::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QTechniqueFilter); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); diff --git a/src/render/framegraph/rendercapture.cpp b/src/render/framegraph/rendercapture.cpp index 166294889..68d62b6a5 100644 --- a/src/render/framegraph/rendercapture.cpp +++ b/src/render/framegraph/rendercapture.cpp @@ -70,16 +70,23 @@ QRenderCaptureRequest RenderCapture::takeCaptureRequest() return m_requestedCaptures.takeFirst(); } -void RenderCapture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void RenderCapture::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("renderCaptureRequest")) { - requestCapture(propertyChange->value().value<QRenderCaptureRequest>()); - markDirty(AbstractRenderer::FrameGraphDirty); - } + const QRenderCapture *node = qobject_cast<const QRenderCapture *>(frontEnd); + if (!node) + return; + + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + const QRenderCapturePrivate *d = static_cast<const QRenderCapturePrivate *>(QFrameGraphNodePrivate::get(node)); + const auto newPendingsCaptures = std::move(d->m_pendingRequests); + if (newPendingsCaptures.size() > 0) { + m_requestedCaptures.append(newPendingsCaptures); + markDirty(AbstractRenderer::FrameGraphDirty); } - FrameGraphNode::sceneChangeEvent(e); + + if (firstTime) + markDirty(AbstractRenderer::FrameGraphDirty); } // called by render thread diff --git a/src/render/framegraph/rendercapture_p.h b/src/render/framegraph/rendercapture_p.h index 71fa01ec1..4560c525d 100644 --- a/src/render/framegraph/rendercapture_p.h +++ b/src/render/framegraph/rendercapture_p.h @@ -68,8 +68,7 @@ public: void addRenderCapture(int captureId, const QImage &image); void sendRenderCaptures(); -protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: diff --git a/src/render/framegraph/renderpassfilternode.cpp b/src/render/framegraph/renderpassfilternode.cpp index e3da1e36d..afc49a563 100644 --- a/src/render/framegraph/renderpassfilternode.cpp +++ b/src/render/framegraph/renderpassfilternode.cpp @@ -58,16 +58,33 @@ RenderPassFilter::RenderPassFilter() { } -void RenderPassFilter::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void RenderPassFilter::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderPassFilterData>>(change); - const auto &data = typedChange->data; - m_filters = data.matchIds; - m_parameterPack.clear(); - m_parameterPack.setParameters(data.parameterIds); + const QRenderPassFilter *node = qobject_cast<const QRenderPassFilter *>(frontEnd); + if (!node) + return; + + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + if (firstTime) + m_parameterPack.clear(); + + auto parameters = qIdsForNodes(node->parameters()); + std::sort(std::begin(parameters), std::end(parameters)); + if (m_parameterPack.parameters() != parameters) { + m_parameterPack.setParameters(parameters); + markDirty(AbstractRenderer::FrameGraphDirty); + } + + auto filterIds = qIdsForNodes(node->matchAny()); + std::sort(std::begin(filterIds), std::end(filterIds)); + if (m_filters != filterIds) { + m_filters = filterIds; + markDirty(AbstractRenderer::FrameGraphDirty); + } } + QVector<Qt3DCore::QNodeId> RenderPassFilter::filters() const { return m_filters; @@ -89,40 +106,6 @@ QVector<Qt3DCore::QNodeId> RenderPassFilter::parameters() const return m_parameterPack.parameters(); } -void RenderPassFilter::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("match")) { - appendFilter(change->addedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (change->propertyName() == QByteArrayLiteral("parameter")) { - m_parameterPack.appendParameter(change->addedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } - break; - } - - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("match")) { - removeFilter(change->removedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (change->propertyName() == QByteArrayLiteral("parameter")) { - m_parameterPack.removeParameter(change->removedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } - break; - } - - default: - break; - } - FrameGraphNode::sceneChangeEvent(e); -} - } // namespace Render } // namespace Qt3DRender diff --git a/src/render/framegraph/renderpassfilternode_p.h b/src/render/framegraph/renderpassfilternode_p.h index 398d42049..157a162bb 100644 --- a/src/render/framegraph/renderpassfilternode_p.h +++ b/src/render/framegraph/renderpassfilternode_p.h @@ -76,11 +76,9 @@ public: QVector<Qt3DCore::QNodeId> parameters() const; void appendFilter(Qt3DCore::QNodeId criterionId); void removeFilter(Qt3DCore::QNodeId criterionId); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_filters; ParameterPack m_parameterPack; }; diff --git a/src/render/framegraph/rendersurfaceselector.cpp b/src/render/framegraph/rendersurfaceselector.cpp index 16a1199b5..173da77d6 100644 --- a/src/render/framegraph/rendersurfaceselector.cpp +++ b/src/render/framegraph/rendersurfaceselector.cpp @@ -73,6 +73,7 @@ namespace Render { RenderSurfaceSelector::RenderSurfaceSelector() : FrameGraphNode(FrameGraphNode::Surface) + , m_surfaceObj(nullptr) , m_surface(nullptr) , m_width(0) , m_height(0) @@ -80,45 +81,41 @@ RenderSurfaceSelector::RenderSurfaceSelector() { } -void RenderSurfaceSelector::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void RenderSurfaceSelector::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderSurfaceSelectorData>>(change); - const auto &data = typedChange->data; - m_surface = surfaceFromQObject(data.surface); - m_renderTargetSize = data.externalRenderTargetSize; - m_devicePixelRatio = data.surfacePixelRatio; + const QRenderSurfaceSelector *node = qobject_cast<const QRenderSurfaceSelector *>(frontEnd); + if (!node) + return; - if (m_surface && m_surface->surfaceClass() == QSurface::Window) { - QWindow *window = static_cast<QWindow *>(m_surface); - m_width = window->width(); - m_height = window->height(); + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + if (node->surface() != m_surfaceObj) { + m_surfaceObj = node->surface(); + m_surface = surfaceFromQObject(m_surfaceObj); + markDirty(AbstractRenderer::FrameGraphDirty); } -} -void RenderSurfaceSelector::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - qCDebug(Render::Framegraph) << Q_FUNC_INFO; - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("surface")) { - m_surface = surfaceFromQObject(propertyChange->value().value<QObject *>()); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("externalRenderTargetSize")) { - setRenderTargetSize(propertyChange->value().toSize()); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("width")) { - m_width = propertyChange->value().toInt(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("height")) { - m_height = propertyChange->value().toInt(); + if (m_surface && m_surface->surfaceClass() == QSurface::Window) { + QWindow *window = static_cast<QWindow *>(m_surface); + if (window->width() != m_width) { + m_width = window->width(); markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("surfacePixelRatio")) { - m_devicePixelRatio = propertyChange->value().toFloat(); + } + if (window->height() != m_height) { + m_height = window->height(); markDirty(AbstractRenderer::FrameGraphDirty); } } - FrameGraphNode::sceneChangeEvent(e); + + if (node->externalRenderTargetSize() != m_renderTargetSize) { + m_renderTargetSize = node->externalRenderTargetSize(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + + if (node->surfacePixelRatio() != m_devicePixelRatio) { + m_devicePixelRatio = node->surfacePixelRatio(); + markDirty(AbstractRenderer::FrameGraphDirty); + } } QSize RenderSurfaceSelector::renderTargetSize() const diff --git a/src/render/framegraph/rendersurfaceselector_p.h b/src/render/framegraph/rendersurfaceselector_p.h index 74863aa36..f1a139e84 100644 --- a/src/render/framegraph/rendersurfaceselector_p.h +++ b/src/render/framegraph/rendersurfaceselector_p.h @@ -68,7 +68,7 @@ public: QSize renderTargetSize() const; void setRenderTargetSize(const QSize &size) { m_renderTargetSize = size; } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; QSurface *surface() const { return m_surface; } inline int width() const Q_DECL_NOTHROW { return m_width; } @@ -76,8 +76,7 @@ public: inline float devicePixelRatio() const Q_DECL_NOTHROW { return m_devicePixelRatio; } private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - + QObject *m_surfaceObj; QSurface *m_surface; QSize m_renderTargetSize; int m_width; diff --git a/src/render/framegraph/rendertargetselectornode.cpp b/src/render/framegraph/rendertargetselectornode.cpp index 615608bd2..871a00154 100644 --- a/src/render/framegraph/rendertargetselectornode.cpp +++ b/src/render/framegraph/rendertargetselectornode.cpp @@ -59,29 +59,24 @@ RenderTargetSelector::RenderTargetSelector() : { } -void RenderTargetSelector::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void RenderTargetSelector::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderTargetSelectorData>>(change); - const auto &data = typedChange->data; - m_renderTargetUuid = data.targetId; - m_outputs = data.outputs; -} + const QRenderTargetSelector *node = qobject_cast<const QRenderTargetSelector *>(frontEnd); + if (!node) + return; -void RenderTargetSelector::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - qCDebug(Render::Framegraph) << Q_FUNC_INFO; - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("target")) { - m_renderTargetUuid = propertyChange->value().value<QNodeId>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("outputs")) { - m_outputs = propertyChange->value().value<QVector<Qt3DRender::QRenderTargetOutput::AttachmentPoint> >(); - markDirty(AbstractRenderer::FrameGraphDirty); - } + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + const QNodeId renderTargetId = qIdForNode(node->target()); + if (renderTargetId != m_renderTargetUuid) { + m_renderTargetUuid = renderTargetId; + markDirty(AbstractRenderer::FrameGraphDirty); + } + + if (node->outputs() != m_outputs) { + m_outputs = node->outputs(); + markDirty(AbstractRenderer::FrameGraphDirty); } - FrameGraphNode::sceneChangeEvent(e); } } // namespace Render diff --git a/src/render/framegraph/rendertargetselectornode_p.h b/src/render/framegraph/rendertargetselectornode_p.h index 81ac8a3d3..232ee9ecc 100644 --- a/src/render/framegraph/rendertargetselectornode_p.h +++ b/src/render/framegraph/rendertargetselectornode_p.h @@ -66,14 +66,12 @@ class RenderTargetSelector : public FrameGraphNode public: RenderTargetSelector(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Qt3DCore::QNodeId renderTargetUuid() const { return m_renderTargetUuid; } QVector<QRenderTargetOutput::AttachmentPoint> outputs() const { return m_outputs; } private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_renderTargetUuid; QVector<QRenderTargetOutput::AttachmentPoint> m_outputs; }; diff --git a/src/render/framegraph/sortpolicy.cpp b/src/render/framegraph/sortpolicy.cpp index b81d1f6cb..3c7975945 100644 --- a/src/render/framegraph/sortpolicy.cpp +++ b/src/render/framegraph/sortpolicy.cpp @@ -53,18 +53,19 @@ SortPolicy::SortPolicy() { } -void SortPolicy::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void SortPolicy::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("sortTypes")) { - auto sortTypesInt = propertyChange->value().value<QVector<int>>(); - m_sortTypes.clear(); - transformVector(sortTypesInt, m_sortTypes); - markDirty(AbstractRenderer::FrameGraphDirty); - } + const QSortPolicy *node = qobject_cast<const QSortPolicy *>(frontEnd); + if (!node) + return; + + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + const auto sortTypes = node->sortTypes(); + if (sortTypes != m_sortTypes) { + m_sortTypes = sortTypes; + markDirty(AbstractRenderer::FrameGraphDirty); } - FrameGraphNode::sceneChangeEvent(e); } QVector<QSortPolicy::SortType> SortPolicy::sortTypes() const @@ -72,14 +73,6 @@ QVector<QSortPolicy::SortType> SortPolicy::sortTypes() const return m_sortTypes; } -void SortPolicy::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) -{ - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QSortPolicyData>>(change); - const QSortPolicyData &data = typedChange->data; - m_sortTypes = data.sortTypes; -} - } // namepace Render } // namespace Qt3DRender diff --git a/src/render/framegraph/sortpolicy_p.h b/src/render/framegraph/sortpolicy_p.h index ef928af7b..8d572ead7 100644 --- a/src/render/framegraph/sortpolicy_p.h +++ b/src/render/framegraph/sortpolicy_p.h @@ -65,13 +65,11 @@ class Q_AUTOTEST_EXPORT SortPolicy : public FrameGraphNode public: SortPolicy(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; QVector<Qt3DRender::QSortPolicy::SortType> sortTypes() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DRender::QSortPolicy::SortType> m_sortTypes; }; diff --git a/src/render/framegraph/statesetnode.cpp b/src/render/framegraph/statesetnode.cpp index 96551684e..32ac5e569 100644 --- a/src/render/framegraph/statesetnode.cpp +++ b/src/render/framegraph/statesetnode.cpp @@ -68,40 +68,20 @@ QVector<QNodeId> StateSetNode::renderStates() const return m_renderStates; } -void StateSetNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void StateSetNode::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderStateSetData>>(change); - const auto &data = typedChange->data; - for (const auto &stateId : qAsConst(data.renderStateIds)) - addRenderState(stateId); -} + const QRenderStateSet *node = qobject_cast<const QRenderStateSet *>(frontEnd); + if (!node) + return; -void StateSetNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("renderState")) { - addRenderState(change->addedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } - break; - } - - case PropertyValueRemoved: { - const auto propertyChange = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("renderState")) { - removeRenderState(propertyChange->removedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } - break; - } + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); - default: - break; + auto stateIds = qIdsForNodes(node->renderStates()); + std::sort(std::begin(stateIds), std::end(stateIds)); + if (m_renderStates != stateIds) { + m_renderStates = stateIds; + markDirty(AbstractRenderer::FrameGraphDirty); } - FrameGraphNode::sceneChangeEvent(e); } void StateSetNode::addRenderState(QNodeId renderStateId) diff --git a/src/render/framegraph/statesetnode_p.h b/src/render/framegraph/statesetnode_p.h index d33e118cb..5081f3215 100644 --- a/src/render/framegraph/statesetnode_p.h +++ b/src/render/framegraph/statesetnode_p.h @@ -68,13 +68,13 @@ public: inline bool hasRenderStates() const { return !m_renderStates.empty(); } QVector<Qt3DCore::QNodeId> renderStates() const; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; + protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void addRenderState(Qt3DCore::QNodeId renderStateId); void removeRenderState(Qt3DCore::QNodeId renderStateId); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; QVector<Qt3DCore::QNodeId> m_renderStates; }; diff --git a/src/render/framegraph/techniquefilternode.cpp b/src/render/framegraph/techniquefilternode.cpp index 8816984ee..8739143e6 100644 --- a/src/render/framegraph/techniquefilternode.cpp +++ b/src/render/framegraph/techniquefilternode.cpp @@ -59,13 +59,30 @@ TechniqueFilter::TechniqueFilter() { } -void TechniqueFilter::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void TechniqueFilter::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QTechniqueFilterData>>(change); - const auto &data = typedChange->data; - m_filters = data.matchIds; - m_parameterPack.setParameters(data.parameterIds); + const QTechniqueFilter *node = qobject_cast<const QTechniqueFilter *>(frontEnd); + if (!node) + return; + + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + if (firstTime) + m_parameterPack.clear(); + + auto parameters = qIdsForNodes(node->parameters()); + std::sort(std::begin(parameters), std::end(parameters)); + if (m_parameterPack.parameters() != parameters) { + m_parameterPack.setParameters(parameters); + markDirty(AbstractRenderer::FrameGraphDirty); + } + + auto filterIds = qIdsForNodes(node->matchAll()); + std::sort(std::begin(filterIds), std::end(filterIds)); + if (m_filters != filterIds) { + m_filters = filterIds; + markDirty(AbstractRenderer::FrameGraphDirty); + } } QVector<Qt3DCore::QNodeId> TechniqueFilter::parameters() const @@ -89,39 +106,6 @@ void TechniqueFilter::removeFilter(Qt3DCore::QNodeId criterionId) m_filters.removeOne(criterionId); } -void TechniqueFilter::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("matchAll")) { - appendFilter(change->addedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (change->propertyName() == QByteArrayLiteral("parameter")) { - m_parameterPack.appendParameter(change->addedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } - break; - } - - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("matchAll")) { - removeFilter(change->removedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (change->propertyName() == QByteArrayLiteral("parameter")) { - m_parameterPack.removeParameter(change->removedNodeId()); - markDirty(AbstractRenderer::FrameGraphDirty); - } - break; - } - - default: - break; - } - FrameGraphNode::sceneChangeEvent(e); -} - } // namespace Render } // namespace Qt3DRender diff --git a/src/render/framegraph/techniquefilternode_p.h b/src/render/framegraph/techniquefilternode_p.h index d7e6c1508..e424e37e5 100644 --- a/src/render/framegraph/techniquefilternode_p.h +++ b/src/render/framegraph/techniquefilternode_p.h @@ -79,11 +79,9 @@ public: QVector<Qt3DCore::QNodeId> parameters() const; QVector<Qt3DCore::QNodeId> filters() const; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - void appendFilter(Qt3DCore::QNodeId criterionId); void removeFilter(Qt3DCore::QNodeId criterionId); diff --git a/src/render/framegraph/viewportnode.cpp b/src/render/framegraph/viewportnode.cpp index b3b53b0f9..c37278817 100644 --- a/src/render/framegraph/viewportnode.cpp +++ b/src/render/framegraph/viewportnode.cpp @@ -59,16 +59,28 @@ ViewportNode::ViewportNode() { } -void ViewportNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) + +void ViewportNode::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QViewportData>>(change); - const auto &data = typedChange->data; - m_xMin = data.normalizedRect.x(); - m_xMax = data.normalizedRect.width(); - m_yMin = data.normalizedRect.y(); - m_yMax = data.normalizedRect.height(); - m_gamma = data.gamma; + const QViewport *node = qobject_cast<const QViewport *>(frontEnd); + if (!node) + return; + + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + const QRectF oldRect(m_xMin, m_yMin, m_xMax, m_yMax); + if (oldRect != node->normalizedRect()) { + m_xMin = node->normalizedRect().x(); + m_yMin = node->normalizedRect().y(); + m_xMax = node->normalizedRect().width(); + m_yMax = node->normalizedRect().height(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + + if (node->gamma() != m_gamma) { + m_gamma = node->gamma(); + markDirty(AbstractRenderer::FrameGraphDirty); + } } float ViewportNode::xMin() const @@ -118,25 +130,6 @@ void ViewportNode::setGamma(float gamma) m_gamma = gamma; } -void ViewportNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("normalizedRect")) { - QRectF normalizedRect = propertyChange->value().toRectF(); - setXMin(normalizedRect.x()); - setYMin(normalizedRect.y()); - setXMax(normalizedRect.width()); - setYMax(normalizedRect.height()); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("gamma")) { - setGamma(propertyChange->value().toFloat()); - markDirty(AbstractRenderer::FrameGraphDirty); - } - } - FrameGraphNode::sceneChangeEvent(e); -} - QRectF ViewportNode::computeViewport(const QRectF &childViewport, const ViewportNode *parentViewport) { QRectF vp(parentViewport->xMin(), diff --git a/src/render/framegraph/viewportnode_p.h b/src/render/framegraph/viewportnode_p.h index 799b9b3dc..3e291a9da 100644 --- a/src/render/framegraph/viewportnode_p.h +++ b/src/render/framegraph/viewportnode_p.h @@ -84,13 +84,11 @@ public: float gamma() const; void setGamma(float gamma); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; static QRectF computeViewport(const QRectF &childViewport, const ViewportNode *parentViewport); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - float m_xMin; float m_yMin; float m_xMax; diff --git a/src/render/framegraph/waitfence.cpp b/src/render/framegraph/waitfence.cpp index 9480fb7a0..68ddda3d7 100644 --- a/src/render/framegraph/waitfence.cpp +++ b/src/render/framegraph/waitfence.cpp @@ -71,33 +71,30 @@ WaitFence::~WaitFence() { } -void WaitFence::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void WaitFence::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("handle")) { - m_data.handle = propertyChange->value(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("handleType")) { - m_data.handleType = static_cast<QWaitFence::HandleType>(propertyChange->value().toInt()); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("timeout")) { - m_data.timeout = propertyChange->value().value<quint64>(); - markDirty(AbstractRenderer::FrameGraphDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("waitOnCPU")) { - m_data.waitOnCPU = propertyChange->value().toBool(); - markDirty(AbstractRenderer::FrameGraphDirty); - } - } - FrameGraphNode::sceneChangeEvent(e); -} + const QWaitFence *node = qobject_cast<const QWaitFence *>(frontEnd); + if (!node) + return; -void WaitFence::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - FrameGraphNode::initializeFromPeer(change); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QWaitFenceData>>(change); - const QWaitFenceData &data = typedChange->data; - m_data = data; + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + if (node->handleType() != m_data.handleType) { + m_data.handleType = node->handleType(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + if (node->handle() != m_data.handle) { + m_data.handle = node->handle(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + if (node->timeout() != m_data.timeout) { + m_data.timeout = node->timeout(); + markDirty(AbstractRenderer::FrameGraphDirty); + } + if (node->waitOnCPU() != m_data.waitOnCPU) { + m_data.waitOnCPU = node->waitOnCPU(); + markDirty(AbstractRenderer::FrameGraphDirty); + } } } // namespace Render diff --git a/src/render/framegraph/waitfence_p.h b/src/render/framegraph/waitfence_p.h index dd48e0efa..811fc80a2 100644 --- a/src/render/framegraph/waitfence_p.h +++ b/src/render/framegraph/waitfence_p.h @@ -68,11 +68,9 @@ public: ~WaitFence(); inline QWaitFenceData data() const { return m_data; } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override; - QWaitFenceData m_data; }; diff --git a/src/render/frontend/qcamera.cpp b/src/render/frontend/qcamera.cpp index 1bf8caad9..2dcec7ed6 100644 --- a/src/render/frontend/qcamera.cpp +++ b/src/render/frontend/qcamera.cpp @@ -348,6 +348,18 @@ void QCameraPrivate::updateViewMatrixAndTransform(bool doEmit) * Holds the current projection matrix of the camera. */ +/*! + * \qmlproperty real Qt3D.Render::Camera::exposure + * Holds the current exposure of the camera. + * + * The default value is 0.0. + * + * The MetalRoughMaterial in Qt 3D Extras is currently the only provided + * material that makes use of camera exposure. Negative values will cause + * the material to be darker, and positive values will cause it to be lighter. + * + * Custom materials may choose to interpret the value differently. + */ /*! * \qmlproperty vector3d Qt3D.Render::Camera::position @@ -493,6 +505,14 @@ void QCameraPrivate::updateViewMatrixAndTransform(bool doEmit) /*! * \property QCamera::exposure * Holds the current exposure of the camera. + * + * The default value is 0.0. + * + * The MetalRoughMaterial in Qt 3D Extras is currently the only provided + * material that makes use of camera exposure. Negative values will cause + * the material to be darker, and positive values will cause it to be lighter. + * + * Custom materials may choose to interpret the value differently. */ /*! diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 8a0defceb..67bcb6c02 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -96,6 +96,7 @@ #include <Qt3DCore/qjoint.h> #include <Qt3DCore/qskeletonloader.h> +#include <Qt3DRender/private/backendnode_p.h> #include <Qt3DRender/private/cameraselectornode_p.h> #include <Qt3DRender/private/layerfilternode_p.h> #include <Qt3DRender/private/cameralens_p.h> @@ -232,6 +233,12 @@ QRenderAspectPrivate *QRenderAspectPrivate::findPrivate(Qt3DCore::QAspectEngine return nullptr; } +void QRenderAspectPrivate::syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const +{ + Render::BackendNode *renderBackend = static_cast<Render::BackendNode *>(backend); + renderBackend->syncFromFrontEnd(node, firstTime); +} + /*! \internal */ void QRenderAspectPrivate::registerBackendTypes() { @@ -245,8 +252,8 @@ void QRenderAspectPrivate::registerBackendTypes() qRegisterMetaType<Qt3DRender::QViewport*>(); qRegisterMetaType<Qt3DCore::QJoint*>(); - q->registerBackendType<Qt3DCore::QEntity>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers)); - q->registerBackendType<Qt3DCore::QTransform>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer)); + q->registerBackendType<Qt3DCore::QEntity, true>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers)); + q->registerBackendType<Qt3DCore::QTransform, true>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer)); q->registerBackendType<Qt3DRender::QCameraLens>(QSharedPointer<Render::CameraLensFunctor>::create(m_renderer, q)); q->registerBackendType<QLayer>(QSharedPointer<Render::NodeFunctor<Render::Layer, Render::LayerManager> >::create(m_renderer)); @@ -259,58 +266,58 @@ void QRenderAspectPrivate::registerBackendTypes() q->registerBackendType<QRenderState>(QSharedPointer<Render::NodeFunctor<Render::RenderStateNode, Render::RenderStateManager> >::create(m_renderer)); // Geometry + Compute - q->registerBackendType<QAttribute>(QSharedPointer<Render::NodeFunctor<Render::Attribute, Render::AttributeManager> >::create(m_renderer)); - q->registerBackendType<QBuffer>(QSharedPointer<Render::BufferFunctor>::create(m_renderer, m_nodeManagers->bufferManager())); + q->registerBackendType<QAttribute, true>(QSharedPointer<Render::NodeFunctor<Render::Attribute, Render::AttributeManager> >::create(m_renderer)); + q->registerBackendType<QBuffer, true>(QSharedPointer<Render::BufferFunctor>::create(m_renderer, m_nodeManagers->bufferManager())); q->registerBackendType<QComputeCommand>(QSharedPointer<Render::NodeFunctor<Render::ComputeCommand, Render::ComputeCommandManager> >::create(m_renderer)); - q->registerBackendType<QGeometry>(QSharedPointer<Render::NodeFunctor<Render::Geometry, Render::GeometryManager> >::create(m_renderer)); - q->registerBackendType<QGeometryRenderer>(QSharedPointer<Render::GeometryRendererFunctor>::create(m_renderer, m_nodeManagers->geometryRendererManager())); - q->registerBackendType<Qt3DCore::QArmature>(QSharedPointer<Render::NodeFunctor<Render::Armature, Render::ArmatureManager>>::create(m_renderer)); - q->registerBackendType<Qt3DCore::QAbstractSkeleton>(QSharedPointer<Render::SkeletonFunctor>::create(m_renderer, m_nodeManagers->skeletonManager(), m_nodeManagers->jointManager())); - q->registerBackendType<Qt3DCore::QJoint>(QSharedPointer<Render::JointFunctor>::create(m_renderer, m_nodeManagers->jointManager(), m_nodeManagers->skeletonManager())); + q->registerBackendType<QGeometry, true>(QSharedPointer<Render::NodeFunctor<Render::Geometry, Render::GeometryManager> >::create(m_renderer)); + q->registerBackendType<QGeometryRenderer, true>(QSharedPointer<Render::GeometryRendererFunctor>::create(m_renderer, m_nodeManagers->geometryRendererManager())); + q->registerBackendType<Qt3DCore::QArmature, true>(QSharedPointer<Render::NodeFunctor<Render::Armature, Render::ArmatureManager>>::create(m_renderer)); + q->registerBackendType<Qt3DCore::QAbstractSkeleton, true>(QSharedPointer<Render::SkeletonFunctor>::create(m_renderer, m_nodeManagers->skeletonManager(), m_nodeManagers->jointManager())); + q->registerBackendType<Qt3DCore::QJoint, true>(QSharedPointer<Render::JointFunctor>::create(m_renderer, m_nodeManagers->jointManager(), m_nodeManagers->skeletonManager())); // Textures - q->registerBackendType<QAbstractTexture>(QSharedPointer<Render::TextureFunctor>::create(m_renderer, m_nodeManagers->textureManager())); + q->registerBackendType<QAbstractTexture, true>(QSharedPointer<Render::TextureFunctor>::create(m_renderer, m_nodeManagers->textureManager())); q->registerBackendType<QAbstractTextureImage>(QSharedPointer<Render::TextureImageFunctor>::create(m_renderer, m_nodeManagers->textureImageManager())); // Material system - q->registerBackendType<QEffect>(QSharedPointer<Render::NodeFunctor<Render::Effect, Render::EffectManager> >::create(m_renderer)); + q->registerBackendType<QEffect, true>(QSharedPointer<Render::NodeFunctor<Render::Effect, Render::EffectManager> >::create(m_renderer)); q->registerBackendType<QFilterKey>(QSharedPointer<Render::NodeFunctor<Render::FilterKey, Render::FilterKeyManager> >::create(m_renderer)); - q->registerBackendType<QAbstractLight>(QSharedPointer<Render::RenderLightFunctor>::create(m_renderer, m_nodeManagers)); - q->registerBackendType<QEnvironmentLight>(QSharedPointer<Render::NodeFunctor<Render::EnvironmentLight, Render::EnvironmentLightManager> >::create(m_renderer)); - q->registerBackendType<QMaterial>(QSharedPointer<Render::NodeFunctor<Render::Material, Render::MaterialManager> >::create(m_renderer)); - q->registerBackendType<QParameter>(QSharedPointer<Render::NodeFunctor<Render::Parameter, Render::ParameterManager> >::create(m_renderer)); - q->registerBackendType<QRenderPass>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer)); + q->registerBackendType<QAbstractLight, true>(QSharedPointer<Render::RenderLightFunctor>::create(m_renderer, m_nodeManagers)); + q->registerBackendType<QEnvironmentLight, true>(QSharedPointer<Render::NodeFunctor<Render::EnvironmentLight, Render::EnvironmentLightManager> >::create(m_renderer)); + q->registerBackendType<QMaterial, true>(QSharedPointer<Render::NodeFunctor<Render::Material, Render::MaterialManager> >::create(m_renderer)); + q->registerBackendType<QParameter, true>(QSharedPointer<Render::NodeFunctor<Render::Parameter, Render::ParameterManager> >::create(m_renderer)); + q->registerBackendType<QRenderPass, true>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer)); q->registerBackendType<QShaderData>(QSharedPointer<Render::RenderShaderDataFunctor>::create(m_renderer, m_nodeManagers)); q->registerBackendType<QShaderProgram>(QSharedPointer<Render::NodeFunctor<Render::Shader, Render::ShaderManager> >::create(m_renderer)); q->registerBackendType<QShaderProgramBuilder>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer)); - q->registerBackendType<QTechnique>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers)); + q->registerBackendType<QTechnique, true>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers)); q->registerBackendType<QShaderImage>(QSharedPointer<Render::NodeFunctor<Render::ShaderImage, Render::ShaderImageManager>>::create(m_renderer)); // Framegraph - q->registerBackendType<QFrameGraphNode>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrameGraphNode, QFrameGraphNode> >::create(m_renderer)); - q->registerBackendType<QCameraSelector>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::CameraSelector, QCameraSelector> >::create(m_renderer)); - q->registerBackendType<QClearBuffers>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ClearBuffers, QClearBuffers> >::create(m_renderer)); - q->registerBackendType<QDispatchCompute>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::DispatchCompute, QDispatchCompute> >::create(m_renderer)); - q->registerBackendType<QFrustumCulling>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrustumCulling, QFrustumCulling> >::create(m_renderer)); - q->registerBackendType<QLayerFilter>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::LayerFilterNode, QLayerFilter> >::create(m_renderer)); - q->registerBackendType<QNoDraw>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::NoDraw, QNoDraw> >::create(m_renderer)); - q->registerBackendType<QRenderPassFilter>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderPassFilter, QRenderPassFilter> >::create(m_renderer)); - q->registerBackendType<QRenderStateSet>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::StateSetNode, QRenderStateSet> >::create(m_renderer)); - q->registerBackendType<QRenderSurfaceSelector>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderSurfaceSelector, QRenderSurfaceSelector> >::create(m_renderer)); - q->registerBackendType<QRenderTargetSelector>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderTargetSelector, QRenderTargetSelector> >::create(m_renderer)); - q->registerBackendType<QSortPolicy>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SortPolicy, QSortPolicy> >::create(m_renderer)); - q->registerBackendType<QTechniqueFilter>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::TechniqueFilter, QTechniqueFilter> >::create(m_renderer)); - q->registerBackendType<QViewport>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ViewportNode, QViewport> >::create(m_renderer)); - q->registerBackendType<QRenderCapture>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderCapture, QRenderCapture> >::create(m_renderer)); - q->registerBackendType<QBufferCapture>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BufferCapture, QBufferCapture> >::create(m_renderer)); - q->registerBackendType<QMemoryBarrier>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::MemoryBarrier, QMemoryBarrier> >::create(m_renderer)); - q->registerBackendType<QProximityFilter>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ProximityFilter, QProximityFilter> >::create(m_renderer)); - q->registerBackendType<QBlitFramebuffer>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BlitFramebuffer, QBlitFramebuffer> >::create(m_renderer)); - q->registerBackendType<QSetFence>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SetFence, QSetFence> >::create(m_renderer)); - q->registerBackendType<QWaitFence>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::WaitFence, QWaitFence> >::create(m_renderer)); - q->registerBackendType<QNoPicking>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::NoPicking, QNoPicking> >::create(m_renderer)); - q->registerBackendType<QSubtreeEnabler>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SubtreeEnabler, QSubtreeEnabler> >::create(m_renderer)); + q->registerBackendType<QFrameGraphNode, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrameGraphNode, QFrameGraphNode> >::create(m_renderer)); + q->registerBackendType<QCameraSelector, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::CameraSelector, QCameraSelector> >::create(m_renderer)); + q->registerBackendType<QClearBuffers, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ClearBuffers, QClearBuffers> >::create(m_renderer)); + q->registerBackendType<QDispatchCompute, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::DispatchCompute, QDispatchCompute> >::create(m_renderer)); + q->registerBackendType<QFrustumCulling, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrustumCulling, QFrustumCulling> >::create(m_renderer)); + q->registerBackendType<QLayerFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::LayerFilterNode, QLayerFilter> >::create(m_renderer)); + q->registerBackendType<QNoDraw, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::NoDraw, QNoDraw> >::create(m_renderer)); + q->registerBackendType<QRenderPassFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderPassFilter, QRenderPassFilter> >::create(m_renderer)); + q->registerBackendType<QRenderStateSet, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::StateSetNode, QRenderStateSet> >::create(m_renderer)); + q->registerBackendType<QRenderSurfaceSelector, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderSurfaceSelector, QRenderSurfaceSelector> >::create(m_renderer)); + q->registerBackendType<QRenderTargetSelector, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderTargetSelector, QRenderTargetSelector> >::create(m_renderer)); + q->registerBackendType<QSortPolicy, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SortPolicy, QSortPolicy> >::create(m_renderer)); + q->registerBackendType<QTechniqueFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::TechniqueFilter, QTechniqueFilter> >::create(m_renderer)); + q->registerBackendType<QViewport, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ViewportNode, QViewport> >::create(m_renderer)); + q->registerBackendType<QRenderCapture, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderCapture, QRenderCapture> >::create(m_renderer)); + q->registerBackendType<QBufferCapture, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BufferCapture, QBufferCapture> >::create(m_renderer)); + q->registerBackendType<QMemoryBarrier, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::MemoryBarrier, QMemoryBarrier> >::create(m_renderer)); + q->registerBackendType<QProximityFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ProximityFilter, QProximityFilter> >::create(m_renderer)); + q->registerBackendType<QBlitFramebuffer, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BlitFramebuffer, QBlitFramebuffer> >::create(m_renderer)); + q->registerBackendType<QSetFence, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SetFence, QSetFence> >::create(m_renderer)); + q->registerBackendType<QWaitFence, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::WaitFence, QWaitFence> >::create(m_renderer)); + q->registerBackendType<QNoPicking, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::NoPicking, QNoPicking> >::create(m_renderer)); + q->registerBackendType<QSubtreeEnabler, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SubtreeEnabler, QSubtreeEnabler> >::create(m_renderer)); // Picking q->registerBackendType<QObjectPicker>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer)); @@ -542,7 +549,7 @@ void QRenderAspect::onEngineStartup() Render::NodeManagers *managers = d->m_renderer->nodeManagers(); Render::Entity *rootEntity = managers->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId()); Q_ASSERT(rootEntity); - d->m_renderer->setSceneRoot(d, rootEntity); + d->m_renderer->setSceneRoot(rootEntity); } void QRenderAspect::onRegistered() diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h index 657e6a301..8ef4ecd12 100644 --- a/src/render/frontend/qrenderaspect_p.h +++ b/src/render/frontend/qrenderaspect_p.h @@ -85,6 +85,8 @@ public: static QRenderAspectPrivate* findPrivate(Qt3DCore::QAspectEngine *engine); + void syncDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QBackendNode *backend, bool firstTime) const override; + void registerBackendTypes(); void unregisterBackendTypes(); void loadSceneParsers(); diff --git a/src/render/geometry/armature.cpp b/src/render/geometry/armature.cpp index 15a26c9ec..cfa2e572a 100644 --- a/src/render/geometry/armature.cpp +++ b/src/render/geometry/armature.cpp @@ -36,6 +36,8 @@ #include "armature_p.h" +#include <Qt3DCore/qarmature.h> +#include <Qt3DCore/qabstractskeleton.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qarmature_p.h> @@ -52,32 +54,20 @@ Armature::Armature() { } -void Armature::cleanup() +void Armature::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - m_skeletonId = Qt3DCore::QNodeId(); - setEnabled(false); -} + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QArmature *node = qobject_cast<const QArmature *>(frontEnd); + if (!node) + return; -void Armature::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<QNodeCreatedChange<QArmatureData>>(change); - m_skeletonId = typedChange->data.skeletonId; + m_skeletonId = node->skeleton() ? node->skeleton()->id() : QNodeId{}; } -void Armature::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void Armature::cleanup() { - switch (e->type()) { - case Qt3DCore::PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("skeleton")) - m_skeletonId = change->value().value<QNodeId>(); - break; - } - - default: - break; - } - QBackendNode::sceneChangeEvent(e); + m_skeletonId = Qt3DCore::QNodeId(); + setEnabled(false); } } // namespace Render diff --git a/src/render/geometry/armature_p.h b/src/render/geometry/armature_p.h index 3e6e52a3f..39baa4a79 100644 --- a/src/render/geometry/armature_p.h +++ b/src/render/geometry/armature_p.h @@ -63,7 +63,7 @@ class Q_AUTOTEST_EXPORT Armature : public BackendNode public: Armature(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void cleanup(); Qt3DCore::QNodeId skeletonId() const { return m_skeletonId; } @@ -73,8 +73,6 @@ public: const UniformValue &skinningPaletteUniform() const { return m_skinningPaletteUniform; } private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_skeletonId; UniformValue m_skinningPaletteUniform; }; diff --git a/src/render/geometry/attribute.cpp b/src/render/geometry/attribute.cpp index bc6b27851..f241a85e5 100644 --- a/src/render/geometry/attribute.cpp +++ b/src/render/geometry/attribute.cpp @@ -83,78 +83,54 @@ void Attribute::cleanup() m_nameId = 0; } -void Attribute::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Attribute::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAttributeData>>(change); - const auto &data = typedChange->data; - m_bufferId = data.bufferId; - m_name = data.name; - m_nameId = StringToInt::lookupId(m_name); - m_vertexBaseType = data.vertexBaseType; - m_vertexSize = data.vertexSize; - m_count = data.count; - m_byteStride = data.byteStride; - m_byteOffset = data.byteOffset; - m_divisor = data.divisor; - m_attributeType = data.attributeType; - m_attributeDirty = true; -} - -/*! - \fn Qt3DRender::QAttribute::dataSizeChanged(uint vertexSize) - - The signal is emitted with \a vertexSize when the dataSize changes. - -*/ -/*! - \fn Qt3DRender::QAttribute::dataTypeChanged(Qt3DRender::QAttribute::VertexBaseType vertexBaseType) - - The signal is emitted with \a vertexBaseType when the dataType changed. -*/ -void Attribute::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyUpdated: { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - QByteArray propertyName = propertyChange->propertyName(); - - if (propertyName == QByteArrayLiteral("name")) { - m_name = propertyChange->value().toString(); - m_nameId = StringToInt::lookupId(m_name); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("vertexBaseType")) { - m_vertexBaseType = static_cast<QAttribute::VertexBaseType>(propertyChange->value().value<int>()); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("vertexSize")) { - m_vertexSize = propertyChange->value().value<uint>(); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("count")) { - m_count = propertyChange->value().value<uint>(); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("byteStride")) { - m_byteStride = propertyChange->value().value<uint>(); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("byteOffset")) { - m_byteOffset = propertyChange->value().value<uint>(); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("divisor")) { - m_divisor = propertyChange->value().value<uint>(); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("attributeType")) { - m_attributeType = static_cast<QAttribute::AttributeType>(propertyChange->value().value<int>()); - m_attributeDirty = true; - } else if (propertyName == QByteArrayLiteral("buffer")) { - m_bufferId = propertyChange->value().value<QNodeId>(); - m_attributeDirty = true; - } - markDirty(AbstractRenderer::AllDirty); - break; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAttribute *node = qobject_cast<const QAttribute *>(frontEnd); + if (!node) + return; + + m_attributeDirty = firstTime; + if (m_name != node->name()) { + m_name = node->name(); + m_nameId = StringToInt::lookupId(m_name); + m_attributeDirty = true; } - - default: - break; + if (m_vertexBaseType != node->vertexBaseType()) { + m_vertexBaseType = node->vertexBaseType(); + m_attributeDirty = true; } - BackendNode::sceneChangeEvent(e); + if (m_vertexSize != node->vertexSize()) { + m_vertexSize = node->vertexSize(); + m_attributeDirty = true; + } + if (m_count != node->count()) { + m_count = node->count(); + m_attributeDirty = true; + } + if (m_byteStride != node->byteStride()) { + m_byteStride = node->byteStride(); + m_attributeDirty = true; + } + if (m_byteOffset != node->byteOffset()) { + m_byteOffset = node->byteOffset(); + m_attributeDirty = true; + } + if (m_divisor != node->divisor()) { + m_divisor = node->divisor(); + m_attributeDirty = true; + } + if (m_attributeType != node->attributeType()) { + m_attributeType = node->attributeType(); + m_attributeDirty = true; + } + const auto bufferId = node->buffer() ? node->buffer()->id() : QNodeId{}; + if (bufferId != m_bufferId) { + m_bufferId = bufferId; + m_attributeDirty = true; + } + + markDirty(AbstractRenderer::AllDirty); } void Attribute::unsetDirty() diff --git a/src/render/geometry/attribute_p.h b/src/render/geometry/attribute_p.h index e01537605..4b47146e1 100644 --- a/src/render/geometry/attribute_p.h +++ b/src/render/geometry/attribute_p.h @@ -68,7 +68,7 @@ public: void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; inline Qt3DCore::QNodeId bufferId() const { return m_bufferId; } inline QString name() const { return m_name; } @@ -84,8 +84,6 @@ public: void unsetDirty(); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_bufferId; QString m_name; int m_nameId; diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp index d60f89c7d..998db3640 100644 --- a/src/render/geometry/buffer.cpp +++ b/src/render/geometry/buffer.cpp @@ -113,28 +113,6 @@ void Buffer::updateDataFromGPUToCPU(QByteArray data) notifyObservers(e); } -void Buffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QBufferData>>(change); - const auto &data = typedChange->data; - m_data = data.data; - m_usage = data.usage; - m_syncData = data.syncData; - m_access = data.access; - m_bufferDirty = true; - - if (!m_data.isEmpty()) - forceDataUpload(); - - m_functor = data.functor; - Q_ASSERT(m_manager); - if (m_functor) - m_manager->addDirtyBuffer(peerId()); - - m_manager->addBufferReference(peerId()); - markDirty(AbstractRenderer::BuffersDirty); -} - void Buffer::forceDataUpload() { // We push back an update with offset = -1 @@ -145,40 +123,50 @@ void Buffer::forceDataUpload() m_bufferUpdates.push_back(updateNewData); } -void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void Buffer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - QByteArray propertyName = propertyChange->propertyName(); - if (propertyName == QByteArrayLiteral("data")) { - QByteArray newData = propertyChange->value().toByteArray(); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QBuffer *node = qobject_cast<const QBuffer *>(frontEnd); + if (!node) + return; + + if (firstTime && m_manager != nullptr) + m_manager->addBufferReference(peerId()); + + m_syncData = node->isSyncData(); + m_access = node->accessType(); + if (m_usage != node->usage()) { + m_usage = node->usage(); + m_bufferDirty = true; + } + { + QBufferDataGeneratorPtr newGenerator = node->dataGenerator(); + bool dirty = (newGenerator && m_functor && !(*newGenerator == *m_functor)) || + (newGenerator.isNull() && !m_functor.isNull()) || + (!newGenerator.isNull() && m_functor.isNull()); + m_bufferDirty |= dirty; + m_functor = newGenerator; + if (m_functor && m_manager != nullptr) + m_manager->addDirtyBuffer(peerId()); + } + { + QVariant v = node->property("QT3D_updateData"); + if (v.isValid()) { + Qt3DRender::QBufferUpdate updateData = v.value<Qt3DRender::QBufferUpdate>(); + m_data.replace(updateData.offset, updateData.data.size(), updateData.data); + m_bufferUpdates.push_back(updateData); + m_bufferDirty = true; + const_cast<QBuffer *>(node)->setProperty("QT3D_updateData", {}); + } else { + QByteArray newData = node->data(); bool dirty = m_data != newData; m_bufferDirty |= dirty; m_data = newData; - if (dirty) + if (dirty && !m_data.isEmpty()) forceDataUpload(); - } else if (propertyName == QByteArrayLiteral("updateData")) { - Qt3DRender::QBufferUpdate updateData = propertyChange->value().value<Qt3DRender::QBufferUpdate>(); - m_data.replace(updateData.offset, updateData.data.size(), updateData.data); - m_bufferUpdates.push_back(updateData); - m_bufferDirty = true; - } else if (propertyName == QByteArrayLiteral("usage")) { - m_usage = static_cast<QBuffer::UsageType>(propertyChange->value().value<int>()); - m_bufferDirty = true; - } else if (propertyName == QByteArrayLiteral("accessType")) { - m_access = static_cast<QBuffer::AccessType>(propertyChange->value().value<int>()); - } else if (propertyName == QByteArrayLiteral("dataGenerator")) { - QBufferDataGeneratorPtr newGenerator = propertyChange->value().value<QBufferDataGeneratorPtr>(); - m_bufferDirty |= !(newGenerator && m_functor && *newGenerator == *m_functor); - m_functor = newGenerator; - if (m_functor && m_manager != nullptr) - m_manager->addDirtyBuffer(peerId()); - } else if (propertyName == QByteArrayLiteral("syncData")) { - m_syncData = propertyChange->value().toBool(); } - markDirty(AbstractRenderer::BuffersDirty); } - BackendNode::sceneChangeEvent(e); + markDirty(AbstractRenderer::BuffersDirty); } // Called by Renderer once the buffer has been uploaded to OpenGL diff --git a/src/render/geometry/buffer_p.h b/src/render/geometry/buffer_p.h index 9a171599d..a3f52d1b3 100644 --- a/src/render/geometry/buffer_p.h +++ b/src/render/geometry/buffer_p.h @@ -73,7 +73,7 @@ public: ~Buffer(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void setManager(BufferManager *manager); void executeFunctor(); @@ -88,7 +88,6 @@ public: void unsetDirty(); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; void forceDataUpload(); QBuffer::UsageType m_usage; diff --git a/src/render/geometry/geometry.cpp b/src/render/geometry/geometry.cpp index 4ee02a74d..cb401df5b 100644 --- a/src/render/geometry/geometry.cpp +++ b/src/render/geometry/geometry.cpp @@ -45,6 +45,8 @@ #include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qpropertynoderemovedchange.h> +#include <algorithm> + QT_BEGIN_NAMESPACE using namespace Qt3DCore; @@ -76,51 +78,29 @@ void Geometry::cleanup() m_shouldNotifyMaxExtentChanged = false; } -void Geometry::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QGeometryData>>(change); - const auto &data = typedChange->data; - m_attributes = data.attributeIds; - m_boundingPositionAttribute = data.boundingVolumePositionAttributeId; - m_geometryDirty = true; - markDirty(AbstractRenderer::GeometryDirty); -} - -void Geometry::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void Geometry::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("attribute")) { - m_attributes.push_back(change->addedNodeId()); - m_geometryDirty = true; - } - break; - } - - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("attribute")) { - m_attributes.removeOne(change->removedNodeId()); - m_geometryDirty = true; - } - break; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QGeometry *node = qobject_cast<const QGeometry *>(frontEnd); + if (!node) + return; + + m_geometryDirty |= firstTime; + + QNodeIdVector attribs = qIdsForNodes(node->attributes()); + std::sort(std::begin(attribs), std::end(attribs)); + if (m_attributes != attribs) { + m_attributes = attribs; + m_geometryDirty = true; } - case PropertyUpdated: { + if ((node->boundingVolumePositionAttribute() && node->boundingVolumePositionAttribute()->id() != m_boundingPositionAttribute) || // Note: doesn't set dirtyness as this parameter changing doesn't need a new VAO update. - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("boundingVolumePositionAttribute")) { - m_boundingPositionAttribute = change->value().value<QNodeId>(); - break; - } + (!node->boundingVolumePositionAttribute() && !m_boundingPositionAttribute.isNull())) { + m_boundingPositionAttribute = node->boundingVolumePositionAttribute() ? node->boundingVolumePositionAttribute()->id() : QNodeId{}; } - default: - break; - } markDirty(AbstractRenderer::GeometryDirty); - BackendNode::sceneChangeEvent(e); } void Geometry::unsetDirty() diff --git a/src/render/geometry/geometry_p.h b/src/render/geometry/geometry_p.h index e66524787..429a577b0 100644 --- a/src/render/geometry/geometry_p.h +++ b/src/render/geometry/geometry_p.h @@ -68,7 +68,7 @@ public: void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; inline QVector<Qt3DCore::QNodeId> attributes() const { return m_attributes; } inline bool isDirty() const { return m_geometryDirty; } @@ -82,8 +82,6 @@ public: void notifyExtentChanged(); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_attributes; bool m_geometryDirty; Qt3DCore::QNodeId m_boundingPositionAttribute; diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp index ea059c6ee..b5c741659 100644 --- a/src/render/geometry/geometryrenderer.cpp +++ b/src/render/geometry/geometryrenderer.cpp @@ -105,95 +105,47 @@ void GeometryRenderer::setManager(GeometryRendererManager *manager) m_manager = manager; } -void GeometryRenderer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void GeometryRenderer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QGeometryRendererData>>(change); - const auto &data = typedChange->data; - m_geometryId = data.geometryId; - m_instanceCount = data.instanceCount; - m_vertexCount = data.vertexCount; - m_indexOffset = data.indexOffset; - m_firstInstance = data.firstInstance; - m_firstVertex = data.firstVertex; - m_indexBufferByteOffset = data.indexBufferByteOffset; - m_restartIndexValue = data.restartIndexValue; - m_verticesPerPatch = data.verticesPerPatch; - m_primitiveRestartEnabled = data.primitiveRestart; - m_primitiveType = data.primitiveType; - - Q_ASSERT(m_manager); - m_geometryFactory = data.geometryFactory; - if (m_geometryFactory) - m_manager->addDirtyGeometryRenderer(peerId()); - - m_dirty = true; - markDirty(AbstractRenderer::GeometryDirty); -} - -void GeometryRenderer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyUpdated: { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - QByteArray propertyName = propertyChange->propertyName(); - - if (propertyName == QByteArrayLiteral("instanceCount")) { - m_instanceCount = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("vertexCount")) { - m_vertexCount = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("indexOffset")) { - m_indexOffset = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("firstInstance")) { - m_firstInstance = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("firstVertex")) { - m_firstVertex = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("indexBufferByteOffset")) { - m_indexBufferByteOffset = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("restartIndexValue")) { - m_restartIndexValue = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("verticesPerPatch")) { - m_verticesPerPatch = propertyChange->value().value<int>(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("primitiveRestartEnabled")) { - m_primitiveRestartEnabled = propertyChange->value().toBool(); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("primitiveType")) { - m_primitiveType = static_cast<QGeometryRenderer::PrimitiveType>(propertyChange->value().value<int>()); - m_dirty = true; - } else if (propertyName == QByteArrayLiteral("geometryFactory")) { - QGeometryFactoryPtr newFunctor = propertyChange->value().value<QGeometryFactoryPtr>(); - const bool functorDirty = ((m_geometryFactory && !newFunctor) - || (!m_geometryFactory && newFunctor) - || (m_geometryFactory && newFunctor && !(*newFunctor == *m_geometryFactory))); - m_dirty |= functorDirty; - if (functorDirty) { - m_geometryFactory = newFunctor; - if (m_geometryFactory && m_manager != nullptr) - m_manager->addDirtyGeometryRenderer(peerId()); - } - } else if (propertyName == QByteArrayLiteral("geometry")) { - m_geometryId = propertyChange->value().value<Qt3DCore::QNodeId>(); - m_dirty = true; - } - break; - } - - default: - break; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QGeometryRenderer *node = qobject_cast<const QGeometryRenderer *>(frontEnd); + if (!node) + return; + + m_dirty |= m_instanceCount != node->instanceCount(); + m_instanceCount = node->instanceCount(); + m_dirty |= m_vertexCount != node->vertexCount(); + m_vertexCount = node->vertexCount(); + m_dirty |= m_indexOffset != node->indexOffset(); + m_indexOffset = node->indexOffset(); + m_dirty |= m_firstInstance != node->firstInstance(); + m_firstInstance = node->firstInstance(); + m_dirty |= m_firstVertex != node->firstVertex(); + m_firstVertex = node->firstVertex(); + m_dirty |= m_indexBufferByteOffset != node->indexBufferByteOffset(); + m_indexBufferByteOffset = node->indexBufferByteOffset(); + m_dirty |= m_restartIndexValue != node->restartIndexValue(); + m_restartIndexValue = node->restartIndexValue(); + m_dirty |= m_verticesPerPatch != node->verticesPerPatch(); + m_verticesPerPatch = node->verticesPerPatch(); + m_dirty |= m_primitiveRestartEnabled != node->primitiveRestartEnabled(); + m_primitiveRestartEnabled = node->primitiveRestartEnabled(); + m_dirty |= m_primitiveType != node->primitiveType(); + m_primitiveType = node->primitiveType(); + m_dirty |= (node->geometry() && m_geometryId != node->geometry()->id()) || (!node->geometry() && !m_geometryId.isNull()); + m_geometryId = node->geometry() ? node->geometry()->id() : Qt3DCore::QNodeId(); + QGeometryFactoryPtr newFunctor = node->geometryFactory(); + const bool functorDirty = ((m_geometryFactory && !newFunctor) + || (!m_geometryFactory && newFunctor) + || (m_geometryFactory && newFunctor && !(*newFunctor == *m_geometryFactory))); + if (functorDirty) { + m_dirty = true; + m_geometryFactory = newFunctor; + if (m_geometryFactory && m_manager != nullptr) + m_manager->addDirtyGeometryRenderer(peerId()); } markDirty(AbstractRenderer::GeometryDirty); - - BackendNode::sceneChangeEvent(e); - - // Add to dirty list in manager } void GeometryRenderer::executeFunctor() diff --git a/src/render/geometry/geometryrenderer_p.h b/src/render/geometry/geometryrenderer_p.h index 57d1ca0be..da538a00d 100644 --- a/src/render/geometry/geometryrenderer_p.h +++ b/src/render/geometry/geometryrenderer_p.h @@ -74,7 +74,7 @@ public: void cleanup(); void setManager(GeometryRendererManager *manager); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void executeFunctor(); inline Qt3DCore::QNodeId geometryId() const { return m_geometryId; } @@ -98,8 +98,6 @@ public: QVector<RayCasting::QBoundingVolume *> triangleData() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_geometryId; int m_instanceCount; int m_vertexCount; diff --git a/src/render/geometry/joint.cpp b/src/render/geometry/joint.cpp index c770564f9..86d583f51 100644 --- a/src/render/geometry/joint.cpp +++ b/src/render/geometry/joint.cpp @@ -39,11 +39,14 @@ #include "joint_p.h" #include <Qt3DRender/private/managers_p.h> +#include <Qt3DCore/QJoint> #include <Qt3DCore/private/qjoint_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qpropertynoderemovedchange.h> +#include <algorithm> + QT_BEGIN_NAMESPACE using namespace Qt3DCore; @@ -69,21 +72,7 @@ void Joint::cleanup() setEnabled(false); } -void Joint::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - Q_ASSERT(m_jointManager); - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QJointData>>(change); - const auto &data = typedChange->data; - m_inverseBindMatrix = data.inverseBindMatrix; - m_localPose.rotation = data.rotation; - m_localPose.scale = data.scale; - m_localPose.translation = data.translation; - m_childJointIds = data.childJointIds; - m_name = data.name; - markDirty(AbstractRenderer::JointDirty); - m_jointManager->addDirtyJoint(peerId()); -} - +// TODOSYNC remove once animation changes don't use messages anymore void Joint::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { if (e->type() == PropertyUpdated) { @@ -123,10 +112,60 @@ void Joint::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) if (removedChange->propertyName() == QByteArrayLiteral("childJoint")) m_childJointIds.removeOne(removedChange->removedNodeId()); } - BackendNode::sceneChangeEvent(e); } +void Joint::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) +{ + const Qt3DCore::QJoint *joint = qobject_cast<const Qt3DCore::QJoint *>(frontEnd); + if (!joint) + return; + + if (m_localPose.scale != joint->scale()) { + m_localPose.scale = joint->scale(); + markDirty(AbstractRenderer::JointDirty); + m_jointManager->addDirtyJoint(peerId()); + } + if (m_localPose.rotation != joint->rotation()) { + m_localPose.rotation = joint->rotation(); + markDirty(AbstractRenderer::JointDirty); + m_jointManager->addDirtyJoint(peerId()); + } + if (m_localPose.translation != joint->translation()) { + m_localPose.translation = joint->translation(); + markDirty(AbstractRenderer::JointDirty); + m_jointManager->addDirtyJoint(peerId()); + } + if (m_inverseBindMatrix != joint->inverseBindMatrix()) { + // Setting the inverse bind matrix should be a rare operation. Usually it is + // set once and then remains constant for the duration of the skeleton. So just + // trigger a rebuild of the skeleton's SkeletonData which will include obtaining + // the inverse bind matrix. + m_inverseBindMatrix = joint->inverseBindMatrix(); + m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_owningSkeleton); + } + if (m_name != joint->name()) { + // Joint name doesn't affect anything in the render aspect so no need + // to mark anything as dirty. + m_name = joint->name(); + + // TODO: Notify other aspects (animation) about the name change. + } + + Qt3DCore::QNodeIdVector childIds = qIdsForNodes(joint->childJoints()); + std::sort(std::begin(childIds), std::end(childIds)); + if (m_childJointIds != childIds) { + m_childJointIds = childIds; + } + + if (firstTime) { + markDirty(AbstractRenderer::JointDirty); + m_jointManager->addDirtyJoint(peerId()); + } + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); +} + JointFunctor::JointFunctor(AbstractRenderer *renderer, JointManager *jointManager, diff --git a/src/render/geometry/joint_p.h b/src/render/geometry/joint_p.h index e144ac489..d0530ac04 100644 --- a/src/render/geometry/joint_p.h +++ b/src/render/geometry/joint_p.h @@ -70,6 +70,7 @@ public: void cleanup(); void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Qt3DCore::Sqt localPose() const { return m_localPose; } QMatrix4x4 inverseBindMatrix() const { return m_inverseBindMatrix; } @@ -90,8 +91,6 @@ public: SkeletonManager *skeletonManager() const { return m_skeletonManager; } private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QMatrix4x4 m_inverseBindMatrix; Qt3DCore::Sqt m_localPose; QVector<Qt3DCore::QNodeId> m_childJointIds; diff --git a/src/render/geometry/qattribute.cpp b/src/render/geometry/qattribute.cpp index ca467fda9..a28d0baa6 100644 --- a/src/render/geometry/qattribute.cpp +++ b/src/render/geometry/qattribute.cpp @@ -505,6 +505,19 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAttribute::createNodeCreationChange() const return creationChange; } + +/*! +\fn Qt3DRender::QAttribute::dataSizeChanged(uint vertexSize) + +The signal is emitted with \a vertexSize when the dataSize changes. +*/ +/*! +\fn Qt3DRender::QAttribute::dataTypeChanged(Qt3DRender::QAttribute::VertexBaseType vertexBaseType) + +The signal is emitted with \a vertexBaseType when the dataType changed. +*/ + + } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp index e0574a4c5..f27005f2b 100644 --- a/src/render/geometry/qbuffer.cpp +++ b/src/render/geometry/qbuffer.cpp @@ -329,7 +329,7 @@ void QBuffer::setData(const QByteArray &bytes) Q_D(QBuffer); if (bytes != d->m_data) { d->m_data = bytes; - Qt3DCore::QNodePrivate::get(this)->notifyPropertyChange("data", QVariant::fromValue(d->m_data)); + Qt3DCore::QNodePrivate::get(this)->update(); emit dataChanged(bytes); } } @@ -351,11 +351,8 @@ void QBuffer::updateData(int offset, const QByteArray &bytes) QBufferUpdate updateData; updateData.offset = offset; updateData.data = bytes; - - auto e = QPropertyUpdatedChangePtr::create(id()); - e->setPropertyName("updateData"); - e->setValue(QVariant::fromValue(updateData)); - notifyObservers(e); + setProperty("QT3D_updateData", QVariant::fromValue(updateData)); + d->update(); } /*! @@ -409,12 +406,7 @@ void QBuffer::setDataGenerator(const QBufferDataGeneratorPtr &functor) if (functor && d->m_functor && *functor == *d->m_functor) return; d->m_functor = functor; - if (d->m_changeArbiter != nullptr) { - auto change = QPropertyUpdatedChangePtr::create(d->m_id); - change->setPropertyName("dataGenerator"); - change->setValue(QVariant::fromValue(d->m_functor)); - d->notifyObservers(change); - } + d->update(); } /*! diff --git a/src/render/geometry/qgeometry.cpp b/src/render/geometry/qgeometry.cpp index ec80e2657..47fad4302 100644 --- a/src/render/geometry/qgeometry.cpp +++ b/src/render/geometry/qgeometry.cpp @@ -196,11 +196,7 @@ void QGeometry::addAttribute(QAttribute *attribute) if (!attribute->parent()) attribute->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), attribute); - change->setPropertyName("attribute"); - d->notifyObservers(change); - } + d->update(); } } @@ -212,14 +208,10 @@ void QGeometry::removeAttribute(QAttribute *attribute) { Q_ASSERT(attribute); Q_D(QGeometry); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), attribute); - change->setPropertyName("attribute"); - d->notifyObservers(change); - } d->m_attributes.removeOne(attribute); // Remove bookkeeping connection d->unregisterDestructionHelper(attribute); + d->update(); } void QGeometry::setBoundingVolumePositionAttribute(QAttribute *boundingVolumePositionAttribute) diff --git a/src/render/geometry/qgeometryrenderer.cpp b/src/render/geometry/qgeometryrenderer.cpp index 6bff3462f..ddea873a7 100644 --- a/src/render/geometry/qgeometryrenderer.cpp +++ b/src/render/geometry/qgeometryrenderer.cpp @@ -480,12 +480,7 @@ void QGeometryRenderer::setGeometryFactory(const QGeometryFactoryPtr &factory) if (factory && d->m_geometryFactory && *factory == *d->m_geometryFactory) return; d->m_geometryFactory = factory; - if (d->m_changeArbiter != nullptr) { - auto change = QPropertyUpdatedChangePtr::create(d->m_id); - change->setPropertyName("geometryFactory"); - change->setValue(QVariant::fromValue(d->m_geometryFactory)); - d->notifyObservers(change); - } + d->update(); } /*! diff --git a/src/render/geometry/skeleton.cpp b/src/render/geometry/skeleton.cpp index 615b76c88..d4af1fe3c 100644 --- a/src/render/geometry/skeleton.cpp +++ b/src/render/geometry/skeleton.cpp @@ -80,39 +80,68 @@ void Skeleton::cleanup() setEnabled(false); } -void Skeleton::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Skeleton::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - Q_ASSERT(m_skeletonManager); - m_skeletonHandle = m_skeletonManager->lookupHandle(peerId()); - - const auto skeletonCreatedChange = qSharedPointerCast<QSkeletonCreatedChangeBase>(change); - switch (skeletonCreatedChange->type()) { - case QSkeletonCreatedChangeBase::SkeletonLoader: { - const auto loaderTypedChange = qSharedPointerCast<QSkeletonCreatedChange<QSkeletonLoaderData>>(change); - const auto &data = loaderTypedChange->data; - m_dataType = File; - m_source = data.source; - m_createJoints = data.createJoints; - if (!m_source.isEmpty()) { - markDirty(AbstractRenderer::SkeletonDataDirty); - m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAbstractSkeleton *node = qobject_cast<const QAbstractSkeleton *>(frontEnd); + if (!node) + return; + const QSkeleton *skeletonNode = qobject_cast<const QSkeleton *>(frontEnd); + const QSkeletonLoader *loaderNode = qobject_cast<const QSkeletonLoader *>(frontEnd); + + if (firstTime) { + m_skeletonHandle = m_skeletonManager->lookupHandle(peerId()); + + if (skeletonNode) { + m_dataType = Data; + m_rootJointId = skeletonNode->rootJoint()->id(); + if (!m_rootJointId.isNull()) { + markDirty(AbstractRenderer::SkeletonDataDirty); + m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); + } + } + + if (loaderNode) { + m_dataType = File; + m_source = loaderNode->source(); + if (!m_source.isEmpty()) { + markDirty(AbstractRenderer::SkeletonDataDirty); + m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); + } } - break; } - case QSkeletonCreatedChangeBase::Skeleton: - const auto typedChange = qSharedPointerCast<QSkeletonCreatedChange<QSkeletonData>>(change); - const auto &data = typedChange->data; - m_dataType = Data; - m_rootJointId = data.rootJointId; - if (!m_rootJointId.isNull()) { + if (loaderNode) { + if (loaderNode->source() != m_source) { + m_source = loaderNode->source(); markDirty(AbstractRenderer::SkeletonDataDirty); m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); } - break; + m_createJoints = loaderNode->isCreateJointsEnabled(); + + if ((loaderNode->rootJoint() && loaderNode->rootJoint()->id() != m_rootJointId) || + (!loaderNode->rootJoint() && !m_rootJointId.isNull())) { + m_rootJointId = loaderNode->rootJoint() ? loaderNode->rootJoint()->id() : Qt3DCore::QNodeId{}; + + // If using a QSkeletonLoader to create frontend QJoints, when those joints are + // set on the skeleton, we end up here. In order to allow the subsequent call + // to loadSkeleton(), see below, to build the internal data from the frontend + // joints rather than from the source url again, we need to change the data type + // to Data. + m_dataType = Data; + + // If the joint changes, we need to rebuild our internal SkeletonData and + // the relationships between joints and skeleton. Mark the skeleton data as + // dirty so that we get a loadSkeletonJob executed to process this skeleton. + if (!m_rootJointId.isNull()) { + markDirty(AbstractRenderer::SkeletonDataDirty); + m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); + } + } } } +// TODOSYNC remove once animation aspect no longer requires messages void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) { switch (e->type()) { @@ -123,31 +152,6 @@ void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) // need to do is copy them into place. The existing jobs will then update // the skinning matrix palette. m_skeletonData.localPoses = change->value().value<QVector<Qt3DCore::Sqt>>(); - } else if (change->propertyName() == QByteArrayLiteral("source")) { - Q_ASSERT(m_dataType == File); - const auto source = change->value().toUrl(); - if (source != m_source) { - m_source = source; - markDirty(AbstractRenderer::SkeletonDataDirty); - m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); - } - } else if (change->propertyName() == QByteArrayLiteral("createJointsEnabled")) { - m_createJoints = change->value().toBool(); - } else if (change->propertyName() == QByteArrayLiteral("rootJoint")) { - m_rootJointId = change->value().value<QNodeId>(); - - // If using a QSkeletonLoader to create frontend QJoints, when those joints are - // set on the skeleton, we end up here. In order to allow the subsequent call - // to loadSkeleton(), see below, to build the internal data from the frontend - // joints rather than from the source url again, we need to change the data type - // to Data. - m_dataType = Data; - - // If the joint changes, we need to rebuild our internal SkeletonData and - // the relationships between joints and skeleton. Mark the skeleton data as - // dirty so that we get a loadSkeletonJob executed to process this skeleton. - markDirty(AbstractRenderer::SkeletonDataDirty); - m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle); } break; diff --git a/src/render/geometry/skeleton_p.h b/src/render/geometry/skeleton_p.h index 4a14e5c1c..d71b404e5 100644 --- a/src/render/geometry/skeleton_p.h +++ b/src/render/geometry/skeleton_p.h @@ -85,6 +85,7 @@ public: void cleanup(); void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void setStatus(Qt3DCore::QSkeletonLoader::Status status); Qt3DCore::QSkeletonLoader::Status status() const { return m_status; } @@ -120,7 +121,6 @@ public: #endif private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; void loadSkeletonFromUrl(); void loadSkeletonFromData(); Qt3DCore::QJoint *createFrontendJoints(const SkeletonData &skeletonData) const; diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h index 5fe16f933..9c83624b8 100644 --- a/src/render/jobs/job_common_p.h +++ b/src/render/jobs/job_common_p.h @@ -109,7 +109,6 @@ namespace JobTypes { UpdateLayerEntity, SendTextureChangesToFrontend, SendSetFenceHandlesToFrontend, - UpdateEntityHierarchy, }; } // JobTypes diff --git a/src/render/jobs/jobs.pri b/src/render/jobs/jobs.pri index 6cdf891fc..2181e4a95 100644 --- a/src/render/jobs/jobs.pri +++ b/src/render/jobs/jobs.pri @@ -30,7 +30,6 @@ HEADERS += \ $$PWD/filterproximitydistancejob_p.h \ $$PWD/abstractpickingjob_p.h \ $$PWD/raycastingjob_p.h \ - $$PWD/updateentityhierarchyjob_p.h \ $$PWD/updateentitylayersjob_p.h SOURCES += \ @@ -60,6 +59,5 @@ SOURCES += \ $$PWD/filterproximitydistancejob.cpp \ $$PWD/abstractpickingjob.cpp \ $$PWD/raycastingjob.cpp \ - $$PWD/updateentityhierarchyjob.cpp \ $$PWD/updateentitylayersjob.cpp diff --git a/src/render/jobs/updateentityhierarchyjob.cpp b/src/render/jobs/updateentityhierarchyjob.cpp deleted file mode 100644 index 7c18514bb..000000000 --- a/src/render/jobs/updateentityhierarchyjob.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** 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 deleted file mode 100644 index fd2b13631..000000000 --- a/src/render/jobs/updateentityhierarchyjob_p.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** 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/lights/environmentlight.cpp b/src/render/lights/environmentlight.cpp index d4245fb6e..20364fdfa 100644 --- a/src/render/lights/environmentlight.cpp +++ b/src/render/lights/environmentlight.cpp @@ -53,11 +53,17 @@ QNodeId EnvironmentLight::shaderData() const return m_shaderDataId; } -void EnvironmentLight::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) +void EnvironmentLight::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QEnvironmentLightData>>(change); - const auto &data = typedChange->data; - m_shaderDataId = data.shaderDataId; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QEnvironmentLight *node = qobject_cast<const QEnvironmentLight *>(frontEnd); + if (!node) + return; + + if (firstTime) { + QEnvironmentLightPrivate *d = static_cast<QEnvironmentLightPrivate *>(QEnvironmentLightPrivate::get(const_cast<Qt3DCore::QNode *>(frontEnd))); + m_shaderDataId = d->m_shaderData ? d->m_shaderData->id() : QNodeId{}; + } } } // namespace Render diff --git a/src/render/lights/environmentlight_p.h b/src/render/lights/environmentlight_p.h index 00d49d298..92f6ce100 100644 --- a/src/render/lights/environmentlight_p.h +++ b/src/render/lights/environmentlight_p.h @@ -63,10 +63,9 @@ class Q_AUTOTEST_EXPORT EnvironmentLight : public BackendNode { public: Qt3DCore::QNodeId shaderData() const; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_shaderDataId; }; diff --git a/src/render/lights/light.cpp b/src/render/lights/light.cpp index e8474b728..30d71082b 100644 --- a/src/render/lights/light.cpp +++ b/src/render/lights/light.cpp @@ -58,14 +58,18 @@ QNodeId Light::shaderData() const return m_shaderDataId; } -void Light::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) +void Light::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractLightData>>(change); - const auto &data = typedChange->data; - m_shaderDataId = data.shaderDataId; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAbstractLight *node = qobject_cast<const QAbstractLight *>(frontEnd); + if (!node) + return; - Q_ASSERT(m_renderer); - BackendNode::markDirty(AbstractRenderer::LightsDirty); + if (firstTime) { + QAbstractLightPrivate *d = static_cast<QAbstractLightPrivate *>(QAbstractLightPrivate::get(const_cast<Qt3DCore::QNode *>(frontEnd))); + m_shaderDataId = d->m_shaderData ? d->m_shaderData->id() : QNodeId{}; + BackendNode::markDirty(AbstractRenderer::LightsDirty); + } } RenderLightFunctor::RenderLightFunctor(AbstractRenderer *renderer, NodeManagers *managers) diff --git a/src/render/lights/light_p.h b/src/render/lights/light_p.h index 8ecc87585..5f5f8140e 100644 --- a/src/render/lights/light_p.h +++ b/src/render/lights/light_p.h @@ -66,9 +66,9 @@ class Q_AUTOTEST_EXPORT Light : public BackendNode public: Qt3DCore::QNodeId shaderData() const; -private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; +private: Qt3DCore::QNodeId m_shaderDataId; }; diff --git a/src/render/lights/qenvironmentlight.cpp b/src/render/lights/qenvironmentlight.cpp index b3dac56ff..86ef04f95 100644 --- a/src/render/lights/qenvironmentlight.cpp +++ b/src/render/lights/qenvironmentlight.cpp @@ -55,7 +55,21 @@ namespace Qt3DRender * \since 5.9 * * EnvironmentLight uses cubemaps to implement image-based lighting (IBL), a technique - * often used in conjunction with physically-based rendering (PBR). + * often used in conjunction with physically-based rendering (PBR). The cubemaps are + * typically expected be based on high dynamic range (HDR) images, with a suitable + * OpenGL format (such as RGBA16F) that can handle the increased range of values. + * + * There are a variety of tools that can be used to produce the cubemaps needed by + * EnvironmentLight. Some examples include + * + * \list + * \li \l {https://github.com/dariomanesku/cmftStudio}{cmftStudio} + * \li \l {https://github.com/derkreature/IBLBaker}{IBLBaker} + * \li \l {https://www.knaldtech.com/lys/}{Lys} + * \endlist + * + * \l {https://hdrihaven.com/hdris/}{HDRI Haven} provides many CC0-licensed HDR images + * that can be used as source material for the above tools. */ QEnvironmentLightPrivate::QEnvironmentLightPrivate() @@ -101,8 +115,22 @@ Qt3DCore::QNodeCreatedChangeBasePtr QEnvironmentLight::createNodeCreationChange( \brief Encapsulate an environment light object in a Qt 3D scene. \since 5.9 - EnvironmentLight uses cubemaps to implement image-based lighting (IBL), a technique - often used in conjunction with physically-based rendering (PBR). + QEnvironmentLight uses cubemaps to implement image-based lighting (IBL), a technique + often used in conjunction with physically-based rendering (PBR). The cubemaps are + typically expected be based on high dynamic range (HDR) images, with a suitable + OpenGL format (such as RGBA16F) that can handle the increased range of values. + + There are a variety of tools that can be used to produce the cubemaps needed by + QEnvironmentLight. Some examples include + + \list + \li \l {https://github.com/dariomanesku/cmftStudio}{cmftStudio} + \li \l {https://github.com/derkreature/IBLBaker}{IBLBaker} + \li \l {https://www.knaldtech.com/lys/}{Lys} + \endlist + + \l {https://hdrihaven.com/hdris/}{HDRI Haven} provides many CC0-licensed HDR images + that can be used as source material for the above tools. */ QEnvironmentLight::QEnvironmentLight(Qt3DCore::QNode *parent) diff --git a/src/render/materialsystem/effect.cpp b/src/render/materialsystem/effect.cpp index 29d05ed01..76036bd1f 100644 --- a/src/render/materialsystem/effect.cpp +++ b/src/render/materialsystem/effect.cpp @@ -48,6 +48,7 @@ #include <Qt3DCore/qpropertynoderemovedchange.h> #include <QVariant> +#include <algorithm> QT_BEGIN_NAMESPACE @@ -73,41 +74,25 @@ void Effect::cleanup() m_techniques.clear(); } -void Effect::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Effect::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QEffectData>>(change); - const auto &data = typedChange->data; - m_techniques = data.techniqueIds; - m_parameterPack.setParameters(data.parameterIds); -} - -void Effect::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("technique")) - appendRenderTechnique(change->addedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.appendParameter(change->addedNodeId()); - break; - } - - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("technique")) - m_techniques.removeOne(change->removedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.removeParameter(change->removedNodeId()); - break; - } - - default: - break; - } - - markDirty(AbstractRenderer::AllDirty); - BackendNode::sceneChangeEvent(e); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QEffect *node = qobject_cast<const QEffect *>(frontEnd); + if (!node) + return; + + auto parameters = qIdsForNodes(node->parameters()); + std::sort(std::begin(parameters), std::end(parameters)); + if (m_parameterPack.parameters() != parameters) + m_parameterPack.setParameters(parameters); + + auto techniques = qIdsForNodes(node->techniques()); + std::sort(std::begin(techniques), std::end(techniques)); + if (m_techniques != techniques) + m_techniques = techniques; + + if (!firstTime) + markDirty(AbstractRenderer::AllDirty); } void Effect::appendRenderTechnique(Qt3DCore::QNodeId technique) diff --git a/src/render/materialsystem/effect_p.h b/src/render/materialsystem/effect_p.h index 87ff4a803..e81be2b8d 100644 --- a/src/render/materialsystem/effect_p.h +++ b/src/render/materialsystem/effect_p.h @@ -70,15 +70,13 @@ public: ~Effect(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void appendRenderTechnique(Qt3DCore::QNodeId t); QVector<Qt3DCore::QNodeId> techniques() const; QVector<Qt3DCore::QNodeId> parameters() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_techniques; ParameterPack m_parameterPack; }; diff --git a/src/render/materialsystem/material.cpp b/src/render/materialsystem/material.cpp index a69ff8a13..07764c207 100644 --- a/src/render/materialsystem/material.cpp +++ b/src/render/materialsystem/material.cpp @@ -73,47 +73,26 @@ void Material::cleanup() m_parameterPack.clear(); } -void Material::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Material::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QMaterialData>>(change); - const auto &data = typedChange->data; - m_effectUuid = data.effectId; - m_parameterPack.setParameters(data.parameterIds); - - markDirty(AbstractRenderer::MaterialDirty); -} - -void Material::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - - switch (e->type()) { - case PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("effect")) - m_effectUuid = change->value().value<QNodeId>(); - break; - } - - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.appendParameter(change->addedNodeId()); - break; - } - - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.removeParameter(change->removedNodeId()); - break; - } - - default: - break; - } - markDirty(AbstractRenderer::AllDirty); - - BackendNode::sceneChangeEvent(e); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QMaterial *node = qobject_cast<const QMaterial *>(frontEnd); + if (!node) + return; + + auto parameters = qIdsForNodes(node->parameters()); + std::sort(std::begin(parameters), std::end(parameters)); + if (m_parameterPack.parameters() != parameters) + m_parameterPack.setParameters(parameters); + + const auto effectId = node->effect() ? node->effect()->id() : QNodeId{}; + if (effectId != m_effectUuid) + m_effectUuid = effectId; + + if (firstTime) + markDirty(AbstractRenderer::MaterialDirty); + else + markDirty(AbstractRenderer::AllDirty); } QVector<Qt3DCore::QNodeId> Material::parameters() const diff --git a/src/render/materialsystem/material_p.h b/src/render/materialsystem/material_p.h index 3b55dc657..7a02c6691 100644 --- a/src/render/materialsystem/material_p.h +++ b/src/render/materialsystem/material_p.h @@ -79,14 +79,12 @@ public: ~Material(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; QVector<Qt3DCore::QNodeId> parameters() const; Qt3DCore::QNodeId effect() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - ParameterPack m_parameterPack; Qt3DCore::QNodeId m_effectUuid; }; diff --git a/src/render/materialsystem/parameter.cpp b/src/render/materialsystem/parameter.cpp index 86ca418aa..d32e60a2d 100644 --- a/src/render/materialsystem/parameter.cpp +++ b/src/render/materialsystem/parameter.cpp @@ -70,34 +70,33 @@ void Parameter::cleanup() m_uniformValue = UniformValue(); } -void Parameter::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Parameter::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QParameterData>>(change); - const auto &data = typedChange->data; - m_name = data.name; - m_nameId = StringToInt::lookupId(m_name); - m_uniformValue = UniformValue::fromVariant(data.backendValue); - markDirty(AbstractRenderer::ParameterDirty); -} + const QParameter *node = qobject_cast<const QParameter *>(frontEnd); + if (!node) + return; -void Parameter::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - - if (e->type() == PropertyUpdated) { - if (propertyChange->propertyName() == QByteArrayLiteral("name")) { - m_name = propertyChange->value().toString(); - m_nameId = StringToInt::lookupId(m_name); - markDirty(AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("value")) { - m_uniformValue = UniformValue::fromVariant(propertyChange->value()); - markDirty(AbstractRenderer::ParameterDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) { - markDirty(AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty); - } + AbstractRenderer::BackendNodeDirtySet dirty = firstTime ? AbstractRenderer::ParameterDirty : static_cast<AbstractRenderer::BackendNodeDirtyFlag>(0); + if (node->isEnabled() != isEnabled()) + dirty |= (AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty); + + if (node->name() != m_name) { + m_name = node->name(); + m_nameId = StringToInt::lookupId(m_name); + dirty |= (AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty); } - BackendNode::sceneChangeEvent(e); + QParameterPrivate* d = static_cast<QParameterPrivate *>(QParameterPrivate::get(const_cast<QParameter *>(node))); + if (d->m_backendValue != m_backendValue) { + m_backendValue = d->m_backendValue; + m_uniformValue = UniformValue::fromVariant(m_backendValue); + dirty |= (AbstractRenderer::ParameterDirty); + } + + if (dirty) + markDirty(dirty); + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); } QString Parameter::name() const diff --git a/src/render/materialsystem/parameter_p.h b/src/render/materialsystem/parameter_p.h index 4ab04bc8e..9deaa11f3 100644 --- a/src/render/materialsystem/parameter_p.h +++ b/src/render/materialsystem/parameter_p.h @@ -71,16 +71,15 @@ public: void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; QString name() const; int nameId() const Q_DECL_NOTHROW { return m_nameId; } const UniformValue &uniformValue() const { return m_uniformValue; } private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QString m_name; + QVariant m_backendValue; UniformValue m_uniformValue; int m_nameId; }; diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp index b611657c4..35ac662fb 100644 --- a/src/render/materialsystem/qeffect.cpp +++ b/src/render/materialsystem/qeffect.cpp @@ -192,11 +192,7 @@ void QEffect::addParameter(QParameter *parameter) if (!parameter->parent()) parameter->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); } } @@ -207,14 +203,10 @@ void QEffect::removeParameter(QParameter *parameter) { Q_D(QEffect); - if (parameter && d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); + d->update(); } /*! @@ -246,11 +238,7 @@ void QEffect::addTechnique(QTechnique *t) if (!t->parent()) t->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), t); - change->setPropertyName("technique"); - d->notifyObservers(change); - } + d->update(); } } @@ -260,11 +248,8 @@ void QEffect::addTechnique(QTechnique *t) void QEffect::removeTechnique(QTechnique *t) { Q_D(QEffect); - if (t && d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), t); - change->setPropertyName("technique"); - d->notifyObservers(change); - } + if (t) + d->update(); d->m_techniques.removeOne(t); // Remove bookkeeping connection d->unregisterDestructionHelper(t); diff --git a/src/render/materialsystem/qgraphicsapifilter.cpp b/src/render/materialsystem/qgraphicsapifilter.cpp index 70f329172..9b5557930 100644 --- a/src/render/materialsystem/qgraphicsapifilter.cpp +++ b/src/render/materialsystem/qgraphicsapifilter.cpp @@ -107,6 +107,11 @@ QGraphicsApiFilterPrivate *QGraphicsApiFilterPrivate::get(QGraphicsApiFilter *q) return q->d_func(); } +const QGraphicsApiFilterPrivate *QGraphicsApiFilterPrivate::get(const QGraphicsApiFilter *q) +{ + return q->d_func(); +} + /*! \class Qt3DRender::QGraphicsApiFilter \inmodule Qt3DRender diff --git a/src/render/materialsystem/qgraphicsapifilter_p.h b/src/render/materialsystem/qgraphicsapifilter_p.h index 3961d4f93..435451c27 100644 --- a/src/render/materialsystem/qgraphicsapifilter_p.h +++ b/src/render/materialsystem/qgraphicsapifilter_p.h @@ -84,6 +84,7 @@ public: } static QGraphicsApiFilterPrivate *get(QGraphicsApiFilter *q); + static const QGraphicsApiFilterPrivate *get(const QGraphicsApiFilter *q); Q_DECLARE_PUBLIC(QGraphicsApiFilter) GraphicsApiFilterData m_data; diff --git a/src/render/materialsystem/qmaterial.cpp b/src/render/materialsystem/qmaterial.cpp index c6913441e..db523a700 100644 --- a/src/render/materialsystem/qmaterial.cpp +++ b/src/render/materialsystem/qmaterial.cpp @@ -275,11 +275,7 @@ void QMaterial::addParameter(QParameter *parameter) if (!parameter->parent()) parameter->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); } } @@ -290,11 +286,7 @@ void QMaterial::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QMaterial); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); d->m_parameters.removeOne(parameter); } diff --git a/src/render/materialsystem/qrenderpass.cpp b/src/render/materialsystem/qrenderpass.cpp index 111bb7b5f..d0821c49c 100644 --- a/src/render/materialsystem/qrenderpass.cpp +++ b/src/render/materialsystem/qrenderpass.cpp @@ -231,12 +231,6 @@ void QRenderPass::setShaderProgram(QShaderProgram *shaderProgram) Q_D(QRenderPass); if (d->m_shader != shaderProgram) { - if (d->m_shader != nullptr && d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), d->m_shader); - change->setPropertyName("shaderProgram"); - d->notifyObservers(change); - } - if (d->m_shader) d->unregisterDestructionHelper(d->m_shader); @@ -283,11 +277,7 @@ void QRenderPass::addFilterKey(QFilterKey *filterKey) if (!filterKey->parent()) filterKey->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), filterKey); - change->setPropertyName("filterKeys"); - d->notifyObservers(change); - } + d->update(); } } @@ -298,11 +288,7 @@ void QRenderPass::removeFilterKey(QFilterKey *filterKey) { Q_ASSERT(filterKey); Q_D(QRenderPass); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), filterKey); - change->setPropertyName("filterKeys"); - d->notifyObservers(change); - } + d->update(); d->m_filterKeyList.removeOne(filterKey); // Remove bookkeeping connection d->unregisterDestructionHelper(filterKey); @@ -339,11 +325,7 @@ void QRenderPass::addRenderState(QRenderState *state) if (!state->parent()) state->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), state); - change->setPropertyName("renderState"); - d->notifyObservers(change); - } + d->update(); } } @@ -354,11 +336,7 @@ void QRenderPass::removeRenderState(QRenderState *state) { Q_ASSERT(state); Q_D(QRenderPass); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), state); - change->setPropertyName("renderState"); - d->notifyObservers(change); - } + d->update(); d->m_renderStates.removeOne(state); // Remove bookkeeping connection d->unregisterDestructionHelper(state); @@ -394,11 +372,7 @@ void QRenderPass::addParameter(QParameter *parameter) if (!parameter->parent()) parameter->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); } } @@ -409,11 +383,7 @@ void QRenderPass::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QRenderPass); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp index b668eb25f..dadeb98bd 100644 --- a/src/render/materialsystem/qtechnique.cpp +++ b/src/render/materialsystem/qtechnique.cpp @@ -234,12 +234,7 @@ QTechnique::QTechnique(QTechniquePrivate &dd, QNode *parent) /*! \internal */ void QTechniquePrivate::_q_graphicsApiFilterChanged() { - if (m_changeArbiter != nullptr) { - auto change = QPropertyUpdatedChangePtr::create(m_id); - change->setPropertyName("graphicsApiFilterData"); - change->setValue(QVariant::fromValue(QGraphicsApiFilterPrivate::get(const_cast<QGraphicsApiFilter *>(&m_graphicsApiFilter))->m_data)); - notifyObservers(change); - } + update(); } /*! @@ -262,11 +257,7 @@ void QTechnique::addFilterKey(QFilterKey *filterKey) if (!filterKey->parent()) filterKey->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), filterKey); - change->setPropertyName("filterKeys"); - d->notifyObservers(change); - } + d->update(); } } @@ -277,11 +268,7 @@ void QTechnique::removeFilterKey(QFilterKey *filterKey) { Q_ASSERT(filterKey); Q_D(QTechnique); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), filterKey); - change->setPropertyName("filterKeys"); - d->notifyObservers(change); - } + d->update(); d->m_filterKeys.removeOne(filterKey); // Remove bookkeeping connection d->unregisterDestructionHelper(filterKey); @@ -317,11 +304,7 @@ void QTechnique::addParameter(QParameter *parameter) if (!parameter->parent()) parameter->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); } } @@ -332,11 +315,7 @@ void QTechnique::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QTechnique); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter); - change->setPropertyName("parameter"); - d->notifyObservers(change); - } + d->update(); d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); @@ -362,11 +341,7 @@ void QTechnique::addRenderPass(QRenderPass *pass) if (!pass->parent()) pass->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), pass); - change->setPropertyName("pass"); - d->notifyObservers(change); - } + d->update(); } } @@ -377,11 +352,7 @@ void QTechnique::removeRenderPass(QRenderPass *pass) { Q_ASSERT(pass); Q_D(QTechnique); - if (d->m_changeArbiter) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), pass); - change->setPropertyName("pass"); - d->notifyObservers(change); - } + d->update(); d->m_renderPasses.removeOne(pass); // Remove bookkeeping connection d->unregisterDestructionHelper(pass); @@ -405,12 +376,19 @@ QVector<QParameter *> QTechnique::parameters() const return d->m_parameters; } +// TODO Qt 6 -> Remove QGraphicsApiFilter *QTechnique::graphicsApiFilter() { Q_D(QTechnique); return &d->m_graphicsApiFilter; } +const QGraphicsApiFilter *QTechnique::graphicsApiFilter() const +{ + Q_D(const QTechnique); + return &d->m_graphicsApiFilter; +} + Qt3DCore::QNodeCreatedChangeBasePtr QTechnique::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QTechniqueData>::create(this); diff --git a/src/render/materialsystem/qtechnique.h b/src/render/materialsystem/qtechnique.h index 7711cd67f..f0c857c2b 100644 --- a/src/render/materialsystem/qtechnique.h +++ b/src/render/materialsystem/qtechnique.h @@ -76,7 +76,8 @@ public: void removeRenderPass(QRenderPass *pass); QVector<QRenderPass *> renderPasses() const; - QGraphicsApiFilter *graphicsApiFilter(); + Q_DECL_DEPRECATED QGraphicsApiFilter *graphicsApiFilter(); + const QGraphicsApiFilter *graphicsApiFilter() const; protected: explicit QTechnique(QTechniquePrivate &dd, Qt3DCore::QNode *parent = nullptr); diff --git a/src/render/materialsystem/renderpass.cpp b/src/render/materialsystem/renderpass.cpp index e0fadddd9..aaeca3bb4 100644 --- a/src/render/materialsystem/renderpass.cpp +++ b/src/render/materialsystem/renderpass.cpp @@ -52,6 +52,8 @@ #include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qpropertynoderemovedchange.h> +#include <algorithm> + QT_BEGIN_NAMESPACE using namespace Qt3DCore; @@ -77,58 +79,33 @@ void RenderPass::cleanup() m_shaderUuid = Qt3DCore::QNodeId(); } -void RenderPass::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderPassData>>(change); - const auto &data = typedChange->data; - m_filterKeyList = data.filterKeyIds; - m_parameterPack.setParameters(data.parameterIds); - for (const auto &renderStateId : qAsConst(data.renderStateIds)) - addRenderState(renderStateId); - m_shaderUuid = data.shaderId; -} - -void RenderPass::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void RenderPass::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("filterKeys")) - appendFilterKey(change->addedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("shaderProgram")) - m_shaderUuid = change->addedNodeId(); - else if (change->propertyName() == QByteArrayLiteral("renderState")) - addRenderState(change->addedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.appendParameter(change->addedNodeId()); - break; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QRenderPass *node = qobject_cast<const QRenderPass *>(frontEnd); + if (!node) + return; + + if ((node->shaderProgram() && node->shaderProgram()->id() != m_shaderUuid) || + (!node->shaderProgram() && !m_shaderUuid.isNull())) { + m_shaderUuid = node->shaderProgram() ? node->shaderProgram()->id() : QNodeId{}; } - case PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("shaderProgram")) - m_shaderUuid = change->value().value<Qt3DCore::QNodeId>(); - break; - } + auto filterList = qIdsForNodes(node->filterKeys()); + std::sort(std::begin(filterList), std::end(filterList)); + if (m_filterKeyList != filterList) + m_filterKeyList = filterList; - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("filterKeys")) - removeFilterKey(change->removedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("shaderProgram")) - m_shaderUuid = QNodeId(); - else if (change->propertyName() == QByteArrayLiteral("renderState")) - removeRenderState(change->removedNodeId()); - else if (change->propertyName() == QByteArrayLiteral("parameter")) - m_parameterPack.removeParameter(change->removedNodeId()); - break; - } + auto parameters = qIdsForNodes(node->parameters()); + std::sort(std::begin(parameters), std::end(parameters)); + if (m_parameterPack.parameters() != parameters) + m_parameterPack.setParameters(parameters); - default: - break; - } + auto renderStates = qIdsForNodes(node->renderStates()); + std::sort(std::begin(renderStates), std::end(renderStates)); + if (m_renderStates != renderStates) + m_renderStates = renderStates; - BackendNode::sceneChangeEvent(e); markDirty(AbstractRenderer::AllDirty); } diff --git a/src/render/materialsystem/renderpass_p.h b/src/render/materialsystem/renderpass_p.h index 1ca02b1ad..314386ad1 100644 --- a/src/render/materialsystem/renderpass_p.h +++ b/src/render/materialsystem/renderpass_p.h @@ -79,7 +79,7 @@ public: void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Qt3DCore::QNodeId shaderProgram() const; QVector<Qt3DCore::QNodeId> filterKeys() const; @@ -95,8 +95,6 @@ private: void addRenderState(Qt3DCore::QNodeId renderStateId); void removeRenderState(Qt3DCore::QNodeId renderStateId); - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_shaderUuid; QVector<Qt3DCore::QNodeId> m_filterKeyList; ParameterPack m_parameterPack; diff --git a/src/render/materialsystem/technique.cpp b/src/render/materialsystem/technique.cpp index 42430883e..d4199b7e3 100644 --- a/src/render/materialsystem/technique.cpp +++ b/src/render/materialsystem/technique.cpp @@ -85,72 +85,48 @@ void Technique::cleanup() m_isCompatibleWithRenderer = false; } -void Technique::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Technique::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QTechniqueData>>(change); - const QTechniqueData &data = typedChange->data; - - m_graphicsApiFilterData = data.graphicsApiFilterData; - m_filterKeyList = data.filterKeyIds; - m_parameterPack.setParameters(data.parameterIds); - m_renderPasses = data.renderPassIds; - m_nodeManager->techniqueManager()->addDirtyTechnique(peerId()); - markDirty(AbstractRenderer::TechniquesDirty); -} + const QTechnique *node = qobject_cast<const QTechnique *>(frontEnd); -void Technique::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyUpdated: { - const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("enabled")) { - markDirty(AbstractRenderer::TechniquesDirty); - } else if (change->propertyName() == QByteArrayLiteral("graphicsApiFilterData")) { - GraphicsApiFilterData filterData = change->value().value<GraphicsApiFilterData>(); - m_graphicsApiFilterData = filterData; - // Notify the manager that our graphicsApiFilterData has changed - // and that we therefore need to be check for compatibility again - m_isCompatibleWithRenderer = false; - m_nodeManager->techniqueManager()->addDirtyTechnique(peerId()); - markDirty(AbstractRenderer::TechniquesDirty); - } - break; + if (!node) + return; + + bool dirty = isEnabled() != frontEnd->isEnabled(); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + auto renderPasses = qIdsForNodes(node->renderPasses()); + std::sort(std::begin(renderPasses), std::end(renderPasses)); + if (m_renderPasses != renderPasses) { + m_renderPasses = renderPasses; + dirty = true; } - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("pass")) { - appendRenderPass(change->addedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } else if (change->propertyName() == QByteArrayLiteral("parameter")) { - m_parameterPack.appendParameter(change->addedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } else if (change->propertyName() == QByteArrayLiteral("filterKeys")) { - appendFilterKey(change->addedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } - break; + auto parameters = qIdsForNodes(node->parameters()); + std::sort(std::begin(parameters), std::end(parameters)); + if (m_parameterPack.parameters() != parameters) { + m_parameterPack.setParameters(parameters); + dirty = true; } - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("pass")) { - removeRenderPass(change->removedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } else if (change->propertyName() == QByteArrayLiteral("parameter")) { - m_parameterPack.removeParameter(change->removedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } else if (change->propertyName() == QByteArrayLiteral("filterKeys")) { - removeFilterKey(change->removedNodeId()); - markDirty(AbstractRenderer::TechniquesDirty); - } - break; + auto filterKeys = qIdsForNodes(node->filterKeys()); + std::sort(std::begin(filterKeys), std::end(filterKeys)); + if (m_filterKeyList != filterKeys) { + m_filterKeyList = filterKeys; + dirty = true; + } + + auto graphicsApiFilterData = QGraphicsApiFilterPrivate::get(node->graphicsApiFilter())->m_data; + if (m_graphicsApiFilterData != graphicsApiFilterData) { + m_graphicsApiFilterData = graphicsApiFilterData; + m_isCompatibleWithRenderer = false; + dirty = true; } - default: - break; + if (dirty) { + m_nodeManager->techniqueManager()->addDirtyTechnique(peerId()); + markDirty(AbstractRenderer::TechniquesDirty); } - BackendNode::sceneChangeEvent(e); } QVector<Qt3DCore::QNodeId> Technique::parameters() const diff --git a/src/render/materialsystem/technique_p.h b/src/render/materialsystem/technique_p.h index d885c1b87..1d0d0a9dd 100644 --- a/src/render/materialsystem/technique_p.h +++ b/src/render/materialsystem/technique_p.h @@ -80,7 +80,8 @@ public: ~Technique(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; + QVector<Qt3DCore::QNodeId> parameters() const; void appendRenderPass(Qt3DCore::QNodeId renderPassId); @@ -102,7 +103,6 @@ public: NodeManagers *nodeManager() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; GraphicsApiFilterData m_graphicsApiFilterData; ParameterPack m_parameterPack; diff --git a/src/render/picking/qpickevent.cpp b/src/render/picking/qpickevent.cpp index a18c6ead8..ae5748082 100644 --- a/src/render/picking/qpickevent.cpp +++ b/src/render/picking/qpickevent.cpp @@ -309,14 +309,14 @@ int QPickEvent::modifiers() const * The viewport in which this event originated. A null value means the event originated from a frame graph branch without a Viewport. * If a frame graph branch has a Viewport inside a Viewport the property will contain the leaf viewport. * - * \since 5.13 + * \since 5.14 */ /*! * \property Qt3DRender::QPickEvent::viewport * The viewport in which this event originated. A null value means the event originated from a frame graph branch without a QViewport. * If a frame graph branch has a Viewport inside a Viewport the property will contain the leaf viewport. * - * \since 5.13 + * \since 5.14 */ QViewport *QPickEvent::viewport() const { @@ -332,7 +332,7 @@ QViewport *QPickEvent::viewport() const * If the object picker is not attached to a leaf node in the scene graph, * this is useful to find which child entity was actually picked. * - * \since 5.13 + * \since 5.14 */ /*! * \property Qt3DRender::QPickEvent::entity @@ -341,7 +341,7 @@ QViewport *QPickEvent::viewport() const * If the object picker is not attached to a leaf node in the scene graph, * this is useful to find which child entity was actually picked. * - * \since 5.13 + * \since 5.14 */ Qt3DCore::QEntity *QPickEvent::entity() const { diff --git a/src/render/picking/qpickevent.h b/src/render/picking/qpickevent.h index 21d072ffe..854008aaf 100644 --- a/src/render/picking/qpickevent.h +++ b/src/render/picking/qpickevent.h @@ -70,8 +70,8 @@ class Q_3DRENDERSHARED_EXPORT QPickEvent : public QObject Q_PROPERTY(Qt3DRender::QPickEvent::Buttons button READ button CONSTANT) Q_PROPERTY(int buttons READ buttons CONSTANT) Q_PROPERTY(int modifiers READ modifiers CONSTANT) - Q_PROPERTY(Qt3DRender::QViewport *viewport READ viewport CONSTANT) - Q_PROPERTY(Qt3DCore::QEntity *entity READ entity CONSTANT) + Q_PROPERTY(Qt3DRender::QViewport *viewport READ viewport CONSTANT REVISION 14) + Q_PROPERTY(Qt3DCore::QEntity *entity READ entity CONSTANT REVISION 14) public: enum Buttons { LeftButton = Qt::LeftButton, diff --git a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp index c9b04fa8f..f4bd8b871 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp +++ b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp @@ -269,7 +269,7 @@ QOpenGLShaderProgram *GraphicsContext::createShaderProgram(Shader *shaderNode) // That assumes that the shaderProgram in Shader stays the same void GraphicsContext::introspectShaderInterface(Shader *shader, QOpenGLShaderProgram *shaderProgram) { - GraphicsHelperInterface *glHelper = resolveHighestOpenGLFunctions(); + QScopedPointer<GraphicsHelperInterface> glHelper(resolveHighestOpenGLFunctions()); shader->initializeUniforms(glHelper->programUniformsAndLocations(shaderProgram->programId())); shader->initializeAttributes(glHelper->programAttributesAndLocations(shaderProgram->programId())); if (m_glHelper->supportsFeature(GraphicsHelperInterface::UniformBufferObject)) diff --git a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp index 24978fd87..c70f82dea 100644 --- a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp +++ b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp @@ -197,7 +197,7 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN // Add states from new stateSet we might be missing // but don' t override existing states (lower StateSetNode always has priority) if (rStateSet->hasRenderStates()) - addUniqueStatesToRenderStateSet(stateSet, rStateSet->renderStates(), manager->renderStateManager()); + addStatesToRenderStateSet(stateSet, rStateSet->renderStates(), manager->renderStateManager()); break; } @@ -436,13 +436,13 @@ void parametersFromMaterialEffectTechnique(ParameterInfoList *infoList, } // Only add states with types we don't already have -void addUniqueStatesToRenderStateSet(RenderStateSet *stateSet, - const QVector<Qt3DCore::QNodeId> stateIds, - RenderStateManager *manager) +void addStatesToRenderStateSet(RenderStateSet *stateSet, + const QVector<Qt3DCore::QNodeId> stateIds, + RenderStateManager *manager) { for (const Qt3DCore::QNodeId &stateId : stateIds) { RenderStateNode *node = manager->lookupResource(stateId); - if (node->isEnabled() && !stateSet->hasStateOfType(node->type())) { + if (node->isEnabled() && stateSet->canAddStateOfType(node->type())) { stateSet->addState(node->impl()); } } diff --git a/src/render/renderers/opengl/jobs/renderviewjobutils_p.h b/src/render/renderers/opengl/jobs/renderviewjobutils_p.h index bd2e12534..b2fa59785 100644 --- a/src/render/renderers/opengl/jobs/renderviewjobutils_p.h +++ b/src/render/renderers/opengl/jobs/renderviewjobutils_p.h @@ -150,9 +150,9 @@ void parametersFromParametersProvider(ParameterInfoList *infoList, Q_AUTOTEST_EXPORT ParameterInfoList::const_iterator findParamInfo(ParameterInfoList *infoList, const int nameId); -Q_AUTOTEST_EXPORT void addUniqueStatesToRenderStateSet(RenderStateSet *stateSet, - const QVector<Qt3DCore::QNodeId> stateIds, - RenderStateManager *manager); +Q_AUTOTEST_EXPORT void addStatesToRenderStateSet(RenderStateSet *stateSet, + const QVector<Qt3DCore::QNodeId> stateIds, + RenderStateManager *manager); typedef QHash<int, QVariant> UniformBlockValueBuilderHash; diff --git a/src/render/renderers/opengl/renderer/commandthread.cpp b/src/render/renderers/opengl/renderer/commandthread.cpp index dcaacadcc..a518d3b68 100644 --- a/src/render/renderers/opengl/renderer/commandthread.cpp +++ b/src/render/renderers/opengl/renderer/commandthread.cpp @@ -176,7 +176,7 @@ void CommandThread::run() m_commandRequestedSemaphore.acquire(); // Are we still running? - if (!m_running.load()) { + if (!m_running.loadRelaxed()) { m_graphicsContext->doneCurrent(); // to prevent executeCommand being locked m_commandExecutionSemaphore.release(); diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index e7112b3f4..2df3d1270 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -192,7 +192,6 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_updateMeshTriangleListJob(Render::UpdateMeshTriangleListJobPtr::create()) , m_filterCompatibleTechniqueJob(Render::FilterCompatibleTechniqueJobPtr::create()) , m_updateEntityLayersJob(Render::UpdateEntityLayersJobPtr::create()) - , m_updateEntityHierarchyJob(Render::UpdateEntityHierarchyJobPtr::create()) , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering)) , m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering)) , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering)) @@ -213,9 +212,6 @@ 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); @@ -304,7 +300,6 @@ void Renderer::setNodeManagers(NodeManagers *managers) m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager()); m_updateEntityLayersJob->setManager(m_nodesManager); m_updateTreeEnabledJob->setManagers(m_nodesManager); - m_updateEntityHierarchyJob->setManager(m_nodesManager); } void Renderer::setServices(QServiceLocator *services) @@ -448,7 +443,7 @@ void Renderer::shutdown() QMutexLocker lock(&m_hasBeenInitializedMutex); qCDebug(Backend) << Q_FUNC_INFO << "Requesting renderer shutdown"; - m_running.store(0); + m_running.storeRelaxed(0); // We delete any renderqueue that we may not have had time to render // before the surface was destroyed @@ -559,10 +554,9 @@ Render::FrameGraphNode *Renderer::frameGraphRoot() const // 2) setSceneRoot waits to acquire initialization // 3) submitRenderView -> check for surface // -> make surface current + create proper glHelper if needed -void Renderer::setSceneRoot(QBackendNodeFactory *factory, Entity *sgRoot) +void Renderer::setSceneRoot(Entity *sgRoot) { Q_ASSERT(sgRoot); - Q_UNUSED(factory); // If initialization hasn't been completed we must wait m_waitForInitializationToBeCompleted.acquire(); @@ -620,7 +614,7 @@ void Renderer::render() // One scene description // One framegraph description - while (m_running.load() > 0) { + while (m_running.loadRelaxed() > 0) { doRender(); // TO DO: Restore windows exposed detection // Probably needs to happens some place else though @@ -790,7 +784,7 @@ void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder const bool isQueueComplete = m_renderQueue->queueRenderView(renderView, submitOrder); locker.unlock(); // We're done protecting the queue at this point if (isQueueComplete) { - if (m_renderThread && m_running.load()) + if (m_renderThread && m_running.loadRelaxed()) Q_ASSERT(m_submitRenderViewsSemaphore.available() == 0); m_submitRenderViewsSemaphore.release(1); } @@ -799,7 +793,7 @@ void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder bool Renderer::canRender() const { // Make sure that we've not been told to terminate - if (m_renderThread && !m_running.load()) { + if (m_renderThread && !m_running.loadRelaxed()) { qCDebug(Rendering) << "RenderThread termination requested whilst waiting"; return false; } @@ -818,7 +812,7 @@ bool Renderer::isReadyToSubmit() m_submitRenderViewsSemaphore.acquire(1); // Check if shutdown has been requested - if (m_running.load() == 0) + if (m_running.loadRelaxed() == 0) return false; // The semaphore should only @@ -1425,7 +1419,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren const int renderViewsCount = renderViews.size(); quint64 frameElapsed = queueElapsed; - m_lastFrameCorrect.store(1); // everything fine until now..... + m_lastFrameCorrect.storeRelaxed(1); // everything fine until now..... qCDebug(Memory) << Q_FUNC_INFO << "rendering frame "; @@ -1458,7 +1452,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren // to use when surface is null. Or if we should instead expose an // offscreensurface to Qt3D. if (!surface || !surfaceLock.isSurfaceValid()) { - m_lastFrameCorrect.store(0); + m_lastFrameCorrect.storeRelaxed(0); continue; } @@ -1478,7 +1472,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren // next RenderView. We won't get the full frame but we may get something if (!m_submissionContext->beginDrawing(surface)) { qWarning() << "Failed to make OpenGL context current on surface"; - m_lastFrameCorrect.store(0); + m_lastFrameCorrect.storeRelaxed(0); continue; } @@ -1579,7 +1573,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren // Execute the render commands if (!executeCommandsSubmission(renderView)) - m_lastFrameCorrect.store(0); // something went wrong; make sure to render the next frame! + m_lastFrameCorrect.storeRelaxed(0); // something went wrong; make sure to render the next frame! // executeCommandsSubmission takes care of restoring the stateset to the value // of gc->currentContext() at the moment it was called (either @@ -1682,7 +1676,7 @@ bool Renderer::shouldRender() || m_renderThread == nullptr // <==> we use Scene3D || m_dirtyBits.marked != 0 || m_dirtyBits.remaining != 0 - || !m_lastFrameCorrect.load()); + || !m_lastFrameCorrect.loadRelaxed()); } void Renderer::skipNextFrame() @@ -1749,17 +1743,14 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() // Add jobs const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty; - const bool entityHierarchyNeedsToBeRebuilt = dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty; - if (entitiesEnabledDirty || entityHierarchyNeedsToBeRebuilt) { + if (entitiesEnabledDirty) { 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 || - dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty) { + if (dirtyBitsForFrame & AbstractRenderer::TransformDirty) { renderBinJobs.push_back(m_worldTransformJob); renderBinJobs.push_back(m_updateWorldBoundingVolumeJob); renderBinJobs.push_back(m_updateShaderDataTransformJob); @@ -1772,7 +1763,6 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() } if (dirtyBitsForFrame & AbstractRenderer::GeometryDirty || - dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty || dirtyBitsForFrame & AbstractRenderer::TransformDirty) { renderBinJobs.push_back(m_expandBoundingVolumeJob); } @@ -1799,7 +1789,7 @@ 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 || entityHierarchyNeedsToBeRebuilt; + const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty; const bool layersCacheNeedsToBeRebuilt = layersDirty || entitiesEnabledDirty || frameGraphDirty; const bool materialDirty = dirtyBitsForFrame & AbstractRenderer::MaterialDirty; const bool lightsDirty = dirtyBitsForFrame & AbstractRenderer::LightsDirty; @@ -1807,10 +1797,6 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() const bool renderableDirty = dirtyBitsForFrame & AbstractRenderer::GeometryDirty; const bool materialCacheNeedsToBeRebuilt = materialDirty || frameGraphDirty; - // Rebuild Entity Hierarchy if dirty - if (entityHierarchyNeedsToBeRebuilt) - renderBinJobs.push_back(m_updateEntityHierarchyJob); - // Rebuild Entity Layers list if layers are dirty if (layersDirty) renderBinJobs.push_back(m_updateEntityLayersJob); diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h index 5b566b3e7..bfab85e4f 100644 --- a/src/render/renderers/opengl/renderer/renderer_p.h +++ b/src/render/renderers/opengl/renderer/renderer_p.h @@ -78,7 +78,6 @@ #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> @@ -185,9 +184,9 @@ public: void doRender(bool swapBuffers = true) override; void cleanGraphicsResources() override; - bool isRunning() const override { return m_running.load(); } + bool isRunning() const override { return m_running.loadRelaxed(); } - void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Entity *sgRoot) override; + void setSceneRoot(Entity *sgRoot) override; Entity *sceneRoot() const override { return m_renderSceneRoot; } FrameGraphNode *frameGraphRoot() const override; @@ -368,7 +367,6 @@ 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/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp index 5845fe147..b00f2c473 100644 --- a/src/render/renderers/opengl/renderer/renderview.cpp +++ b/src/render/renderers/opengl/renderer/renderview.cpp @@ -425,7 +425,6 @@ struct SubRangeSorter<QSortPolicy::Texture> QVector<ShaderParameterPack::NamedResource> texturesB = b->m_parameterPack.textures(); const int originalTextureASize = texturesA.size(); - const bool isSuperior = originalTextureASize > texturesB.size(); if (texturesB.size() > texturesA.size()) qSwap(texturesA, texturesB); @@ -656,7 +655,7 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit RenderPass *pass = passData.pass; if (pass->hasRenderStates()) { command->m_stateSet = new RenderStateSet(); - addUniqueStatesToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager()); + addStatesToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager()); if (m_stateSet != nullptr) command->m_stateSet->merge(m_stateSet); command->m_changeCost = m_renderer->defaultRenderState()->changeCost(command->m_stateSet); @@ -781,7 +780,7 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En if (pass->hasRenderStates()) { command->m_stateSet = new RenderStateSet(); - addUniqueStatesToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager()); + addStatesToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager()); // Merge per pass stateset with global stateset // so that the local stateset only overrides diff --git a/src/render/renderers/opengl/renderstates/renderstateset.cpp b/src/render/renderers/opengl/renderstates/renderstateset.cpp index b14695c77..d667d9c76 100644 --- a/src/render/renderers/opengl/renderstates/renderstateset.cpp +++ b/src/render/renderers/opengl/renderstates/renderstateset.cpp @@ -112,17 +112,28 @@ void RenderStateSet::merge(RenderStateSet *other) // We only add states which are new (different type) for (const StateVariant &otherState : otherStates) { - const bool hasFoundStateOfSameType = hasStateOfType(otherState.type); - if (!hasFoundStateOfSameType) + const bool canAdd = canAddStateOfType(otherState.type); + if (canAdd) m_states.push_back(otherState); } } +bool RenderStateSet::canAddStateOfType(StateMask type) const +{ + return !hasStateOfType(type) || allowMultipleStatesOfType(type); +} + bool RenderStateSet::hasStateOfType(StateMask type) const { return (type & stateMask()); } +bool RenderStateSet::allowMultipleStatesOfType(StateMask type) const +{ + return (type == BlendEquationArgumentsMask) || + (type == ClipPlaneMask); +} + bool RenderStateSet::contains(const StateVariant &ds) const { // trivial reject using the state mask bits diff --git a/src/render/renderers/opengl/renderstates/renderstateset_p.h b/src/render/renderers/opengl/renderstates/renderstateset_p.h index 29be4d2f1..c2f3a0219 100644 --- a/src/render/renderers/opengl/renderstates/renderstateset_p.h +++ b/src/render/renderers/opengl/renderstates/renderstateset_p.h @@ -93,8 +93,7 @@ public: QVector<StateVariant> states() const { return m_states; } - bool hasStateOfType(StateMask type) const; - + bool canAddStateOfType(StateMask type) const; /** * @brief contains - check if this set contains a matching piece of state @@ -102,6 +101,11 @@ public: * @return */ bool contains(const StateVariant &ds) const; + +private: + bool hasStateOfType(StateMask type) const; + bool allowMultipleStatesOfType(StateMask type) const; + private: StateMaskSet m_stateMask; QVector<StateVariant> m_states; diff --git a/src/render/renderers/opengl/textures/gltexture.cpp b/src/render/renderers/opengl/textures/gltexture.cpp index 93348d0b0..11d2c2be9 100644 --- a/src/render/renderers/opengl/textures/gltexture.cpp +++ b/src/render/renderers/opengl/textures/gltexture.cpp @@ -474,15 +474,15 @@ QOpenGLTexture *GLTexture::buildGLTexture() QAbstractTexture::TextureFormat format = m_properties.format; if (ctx->isOpenGLES() && ctx->format().majorVersion() < 3) { switch (m_properties.format) { - case QOpenGLTexture::RGBA8_UNorm: - case QOpenGLTexture::RGBAFormat: + case QAbstractTexture::RGBA8_UNorm: + case QAbstractTexture::RGBAFormat: format = QAbstractTexture::RGBAFormat; break; - case QOpenGLTexture::RGB8_UNorm: - case QOpenGLTexture::RGBFormat: + case QAbstractTexture::RGB8_UNorm: + case QAbstractTexture::RGBFormat: format = QAbstractTexture::RGBFormat; break; - case QOpenGLTexture::DepthFormat: + case QAbstractTexture::DepthFormat: format = QAbstractTexture::DepthFormat; break; default: @@ -682,8 +682,8 @@ void GLTexture::introspectPropertiesFromSharedTextureId() const QPair<int, int> ctxGLVersion = ctx->format().version(); if (ctxGLVersion.first > 4 || (ctxGLVersion.first == 4 && ctxGLVersion.second >= 5)) { // Only for GL 4.5+ - QOpenGLFunctions_4_5_Core *gl5 = ctx->versionFunctions<QOpenGLFunctions_4_5_Core>(); #ifdef GL_TEXTURE_TARGET + QOpenGLFunctions_4_5_Core *gl5 = ctx->versionFunctions<QOpenGLFunctions_4_5_Core>(); if (gl5 != nullptr) gl5->glGetTextureParameteriv(m_sharedTextureId, GL_TEXTURE_TARGET, reinterpret_cast<int *>(&m_properties.target)); #endif diff --git a/src/render/renderstates/qdepthrange.cpp b/src/render/renderstates/qdepthrange.cpp index 58b8b744a..ec5bbce9f 100644 --- a/src/render/renderstates/qdepthrange.cpp +++ b/src/render/renderstates/qdepthrange.cpp @@ -48,7 +48,7 @@ namespace Qt3DRender { /*! \class Qt3DRender::QDepthRange \inmodule Qt3DRender - \since 5.13 + \since 5.14 \ingroup renderstates \brief Enables remapping depth values written into the depth buffer. @@ -65,7 +65,7 @@ namespace Qt3DRender { \inherits RenderState \inqmlmodule Qt3D.Render \ingroup renderstates - \since 5.13 + \since 5.14 \brief Enables remapping depth values written into the depth buffer. By default, OpenGL writes scene depth information into the depth buffer in diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp index 399314f24..229d773ad 100644 --- a/src/render/texture/qabstracttexture.cpp +++ b/src/render/texture/qabstracttexture.cpp @@ -81,10 +81,7 @@ void QAbstractTexturePrivate::setDataFunctor(const QTextureGeneratorPtr &generat { if (generator != m_dataFunctor) { m_dataFunctor = generator; - auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id); - change->setPropertyName("generator"); - change->setValue(QVariant::fromValue(generator)); - notifyObservers(change); + update(); } } @@ -811,24 +808,15 @@ void QAbstractTexture::setWrapMode(const QTextureWrapMode &wrapMode) Q_D(QAbstractTexture); if (d->m_wrapMode.x() != wrapMode.x()) { d->m_wrapMode.setX(wrapMode.x()); - auto e = QPropertyUpdatedChangePtr::create(d->m_id); - e->setPropertyName("wrapModeX"); - e->setValue(static_cast<int>(d->m_wrapMode.x())); - d->notifyObservers(e); + d->update(); } if (d->m_wrapMode.y() != wrapMode.y()) { d->m_wrapMode.setY(wrapMode.y()); - auto e = QPropertyUpdatedChangePtr::create(d->m_id); - e->setPropertyName("wrapModeY"); - e->setValue(static_cast<int>(d->m_wrapMode.y())); - d->notifyObservers(e); + d->update(); } if (d->m_wrapMode.z() != wrapMode.z()) { d->m_wrapMode.setZ(wrapMode.z()); - auto e = QPropertyUpdatedChangePtr::create(d->m_id); - e->setPropertyName("wrapModeZ"); - e->setValue(static_cast<int>(d->m_wrapMode.z())); - d->notifyObservers(e); + d->update(); } } @@ -983,16 +971,8 @@ void QAbstractTexture::updateData(const QTextureDataUpdate &update) { Q_D(QAbstractTexture); - // Send update to backend if we have the changeArbiter - if (d->m_changeArbiter != nullptr) { - auto e = QPropertyUpdatedChangePtr::create(id()); - e->setPropertyName("updateData"); - e->setValue(QVariant::fromValue(update)); - notifyObservers(e); - } else { - // If we have no arbiter (no backend), record the update as part of the creation changes - d->m_initialDataUpdates.push_back(update); - } + d->m_pendingDataUpdates.push_back(update); + d->update(); } Qt3DCore::QNodeCreatedChangeBasePtr QAbstractTexture::createNodeCreationChange() const @@ -1019,8 +999,8 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAbstractTexture::createNodeCreationChange() data.samples = d->m_samples; data.dataFunctor = d->m_dataFunctor; data.sharedTextureId = d->m_sharedTextureId; - data.initialDataUpdates = d->m_initialDataUpdates; - return creationChange; + data.initialDataUpdates = d->m_pendingDataUpdates; + return std::move(creationChange); } /*! diff --git a/src/render/texture/qabstracttexture_p.h b/src/render/texture/qabstracttexture_p.h index 072bd8159..573eac8c7 100644 --- a/src/render/texture/qabstracttexture_p.h +++ b/src/render/texture/qabstracttexture_p.h @@ -96,7 +96,7 @@ public : QTextureGeneratorPtr dataFunctor() const; void setDataFunctor(const QTextureGeneratorPtr &generator); - QVector<QTextureDataUpdate> m_initialDataUpdates; + QVector<QTextureDataUpdate> m_pendingDataUpdates; private: QTextureGeneratorPtr m_dataFunctor; diff --git a/src/render/texture/qabstracttextureimage.cpp b/src/render/texture/qabstracttextureimage.cpp index a95e1fffd..42f8eb747 100644 --- a/src/render/texture/qabstracttextureimage.cpp +++ b/src/render/texture/qabstracttextureimage.cpp @@ -255,12 +255,7 @@ void QAbstractTextureImage::setFace(QAbstractTexture::CubeMapFace face) void QAbstractTextureImage::notifyDataGeneratorChanged() { Q_D(QAbstractTextureImage); - if (d->m_changeArbiter != nullptr) { - auto change = QPropertyUpdatedChangePtr::create(d->m_id); - change->setPropertyName("dataGenerator"); - change->setValue(QVariant::fromValue(dataGenerator())); - d->notifyObservers(change); - } + d->update(); } /*! \internal */ diff --git a/src/render/texture/qtexturedataupdate.cpp b/src/render/texture/qtexturedataupdate.cpp index f196a6b7b..e3d5220f0 100644 --- a/src/render/texture/qtexturedataupdate.cpp +++ b/src/render/texture/qtexturedataupdate.cpp @@ -68,6 +68,7 @@ static bool operator==(const QTextureDataUpdatePrivate &lhs, const QTextureDataU as well as the eventual layer, mipLevel and face. \sa QAbstractTexture + \since 5.14 */ QTextureDataUpdate::QTextureDataUpdate() diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp index c7a739724..53216d27d 100644 --- a/src/render/texture/texture.cpp +++ b/src/render/texture/texture.cpp @@ -61,6 +61,7 @@ Texture::Texture() // We need backend -> frontend notifications to update the status of the texture : BackendNode(ReadWrite) , m_dirty(DirtyImageGenerators|DirtyProperties|DirtyParameters|DirtyDataGenerator) + , m_sharedTextureId(-1) { } @@ -130,67 +131,6 @@ void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) DirtyFlags dirty; switch (e->type()) { - case PropertyUpdated: { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("width")) { - m_properties.width = propertyChange->value().toInt(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("height")) { - m_properties.height = propertyChange->value().toInt(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("depth")) { - m_properties.depth = propertyChange->value().toInt(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("format")) { - m_properties.format = static_cast<QAbstractTexture::TextureFormat>(propertyChange->value().toInt()); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("target")) { - m_properties.target = static_cast<QAbstractTexture::Target>(propertyChange->value().toInt()); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("mipmaps")) { - m_properties.generateMipMaps = propertyChange->value().toBool(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("minificationFilter")) { - m_parameters.minificationFilter = static_cast<QAbstractTexture::Filter>(propertyChange->value().toInt()); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("magnificationFilter")) { - m_parameters.magnificationFilter = static_cast<QAbstractTexture::Filter>(propertyChange->value().toInt()); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeX")) { - m_parameters.wrapModeX = static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt()); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeY")) { - m_parameters.wrapModeY = static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt()); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeZ")) { - m_parameters.wrapModeZ =static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt()); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("maximumAnisotropy")) { - m_parameters.maximumAnisotropy = propertyChange->value().toFloat(); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("comparisonFunction")) { - m_parameters.comparisonFunction = propertyChange->value().value<QAbstractTexture::ComparisonFunction>(); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("comparisonMode")) { - m_parameters.comparisonMode = propertyChange->value().value<QAbstractTexture::ComparisonMode>(); - dirty = DirtyParameters; - } else if (propertyChange->propertyName() == QByteArrayLiteral("layers")) { - m_properties.layers = propertyChange->value().toInt(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("samples")) { - m_properties.samples = propertyChange->value().toInt(); - dirty = DirtyProperties; - } else if (propertyChange->propertyName() == QByteArrayLiteral("generator")) { - setDataGenerator(propertyChange->value().value<QTextureGeneratorPtr>()); - } else if (propertyChange->propertyName() == QByteArrayLiteral("textureId")) { - m_sharedTextureId = propertyChange->value().toInt(); - dirty = DirtySharedTextureId; - } else if (propertyChange->propertyName() == QByteArrayLiteral("updateData")) { - Qt3DRender::QTextureDataUpdate updateData = propertyChange->value().value<Qt3DRender::QTextureDataUpdate>(); - addTextureDataUpdate(updateData); - } - break; - } case PropertyValueAdded: { const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); @@ -217,6 +157,62 @@ void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) BackendNode::sceneChangeEvent(e); } +void Texture::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) +{ + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QAbstractTexture *node = qobject_cast<const QAbstractTexture *>(frontEnd); + if (!node) + return; + + TextureProperties p = m_properties; + p.width = node->width(); + p.height = node->height(); + p.depth = node->depth(); + p.format = node->format(); + p.target = node->target(); + p.generateMipMaps = node->generateMipMaps(); + p.layers = node->layers(); + p.samples = node->samples(); + if (p != m_properties) { + m_properties = p; + addDirtyFlag(DirtyProperties); + } + + TextureParameters q = m_parameters; + q.magnificationFilter = node->magnificationFilter(); + q.minificationFilter = node->minificationFilter(); + q.wrapModeX = const_cast<QAbstractTexture *>(node)->wrapMode()->x(); + q.wrapModeY = const_cast<QAbstractTexture *>(node)->wrapMode()->y(); + q.wrapModeZ = const_cast<QAbstractTexture *>(node)->wrapMode()->z(); + q.maximumAnisotropy = node->maximumAnisotropy(); + q.comparisonFunction = node->comparisonFunction(); + q.comparisonMode = node->comparisonMode(); + if (q != m_parameters) { + m_parameters = q; + addDirtyFlag(DirtyParameters); + } + + auto newGenerator = node->dataGenerator(); + if (newGenerator != m_dataFunctor) { + setDataGenerator(newGenerator); + } + + QAbstractTexturePrivate *dnode = dynamic_cast<QAbstractTexturePrivate *>(QAbstractTexturePrivate::get(const_cast<QAbstractTexture *>(node))); + if (dnode) { + for (const QTextureDataUpdate &pendingUpdate : dnode->m_pendingDataUpdates) + addTextureDataUpdate(pendingUpdate); + dnode->m_pendingDataUpdates.clear(); + + for (const auto imgNode : dnode->m_textureImages) + addTextureImage(imgNode->id()); + } + + if (dnode->m_sharedTextureId != m_sharedTextureId) { + m_sharedTextureId = dnode->m_sharedTextureId; + addDirtyFlag(DirtySharedTextureId); + } +} + // Called by sceneChangeEvent or TextureDownloadRequest (both in AspectThread context) void Texture::setDataGenerator(const QTextureGeneratorPtr &generator) { @@ -308,7 +304,7 @@ void Texture::updatePropertiesAndNotify(const TextureUpdateInfo &updateInfo) bool Texture::isValid(TextureImageManager *manager) const { - for (const QNodeId id : m_textureImageIds) { + for (const QNodeId &id : m_textureImageIds) { TextureImage *img = manager->lookupResource(id); if (img == nullptr) return false; @@ -340,7 +336,7 @@ void Texture::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chan m_dataFunctor = data.dataFunctor; m_sharedTextureId = data.sharedTextureId; - for (const QNodeId imgId : data.textureImageIds) + for (const QNodeId &imgId : data.textureImageIds) addTextureImage(imgId); const QVector<QTextureDataUpdate> initialDataUpdates = data.initialDataUpdates; diff --git a/src/render/texture/texture_p.h b/src/render/texture/texture_p.h index 28580c92a..967b2a44a 100644 --- a/src/render/texture/texture_p.h +++ b/src/render/texture/texture_p.h @@ -164,6 +164,7 @@ public: QVector<QTextureDataUpdate> takePendingTextureDataUpdates() { return std::move(m_pendingTextureDataUpdates); } void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; inline const TextureProperties& properties() const { return m_properties; } inline const TextureParameters& parameters() const { return m_parameters; } |