Integrated IncementalCompileOperation into DatabasePager.
Improved various facilities in IncrementalCompileOperation.
This commit is contained in:
@@ -226,6 +226,9 @@ class OSG_EXPORT Image : public BufferData
|
||||
void setPacking(unsigned int packing) { _packing = packing; }
|
||||
inline unsigned int getPacking() const { return _packing; }
|
||||
|
||||
/** return true of the pixel format is an OpenGL compressed pixel format.*/
|
||||
bool isCompressed() const;
|
||||
|
||||
/** Set the pixel aspect ratio, defined as the pixel width divided by the pixel height.*/
|
||||
inline void setPixelAspectRatio(float pixelAspectRatio) { _pixelAspectRatio = pixelAspectRatio; }
|
||||
|
||||
@@ -301,7 +304,7 @@ class OSG_EXPORT Image : public BufferData
|
||||
static unsigned int computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing);
|
||||
static int computeNearestPowerOfTwo(int s,float bias=0.5f);
|
||||
static int computeNumberOfMipmapLevels(int s,int t = 1, int r = 1);
|
||||
|
||||
|
||||
/** Precomputed mipmaps stuff. */
|
||||
typedef std::vector< unsigned int > MipmapDataType;
|
||||
|
||||
|
||||
@@ -350,8 +350,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
|
||||
|
||||
typedef std::set< osg::ref_ptr<osg::StateSet> > StateSetList;
|
||||
typedef std::vector< osg::ref_ptr<osg::Drawable> > DrawableList;
|
||||
//typedef std::pair<StateSetList,DrawableList> DataToCompile;
|
||||
typedef osgUtil::IncrementalCompileOperation::CompileData DataToCompile;
|
||||
typedef osgUtil::CompileData DataToCompile;
|
||||
typedef std::map< unsigned int, DataToCompile > DataToCompileMap;
|
||||
typedef std::set<unsigned int> ActiveGraphicsContexts;
|
||||
typedef std::vector< osg::observer_ptr<osg::GraphicsContext> > CompileGraphicsContexts;
|
||||
|
||||
@@ -19,6 +19,144 @@
|
||||
|
||||
namespace osgUtil {
|
||||
|
||||
class CompileData : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
CompileData() {}
|
||||
|
||||
typedef std::set< osg::ref_ptr<osg::Drawable> > Drawables;
|
||||
typedef std::set< osg::ref_ptr<osg::Texture> > Textures;
|
||||
typedef std::set< osg::ref_ptr<osg::Program> > Programs;
|
||||
|
||||
bool empty() const { return _drawables.empty() && _textures.empty() && _programs.empty(); }
|
||||
|
||||
void reset()
|
||||
{
|
||||
_drawables.clear();
|
||||
_textures.clear();
|
||||
_programs.clear();
|
||||
}
|
||||
|
||||
Drawables _drawables;
|
||||
Textures _textures;
|
||||
Programs _programs;
|
||||
};
|
||||
|
||||
class OSGUTIL_EXPORT CompileStats : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
CompileStats();
|
||||
|
||||
void add(const std::string& name,double size, double time);
|
||||
|
||||
double estimateTime(const std::string& name, double size) const;
|
||||
double estimateTime2(const std::string& name, double size) const;
|
||||
double estimateTime3(const std::string& name, double size) const;
|
||||
double estimateTime4(const std::string& name, double size) const;
|
||||
double averageTime(const std::string& name) const;
|
||||
|
||||
void print(std::ostream& out) const;
|
||||
|
||||
protected:
|
||||
|
||||
struct OSGUTIL_EXPORT Values
|
||||
{
|
||||
Values():
|
||||
totalSize(0.0), totalTime(0.0), totalNum(0.0),
|
||||
minSize(0.0), minTime(0.0),
|
||||
a(0.0), b(0.0),
|
||||
m(0.0), n(0.0), o(0.0), p(0.0) {}
|
||||
|
||||
void add(double size, double time);
|
||||
|
||||
double estimateTime(double size) const
|
||||
{
|
||||
return a + b * size;
|
||||
}
|
||||
|
||||
double estimateTime2(double size) const
|
||||
{
|
||||
return (totalTime/totalSize) * size;
|
||||
}
|
||||
|
||||
double estimateTime3(double size) const
|
||||
{
|
||||
if (size<minSize) return minTime;
|
||||
return minTime + (totalTime/totalSize) * (size-minSize);
|
||||
}
|
||||
|
||||
double estimateTime4(double size) const
|
||||
{
|
||||
if (size<minSize) return minTime;
|
||||
double denominator = totalSize-minSize*totalNum;
|
||||
return denominator==0.0 ? minTime :
|
||||
minTime + (totalTime-minTime*totalNum)/(totalSize-minSize*totalNum) * (size-minSize);
|
||||
}
|
||||
|
||||
double averageTime() const
|
||||
{
|
||||
if (totalNum!=0.0) return totalTime/totalTime;
|
||||
else return 0.0;
|
||||
}
|
||||
|
||||
double totalSize, totalTime, totalNum;
|
||||
double minSize, minTime;
|
||||
double a,b;
|
||||
double m,n,o,p;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, Values> StatsMap;
|
||||
StatsMap _statsMap;
|
||||
};
|
||||
|
||||
class OSGUTIL_EXPORT CompileOperator : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
CompileOperator();
|
||||
|
||||
/** Assign a geometry and associated StateSet than is applied after each texture compile to atttempt to force the OpenGL
|
||||
* drive to download the texture object to OpenGL graphics card.*/
|
||||
void assignForceTextureDownloadGeometry();
|
||||
|
||||
/** Set the osg::Geometry to apply after each texture compile to atttempt to force the OpenGL
|
||||
* drive to download the texture object to OpenGL graphics card.*/
|
||||
void setForceTextureDownloadGeometry(osg::Geometry* geom) { _forceTextureDownloadGeometry = geom; }
|
||||
osg::Geometry* getForceTextureDownloadGeometry() { return _forceTextureDownloadGeometry.get(); }
|
||||
const osg::Geometry* getForceTextureDownloadGeometry() const { return _forceTextureDownloadGeometry.get(); }
|
||||
|
||||
/** Compile as many elements in the CompileData container as possible within specified time.
|
||||
* return true if all have been compiled. */
|
||||
virtual bool compile(osg::RenderInfo& renderInfo, CompileData& compileData, unsigned int& maxNumObjectsToCompile, double& availableTime);
|
||||
|
||||
/** Compile all the elements in the CompileData container. */
|
||||
void compileAll(osg::RenderInfo& renderInfo, CompileData& compileData)
|
||||
{
|
||||
unsigned int maxNumObjectsToCompile = 32768;
|
||||
double availableTime = DBL_MAX;
|
||||
compile(renderInfo, compileData, maxNumObjectsToCompile, availableTime);
|
||||
}
|
||||
|
||||
CompileStats* getCompileStats() { return _compileStats.get(); }
|
||||
const CompileStats* getCompileStats() const { return _compileStats.get(); }
|
||||
|
||||
protected:
|
||||
|
||||
void runTimingTests(osg::RenderInfo& renderInfo);
|
||||
|
||||
double timeCompile(osg::RenderInfo& renderInfo, osg::Geometry* geometry) const;
|
||||
double timeCompile(osg::RenderInfo& renderInfo, osg::StateSet* stateset) const;
|
||||
osg::Geometry* createTestGeometry(unsigned int numVertices, bool vbo) const;
|
||||
osg::StateSet* createTestStateSet(unsigned int imageSize, bool mipmapped) const;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> _forceTextureDownloadGeometry;
|
||||
osg::ref_ptr<CompileStats> _compileStats;
|
||||
bool _timingTestsCompleted;
|
||||
};
|
||||
|
||||
|
||||
class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
|
||||
{
|
||||
public:
|
||||
@@ -90,19 +228,6 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
|
||||
|
||||
|
||||
|
||||
struct CompileData : public osg::Referenced
|
||||
{
|
||||
typedef std::list< osg::ref_ptr<osg::Drawable> > Drawables;
|
||||
typedef std::list< osg::ref_ptr<osg::Texture> > Textures;
|
||||
typedef std::list< osg::ref_ptr<osg::Program> > Programs;
|
||||
|
||||
bool empty() const { return _drawables.empty() && _textures.empty() && _programs.empty(); }
|
||||
|
||||
Drawables _drawables;
|
||||
Textures _textures;
|
||||
Programs _programs;
|
||||
};
|
||||
|
||||
class CompileSet;
|
||||
typedef std::set<osg::GraphicsContext*> ContextSet;
|
||||
typedef std::map<osg::GraphicsContext*, CompileData > CompileMap;
|
||||
@@ -145,14 +270,13 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
|
||||
osg::ref_ptr<osg::Node> _subgraphToCompile;
|
||||
osg::ref_ptr<CompileCompletedCallback> _compileCompletedCallback;
|
||||
CompileMap _compileMap;
|
||||
|
||||
|
||||
// protected:
|
||||
|
||||
|
||||
virtual ~CompileSet() {}
|
||||
};
|
||||
|
||||
typedef std::list< osg::ref_ptr<CompileSet> > CompileSets;
|
||||
|
||||
typedef std::list< osg::ref_ptr<CompileSet> > CompileSets;
|
||||
|
||||
/** Add a subgraph to be compiled.*/
|
||||
void add(osg::Node* subgraphToCompile);
|
||||
@@ -170,16 +294,14 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
|
||||
OpenThreads::Mutex* getCompiledMutex() { return &_compiledMutex; }
|
||||
CompileSets& getCompiled() { return _compiled; }
|
||||
|
||||
void setCompileOperator(CompileOperator* compileOperator) { _compileOperator = compileOperator; }
|
||||
CompileOperator* getCompileOperator() { return _compileOperator.get(); }
|
||||
const CompileOperator* getCompileOperator() const { return _compileOperator.get(); }
|
||||
|
||||
/** Assign a geometry and associated StateSet than is applied after each texture compile to atttempt to force the OpenGL
|
||||
* drive to download the texture object to OpenGL graphics card.*/
|
||||
void assignForceTextureDownloadGeometry();
|
||||
|
||||
/** Set the osg::Geometry to apply after each texture compile to atttempt to force the OpenGL
|
||||
* drive to download the texture object to OpenGL graphics card.*/
|
||||
void setForceTextureDownloadGeometry(osg::Geometry* geom) { _forceTextureDownloadGeometry = geom; }
|
||||
osg::Geometry* getForceTextureDownloadGeometry() { return _forceTextureDownloadGeometry.get(); }
|
||||
const osg::Geometry* getForceTextureDownloadGeometry() const { return _forceTextureDownloadGeometry.get(); }
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~IncrementalCompileOperation();
|
||||
@@ -193,7 +315,7 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
|
||||
double _flushTimeRatio;
|
||||
double _conservativeTimeRatio;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> _forceTextureDownloadGeometry;
|
||||
osg::ref_ptr<CompileOperator> _compileOperator;
|
||||
|
||||
OpenThreads::Mutex _toCompileMutex;
|
||||
CompileSets _toCompile;
|
||||
|
||||
@@ -941,6 +941,7 @@ void Geometry::compileGLObjects(RenderInfo& renderInfo) const
|
||||
if ((*itr)->getBufferObject()) bufferObjects.insert((*itr)->getBufferObject());
|
||||
}
|
||||
|
||||
osg::ElapsedTime timer;
|
||||
|
||||
// now compile any buffer objects that require it.
|
||||
for(BufferObjects::iterator itr = bufferObjects.begin();
|
||||
@@ -955,6 +956,8 @@ void Geometry::compileGLObjects(RenderInfo& renderInfo) const
|
||||
}
|
||||
}
|
||||
|
||||
// OSG_NOTICE<<"Time to compile "<<timer.elapsedTime_m()<<"ms"<<std::endl;
|
||||
|
||||
// unbind the BufferObjects
|
||||
extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
|
||||
extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
|
||||
|
||||
@@ -533,6 +533,30 @@ int Image::computeNumberOfMipmapLevels(int s,int t, int r)
|
||||
return 1 + static_cast<int>(floor(logf(w)/logf(2.0f)));
|
||||
}
|
||||
|
||||
bool Image::isCompressed() const
|
||||
{
|
||||
switch(_pixelFormat)
|
||||
{
|
||||
case(GL_COMPRESSED_ALPHA_ARB):
|
||||
case(GL_COMPRESSED_INTENSITY_ARB):
|
||||
case(GL_COMPRESSED_LUMINANCE_ALPHA_ARB):
|
||||
case(GL_COMPRESSED_LUMINANCE_ARB):
|
||||
case(GL_COMPRESSED_RGBA_ARB):
|
||||
case(GL_COMPRESSED_RGB_ARB):
|
||||
case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT):
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT):
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
|
||||
case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
|
||||
case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT):
|
||||
case(GL_COMPRESSED_RED_RGTC1_EXT):
|
||||
case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT):
|
||||
case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT):
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Image::getTotalSizeInBytesIncludingMipmaps() const
|
||||
{
|
||||
if (_mipmapData.empty())
|
||||
|
||||
@@ -405,7 +405,7 @@ public:
|
||||
|
||||
if (!_pager->isCompiled(texture))
|
||||
{
|
||||
_dataToCompile->_textures.push_back(texture);
|
||||
_dataToCompile->_textures.insert(texture);
|
||||
|
||||
if (osg::getNotifyLevel() >= osg::DEBUG_INFO)
|
||||
{
|
||||
@@ -459,7 +459,7 @@ public:
|
||||
// anything for VBOs, does it?
|
||||
if (_dataToCompile && (drawable->getUseVertexBufferObjects() || drawable->getUseDisplayList()) && !_pager->isCompiled(drawable))
|
||||
{
|
||||
_dataToCompile->_drawables.push_back(drawable);
|
||||
_dataToCompile->_drawables.insert(drawable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2143,7 +2143,7 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime, b
|
||||
//OSG_INFO<<"Compiling textures"<<std::endl;
|
||||
|
||||
// we have Textures to compile
|
||||
typedef osgUtil::IncrementalCompileOperation::CompileData::Textures Textures;
|
||||
typedef osgUtil::CompileData::Textures Textures;
|
||||
Textures& textures = dtc._textures;
|
||||
Textures::iterator itr=textures.begin();
|
||||
unsigned int objTemp = numObjectsCompiled;
|
||||
@@ -2187,7 +2187,7 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime, b
|
||||
{
|
||||
// we have Drawable's to compile
|
||||
//OSG_INFO<<"Compiling drawables"<<std::endl;
|
||||
typedef osgUtil::IncrementalCompileOperation::CompileData::Drawables Drawables;
|
||||
typedef osgUtil::CompileData::Drawables Drawables;
|
||||
Drawables& dwlist = dtc._drawables;
|
||||
Drawables::iterator itr = dwlist.begin();
|
||||
unsigned int objTemp = numObjectsCompiled;
|
||||
|
||||
@@ -89,7 +89,8 @@ void GLObjectsVisitor::apply(osg::Drawable& drawable)
|
||||
drawable.setUseVertexBufferObjects(false);
|
||||
}
|
||||
|
||||
if (_mode&COMPILE_DISPLAY_LISTS && _renderInfo.getState())
|
||||
if (_mode&COMPILE_DISPLAY_LISTS && _renderInfo.getState() &&
|
||||
(drawable.getUseDisplayList() || drawable.getUseVertexBufferObjects()))
|
||||
{
|
||||
drawable.compileGLObjects(_renderInfo);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,417 @@
|
||||
namespace osgUtil
|
||||
{
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CompileStats
|
||||
//
|
||||
CompileStats::CompileStats()
|
||||
{
|
||||
}
|
||||
|
||||
void CompileStats::add(const std::string& name,double size, double time)
|
||||
{
|
||||
Values& values = _statsMap[name];
|
||||
values.add(size,time);
|
||||
}
|
||||
|
||||
double CompileStats::estimateTime(const std::string& name, double size) const
|
||||
{
|
||||
StatsMap::const_iterator itr = _statsMap.find(name);
|
||||
return (itr!=_statsMap.end()) ? itr->second.estimateTime(size) : 0.0;
|
||||
}
|
||||
|
||||
double CompileStats::estimateTime2(const std::string& name, double size) const
|
||||
{
|
||||
StatsMap::const_iterator itr = _statsMap.find(name);
|
||||
return (itr!=_statsMap.end()) ? itr->second.estimateTime2(size) : 0.0;
|
||||
}
|
||||
|
||||
double CompileStats::estimateTime3(const std::string& name, double size) const
|
||||
{
|
||||
StatsMap::const_iterator itr = _statsMap.find(name);
|
||||
return (itr!=_statsMap.end()) ? itr->second.estimateTime3(size) : 0.0;
|
||||
}
|
||||
|
||||
double CompileStats::estimateTime4(const std::string& name, double size) const
|
||||
{
|
||||
StatsMap::const_iterator itr = _statsMap.find(name);
|
||||
return (itr!=_statsMap.end()) ? itr->second.estimateTime4(size) : 0.0;
|
||||
}
|
||||
|
||||
double CompileStats::averageTime(const std::string& name) const
|
||||
{
|
||||
StatsMap::const_iterator itr = _statsMap.find(name);
|
||||
return (itr!=_statsMap.end()) ? itr->second.averageTime() : 0.0;
|
||||
}
|
||||
|
||||
void CompileStats::print(std::ostream& out) const
|
||||
{
|
||||
for(StatsMap::const_iterator itr = _statsMap.begin();
|
||||
itr != _statsMap.end();
|
||||
++itr)
|
||||
{
|
||||
const Values& values = itr->second;
|
||||
out<<itr->first<<" : averageTime "<<values.averageTime()<<", a="<<values.a<<" b="<<values.b<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void CompileStats::Values::add(double size, double time)
|
||||
{
|
||||
if (totalNum==0.0)
|
||||
{
|
||||
minSize = size;
|
||||
minTime = time;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size<minSize) minSize = size;
|
||||
if (time<minTime) minTime = time;
|
||||
}
|
||||
|
||||
totalSize += size;
|
||||
totalTime += time;
|
||||
totalNum += 1.0;
|
||||
|
||||
m += time/(size*size); // sum of yi/xi^2
|
||||
n += time/size; // sum of yi/xi
|
||||
o += 1.0/(size*size); // sum of 1/xi^2
|
||||
p += 1.0/size; // sum of 1/xi
|
||||
|
||||
double d = o + p*p;
|
||||
if (d!=0.0)
|
||||
{
|
||||
a = (n*p - m)/d;
|
||||
b = (n*o - m*p)/d;
|
||||
}
|
||||
else
|
||||
{
|
||||
a = time;
|
||||
b = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CompileOperator
|
||||
//
|
||||
CompileOperator::CompileOperator():
|
||||
_timingTestsCompleted(false)
|
||||
{
|
||||
_compileStats = new CompileStats;
|
||||
}
|
||||
|
||||
void CompileOperator::assignForceTextureDownloadGeometry()
|
||||
{
|
||||
osg::Geometry* geometry = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
vertices->push_back(osg::Vec3(0.0f,0.0f,0.0f));
|
||||
geometry->setVertexArray(vertices);
|
||||
|
||||
osg::Vec4Array* texcoords = new osg::Vec4Array;
|
||||
texcoords->push_back(osg::Vec4(0.0f,0.0f,0.0f,0.0f));
|
||||
geometry->setTexCoordArray(0, texcoords);
|
||||
|
||||
geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS,0,1));
|
||||
|
||||
osg::StateSet* stateset = geometry->getOrCreateStateSet();
|
||||
stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||
|
||||
osg::Depth* depth = new osg::Depth;
|
||||
depth->setWriteMask(false);
|
||||
stateset->setAttribute(depth);
|
||||
|
||||
osg::ColorMask* colorMask = new osg::ColorMask(false,false,false,false);
|
||||
stateset->setAttribute(colorMask);
|
||||
|
||||
_forceTextureDownloadGeometry = geometry;
|
||||
}
|
||||
|
||||
double CompileOperator::timeCompile(osg::RenderInfo& renderInfo, osg::Geometry* geometry) const
|
||||
{
|
||||
osg::ElapsedTime timer;
|
||||
geometry->compileGLObjects(renderInfo);
|
||||
return timer.elapsedTime();
|
||||
}
|
||||
|
||||
double CompileOperator::timeCompile(osg::RenderInfo& renderInfo, osg::StateSet* stateset) const
|
||||
{
|
||||
osg::ElapsedTime timer;
|
||||
stateset->compileGLObjects(*renderInfo.getState());
|
||||
return timer.elapsedTime();
|
||||
}
|
||||
|
||||
osg::Geometry* CompileOperator::createTestGeometry(unsigned int numVertices, bool vbo) const
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
|
||||
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(numVertices);
|
||||
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array(numVertices);
|
||||
osg::ref_ptr<osg::Vec4Array> colours = new osg::Vec4Array(numVertices);
|
||||
osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array(numVertices);
|
||||
|
||||
geometry->setVertexArray(vertices.get());
|
||||
geometry->setNormalArray(normals.get());
|
||||
geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
geometry->setColorArray(colours.get());
|
||||
geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
geometry->setTexCoordArray(0, texcoords.get());
|
||||
|
||||
for(unsigned int i=0; i<numVertices; ++i)
|
||||
{
|
||||
(*vertices)[i] = osg::Vec3(0.0f,0.0f,0.0f);
|
||||
(*normals)[i] = osg::Vec3(0.0f,0.0f,0.0f);
|
||||
(*colours)[i] = osg::Vec4(1.0f,1.0f,1.0f,1.0f);
|
||||
(*texcoords)[i] = osg::Vec2(0.0f,0.0f);
|
||||
}
|
||||
|
||||
geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0,numVertices));
|
||||
|
||||
geometry->setUseDisplayList(true);
|
||||
geometry->setUseVertexBufferObjects(vbo);
|
||||
|
||||
return geometry.release();
|
||||
}
|
||||
|
||||
osg::StateSet* CompileOperator::createTestStateSet(unsigned int imageSize, bool mipmapped) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CompileOperator::runTimingTests(osg::RenderInfo& renderInfo)
|
||||
{
|
||||
OSG_NOTICE<<"runTimingTests()"<<std::endl;
|
||||
_timingTestsCompleted = true;
|
||||
|
||||
unsigned int mx = 18;
|
||||
double Mbsec = 1.0/(1024.0*1024.0);
|
||||
for(unsigned int j=0; j<4; ++j)
|
||||
{
|
||||
OSG_NOTICE<<"Using display lists"<<std::endl;
|
||||
bool useVBO = false;
|
||||
for(unsigned int i=0; i<mx; ++i)
|
||||
{
|
||||
unsigned int numVertices = pow(2,i);
|
||||
osg::ref_ptr<osg::Geometry> geometry = createTestGeometry(numVertices, useVBO);
|
||||
double size = geometry->getGLObjectSizeHint();
|
||||
double time = timeCompile(renderInfo, geometry);
|
||||
OSG_NOTICE<<" numVertices = "<<numVertices<<" size = "<<size<<", time = "<<time*1000.0<<"ms rate= "<<(size/time)*Mbsec<<"Mb/sec"<<std::endl;
|
||||
}
|
||||
}
|
||||
for(unsigned int j=0; j<4; ++j)
|
||||
{
|
||||
OSG_NOTICE<<"Using VBOs"<<std::endl;
|
||||
bool useVBO = true;
|
||||
for(unsigned int i=0; i<mx; ++i)
|
||||
{
|
||||
unsigned int numVertices = pow(2,i);
|
||||
osg::ref_ptr<osg::Geometry> geometry = createTestGeometry(numVertices, useVBO);
|
||||
double size = geometry->getGLObjectSizeHint();
|
||||
double time = timeCompile(renderInfo, geometry);
|
||||
OSG_NOTICE<<" numVertices = "<<numVertices<<" size = "<<size<<", time = "<<time*1000.0<<"ms rate= "<<(size/time)*Mbsec<<"Mb/sec"<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CompileOperator::compile(osg::RenderInfo& renderInfo, CompileData& cd, unsigned int& maxNumObjectsToCompile, double& compileTime)
|
||||
{
|
||||
osg::Timer_t startTick = osg::Timer::instance()->tick();
|
||||
|
||||
if (!_timingTestsCompleted)
|
||||
{
|
||||
runTimingTests(renderInfo);
|
||||
}
|
||||
|
||||
unsigned int totalDataSizeCompiled = 0;
|
||||
unsigned int drawablesCompiled = 0;
|
||||
unsigned int texturesCompiled = 0;
|
||||
unsigned int programsCompiled = 0;
|
||||
|
||||
if (!cd.empty() && compileTime>0.0)
|
||||
{
|
||||
|
||||
osg::Timer_t previousTick = osg::Timer::instance()->tick();
|
||||
|
||||
const std::string vboDrawablesName("VBO Drawables");
|
||||
const std::string dlDawablesName("DisplayList Drawables");
|
||||
|
||||
while(!cd._drawables.empty() &&
|
||||
maxNumObjectsToCompile>0 &&
|
||||
osg::Timer::instance()->delta_s(startTick, previousTick) < compileTime)
|
||||
{
|
||||
CompileData::Drawables::iterator itr = cd._drawables.begin();
|
||||
const osg::Drawable* drawable = itr->get();
|
||||
unsigned int size = drawable->getGLObjectSizeHint();
|
||||
const std::string& nameOfDrawableType = drawable->getUseVertexBufferObjects() ? vboDrawablesName : dlDawablesName;
|
||||
double estimatedTime = _compileStats->estimateTime(nameOfDrawableType, double(size));
|
||||
double estimatedTime2 = _compileStats->estimateTime2(nameOfDrawableType, double(size));
|
||||
double estimatedTime3 = _compileStats->estimateTime3(nameOfDrawableType, double(size));
|
||||
double estimatedTime4 = _compileStats->estimateTime4(nameOfDrawableType, double(size));
|
||||
|
||||
drawable->compileGLObjects(renderInfo);
|
||||
osg::Timer_t currTick = osg::Timer::instance()->tick();
|
||||
double timeForCompile = osg::Timer::instance()->delta_s(previousTick, currTick);
|
||||
previousTick = currTick;
|
||||
|
||||
OSG_NOTICE<<"Drawable size = "<<size<<std::endl;
|
||||
OSG_NOTICE<<" Estimated time ="<<estimatedTime<<", actual time="<<timeForCompile<<" ratio = "<<timeForCompile/estimatedTime<<std::endl;
|
||||
OSG_NOTICE<<" Estimated time2="<<estimatedTime2<<", actual time="<<timeForCompile<<" ratio = "<<timeForCompile/estimatedTime2<<std::endl;
|
||||
OSG_NOTICE<<" Estimated time3="<<estimatedTime3<<", actual time="<<timeForCompile<<" ratio = "<<timeForCompile/estimatedTime3<<std::endl;
|
||||
OSG_NOTICE<<" Estimated time4="<<estimatedTime4<<", actual time="<<timeForCompile<<" ratio = "<<timeForCompile/estimatedTime4<<std::endl;
|
||||
|
||||
_compileStats->add(nameOfDrawableType, double(size), timeForCompile);
|
||||
|
||||
|
||||
totalDataSizeCompiled += size;
|
||||
// OSG_NOTICE<<"Compiled drawable, getGLObjectSizeHint()="<<(*itr)->getGLObjectSizeHint()<<std::endl;
|
||||
|
||||
++drawablesCompiled;
|
||||
--maxNumObjectsToCompile;
|
||||
cd._drawables.erase(itr);
|
||||
|
||||
|
||||
}
|
||||
|
||||
while(!cd._textures.empty() &&
|
||||
maxNumObjectsToCompile>0 &&
|
||||
osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()) < compileTime)
|
||||
{
|
||||
CompileData::Textures::iterator itr = cd._textures.begin();
|
||||
|
||||
osg::Texture* texture = itr->get();
|
||||
|
||||
osg::Texture::FilterMode minFilter = texture->getFilter(osg::Texture::MIN_FILTER);
|
||||
bool textureMipmapped = (minFilter!=osg::Texture::LINEAR && minFilter!=osg::Texture::NEAREST);
|
||||
bool textureCompressedFormat = texture->isCompressedInternalFormat();
|
||||
bool needtoBuildMipmaps = false;
|
||||
bool needtoCompress = false;
|
||||
|
||||
OSG_NOTICE<<" texture->isCompressedInternalFormat()="<<textureCompressedFormat<<std::endl;
|
||||
|
||||
for(unsigned int i=0; i<texture->getNumImages();++i)
|
||||
{
|
||||
osg::Image* image = texture->getImage(i);
|
||||
if (image)
|
||||
{
|
||||
totalDataSizeCompiled += texture->getImage(i)->getTotalSizeInBytesIncludingMipmaps();
|
||||
if (textureMipmapped && !image->isMipmap()) needtoBuildMipmaps = true;
|
||||
if (textureCompressedFormat && !image->isCompressed()) needtoCompress = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OSG_NOTICE<<"compiling texture, textureMipmapped="<<textureMipmapped<<", needtoBuildMipmaps="<<needtoBuildMipmaps<<std::endl;
|
||||
OSG_NOTICE<<" textureCompressedFormat="<<textureCompressedFormat<<", needtoCompress="<<needtoCompress<<std::endl;
|
||||
|
||||
// if (needtoBuildMipmaps) texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
||||
|
||||
|
||||
if (_forceTextureDownloadGeometry.get())
|
||||
{
|
||||
|
||||
if (_forceTextureDownloadGeometry->getStateSet())
|
||||
{
|
||||
renderInfo.getState()->apply(_forceTextureDownloadGeometry->getStateSet());
|
||||
}
|
||||
|
||||
renderInfo.getState()->applyTextureMode(0, texture->getTextureTarget(), true);
|
||||
renderInfo.getState()->applyTextureAttribute(0, texture);
|
||||
|
||||
_forceTextureDownloadGeometry->draw(renderInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
texture->apply(*renderInfo.getState());
|
||||
}
|
||||
|
||||
++texturesCompiled;
|
||||
--maxNumObjectsToCompile;
|
||||
|
||||
cd._textures.erase(itr);
|
||||
}
|
||||
|
||||
|
||||
if (!cd._programs.empty())
|
||||
{
|
||||
osg::GL2Extensions* extensions = osg::GL2Extensions::Get(renderInfo.getState()->getContextID(), true);
|
||||
if (extensions && extensions->isGlslSupported())
|
||||
{
|
||||
// compile programs
|
||||
while(!cd._programs.empty() &&
|
||||
maxNumObjectsToCompile>0 &&
|
||||
osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()) < compileTime)
|
||||
{
|
||||
CompileData::Programs::iterator itr = cd._programs.begin();
|
||||
(*itr)->apply(*renderInfo.getState());
|
||||
|
||||
++programsCompiled;
|
||||
--maxNumObjectsToCompile;
|
||||
|
||||
cd._programs.erase(itr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
// what shall we do about uniforms???
|
||||
|
||||
osg::Program* program = dynamic_cast<osg::Program*>(stateset.getAttribute(osg::StateAttribute::PROGRAM));
|
||||
if (program) {
|
||||
if( program->isFixedFunction() )
|
||||
_lastCompiledProgram = NULL; // It does not make sense to apply uniforms on fixed pipe
|
||||
else
|
||||
_lastCompiledProgram = program;
|
||||
}
|
||||
|
||||
if (_lastCompiledProgram.valid() && !stateset.getUniformList().empty())
|
||||
{
|
||||
osg::Program::PerContextProgram* pcp = _lastCompiledProgram->getPCP(_renderInfo.getState()->getContextID());
|
||||
if (pcp)
|
||||
{
|
||||
pcp->useProgram();
|
||||
|
||||
_renderInfo.getState()->setLastAppliedProgramObject(pcp);
|
||||
|
||||
osg::StateSet::UniformList& ul = stateset.getUniformList();
|
||||
for(osg::StateSet::UniformList::iterator itr = ul.begin();
|
||||
itr != ul.end();
|
||||
++itr)
|
||||
{
|
||||
pcp->apply(*(itr->second.first));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(_renderInfo.getState()->getLastAppliedProgramObject()){
|
||||
|
||||
osg::GL2Extensions* extensions = osg::GL2Extensions::Get(_renderInfo.getState()->getContextID(), true);
|
||||
extensions->glUseProgram(0);
|
||||
_renderInfo.getState()->setLastAppliedProgramObject(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// switch off Program,
|
||||
extensions->glUseProgram(0);
|
||||
renderInfo.getState()->setLastAppliedProgramObject(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double timeUsed = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick());
|
||||
|
||||
OSG_NOTICE<<"compile time, texturesCompiled="<<texturesCompiled<<", drawablesCompiled="<<drawablesCompiled<<", programsCompiled="<<programsCompiled<<", timeUsed="<<timeUsed*1000.0<<" totalDataSizeCompiled="<<totalDataSizeCompiled<<" bytes, download rate="<<double(totalDataSizeCompiled)/(1024.0*1024*timeUsed)<<"Mb/sec"<<std::endl;
|
||||
|
||||
compileTime -= timeUsed;
|
||||
|
||||
return cd.empty();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IncrementalCompileOperation
|
||||
//
|
||||
IncrementalCompileOperation::IncrementalCompileOperation():
|
||||
osg::GraphicsOperation("IncrementalCompileOperation",true),
|
||||
_flushTimeRatio(0.5),
|
||||
@@ -46,6 +457,8 @@ IncrementalCompileOperation::IncrementalCompileOperation():
|
||||
{
|
||||
_maximumNumOfObjectsToCompilePerFrame = atoi(ptr);
|
||||
}
|
||||
|
||||
_compileOperator = new CompileOperator;
|
||||
}
|
||||
|
||||
IncrementalCompileOperation::~IncrementalCompileOperation()
|
||||
@@ -54,29 +467,7 @@ IncrementalCompileOperation::~IncrementalCompileOperation()
|
||||
|
||||
void IncrementalCompileOperation::assignForceTextureDownloadGeometry()
|
||||
{
|
||||
osg::Geometry* geometry = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
vertices->push_back(osg::Vec3(0.0f,0.0f,0.0f));
|
||||
geometry->setVertexArray(vertices);
|
||||
|
||||
osg::Vec2Array* texcoords = new osg::Vec2Array;
|
||||
texcoords->push_back(osg::Vec2(0.0f,0.0f));
|
||||
geometry->setTexCoordArray(0, texcoords);
|
||||
|
||||
geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS,0,1));
|
||||
|
||||
osg::StateSet* stateset = geometry->getOrCreateStateSet();
|
||||
stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||
|
||||
osg::Depth* depth = new osg::Depth;
|
||||
depth->setWriteMask(false);
|
||||
stateset->setAttribute(depth);
|
||||
|
||||
osg::ColorMask* colorMask = new osg::ColorMask(false,false,false,false);
|
||||
stateset->setAttribute(colorMask);
|
||||
|
||||
_forceTextureDownloadGeometry = geometry;
|
||||
_compileOperator->assignForceTextureDownloadGeometry();
|
||||
}
|
||||
|
||||
void IncrementalCompileOperation::assignContexts(Contexts& contexts)
|
||||
@@ -251,7 +642,8 @@ public:
|
||||
drawable.setUseVertexBufferObjects(false);
|
||||
}
|
||||
|
||||
if (_mode&GLObjectsVisitor::COMPILE_DISPLAY_LISTS)
|
||||
if (_mode&GLObjectsVisitor::COMPILE_DISPLAY_LISTS &&
|
||||
(drawable.getUseDisplayList() || drawable.getUseVertexBufferObjects()))
|
||||
{
|
||||
_drawables.insert(&drawable);
|
||||
}
|
||||
@@ -271,7 +663,7 @@ public:
|
||||
{
|
||||
_programs.insert(program);
|
||||
}
|
||||
|
||||
|
||||
osg::StateSet::TextureAttributeList& tal = stateset.getTextureAttributeList();
|
||||
for(osg::StateSet::TextureAttributeList::iterator itr = tal.begin();
|
||||
itr != tal.end();
|
||||
@@ -306,9 +698,9 @@ void IncrementalCompileOperation::CompileSet::buildCompileMap(ContextSet& contex
|
||||
++itr)
|
||||
{
|
||||
CompileData& cd = _compileMap[*itr];
|
||||
std::copy(cstc._textures.begin(), cstc._textures.end(), std::back_inserter<CompileData::Textures>(cd._textures));
|
||||
std::copy(cstc._programs.begin(), cstc._programs.end(), std::back_inserter<CompileData::Programs>(cd._programs));
|
||||
std::copy(cstc._drawables.begin(), cstc._drawables.end(), std::back_inserter<CompileData::Drawables>(cd._drawables));
|
||||
cd._drawables.insert(cstc._drawables.begin(), cstc._drawables.end());
|
||||
cd._textures.insert(cstc._textures.begin(), cstc._textures.end());
|
||||
cd._programs.insert(cstc._programs.begin(), cstc._programs.end());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -340,6 +732,7 @@ void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
|
||||
|
||||
double flushTime = availableTime * _flushTimeRatio;
|
||||
double compileTime = availableTime - flushTime;
|
||||
unsigned int maxNumOfObjectsToCompilePerFrame = _maximumNumOfObjectsToCompilePerFrame;
|
||||
|
||||
#if 1
|
||||
OSG_NOTIFY(level)<<"total availableTime = "<<availableTime*1000.0<<std::endl;
|
||||
@@ -360,78 +753,21 @@ void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
|
||||
osg::RenderInfo renderInfo;
|
||||
renderInfo.setState(context->getState());
|
||||
|
||||
|
||||
CompileSets toCompileCopy;
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> toCompile_lock(_toCompileMutex);
|
||||
std::copy(_toCompile.begin(),_toCompile.end(),std::back_inserter<CompileSets>(toCompileCopy));
|
||||
}
|
||||
|
||||
osg::Timer_t startTick = osg::Timer::instance()->tick();
|
||||
|
||||
for(CompileSets::iterator itr = toCompileCopy.begin();
|
||||
itr != toCompileCopy.end();
|
||||
for(CompileSets::iterator itr = toCompileCopy.begin();
|
||||
itr != toCompileCopy.end() && compileTime>0.0;
|
||||
++itr)
|
||||
{
|
||||
CompileSet* cs = itr->get();
|
||||
CompileMap& cm = cs->_compileMap;
|
||||
CompileData& cd = cm[context];
|
||||
|
||||
if (!cd.empty())
|
||||
{
|
||||
OSG_NOTIFY(level)<<"cd._drawables.size()="<<cd._drawables.size()<<std::endl;
|
||||
OSG_NOTIFY(level)<<"cd._textures.size()="<<cd._textures.size()<<std::endl;
|
||||
OSG_NOTIFY(level)<<"cd._programs.size()="<<cd._programs.size()<<std::endl;
|
||||
|
||||
|
||||
while(!cd._drawables.empty() &&
|
||||
osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()) < compileTime)
|
||||
{
|
||||
cd._drawables.back()->compileGLObjects(renderInfo);
|
||||
cd._drawables.pop_back();
|
||||
}
|
||||
|
||||
while(!cd._textures.empty() &&
|
||||
osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()) < compileTime)
|
||||
{
|
||||
if (_forceTextureDownloadGeometry.get())
|
||||
{
|
||||
if (_forceTextureDownloadGeometry->getStateSet())
|
||||
{
|
||||
renderInfo.getState()->apply(_forceTextureDownloadGeometry->getStateSet());
|
||||
}
|
||||
|
||||
renderInfo.getState()->applyTextureAttribute(0, cd._textures.back().get());
|
||||
|
||||
_forceTextureDownloadGeometry->draw(renderInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
cd._textures.back()->apply(*renderInfo.getState());
|
||||
}
|
||||
|
||||
cd._textures.pop_back();
|
||||
}
|
||||
|
||||
|
||||
if (!cd._programs.empty())
|
||||
{
|
||||
// compile programs
|
||||
while(!cd._programs.empty() &&
|
||||
osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()) < compileTime)
|
||||
{
|
||||
cd._programs.back()->apply(*renderInfo.getState());
|
||||
cd._programs.pop_back();
|
||||
}
|
||||
|
||||
// switch off Program,
|
||||
osg::GL2Extensions* extensions = osg::GL2Extensions::Get(renderInfo.getState()->getContextID(), true);
|
||||
extensions->glUseProgram(0);
|
||||
renderInfo.getState()->setLastAppliedProgramObject(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (cd.empty())
|
||||
if (_compileOperator->compile(renderInfo, cd, maxNumOfObjectsToCompilePerFrame, compileTime))
|
||||
{
|
||||
bool csCompleted = false;
|
||||
{
|
||||
@@ -443,17 +779,17 @@ void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
|
||||
if (cs_itr != _toCompile.end())
|
||||
{
|
||||
OSG_NOTIFY(level)<<"Erasing from list"<<std::endl;
|
||||
|
||||
|
||||
// remove from the _toCompile list, note cs won't be deleted here as the tempoary
|
||||
// toCompile_Copy list will retain a reference.
|
||||
_toCompile.erase(cs_itr);
|
||||
|
||||
|
||||
// signal that we need to do clean up operations/pass cs on to _compile list.
|
||||
csCompleted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (csCompleted)
|
||||
{
|
||||
if (cs->_compileCompletedCallback.valid() && cs->_compileCompletedCallback->compileCompleted(cs))
|
||||
@@ -466,7 +802,6 @@ void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
|
||||
_compiled.push_back(cs);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
#include <osg/GLExtensions>
|
||||
#include <osgUtil/GLObjectsVisitor>
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgViewer/CompositeViewer>
|
||||
#include <osgViewer/Renderer>
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <osg/DeleteHandler>
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include <osgUtil/GLObjectsVisitor>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
Reference in New Issue
Block a user