speeds up optimizer (#3162)

We can expect marginally improved loading times with this PR. Drawable, Transform and Node counts in stats panels are expected to remain unchanged - this PR does not add new scene graph optimisations, it just increases the speed with which we apply existing ones.

1. We add explicit `NodeVisitor::apply` overrides for commonly encountered node types to avoid additional virtual function calls per node associated with the default `apply` implementation.
2. We skip pushing `StateSet`s when  `_mergeAlphaBlending` is enabled or the `StateSet` contains no relevant state.
3. We add a specialised variant of `CollectLowestTransformsVisitor::addTransform` accepting `MatrixTransform` to avoid matrix copies and multiplications.
pull/3169/head
Bo Svensson 3 years ago committed by GitHub
parent b61140b8ba
commit 031871cd48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -171,7 +171,7 @@ class CollectLowestTransformsVisitor : public BaseOptimizerVisitor
setTraversalMode(osg::NodeVisitor::TRAVERSE_PARENTS);
}
void apply(osg::Node& node) override
void apply(osg::Group& node) override
{
if (node.getNumParents())
{
@ -180,7 +180,7 @@ class CollectLowestTransformsVisitor : public BaseOptimizerVisitor
else
{
// for all current objects mark a nullptr transform for them.
registerWithCurrentObjects(0);
registerWithCurrentObjects(static_cast<osg::Transform*>(nullptr));
}
}
@ -198,15 +198,19 @@ class CollectLowestTransformsVisitor : public BaseOptimizerVisitor
// for all current objects associated this transform with them.
registerWithCurrentObjects(&transform);
}
void apply(osg::MatrixTransform& transform) override
{
// for all current objects associated this transform with them.
registerWithCurrentObjects(&transform);
}
void apply(osg::Geode& geode) override
void apply(osg::Node& node) override
{
traverse(geode);
traverse(node);
}
void apply(osg::Billboard& geode) override
void apply(osg::Geometry& geode) override
{
traverse(geode);
}
void collectDataFor(osg::Node* node)
@ -293,7 +297,19 @@ class CollectLowestTransformsVisitor : public BaseOptimizerVisitor
ObjectStruct():_canBeApplied(true),_moreThanOneMatrixRequired(false) {}
void add(osg::Transform* transform, bool canOptimize)
inline const osg::Matrix& getMatrix(osg::MatrixTransform* transform)
{
return transform->getMatrix();
}
osg::Matrix getMatrix(osg::Transform* transform)
{
osg::Matrix matrix;
transform->computeLocalToWorldMatrix(matrix, 0);
return matrix;
}
template<typename T>
void add(T* transform, bool canOptimize)
{
if (transform)
{
@ -301,12 +317,10 @@ class CollectLowestTransformsVisitor : public BaseOptimizerVisitor
else if (transform->getReferenceFrame()!=osg::Transform::RELATIVE_RF) _moreThanOneMatrixRequired=true;
else
{
if (_transformSet.empty()) transform->computeLocalToWorldMatrix(_firstMatrix,0);
if (_transformSet.empty()) _firstMatrix = getMatrix(transform);
else
{
osg::Matrix matrix;
transform->computeLocalToWorldMatrix(matrix,0);
if (_firstMatrix!=matrix) _moreThanOneMatrixRequired=true;
if (_firstMatrix!=getMatrix(transform)) _moreThanOneMatrixRequired=true;
}
}
}
@ -327,8 +341,8 @@ class CollectLowestTransformsVisitor : public BaseOptimizerVisitor
TransformSet _transformSet;
};
void registerWithCurrentObjects(osg::Transform* transform)
template <typename T>
void registerWithCurrentObjects(T* transform)
{
for(ObjectList::iterator itr=_currentObjectList.begin();
itr!=_currentObjectList.end();
@ -633,19 +647,23 @@ osg::Array* cloneArray(osg::Array* array, osg::VertexBufferObject*& vbo, const o
return array;
}
void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Drawable& drawable)
void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Geometry& geometry)
{
osg::Geometry *geometry = drawable.asGeometry();
if((geometry) && (isOperationPermissibleForObject(&drawable)))
if(isOperationPermissibleForObject(&geometry))
{
osg::VertexBufferObject* vbo = nullptr;
if(geometry->getVertexArray() && geometry->getVertexArray()->referenceCount() > 1)
geometry->setVertexArray(cloneArray(geometry->getVertexArray(), vbo, geometry));
if(geometry->getNormalArray() && geometry->getNormalArray()->referenceCount() > 1)
geometry->setNormalArray(cloneArray(geometry->getNormalArray(), vbo, geometry));
if(geometry->getTexCoordArray(7) && geometry->getTexCoordArray(7)->referenceCount() > 1) // tangents
geometry->setTexCoordArray(7, cloneArray(geometry->getTexCoordArray(7), vbo, geometry));
if(geometry.getVertexArray() && geometry.getVertexArray()->referenceCount() > 1)
geometry.setVertexArray(cloneArray(geometry.getVertexArray(), vbo, &geometry));
if(geometry.getNormalArray() && geometry.getNormalArray()->referenceCount() > 1)
geometry.setNormalArray(cloneArray(geometry.getNormalArray(), vbo, &geometry));
if(geometry.getTexCoordArray(7) && geometry.getTexCoordArray(7)->referenceCount() > 1) // tangents
geometry.setTexCoordArray(7, cloneArray(geometry.getTexCoordArray(7), vbo, &geometry));
}
_drawableSet.insert(&geometry);
}
void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Drawable& drawable)
{
_drawableSet.insert(&drawable);
}
@ -673,6 +691,11 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Transform& transform)
_transformStack.pop_back();
}
void Optimizer::FlattenStaticTransformsVisitor::apply(osg::MatrixTransform& transform)
{
apply(static_cast<osg::Transform&>(transform));
}
bool Optimizer::FlattenStaticTransformsVisitor::removeTransforms(osg::Node* nodeWeCannotRemove)
{
CollectLowestTransformsVisitor cltv(_optimizer);
@ -1112,10 +1135,13 @@ bool isAbleToMerge(const osg::Geometry& g1, const osg::Geometry& g2)
}
void Optimizer::MergeGeometryVisitor::pushStateSet(osg::StateSet *stateSet)
bool Optimizer::MergeGeometryVisitor::pushStateSet(osg::StateSet *stateSet)
{
if (_mergeAlphaBlending || !stateSet || stateSet->getRenderBinMode() & osg::StateSet::INHERIT_RENDERBIN_DETAILS)
return false;
_stateSetStack.push_back(stateSet);
checkAlphaBlendingActive();
return true;
}
void Optimizer::MergeGeometryVisitor::popStateSet()
@ -1145,15 +1171,14 @@ void Optimizer::MergeGeometryVisitor::checkAlphaBlendingActive()
void Optimizer::MergeGeometryVisitor::apply(osg::Group &group)
{
if (group.getStateSet())
pushStateSet(group.getStateSet());
bool pushed = pushStateSet(group.getStateSet());
if (!_alphaBlendingActive || _mergeAlphaBlending)
mergeGroup(group);
traverse(group);
if (group.getStateSet())
if (pushed)
popStateSet();
}

@ -285,9 +285,11 @@ class Optimizer
BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS) {}
void apply(osg::Node& geode) override;
void apply(osg::Geometry& drawable) override;
void apply(osg::Drawable& drawable) override;
void apply(osg::Billboard& geode) override;
void apply(osg::Transform& transform) override;
void apply(osg::Transform& transform) override final;
void apply(osg::MatrixTransform& transform) override;
bool removeTransforms(osg::Node* nodeWeCannotRemove);
@ -316,6 +318,7 @@ class Optimizer
BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS) {}
void apply(osg::MatrixTransform& transform) override;
void apply(osg::Geometry&) override { }
bool removeTransforms(osg::Node* nodeWeCannotRemove);
@ -338,6 +341,7 @@ class Optimizer
BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {}
void apply(osg::Group& group) override;
void apply(osg::Geometry&) override { }
void removeEmptyNodes();
@ -358,6 +362,7 @@ class Optimizer
void apply(osg::Transform& transform) override;
void apply(osg::LOD& lod) override;
void apply(osg::Switch& switchNode) override;
void apply(osg::Geometry&) override { }
bool isOperationPermissible(osg::Node& node);
@ -376,6 +381,7 @@ class Optimizer
bool isOperationPermissible(osg::Group& node);
void apply(osg::Geometry&) override { }
void apply(osg::Group& group) override;
void apply(osg::LOD& lod) override;
void apply(osg::Switch& switchNode) override;
@ -409,10 +415,10 @@ class Optimizer
return _targetMaximumNumberOfVertices;
}
void pushStateSet(osg::StateSet* stateSet);
bool pushStateSet(osg::StateSet* stateSet);
void popStateSet();
void checkAlphaBlendingActive();
void apply(osg::Geometry&) override { }
void apply(osg::Group& group) override;
void apply(osg::Billboard&) override { /* don't do anything*/ }

Loading…
Cancel
Save