diff --git a/include/osg/Image b/include/osg/Image index 150ba9292..cdbfac39c 100644 --- a/include/osg/Image +++ b/include/osg/Image @@ -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; diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index 163367448..5e1c38793 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -350,8 +350,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl typedef std::set< osg::ref_ptr > StateSetList; typedef std::vector< osg::ref_ptr > DrawableList; - //typedef std::pair DataToCompile; - typedef osgUtil::IncrementalCompileOperation::CompileData DataToCompile; + typedef osgUtil::CompileData DataToCompile; typedef std::map< unsigned int, DataToCompile > DataToCompileMap; typedef std::set ActiveGraphicsContexts; typedef std::vector< osg::observer_ptr > CompileGraphicsContexts; diff --git a/include/osgUtil/IncrementalCompileOperation b/include/osgUtil/IncrementalCompileOperation index 36bf95ad9..13333169a 100644 --- a/include/osgUtil/IncrementalCompileOperation +++ b/include/osgUtil/IncrementalCompileOperation @@ -19,6 +19,144 @@ namespace osgUtil { +class CompileData : public osg::Referenced +{ + public: + + CompileData() {} + + typedef std::set< osg::ref_ptr > Drawables; + typedef std::set< osg::ref_ptr > Textures; + typedef std::set< osg::ref_ptr > 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 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 _forceTextureDownloadGeometry; + osg::ref_ptr _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 > Drawables; - typedef std::list< osg::ref_ptr > Textures; - typedef std::list< osg::ref_ptr > Programs; - - bool empty() const { return _drawables.empty() && _textures.empty() && _programs.empty(); } - - Drawables _drawables; - Textures _textures; - Programs _programs; - }; - class CompileSet; typedef std::set ContextSet; typedef std::map CompileMap; @@ -145,14 +270,13 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation osg::ref_ptr _subgraphToCompile; osg::ref_ptr _compileCompletedCallback; CompileMap _compileMap; - + // protected: - + virtual ~CompileSet() {} }; - - typedef std::list< osg::ref_ptr > CompileSets; + typedef std::list< osg::ref_ptr > 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 _forceTextureDownloadGeometry; + osg::ref_ptr _compileOperator; OpenThreads::Mutex _toCompileMutex; CompileSets _toCompile; diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index 1126da8bb..0473ee573 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -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 "<glBindBuffer(GL_ARRAY_BUFFER_ARB,0); extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0); diff --git a/src/osg/Image.cpp b/src/osg/Image.cpp index a6cb2dfc2..fcbe3d15b 100644 --- a/src/osg/Image.cpp +++ b/src/osg/Image.cpp @@ -533,6 +533,30 @@ int Image::computeNumberOfMipmapLevels(int s,int t, int r) return 1 + static_cast(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()) diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index 32704cd91..3ba4deadf 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -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"<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<first<<" : averageTime "< geometry = createTestGeometry(numVertices, useVBO); + double size = geometry->getGLObjectSizeHint(); + double time = timeCompile(renderInfo, geometry); + OSG_NOTICE<<" numVertices = "< geometry = createTestGeometry(numVertices, useVBO); + double size = geometry->getGLObjectSizeHint(); + double time = timeCompile(renderInfo, geometry); + OSG_NOTICE<<" numVertices = "<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 = "<isCompressedInternalFormat()="<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="<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(cd._textures)); - std::copy(cstc._programs.begin(), cstc._programs.end(), std::back_inserter(cd._programs)); - std::copy(cstc._drawables.begin(), cstc._drawables.end(), std::back_inserter(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 = "<getState()); - CompileSets toCompileCopy; { OpenThreads::ScopedLock toCompile_lock(_toCompileMutex); std::copy(_toCompile.begin(),_toCompile.end(),std::back_inserter(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()="<_compileCompletedCallback.valid() && cs->_compileCompletedCallback->compileCompleted(cs)) @@ -466,7 +802,6 @@ void IncrementalCompileOperation::operator () (osg::GraphicsContext* context) _compiled.push_back(cs); } } - } } } diff --git a/src/osgViewer/CompositeViewer.cpp b/src/osgViewer/CompositeViewer.cpp index 71d06bca5..93bb52862 100644 --- a/src/osgViewer/CompositeViewer.cpp +++ b/src/osgViewer/CompositeViewer.cpp @@ -12,7 +12,6 @@ */ #include -#include #include #include #include diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 691abff3b..96275fabd 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include