crashfix + optimiziation

Signed-off-by: Bret Curtis <psi29a@gmail.com>
This commit is contained in:
bzzt lost a hitlab login 2020-04-30 13:37:00 +00:00 committed by Bret Curtis
parent c0f128bcb3
commit ce505a9bb3
10 changed files with 300 additions and 106 deletions

View file

@ -18,6 +18,7 @@
#include "optimizer.hpp"
#include <osg/Version>
#include <osg/Transform>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
@ -587,17 +588,36 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Node& node)
traverse(node);
}
bool needvbo(const osg::Geometry* geom)
{
#if OSG_MIN_VERSION_REQUIRED(3,5,6)
return true;
#else
return geom->getUseVertexBufferObjects();
#endif
}
osg::Array* cloneArray(osg::Array* array, osg::VertexBufferObject*& vbo, const osg::Geometry* geom)
{
array = osg::clone(array, osg::CopyOp::DEEP_COPY_ALL);
if (!vbo && needvbo(geom))
vbo = new osg::VertexBufferObject;
if (vbo)
array->setVertexBufferObject(vbo);
return array;
}
void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Drawable& drawable)
{
osg::Geometry *geometry = drawable.asGeometry();
if((geometry) && (isOperationPermissibleForObject(&drawable)))
{
osg::VertexBufferObject* vbo = nullptr;
if(geometry->getVertexArray() && geometry->getVertexArray()->referenceCount() > 1) {
geometry->setVertexArray(dynamic_cast<osg::Array*>(geometry->getVertexArray()->clone(osg::CopyOp::DEEP_COPY_ALL)));
geometry->setVertexArray(cloneArray(geometry->getVertexArray(), vbo, geometry));
}
if(geometry->getNormalArray() && geometry->getNormalArray()->referenceCount() > 1) {
geometry->setNormalArray(dynamic_cast<osg::Array*>(geometry->getNormalArray()->clone(osg::CopyOp::DEEP_COPY_ALL)));
geometry->setNormalArray(cloneArray(geometry->getNormalArray(), vbo, geometry));
}
}
_drawableSet.insert(&drawable);
@ -1110,14 +1130,30 @@ void Optimizer::MergeGeometryVisitor::apply(osg::Group &group)
popStateSet();
}
osg::PrimitiveSet* clonePrimitive(osg::PrimitiveSet* ps)
osg::PrimitiveSet* clonePrimitive(osg::PrimitiveSet* ps, osg::ElementBufferObject*& ebo, const osg::Geometry* geom)
{
if (ps->referenceCount() <= 1)
return ps;
ps = dynamic_cast<osg::PrimitiveSet*>(ps->clone(osg::CopyOp::DEEP_COPY_ALL));
ps = osg::clone(ps, osg::CopyOp::DEEP_COPY_ALL);
osg::DrawElements* drawElements = ps->getDrawElements();
if (!drawElements) return ps;
if (!ebo && needvbo(geom))
ebo = new osg::ElementBufferObject;
if (ebo)
drawElements->setElementBufferObject(ebo);
return ps;
}
bool containsSharedPrimitives(const osg::Geometry* geom)
{
for (unsigned int i=0; i<geom->getNumPrimitiveSets(); ++i)
if (geom->getPrimitiveSet(i)->referenceCount() > 1) return true;
return false;
}
bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
{
if (!isOperationPermissibleForObject(&group)) return false;
@ -1305,6 +1341,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
if (!drawable)
continue;
osg::Geometry* geom = drawable->asGeometry();
osg::ElementBufferObject* ebo = nullptr;
if (geom)
{
osg::Geometry::PrimitiveSetList& primitives = geom->getPrimitiveSetList();
@ -1317,12 +1354,12 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
{
if (prim->getNumIndices()==3)
{
prim = clonePrimitive(prim); (*itr) = prim;
prim = clonePrimitive(prim, ebo, geom); (*itr) = prim;
prim->setMode(osg::PrimitiveSet::TRIANGLES);
}
else if (prim->getNumIndices()==4)
{
prim = clonePrimitive(prim); (*itr) = prim;
prim = clonePrimitive(prim, ebo, geom); (*itr) = prim;
prim->setMode(osg::PrimitiveSet::QUADS);
}
}
@ -1337,6 +1374,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
if (!drawable)
continue;
osg::Geometry* geom = drawable->asGeometry();
osg::ElementBufferObject* ebo = nullptr;
if (geom)
{
if (geom->getNumPrimitiveSets()>0 &&
@ -1379,7 +1417,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
if (combine)
{
lhs = clonePrimitive(lhs);
lhs = clonePrimitive(lhs, ebo, geom);
primitives[lhsNo] = lhs;
switch(lhs->getType())
@ -1499,6 +1537,12 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
}
}
#endif
if (doneCombine && !geom->containsSharedArrays() && !containsSharedPrimitives(geom))
{
// prefer to use vbo for merged geometries as vbo uses less memory than display lists.
geom->setUseVertexBufferObjects(true);
geom->setUseDisplayList(false);
}
}
}
@ -1578,16 +1622,14 @@ class MergeArrayVisitor : public osg::ArrayVisitor
bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs)
{
if (lhs.containsSharedArrays())
lhs.duplicateSharedArrays();
MergeArrayVisitor merger;
osg::VertexBufferObject* vbo = nullptr;
unsigned int base = 0;
if (lhs.getVertexArray() && rhs.getVertexArray())
{
base = lhs.getVertexArray()->getNumElements();
if (lhs.getVertexArray()->referenceCount() > 1)
lhs.setVertexArray(cloneArray(lhs.getVertexArray(), vbo, &lhs));
if (!merger.merge(lhs.getVertexArray(),rhs.getVertexArray()))
{
OSG_DEBUG << "MergeGeometry: vertex array not merged. Some data may be lost." <<std::endl;
@ -1602,6 +1644,8 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
if (lhs.getNormalArray() && rhs.getNormalArray() && lhs.getNormalArray()->getBinding()!=osg::Array::BIND_OVERALL)
{
if (lhs.getNormalArray()->referenceCount() > 1)
lhs.setNormalArray(cloneArray(lhs.getNormalArray(), vbo, &lhs));
if (!merger.merge(lhs.getNormalArray(),rhs.getNormalArray()))
{
OSG_DEBUG << "MergeGeometry: normal array not merged. Some data may be lost." <<std::endl;
@ -1615,6 +1659,8 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
if (lhs.getColorArray() && rhs.getColorArray() && lhs.getColorArray()->getBinding()!=osg::Array::BIND_OVERALL)
{
if (lhs.getColorArray()->referenceCount() > 1)
lhs.setColorArray(cloneArray(lhs.getColorArray(), vbo, &lhs));
if (!merger.merge(lhs.getColorArray(),rhs.getColorArray()))
{
OSG_DEBUG << "MergeGeometry: color array not merged. Some data may be lost." <<std::endl;
@ -1627,6 +1673,8 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
if (lhs.getSecondaryColorArray() && rhs.getSecondaryColorArray() && lhs.getSecondaryColorArray()->getBinding()!=osg::Array::BIND_OVERALL)
{
if (lhs.getSecondaryColorArray()->referenceCount() > 1)
lhs.setSecondaryColorArray(cloneArray(lhs.getSecondaryColorArray(), vbo, &lhs));
if (!merger.merge(lhs.getSecondaryColorArray(),rhs.getSecondaryColorArray()))
{
OSG_DEBUG << "MergeGeometry: secondary color array not merged. Some data may be lost." <<std::endl;
@ -1639,6 +1687,8 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
if (lhs.getFogCoordArray() && rhs.getFogCoordArray() && lhs.getFogCoordArray()->getBinding()!=osg::Array::BIND_OVERALL)
{
if (lhs.getFogCoordArray()->referenceCount() > 1)
lhs.setFogCoordArray(cloneArray(lhs.getFogCoordArray(), vbo, &lhs));
if (!merger.merge(lhs.getFogCoordArray(),rhs.getFogCoordArray()))
{
OSG_DEBUG << "MergeGeometry: fog coord array not merged. Some data may be lost." <<std::endl;
@ -1653,6 +1703,9 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
unsigned int unit;
for(unit=0;unit<lhs.getNumTexCoordArrays();++unit)
{
if (!lhs.getTexCoordArray(unit)) continue;
if (lhs.getTexCoordArray(unit)->referenceCount() > 1)
lhs.setTexCoordArray(unit, cloneArray(lhs.getTexCoordArray(unit), vbo, &lhs));
if (!merger.merge(lhs.getTexCoordArray(unit),rhs.getTexCoordArray(unit)))
{
OSG_DEBUG << "MergeGeometry: tex coord array not merged. Some data may be lost." <<std::endl;
@ -1661,6 +1714,9 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
for(unit=0;unit<lhs.getNumVertexAttribArrays();++unit)
{
if (!lhs.getVertexAttribArray(unit)) continue;
if (lhs.getVertexAttribArray(unit)->referenceCount() > 1)
lhs.setVertexAttribArray(unit, cloneArray(lhs.getVertexAttribArray(unit), vbo, &lhs));
if (!merger.merge(lhs.getVertexAttribArray(unit),rhs.getVertexAttribArray(unit)))
{
OSG_DEBUG << "MergeGeometry: vertex attrib array not merged. Some data may be lost." <<std::endl;
@ -1668,6 +1724,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
}
// shift the indices of the incoming primitives to account for the pre existing geometry.
osg::ElementBufferObject* ebo = nullptr;
osg::Geometry::PrimitiveSetList::iterator primItr;
for(primItr=rhs.getPrimitiveSetList().begin(); primItr!=rhs.getPrimitiveSetList().end(); ++primItr)
{
@ -1689,6 +1746,11 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
{
// must promote to a DrawElementsUInt
osg::DrawElementsUInt* new_primitive = new osg::DrawElementsUInt(primitive->getMode());
if (needvbo(&lhs))
{
if (!ebo) ebo = new osg::ElementBufferObject;
new_primitive->setElementBufferObject(ebo);
}
std::copy(primitiveUByte->begin(),primitiveUByte->end(),std::back_inserter(*new_primitive));
new_primitive->offsetIndices(base);
(*primItr) = new_primitive;
@ -1696,13 +1758,18 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
{
// must promote to a DrawElementsUShort
osg::DrawElementsUShort* new_primitive = new osg::DrawElementsUShort(primitive->getMode());
if (needvbo(&lhs))
{
if (!ebo) ebo = new osg::ElementBufferObject;
new_primitive->setElementBufferObject(ebo);
}
std::copy(primitiveUByte->begin(),primitiveUByte->end(),std::back_inserter(*new_primitive));
new_primitive->offsetIndices(base);
(*primItr) = new_primitive;
}
else
{
(*primItr) = clonePrimitive(primitive);
(*primItr) = clonePrimitive(primitive, ebo, &lhs);
(*primItr)->offsetIndices(base);
}
}
@ -1722,13 +1789,18 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
{
// must promote to a DrawElementsUInt
osg::DrawElementsUInt* new_primitive = new osg::DrawElementsUInt(primitive->getMode());
if (needvbo(&lhs))
{
if (!ebo) ebo = new osg::ElementBufferObject;
new_primitive->setElementBufferObject(ebo);
}
std::copy(primitiveUShort->begin(),primitiveUShort->end(),std::back_inserter(*new_primitive));
new_primitive->offsetIndices(base);
(*primItr) = new_primitive;
}
else
{
(*primItr) = clonePrimitive(primitive);
(*primItr) = clonePrimitive(primitive, ebo, &lhs);
(*primItr)->offsetIndices(base);
}
}
@ -1738,7 +1810,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
case(osg::PrimitiveSet::DrawArrayLengthsPrimitiveType):
case(osg::PrimitiveSet::DrawElementsUIntPrimitiveType):
default:
(*primItr) = clonePrimitive(primitive);
(*primItr) = clonePrimitive(primitive, ebo, &lhs);
(*primItr)->offsetIndices(base);
break;
}