mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-04 02:41:19 +00:00
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.
This commit is contained in:
parent
b61140b8ba
commit
031871cd48
@ -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::Geode& geode) override
|
||||
void apply(osg::MatrixTransform& transform) override
|
||||
{
|
||||
traverse(geode);
|
||||
// for all current objects associated this transform with them.
|
||||
registerWithCurrentObjects(&transform);
|
||||
}
|
||||
|
||||
void apply(osg::Billboard& geode) override
|
||||
void apply(osg::Node& node) override
|
||||
{
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
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…
Reference in New Issue
Block a user