diff options
author | Mike Krus <mike.krus@kdab.com> | 2019-04-03 18:32:10 +0100 |
---|---|---|
committer | Mike Krus <mike.krus@kdab.com> | 2019-05-25 09:38:51 +0100 |
commit | 95df2e71cd943ea21eba2ee99b1d77b26a84e580 (patch) | |
tree | 373f662c003d42a1c140e8b043a1980c3401af12 | |
parent | 09daf5451c03a96514d7d96cc12aaa279d99fa3e (diff) |
Clean up bounding box updates
Use EntityAccumulator to collect all entities and use a single
map/reduce call. This avoid allocations due to getting entity children
and locking due to using one map/reduce per entity previously.
Change-Id: Iac8eb315bfb302bc68dbdfc961bbc48beb8cd19a
Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r-- | src/render/jobs/calcboundingvolumejob.cpp | 78 |
1 files changed, 41 insertions, 37 deletions
diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp index 68eb308c5..113dc34ce 100644 --- a/src/render/jobs/calcboundingvolumejob.cpp +++ b/src/render/jobs/calcboundingvolumejob.cpp @@ -51,6 +51,7 @@ #include <Qt3DRender/private/buffer_p.h> #include <Qt3DRender/private/sphere_p.h> #include <Qt3DRender/private/buffervisitor_p.h> +#include <Qt3DRender/private/entityaccumulator_p.h> #include <QtCore/qmath.h> #if QT_CONFIG(concurrent) @@ -65,28 +66,6 @@ namespace Render { namespace { -QVector<Geometry*> calculateLocalBoundingVolume(NodeManagers *manager, Entity *node); - -struct UpdateBoundFunctor -{ - NodeManagers *manager; - - // This define is required to work with QtConcurrent - typedef QVector<Geometry *> result_type; - QVector<Geometry *> operator ()(Qt3DRender::Render::Entity *node) - { - return calculateLocalBoundingVolume(manager, node); - } -}; - -struct ReduceUpdateBoundFunctor -{ - void operator ()(QVector<Geometry *> &result, const QVector<Geometry *> &values) - { - result += values; - } -}; - class BoundingVolumeCalculator { public: @@ -318,23 +297,29 @@ QVector<Geometry *> calculateLocalBoundingVolume(NodeManagers *manager, Entity * } } -#if QT_CONFIG(concurrent) - const QVector<Qt3DRender::Render::Entity *> children = node->children(); - if (children.size() > 1) { - UpdateBoundFunctor functor; - functor.manager = manager; - ReduceUpdateBoundFunctor reduceFunctor; - updatedGeometries += QtConcurrent::blockingMappedReduced<decltype(updatedGeometries)>(children, functor, reduceFunctor); - } else -#endif - { - const auto children = node->children(); - for (Entity *child : children) - updatedGeometries += calculateLocalBoundingVolume(manager, child); - } return updatedGeometries; } +struct UpdateBoundFunctor +{ + NodeManagers *manager; + + // This define is required to work with QtConcurrent + typedef QVector<Geometry *> result_type; + QVector<Geometry *> operator ()(Qt3DRender::Render::Entity *node) + { + return calculateLocalBoundingVolume(manager, node); + } +}; + +struct ReduceUpdateBoundFunctor +{ + void operator ()(QVector<Geometry *> &result, const QVector<Geometry *> &values) + { + result += values; + } +}; + } // anonymous CalculateBoundingVolumeJob::CalculateBoundingVolumeJob() @@ -346,7 +331,26 @@ CalculateBoundingVolumeJob::CalculateBoundingVolumeJob() void CalculateBoundingVolumeJob::run() { - const QVector<Geometry *> updatedGeometries = calculateLocalBoundingVolume(m_manager, m_node); + EntityAccumulator accumulator([](Entity *entity) { + return !entity->componentUuid<GeometryRenderer>().isNull(); + }, m_manager); + auto entities = accumulator.apply(m_node); + + QVector<Geometry *> updatedGeometries; + updatedGeometries.reserve(entities.size()); + +#if QT_CONFIG(concurrent) + if (entities.size() > 1) { + UpdateBoundFunctor functor; + functor.manager = m_manager; + ReduceUpdateBoundFunctor reduceFunctor; + updatedGeometries += QtConcurrent::blockingMappedReduced<decltype(updatedGeometries)>(entities, functor, reduceFunctor); + } else +#endif + { + for (Entity *child : entities) + updatedGeometries += calculateLocalBoundingVolume(m_manager, child); + } // Send extent updates to frontend for (Geometry *geometry : updatedGeometries) |