From 4b9ba03e0b8c5bb60410ea016d8436a57c02e6f8 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 18 Aug 2017 09:22:49 +0200 Subject: Fix and improve layer filtering We now handle the case where multiple LayerFilter nodes are nested within the same FrameGraphBranch. We also have improved the Accept/Discard into Accept Any/All and Discard Any/All which should now handle all filtering cases. We now build a list of layerIds stored into Entity based on the recursive flags on the layers being set. This allows to make layer filtering simpler but the layerIds list building step will need to be improved as a follow up commit Unit tests updated Change-Id: I93451493e41c6c9486defa7e88eaee073a9bc932 Reviewed-by: Sean Harmer --- src/render/backend/entity.cpp | 11 + src/render/backend/entity_p.h | 8 + src/render/backend/renderview_p.h | 14 +- src/render/backend/renderviewbuilder.cpp | 4 +- src/render/framegraph/layerfilternode.cpp | 2 +- src/render/framegraph/qlayerfilter.cpp | 63 ++- src/render/framegraph/qlayerfilter.h | 6 +- src/render/jobs/filterlayerentityjob.cpp | 262 ++++++---- src/render/jobs/filterlayerentityjob_p.h | 17 +- src/render/jobs/renderviewjobutils.cpp | 4 +- tests/auto/render/entity/tst_entity.cpp | 3 + .../render/layerfiltering/tst_layerfiltering.cpp | 539 ++++++++++++++++----- .../renderviewbuilder/tst_renderviewbuilder.cpp | 4 +- .../layerfiltering/tst_bench_layerfiltering.cpp | 46 +- 14 files changed, 688 insertions(+), 295 deletions(-) diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index dc621512a..a0f052d06 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -411,6 +411,17 @@ void Entity::unsetBoundingVolumeDirty() m_boundingDirty = false; } +void Entity::addRecursiveLayerId(const QNodeId layerId) +{ + if (!m_recursiveLayerComponents.contains(layerId) && !m_layerComponents.contains(layerId)) + m_recursiveLayerComponents.push_back(layerId); +} + +void Entity::removeRecursiveLayerId(const QNodeId layerId) +{ + m_recursiveLayerComponents.removeOne(layerId); +} + // Handles template<> diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h index 6f8a781e6..9516ee82b 100644 --- a/src/render/backend/entity_p.h +++ b/src/render/backend/entity_p.h @@ -120,6 +120,11 @@ public: void setTreeEnabled(bool enabled) { m_treeEnabled = enabled; } bool isTreeEnabled() const { return m_treeEnabled; } + Qt3DCore::QNodeIdVector layerIds() const { return m_layerComponents + m_recursiveLayerComponents; } + void addRecursiveLayerId(const Qt3DCore::QNodeId layerId); + void removeRecursiveLayerId(const Qt3DCore::QNodeId layerId); + void clearRecursiveLayerIds() { m_recursiveLayerComponents.clear(); } + template Qt3DCore::QHandle componentHandle() const { @@ -197,6 +202,9 @@ private: Qt3DCore::QNodeId m_computeComponent; Qt3DCore::QNodeId m_armatureComponent; + // Includes recursive layers + Qt3DCore::QNodeIdVector m_recursiveLayerComponents; + QString m_objectName; bool m_boundingDirty; // true only if this and all parent nodes are enabled diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h index 1674db0a5..050dfb71e 100644 --- a/src/render/backend/renderview_p.h +++ b/src/render/backend/renderview_p.h @@ -150,12 +150,8 @@ public: inline void setEyePosition(const QVector3D &eyePos) Q_DECL_NOTHROW { m_data.m_eyePos = eyePos; } inline QVector3D eyePosition() const Q_DECL_NOTHROW { return m_data.m_eyePos; } - inline void setHasLayerFilter(bool filter) Q_DECL_NOTHROW { m_data.m_hasLayerFilter = filter; } - inline bool hasLayerFilter() const Q_DECL_NOTHROW { return m_data.m_hasLayerFilter; } - inline void appendLayerFilter(const Qt3DCore::QNodeIdVector &layerIds) Q_DECL_NOTHROW { m_data.m_layerIds << layerIds; } - inline Qt3DCore::QNodeIdVector layerFilter() const Q_DECL_NOTHROW { return m_data.m_layerIds; } - inline QLayerFilter::FilterMode layerFilterFilterMode() const Q_DECL_NOTHROW { return m_data.m_layerFilterFilterMode; } - inline void setLayerFilterFilterMode(QLayerFilter::FilterMode filterMode) Q_DECL_NOTHROW { m_data.m_layerFilterFilterMode = filterMode; } + inline void appendLayerFilter(const Qt3DCore::QNodeId layerFilterId) Q_DECL_NOTHROW { m_data.m_layerFilterIds.push_back(layerFilterId); } + inline Qt3DCore::QNodeIdVector layerFilters() const Q_DECL_NOTHROW { return m_data.m_layerFilterIds; } inline void setRenderPassFilter(const RenderPassFilter *rpFilter) Q_DECL_NOTHROW { m_data.m_passFilter = rpFilter; } inline const RenderPassFilter *renderPassFilter() const Q_DECL_NOTHROW { return m_data.m_passFilter; } @@ -240,8 +236,6 @@ public: , m_renderCameraNode(nullptr) , m_techniqueFilter(nullptr) , m_passFilter(nullptr) - , m_hasLayerFilter(false) - , m_layerFilterFilterMode(QLayerFilter::AcceptMatchingLayers) { } CameraLens *m_renderCameraLens; @@ -250,9 +244,7 @@ public: const RenderPassFilter *m_passFilter; QMatrix4x4 m_viewMatrix; QMatrix4x4 m_viewProjectionMatrix; - bool m_hasLayerFilter; - QLayerFilter::FilterMode m_layerFilterFilterMode; - Qt3DCore::QNodeIdVector m_layerIds; + Qt3DCore::QNodeIdVector m_layerFilterIds; QVector m_sortingTypes; QVector3D m_eyePos; }; diff --git a/src/render/backend/renderviewbuilder.cpp b/src/render/backend/renderviewbuilder.cpp index e651ce180..9676fb32d 100644 --- a/src/render/backend/renderviewbuilder.cpp +++ b/src/render/backend/renderviewbuilder.cpp @@ -137,9 +137,7 @@ public: RenderView *rv = m_renderViewJob->renderView(); // Layer filtering - m_filterEntityByLayerJob->setHasLayerFilter(rv->hasLayerFilter()); - m_filterEntityByLayerJob->setLayers(rv->layerFilter()); - m_filterEntityByLayerJob->setFilterMode(rv->layerFilterFilterMode()); + m_filterEntityByLayerJob->setLayerFilters(rv->layerFilters()); // Material Parameter building for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) { diff --git a/src/render/framegraph/layerfilternode.cpp b/src/render/framegraph/layerfilternode.cpp index 6223543c6..b8fa5c075 100644 --- a/src/render/framegraph/layerfilternode.cpp +++ b/src/render/framegraph/layerfilternode.cpp @@ -53,7 +53,7 @@ namespace Render { LayerFilterNode::LayerFilterNode() : FrameGraphNode(FrameGraphNode::LayerFilter) - , m_filterMode(QLayerFilter::AcceptMatchingLayers) + , m_filterMode(QLayerFilter::AcceptAnyMatchingLayers) { } diff --git a/src/render/framegraph/qlayerfilter.cpp b/src/render/framegraph/qlayerfilter.cpp index 4944fb6cc..04ebca572 100644 --- a/src/render/framegraph/qlayerfilter.cpp +++ b/src/render/framegraph/qlayerfilter.cpp @@ -51,7 +51,7 @@ namespace Qt3DRender { QLayerFilterPrivate::QLayerFilterPrivate() : QFrameGraphNodePrivate() - , m_filterMode(QLayerFilter::AcceptMatchingLayers) + , m_filterMode(QLayerFilter::AcceptAnyMatchingLayers) { } @@ -67,8 +67,17 @@ QLayerFilterPrivate::QLayerFilterPrivate() the QLayerFilter and as components to Qt3DCore::QEntity. QLayerFilter can be configured to select or discard entities with a - specific QLayer depending on the filterMode property. By default, entities - referencing a QLayer that is also added to the QLayerFilter are selected. + specific \l QLayer depending on the filterMode property. By default, + entities referencing one of the \l QLayer objects that are also being + referenced by the \l QLayerFilter are selected (AcceptAnyMatchingLayers). + + Within the FrameGraph tree, multiple \l QLayerFilter nodes can be nested + within a branch going from root to a leaf. In that case the filtering will + first operate on all entities of the scene using the filtering method + specified by the first declared \l QLayerFilter. Then the filtered subset + of entities will be filtered again based on the filtering method set on the + second \l QLayerFilter declared. This is then repeated until all \l + QLayerFilter nodes of the branch have been consumed. */ /*! @@ -76,11 +85,21 @@ QLayerFilterPrivate::QLayerFilterPrivate() Specifies the rules for selecting entities to draw. - \value AcceptMatchingLayers - Accept entities that reference a QLayer added to this QLayerFilter + \value AcceptAnyMatchingLayers + Accept entities that reference one or more \l QLayer objects added to this + QLayerFilter. This is the default - \value DiscardMatchingLayers - Discard entities that reference a QLayer added to this QLayerFilter + \value AcceptAllMatchingLayers + Accept entities that reference all the \l QLayer objects added to this + QLayerFilter + + \value DiscardAnyMatchingLayers + Discard entities that reference one or more \l QLayer objects added to this + QLayerFilter + + \value DiscardAllMatchingLayers + Discard entities that reference all \l QLayer objects added to this + QLayerFilter */ /*! @@ -106,8 +125,16 @@ QLayerFilterPrivate::QLayerFilterPrivate() The LayerFilter can be configured to select or discard entities with a specific \l Layer depending on the filterMode property. By default, - entities referencing a \l Layer that is also added to the LayerFilter are - selected. + entities referencing one of the \l Layer objects that are also being + referenced by the \l LayerFilter are selected (AcceptAnyMatchingLayers). + + Within the FrameGraph tree, multiple \l LayerFilter nodes can be nested + within a branch going from root to a leaf. In that case the filtering will + first operate on all entities of the scene using the filtering method + specified by the first declared \l LayerFilter. Then the filtered subset of + entities will be filtered again based on the filtering method set on the + second \l LayerFilter declared. This is then repeated until all \l + LayerFilter nodes of the branch have been consumed. */ /*! @@ -123,11 +150,21 @@ QLayerFilterPrivate::QLayerFilterPrivate() The default value is \c {LayerFilter.AcceptMatchingLayers}. - \value LayerFilter.AcceptMatchingLayers - Accept entities that reference a \l Layer added to this LayerFilter + \value LayerFilter.AcceptAnyMatchingLayers + Accept entities that reference one or more \l Layer objects added to this + LayerFilter. This is the default + + \value LayerFilter.AcceptAllMatchingLayers + Accept entities that reference all the \l Layer objects added to this + LayerFilter + + \value LayerFilter.DiscardAnyMatchingLayers + Discard entities that reference one or more \l Layer objects added to this + LayerFilter - \value LayerFilter.DiscardMatchingLayers - Discard entities that reference a \l Layer added to this LayerFilter + \value LayerFilter.DiscardAllMatchingLayers + Discard entities that reference all \l Layer objects added to this + LayerFilter */ /*! diff --git a/src/render/framegraph/qlayerfilter.h b/src/render/framegraph/qlayerfilter.h index 243ae7165..68854c722 100644 --- a/src/render/framegraph/qlayerfilter.h +++ b/src/render/framegraph/qlayerfilter.h @@ -57,8 +57,10 @@ class QT3DRENDERSHARED_EXPORT QLayerFilter : public QFrameGraphNode public: enum FilterMode { - AcceptMatchingLayers = 0, - DiscardMatchingLayers + AcceptAnyMatchingLayers = 0, + AcceptAllMatchingLayers, + DiscardAnyMatchingLayers, + DiscardAllMatchingLayers, }; Q_ENUM(FilterMode) // LOVC_EXLC_LINE diff --git a/src/render/jobs/filterlayerentityjob.cpp b/src/render/jobs/filterlayerentityjob.cpp index 1193c4552..902338be7 100644 --- a/src/render/jobs/filterlayerentityjob.cpp +++ b/src/render/jobs/filterlayerentityjob.cpp @@ -42,6 +42,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -51,144 +52,203 @@ namespace Render { namespace { int layerFilterJobCounter = 0; + +// TO DO: This will be moved to a dedicated job with smarter +// heuristics in a later commit +void addLayerIdToEntityChildren(const QVector &children, + const Qt3DCore::QNodeId layerId) +{ + for (Entity *child : children) { + child->addRecursiveLayerId(layerId); + addLayerIdToEntityChildren(child->children(), layerId); + } +} + +void updateEntityLayers(NodeManagers *manager) +{ + EntityManager *entityManager = manager->renderNodesManager(); + + const QVector handles = entityManager->activeHandles(); + + // Clear list of recursive layerIds + for (const HEntity handle : handles) { + Entity *entity = entityManager->data(handle); + entity->clearRecursiveLayerIds(); + } + + LayerManager *layerManager = manager->layerManager(); + + // Set recursive layerIds on children + for (const HEntity handle : handles) { + Entity *entity = entityManager->data(handle); + const Qt3DCore::QNodeIdVector entityLayers = entity->componentsUuid(); + + for (const Qt3DCore::QNodeId layerId : entityLayers) { + Layer *layer = layerManager->lookupResource(layerId); + if (layer->recursive()) { + // Find all children of the entity and add the layers to them + addLayerIdToEntityChildren(entity->children(), layerId); + } + } + } +} + } // anonymous FilterLayerEntityJob::FilterLayerEntityJob() : Qt3DCore::QAspectJob() , m_manager(nullptr) - , m_hasLayerFilter(false) - , m_filterMode(QLayerFilter::AcceptMatchingLayers) { SET_JOB_RUN_STAT_TYPE(this, JobTypes::LayerFiltering, layerFilterJobCounter++); } + void FilterLayerEntityJob::run() { m_filteredEntities.clear(); - if (m_hasLayerFilter) { // LayerFilter set -> filter - LayerManager *layerManager = m_manager->layerManager(); - - // Remove layerIds which are not active/enabled - for (auto i = m_layerIds.size() - 1; i >= 0; --i) { - Layer *backendLayer = layerManager->lookupResource(m_layerIds.at(i)); - if (backendLayer == nullptr || !backendLayer->isEnabled()) - m_layerIds.removeAt(i); - } - + if (hasLayerFilter()) { // LayerFilter set -> filter + updateEntityLayers(m_manager); filterLayerAndEntity(); } else { // No LayerFilter set -> retrieve all selectAllEntities(); } } -void FilterLayerEntityJob::setFilterMode(QLayerFilter::FilterMode filterMode) +// We accept the entity if it contains any of the layers that are in the layer filter +void FilterLayerEntityJob::filterAcceptAnyMatchingLayers(Entity *entity, + const Qt3DCore::QNodeIdVector &layerIds) { - m_filterMode = filterMode; + const Qt3DCore::QNodeIdVector entityLayers = entity->layerIds(); + + for (const Qt3DCore::QNodeId id : entityLayers) { + const bool layerAccepted = layerIds.contains(id); + + if (layerAccepted) { + m_filteredEntities.push_back(entity); + break; + } + } +} + +// We accept the entity if it contains all the layers that are in the layer +// filter +void FilterLayerEntityJob::filterAcceptAllMatchingLayers(Entity *entity, + const Qt3DCore::QNodeIdVector &layerIds) +{ + const Qt3DCore::QNodeIdVector entityLayers = entity->layerIds(); + int layersAccepted = 0; + + for (const Qt3DCore::QNodeId id : entityLayers) { + if (layerIds.contains(id)) + ++layersAccepted; + } + + if (layersAccepted == layerIds.size()) + m_filteredEntities.push_back(entity); +} + +// We discard the entity if it contains any of the layers that are in the layer +// filter +// In other words that means we select an entity if one of its layers is not on +// the layer filter +void FilterLayerEntityJob::filterDiscardAnyMatchingLayers(Entity *entity, + const Qt3DCore::QNodeIdVector &layerIds) +{ + const Qt3DCore::QNodeIdVector entityLayers = entity->layerIds(); + bool entityCanBeDiscarded = false; + + for (const Qt3DCore::QNodeId id : entityLayers) { + if (layerIds.contains(id)) { + entityCanBeDiscarded = true; + break; + } + } + + if (!entityCanBeDiscarded) + m_filteredEntities.push_back(entity); +} + +// We discard the entity if it contains all of the layers that are in the layer +// filter +// In other words that means we select an entity if none of its layers are on +// the layer filter +void FilterLayerEntityJob::filterDiscardAllMatchingLayers(Entity *entity, + const Qt3DCore::QNodeIdVector &layerIds) +{ + const Qt3DCore::QNodeIdVector entityLayers = entity->layerIds(); + + int containedLayers = 0; + + for (const Qt3DCore::QNodeId id : layerIds) { + if (entityLayers.contains(id)) + ++containedLayers; + } + + if (containedLayers != layerIds.size()) + m_filteredEntities.push_back(entity); } -// Note: we assume that m_layerIds contains only enabled layers -// -> meaning that if an Entity references such a layer, it's enabled void FilterLayerEntityJob::filterLayerAndEntity() { EntityManager *entityManager = m_manager->renderNodesManager(); - LayerManager *layerManager = m_manager->layerManager(); const QVector handles = entityManager->activeHandles(); + QVector entitiesToFilter; + entitiesToFilter.reserve(handles.size()); + for (const HEntity handle : handles) { Entity *entity = entityManager->data(handle); - if (!entity->isTreeEnabled()) - continue; + if (entity->isTreeEnabled()) + entitiesToFilter.push_back(entity); + } - const Qt3DCore::QNodeIdVector entityLayers = entity->componentsUuid(); + FrameGraphManager *frameGraphManager = m_manager->frameGraphManager(); + LayerManager *layerManager = m_manager->layerManager(); - // An Entity is positively filtered if it contains at least one Layer component with the same id as the - // layers selected by the LayerFilter - - // If !discard, as soon as one entity layer is managed by the FilterLayer, accept the entity - switch (m_filterMode) { - case QLayerFilter::AcceptMatchingLayers: { - // Be aware that the same entity may appear in the filteredEntities vector, is this a problem? - for (const Qt3DCore::QNodeId id : entityLayers) { - bool entityIsAlreadyAccepted = false; - if (m_layerIds.contains(id)) { - // When we found a layer in the entity that matches a layer in the LayerFilter - - // If the entity hasn't been already accepted, accept it - if (!entityIsAlreadyAccepted) { - m_filteredEntities.push_back(entity); - entityIsAlreadyAccepted = true; - } - - Layer *layer = layerManager->lookupResource(id); - - // If the found layer is recursive, accept children and break - if (layer->recursive()) { - QVector childEntities = entity->children(); - for (int i = 0; i < childEntities.size(); ++i) { - Entity *childEntity = childEntities[i]; - if (childEntity->isTreeEnabled()) { - m_filteredEntities.push_back(childEntity); - - // Add children of the child entity (so that is recursive in the tree) - const QVector childChildEntities = childEntity->children(); - for (Entity *childChildEntity : childChildEntities) - childEntities.push_back(childChildEntity); - } - } - break; - } - - // If the layer is not recursive, maybe another one in the same entity it is, so continue searching - } - } - break; + for (const Qt3DCore::QNodeId layerFilterId : m_layerFilterIds) { + LayerFilterNode *layerFilter = static_cast(frameGraphManager->lookupNode(layerFilterId)); + Qt3DCore::QNodeIdVector layerIds = layerFilter->layerIds(); + + // Remove layerIds which are not active/enabled + for (int i = layerIds.size() - 1; i >= 0; --i) { + Layer *backendLayer = layerManager->lookupResource(layerIds.at(i)); + if (backendLayer == nullptr || !backendLayer->isEnabled()) + layerIds.removeAt(i); } - case QLayerFilter::DiscardMatchingLayers: { - // If discard, the entity must not contain any of the layers managed by the FilterLayer - - // Bootstrap accepting the entity and the children - bool acceptEntity = true; - bool acceptRecursively = true; - bool entityHasLayer = entityLayers.size() != 0; - - // Check if the entity must be dropped and if it must drop also its children - for (const Qt3DCore::QNodeId id : entityLayers) { - if (m_layerIds.contains(id)) { - acceptEntity = false; - - Layer *layer = layerManager->lookupResource(id); - if (layer->recursive()) { - acceptRecursively = false; - break; - } - } - } - if (entityHasLayer && acceptEntity) - m_filteredEntities.push_back(entity); - - if (acceptRecursively) { - QVector childEntities = entity->children(); - for (int i = 0; i < childEntities.size(); ++i) { - Entity *childEntity = childEntities[i]; - if (childEntity->isTreeEnabled()) { - m_filteredEntities.push_back(childEntity); - - // Add children of the child entity (so that is recursive in the tree) - const QVector childChildEntities = childEntity->children(); - for (Entity *childChildEntity : childChildEntities) - childEntities.push_back(childChildEntity); - } - } + const QLayerFilter::FilterMode filterMode = layerFilter->filterMode(); + + // Perform filtering + for (Entity *entity : entitiesToFilter) { + switch (filterMode) { + case QLayerFilter::AcceptAnyMatchingLayers: { + filterAcceptAnyMatchingLayers(entity, layerIds); + break; + } + case QLayerFilter::AcceptAllMatchingLayers: { + filterAcceptAllMatchingLayers(entity, layerIds); + break; + } + case QLayerFilter::DiscardAnyMatchingLayers: { + filterDiscardAnyMatchingLayers(entity, layerIds); + break; + } + case QLayerFilter::DiscardAllMatchingLayers: { + filterDiscardAllMatchingLayers(entity, layerIds); + break; + } + default: + Q_UNREACHABLE(); } - break; - } - default: - break; } + + // Entities to filter for the next frame are the filtered result of the + // current LayerFilter + entitiesToFilter = std::move(m_filteredEntities); } + m_filteredEntities = std::move(entitiesToFilter); } // No layer filter -> retrieve all entities diff --git a/src/render/jobs/filterlayerentityjob_p.h b/src/render/jobs/filterlayerentityjob_p.h index 59be53a14..4e4619a25 100644 --- a/src/render/jobs/filterlayerentityjob_p.h +++ b/src/render/jobs/filterlayerentityjob_p.h @@ -71,28 +71,27 @@ public: FilterLayerEntityJob(); inline void setManager(NodeManagers *manager) Q_DECL_NOEXCEPT { m_manager = manager; } - inline void setLayers(const Qt3DCore::QNodeIdVector &layerIds) Q_DECL_NOEXCEPT { m_layerIds = layerIds; } - inline void setHasLayerFilter(bool hasLayerFilter) Q_DECL_NOEXCEPT { m_hasLayerFilter = hasLayerFilter; } + inline void setLayerFilters(const Qt3DCore::QNodeIdVector &layerIds) Q_DECL_NOEXCEPT { m_layerFilterIds = layerIds; } inline QVector filteredEntities() const Q_DECL_NOEXCEPT { return m_filteredEntities; } - inline bool hasLayerFilter() const Q_DECL_NOTHROW { return m_hasLayerFilter; } - inline Qt3DCore::QNodeIdVector layers() const { return m_layerIds; } + inline bool hasLayerFilter() const Q_DECL_NOTHROW { return !m_layerFilterIds.isEmpty(); } + inline Qt3DCore::QNodeIdVector layerFilters() const { return m_layerFilterIds; } // QAspectJob interface void run() Q_DECL_FINAL; - void setFilterMode(QLayerFilter::FilterMode filterMode); - bool filterMode() const {return m_filterMode;} + void filterAcceptAnyMatchingLayers(Entity *entity, const Qt3DCore::QNodeIdVector &layerIds); + void filterAcceptAllMatchingLayers(Entity *entity, const Qt3DCore::QNodeIdVector &layerIds); + void filterDiscardAnyMatchingLayers(Entity *entity, const Qt3DCore::QNodeIdVector &layerIds); + void filterDiscardAllMatchingLayers(Entity *entity, const Qt3DCore::QNodeIdVector &layerIds); private: void filterLayerAndEntity(); void selectAllEntities(); NodeManagers *m_manager; - Qt3DCore::QNodeIdVector m_layerIds; + Qt3DCore::QNodeIdVector m_layerFilterIds; QVector m_filteredEntities; - bool m_hasLayerFilter; - QLayerFilter::FilterMode m_filterMode; }; typedef QSharedPointer FilterLayerEntityJobPtr; diff --git a/src/render/jobs/renderviewjobutils.cpp b/src/render/jobs/renderviewjobutils.cpp index b9959fe47..41b04190f 100644 --- a/src/render/jobs/renderviewjobutils.cpp +++ b/src/render/jobs/renderviewjobutils.cpp @@ -118,9 +118,7 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN break; case FrameGraphNode::LayerFilter: // Can be set multiple times in the tree - rv->setHasLayerFilter(true); - rv->appendLayerFilter(static_cast(node)->layerIds()); - rv->setLayerFilterFilterMode(static_cast(node)->filterMode()); + rv->appendLayerFilter(static_cast(node)->peerId()); break; case FrameGraphNode::RenderPassFilter: diff --git a/tests/auto/render/entity/tst_entity.cpp b/tests/auto/render/entity/tst_entity.cpp index 96a9683d3..6ad958451 100644 --- a/tests/auto/render/entity/tst_entity.cpp +++ b/tests/auto/render/entity/tst_entity.cpp @@ -122,6 +122,7 @@ private slots: QVERIFY(entity.componentUuid().isNull()); QVERIFY(!entity.isBoundingVolumeDirty()); QVERIFY(entity.childrenHandles().isEmpty()); + QVERIFY(entity.layerIds().isEmpty()); // WHEN Q_FOREACH (QComponent *component, components) { @@ -151,6 +152,7 @@ private slots: QVERIFY(!entity.componentUuid().isNull()); QVERIFY(entity.isBoundingVolumeDirty()); QVERIFY(!entity.childrenHandles().isEmpty()); + QVERIFY(!entity.layerIds().isEmpty()); QVERIFY(renderer.dirtyBits() != 0); bool containsAll = entity.containsComponentsOfType(); @@ -172,6 +174,7 @@ private slots: QVERIFY(entity.componentUuid().isNull()); QVERIFY(!entity.isBoundingVolumeDirty()); QVERIFY(entity.childrenHandles().isEmpty()); + QVERIFY(entity.layerIds().isEmpty()); containsAll = entity.containsComponentsOfType(); QVERIFY(!containsAll); diff --git a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp index ed61fce87..c2651c477 100644 --- a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp +++ b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp @@ -51,18 +51,14 @@ private Q_SLOTS: // THEN QCOMPARE(filterJob.hasLayerFilter(), false); QCOMPARE(filterJob.filteredEntities().size(), 0); - QCOMPARE(filterJob.layers().size(), 0); - QCOMPARE(filterJob.filterMode(), Qt3DRender::QLayerFilter::AcceptMatchingLayers); + QCOMPARE(filterJob.layerFilters().size(), 0); QCOMPARE(frontendLayer.recursive(), false); } void filterEntities_data() { QTest::addColumn("entitySubtree"); - QTest::addColumn("layerIds"); - QTest::addColumn("hasLayerFilter"); - QTest::addColumn("filterMode"); - QTest::addColumn("recursive"); + QTest::addColumn("layerFilterIds"); QTest::addColumn("expectedSelectedEntities"); @@ -77,16 +73,13 @@ private Q_SLOTS: Q_UNUSED(childEntity3); QTest::newRow("EntitiesNoLayerNoLayerFilterNoDiscardNoRecursive-ShouldSelectAll") << rootEntity - << Qt3DCore::QNodeIdVector() - << false - << Qt3DRender::QLayerFilter::AcceptMatchingLayers - << false - << (Qt3DCore::QNodeIdVector() - << rootEntity->id() - << childEntity1->id() - << childEntity2->id() - << childEntity3->id() - ); + << Qt3DCore::QNodeIdVector() + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id() + ); } { @@ -95,21 +88,15 @@ private Q_SLOTS: Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + Q_UNUSED(childEntity1); Q_UNUSED(childEntity2); Q_UNUSED(childEntity3); - QTest::newRow("EntitiesNoLayerNoLayerFilterNoDiscardNoRecursive-ShouldSelectAll") << rootEntity - << Qt3DCore::QNodeIdVector() - << false - << Qt3DRender::QLayerFilter::AcceptMatchingLayers - << false - << (Qt3DCore::QNodeIdVector() - << rootEntity->id() - << childEntity1->id() - << childEntity2->id() - << childEntity3->id() - ); + QTest::newRow("EntityNoLayerWithLayerFilterWithNoFilter-ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << Qt3DCore::QNodeIdVector(); } { @@ -122,18 +109,16 @@ private Q_SLOTS: Q_UNUSED(childEntity2); Q_UNUSED(childEntity3); - QTest::newRow("EntitiesNoLayerNoLayerFilterNoDiscardNoRecursive-ShouldSelectAll") << rootEntity - << Qt3DCore::QNodeIdVector() - << false - << Qt3DRender::QLayerFilter::AcceptMatchingLayers - << false - << (Qt3DCore::QNodeIdVector() - << rootEntity->id() - << childEntity1->id() - << childEntity2->id() - << childEntity3->id() - ); + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + + + QTest::newRow("AcceptAny-NoLayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << Qt3DCore::QNodeIdVector(); } + { Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); @@ -141,16 +126,17 @@ private Q_SLOTS: Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); - Q_UNUSED(childEntity1); - Q_UNUSED(childEntity2); - Q_UNUSED(childEntity3); + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + childEntity1->addComponent(layer); + childEntity2->addComponent(layer); + childEntity3->addComponent(layer); - QTest::newRow("EntityNoLayerWithLayerFilterWithNoFilter-ShouldSelectNone") << rootEntity - << Qt3DCore::QNodeIdVector() - << true - << Qt3DRender::QLayerFilter::AcceptMatchingLayers - << false - << Qt3DCore::QNodeIdVector(); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + + QTest::newRow("AcceptAny-LayerWithLayerFilterWithFilter-ShouldSelectAllButRoot") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() << childEntity1->id() << childEntity2->id() << childEntity3->id()); } { @@ -159,19 +145,20 @@ private Q_SLOTS: Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); - Q_UNUSED(childEntity1); - Q_UNUSED(childEntity2); - Q_UNUSED(childEntity3); + Q_UNUSED(childEntity1) Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + childEntity2->addComponent(layer2); + childEntity3->addComponent(layer); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer2); - QTest::newRow("NoLayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << Qt3DRender::QLayerFilter::AcceptMatchingLayers - << false - << Qt3DCore::QNodeIdVector(); + QTest::newRow("AcceptAny-LayerWithLayerFilterWithFilter-ShouldSelectChild2And3") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); } { @@ -182,16 +169,17 @@ private Q_SLOTS: Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); childEntity1->addComponent(layer); childEntity2->addComponent(layer); childEntity3->addComponent(layer); - QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectAllButRoot") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << Qt3DRender::QLayerFilter::AcceptMatchingLayers - << false - << (Qt3DCore::QNodeIdVector() << childEntity1->id() << childEntity2->id() << childEntity3->id()); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer2); + + QTest::newRow("AcceptAny-LayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << Qt3DCore::QNodeIdVector(); } { @@ -200,19 +188,41 @@ private Q_SLOTS: Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); - Q_UNUSED(childEntity1) + childEntity1->setEnabled(false); Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); - Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); - childEntity2->addComponent(layer2); + childEntity1->addComponent(layer); + childEntity2->addComponent(layer); childEntity3->addComponent(layer); - QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectChild2And3") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id() << layer2->id()) - << true - << Qt3DRender::QLayerFilter::AcceptMatchingLayers - << false - << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + + QTest::newRow("AcceptAny-LayerWithEntityDisabled-ShouldSelectOnlyEntityEnabled") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + rootEntity->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + + QTest::newRow("AcceptAny-RecursiveLayerOnRoot-ShouldSelectAll") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id()); } { @@ -221,19 +231,104 @@ private Q_SLOTS: Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + Q_UNUSED(childEntity1); + Q_UNUSED(childEntity2); + Q_UNUSED(childEntity3); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + rootEntity->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer); + + QTest::newRow("DiscardAny-RecursiveLayerLayerFilterDiscardOnRoot-ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + rootEntity->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer); + + QTest::newRow("DiscardAny-LayerLayerFilterDiscardOnRoot-ShouldSelectAllButRoot") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); - childEntity1->addComponent(layer); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer3); + childEntity3->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAny-LayerLayerFilterDiscardOnRoot-ShouldSelectRoot") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer3); + childEntity1->addComponent(layer2); + childEntity2->addComponent(layer); + childEntity2->addComponent(layer3); + childEntity3->addComponent(layer); + childEntity3->addComponent(layer2); - QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer2->id()) - << true - << Qt3DRender::QLayerFilter::AcceptMatchingLayers - << false - << Qt3DCore::QNodeIdVector(); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + QTest::newRow("AcceptAll-LayerFilterWith2LayersNonRecursive-ShouldSelectChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id()); } { @@ -242,19 +337,99 @@ private Q_SLOTS: Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); - childEntity1->setEnabled(false); + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer3); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("AcceptAll-LayerFilterWith2LayersRecursive-ShouldSelectChild12") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity2->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); - childEntity1->addComponent(layer); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer3); + childEntity1->addComponent(layer2); + childEntity2->addComponent(layer); - childEntity3->addComponent(layer); + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); - QTest::newRow("LayerWithEntityDisabled-ShouldSelectOnlyEntityEnabled") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << Qt3DRender::QLayerFilter::AcceptMatchingLayers - << false - << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("AcceptAll-LayerFilterWith2LayersRecursiveAndDirectReferenceToRecursiveLayer-ShouldSelectChild12") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity2->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer); + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer3); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAllMatchingLayers); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAll-LayerFilterWith2Layers-ShouldSelectRootAndChild12") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id()); } { @@ -265,18 +440,28 @@ private Q_SLOTS: Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + rootEntity->addComponent(layer); - QTest::newRow("RecursiveLayerOnRoot-ShouldSelectAll") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << Qt3DRender::QLayerFilter::AcceptMatchingLayers - << true - << (Qt3DCore::QNodeIdVector() - << rootEntity->id() - << childEntity1->id() - << childEntity2->id() - << childEntity3->id()); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer3); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAll-LayerFilterWith2LayersRecursive-ShouldSelectRootAndChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id()); } { @@ -285,20 +470,76 @@ private Q_SLOTS: Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); - Q_UNUSED(childEntity1); - Q_UNUSED(childEntity2); - Q_UNUSED(childEntity3); + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + childEntity1->addComponent(layer); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer3); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAll-LayerFilterWith2LayersRecursiveAndDirectReference-ShouldSelectRootAndChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer4 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer5 = new Qt3DRender::QLayer(rootEntity); + rootEntity->addComponent(layer); - QTest::newRow("RecursiveLayerLayerFilterDiscardOnRoot-ShouldSelectNone") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << Qt3DRender::QLayerFilter::DiscardMatchingLayers - << true - << (Qt3DCore::QNodeIdVector()); + childEntity1->addComponent(layer2); + childEntity1->addComponent(layer3); + + childEntity2->addComponent(layer2); + childEntity2->addComponent(layer3); + childEntity2->addComponent(layer4); + childEntity2->addComponent(layer5); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer3); + childEntity3->addComponent(layer5); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + Qt3DRender::QLayerFilter *layerFilter2 = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter2->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter2->addLayer(layer4); + layerFilter2->addLayer(layer5); + + QTest::newRow("NestedFiltering-SelectAllOfLayer123AndNoneOf45-ShouldChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id() << layerFilter2->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id()); } { @@ -306,19 +547,73 @@ private Q_SLOTS: Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity4 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity5 = new Qt3DCore::QEntity(rootEntity); Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer4 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer5 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer6 = new Qt3DRender::QLayer(rootEntity); + rootEntity->addComponent(layer); - QTest::newRow("LayerLayerFilterDiscardOnRoot-ShouldSelectAllButRoot") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << Qt3DRender::QLayerFilter::DiscardMatchingLayers - << false - << (Qt3DCore::QNodeIdVector() - << childEntity1->id() - << childEntity2->id() - << childEntity3->id()); + childEntity1->addComponent(layer2); + childEntity1->addComponent(layer3); + + childEntity2->addComponent(layer2); + childEntity2->addComponent(layer3); + childEntity2->addComponent(layer4); + childEntity2->addComponent(layer5); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer5); + + childEntity4->addComponent(layer2); + childEntity4->addComponent(layer); + childEntity4->addComponent(layer3); + childEntity4->addComponent(layer6); + + childEntity5->addComponent(layer3); + childEntity5->addComponent(layer4); + childEntity5->addComponent(layer6); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer5); + layerFilter->addLayer(layer4); + + Qt3DRender::QLayerFilter *layerFilter2 = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter2->setFilterMode(Qt3DRender::QLayerFilter::AcceptAnyMatchingLayers); + layerFilter2->addLayer(layer2); + layerFilter2->addLayer(layer3); + + Qt3DRender::QLayerFilter *layerFilter3 = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter3->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter3->addLayer(layer); + layerFilter3->addLayer(layer6); + + QTest::newRow("NestedFiltering-SelectAllNoneOfAnyLayer45AndAnyOf23AndAllOf16-ShouldSelectChild4-Step1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity4->id() + ); + + QTest::newRow("NestedFiltering-SelectAllNoneOfAnyLayer45AndAnyOf23AndAllOf16-ShouldSelectChild4-Step2") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id() << layerFilter2->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity4->id()); + + QTest::newRow("NestedFiltering-SelectAllNoneOfAnyLayer45AndAnyOf23AndAllOf16-ShouldSelectChild4-Step3") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id() << layerFilter2->id() << layerFilter3->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity4->id()); } } @@ -326,13 +621,9 @@ private Q_SLOTS: { //QSKIP("Skipping until TestAspect can be registered"); QFETCH(Qt3DCore::QEntity *, entitySubtree); - QFETCH(Qt3DCore::QNodeIdVector, layerIds); - QFETCH(bool, hasLayerFilter); - QFETCH(Qt3DRender::QLayerFilter::FilterMode, filterMode); - QFETCH(bool, recursive); + QFETCH(Qt3DCore::QNodeIdVector, layerFilterIds); QFETCH(Qt3DCore::QNodeIdVector, expectedSelectedEntities); - Q_UNUSED(recursive); // GIVEN QScopedPointer aspect(new Qt3DRender::TestAspect(entitySubtree)); @@ -345,17 +636,15 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::FilterLayerEntityJob filterJob; - filterJob.setHasLayerFilter(hasLayerFilter); - filterJob.setLayers(layerIds); - filterJob.setFilterMode(filterMode); + filterJob.setLayerFilters(layerFilterIds); filterJob.setManager(aspect->nodeManagers()); filterJob.run(); // THEN const QVector filterEntities = filterJob.filteredEntities(); - QCOMPARE(expectedSelectedEntities.size(), filterEntities.size()); + QCOMPARE(filterEntities.size(), expectedSelectedEntities.size()); for (auto i = 0, m = expectedSelectedEntities.size(); i < m; ++i) - QCOMPARE(expectedSelectedEntities.at(i), filterEntities.at(i)->peerId()); + QCOMPARE(filterEntities.at(i)->peerId(), expectedSelectedEntities.at(i)); } }; diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp index 1f2f304df..18ad6357e 100644 --- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp +++ b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp @@ -361,7 +361,7 @@ private Q_SLOTS: // THEN QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), false); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layers().size(), 0); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 0); for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { QVERIFY(materialGatherer->techniqueFilter() == nullptr); QVERIFY(materialGatherer->renderPassFilter() == nullptr); @@ -374,7 +374,7 @@ private Q_SLOTS: // THEN QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), true); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layers().size(), 1); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 1); for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { QVERIFY(materialGatherer->techniqueFilter() != nullptr); QVERIFY(materialGatherer->renderPassFilter() != nullptr); diff --git a/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp b/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp index cea52306f..d1ef468b2 100644 --- a/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp +++ b/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp @@ -38,6 +38,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -85,19 +86,21 @@ namespace { Qt3DCore::QEntity *buildTestScene(int layersCount, int entityCount, - QVector &layerIds, + QVector &layerFilterIds, bool alwaysEnabled = true) { Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(root); + layerFilterIds.push_back(layerFilter->id()); QVector layers; layers.reserve(layersCount); - layerIds.reserve(layersCount); + for (int i = 0; i < layersCount; ++i) { Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(root); layers.push_back(layer); - layerIds.push_back(layer->id()); + layerFilter->addLayer(layer); } for (int i = 0; i < entityCount; ++i) { @@ -123,43 +126,38 @@ private Q_SLOTS: void filterEntities_data() { QTest::addColumn("entitySubtree"); - QTest::addColumn("layerIds"); - QTest::addColumn("hasLayerFilter"); + QTest::addColumn("layerFilterIds"); { - Qt3DCore::QNodeIdVector layerIds; - Qt3DCore::QEntity *rootEntity = buildTestScene(0, 5000, layerIds); + Qt3DCore::QNodeIdVector layerFilterIds; + Qt3DCore::QEntity *rootEntity = buildTestScene(0, 5000, layerFilterIds); QTest::newRow("Filter-NoLayerFilterAllEnabled") << rootEntity - << layerIds - << (layerIds.size() != 0); + << layerFilterIds; } { - Qt3DCore::QNodeIdVector layerIds; - Qt3DCore::QEntity *rootEntity = buildTestScene(0, 5000, layerIds, false); + Qt3DCore::QNodeIdVector layerFilterIds; + Qt3DCore::QEntity *rootEntity = buildTestScene(0, 5000, layerFilterIds, false); QTest::newRow("Filter-NoLayerFilterSomeDisabled") << rootEntity - << layerIds - << (layerIds.size() != 0); + << layerFilterIds; } { - Qt3DCore::QNodeIdVector layerIds; - Qt3DCore::QEntity *rootEntity = buildTestScene(10, 5000, layerIds); + Qt3DCore::QNodeIdVector layerFilterIds; + Qt3DCore::QEntity *rootEntity = buildTestScene(10, 5000, layerFilterIds); QTest::newRow("FilterLayerFilterAllEnabled") << rootEntity - << layerIds - << (layerIds.size() != 0); + << layerFilterIds; } { - Qt3DCore::QNodeIdVector layerIds; - Qt3DCore::QEntity *rootEntity = buildTestScene(10, 5000, layerIds, false); + Qt3DCore::QNodeIdVector layerFilterIds; + Qt3DCore::QEntity *rootEntity = buildTestScene(10, 5000, layerFilterIds, false); QTest::newRow("FilterLayerFilterSomeDisabled") << rootEntity - << layerIds - << (layerIds.size() != 0); + << layerFilterIds; } } @@ -167,16 +165,14 @@ private Q_SLOTS: void filterEntities() { QFETCH(Qt3DCore::QEntity *, entitySubtree); - QFETCH(Qt3DCore::QNodeIdVector, layerIds); - QFETCH(bool, hasLayerFilter); + QFETCH(Qt3DCore::QNodeIdVector, layerFilterIds); // GIVEN QScopedPointer aspect(new Qt3DRender::TestAspect(entitySubtree)); // WHEN Qt3DRender::Render::FilterLayerEntityJob filterJob; - filterJob.setHasLayerFilter(hasLayerFilter); - filterJob.setLayers(layerIds); + filterJob.setLayerFilters(layerFilterIds); filterJob.setManager(aspect->nodeManagers()); QBENCHMARK { -- cgit v1.2.3