Integrated IncementalCompileOperation into DatabasePager.

Improved various facilities in IncrementalCompileOperation.
This commit is contained in:
Robert Osfield
2010-10-21 16:29:23 +00:00
parent 2014e85259
commit 1a292ad8e3
10 changed files with 611 additions and 126 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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())

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -12,7 +12,6 @@
*/
#include <osg/GLExtensions>
#include <osgUtil/GLObjectsVisitor>
#include <osgGA/TrackballManipulator>
#include <osgViewer/CompositeViewer>
#include <osgViewer/Renderer>

View File

@@ -17,7 +17,6 @@
#include <osg/DeleteHandler>
#include <osg/io_utils>
#include <osgUtil/GLObjectsVisitor>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>