diff --git a/include/osg/Statistics b/include/osg/Statistics index 0c560707b..0bb9a17c1 100644 --- a/include/osg/Statistics +++ b/include/osg/Statistics @@ -26,42 +26,93 @@ class SG_EXPORT Statistics : public osg::Object { public: - Statistics() { - numOpaque=0, nummat=0; - nprims=0, nlights=0; nbins=0; nimpostor=0; + Statistics() + { reset(); }; + + enum PrimitiveType + { + NO_TYPE, + POINTS, + LINES, + LINE_STRIP, + FLAT_LINE_STRIP, + LINE_LOOP, + TRIANGLES, + TRIANGLE_STRIP, + FLAT_TRIANGLE_STRIP, + TRIANGLE_FAN, + FLAT_TRIANGLE_FAN, + QUADS, + QUAD_STRIP, + POLYGON, + IMPOSTOR + }; + ~Statistics() {}; // no dynamic allocations, so no need to free virtual osg::Object* clone() const { return new Statistics(); } virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=0L; } virtual const char* className() const { return "Statistics"; } - - enum statsType { + + enum statsType + { STAT_NONE, // default STAT_FRAMERATE, STAT_GRAPHS, - STAT_PRIMS, STAT_PRIMSPERVIEW, + STAT_PRIMS, STAT_PRIMSPERVIEW, STAT_PRIMSPERBIN, STAT_DC, STAT_RESTART // hint to restart the stats }; - void reset() { - for (int i=0; i<20; i++) primverts[i]=numprimtypes[i]=primlens[i]=primtypes[i]=0; + void reset() + { + numOpaque=0, nummat=0; depth=0; stattype=STAT_NONE; + nprims=0, nlights=0; nbins=0; nimpostor=0; + for (int i=0; i<=POLYGON; i++) primverts[i]=numprimtypes[i]=primlens[i]=primtypes[i]=0; } + void setType(statsType t) {stattype=t;} + + void addNumPrims(const int typ, const int nprimlen, const int numprimtype, const int primvert) + { + if (typ>NO_TYPE && typ<=POLYGON) { + primtypes[0]++; + primtypes[typ]++; + numprimtypes[0]+=numprimtype; + numprimtypes[typ]+=numprimtype; + primlens[0]+=nprimlen; + primlens[typ]+=nprimlen; + primverts[0]+=primvert; + primverts[typ]+=primvert; + } + } + + void addOpaque() { numOpaque++;} + void addMatrix() { nummat++;} + void addLight(const int np) { nlights+=np;} + void addNumPrims(const int np) { nprims += np; } + void addImpostor(const int np) { nimpostor+= np; } + inline const int getBins() { return nbins;} + void setDepth(const int d) { depth=d; } + void addBins(const int np) { nbins+= np; } + + void setBinNo(const int n) { _binNo=n;} + public: int numOpaque, nummat, nbins; int nprims, nlights; + int depth; // depth into bins - eg 1.1,1.2,1.3 etc + int _binNo; + statsType stattype; int nimpostor; // number of impostors rendered - int numprimtypes[20]; // histogram of number of each type of prim - int primtypes[20]; // histogram of number of each type of prim - int primlens[20]; // histogram of lengths of each type of prim - int primverts[20]; // histogram of number of vertices to be transformed + int numprimtypes[16]; // histogram of number of each type of prim + int primtypes[16]; // histogram of number of each type of prim + int primlens[16]; // histogram of lengths of each type of prim + int primverts[16]; // histogram of number of vertices to be transformed - protected: - }; -} +}; #endif diff --git a/include/osgUtil/RenderBin b/include/osgUtil/RenderBin index aa116e4fe..e4051a54a 100644 --- a/include/osgUtil/RenderBin +++ b/include/osgUtil/RenderBin @@ -58,7 +58,10 @@ class OSGUTIL_EXPORT RenderBin : public osg::Object virtual void draw_local(osg::State& state,RenderLeaf*& previous); /** extract stats for current draw list. */ - void getStats(osg::Statistics& primStats); + bool getStats(osg::Statistics* primStats); + void getPrims(osg::Statistics* primStats); + bool getPrims(osg::Statistics* primStats, const int nbin); + public: diff --git a/include/osgUtil/RenderStage b/include/osgUtil/RenderStage index 6b5a0a83e..a5f148b5a 100644 --- a/include/osgUtil/RenderStage +++ b/include/osgUtil/RenderStage @@ -116,7 +116,7 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin void addToDependencyList(RenderStage* rs); /** extract stats for current draw list. */ - void getStats(osg::Statistics& primStats); + bool getStats(osg::Statistics* primStats); public: diff --git a/src/osgGLUT/Viewer.cpp b/src/osgGLUT/Viewer.cpp index 3a6e5f3ab..f52d5a17f 100644 --- a/src/osgGLUT/Viewer.cpp +++ b/src/osgGLUT/Viewer.cpp @@ -65,7 +65,7 @@ static osg::PolygonMode::Mode polymodes [] = { osg::PolygonMode::FILL, osg::Poly // forward declare functions to be used in stats. GLuint makeRasterFont(void); void displaytext(int x, int y, char *s); -void writePrims( const int ypos, osg::Statistics& stats); +int writePrims( const int ypos, osg::Statistics& stats); using namespace osg; using namespace osgUtil; @@ -448,6 +448,7 @@ void Viewer::keyboardCB(unsigned char key, int x, int y) void Viewer::showStats(const unsigned int viewport) { // collect stats for viewport + static int maxbins=1; // count number of bins static GLfloat tmax=100; glViewport(0,0,ww,wh); float vh = wh; @@ -495,7 +496,7 @@ void Viewer::showStats(const unsigned int viewport) displaytext(0,(int)(0.98f*vh),clin); } - if (_printStats>=Statistics::STAT_GRAPHS && _printStats!=Statistics::STAT_PRIMSPERVIEW) { // more stats - graphs this time + if (_printStats>=Statistics::STAT_GRAPHS && _printStats!=Statistics::STAT_PRIMSPERVIEW && _printStats!=Statistics::STAT_PRIMSPERBIN) { // more stats - graphs this time int sampleIndex = 2; float timeApp=times[sampleIndex].timeApp; @@ -584,9 +585,38 @@ void Viewer::showStats(const unsigned int viewport) ++itr) { osgUtil::RenderStage *stage = itr->sceneView->getRenderStage(); - stage->getStats(primStats); + stage->getPrims(&primStats); } + primStats.setType(Statistics::STAT_PRIMS); // full print out required writePrims((int)(0.86f*vh),primStats); + maxbins=(primStats.getBins()>maxbins)?primStats.getBins():maxbins; + + } + if (_printStats==Statistics::STAT_PRIMSPERBIN) { // more stats - add triangles, number of strips... as seen per bin + /* + * Use the new renderStage. Required mods to RenderBin.cpp, and RenderStage.cpp (add getPrims) + * also needed to define a new class called Statistic (see osgUtil/Statistic). + * RO, July 2001. + */ + + Statistics *primStats=new Statistics[maxbins]; // array of bin stats + ViewportList::iterator itr; + for(itr=_viewportList.begin(); + itr!=_viewportList.end(); + ++itr) + { + osgUtil::RenderStage *stage = itr->sceneView->getRenderStage(); + stage->getPrims(primStats, maxbins); + } + int nbinsUsed=(primStats[0].getBins()maxbins)?primStats[0].getBins():maxbins; + delete [] primStats; // free up } if (_printStats==Statistics::STAT_DC) { // yet more stats - read the depth complexity int wid=ww, ht=wh; // temporary local screen size - must change during this section @@ -1408,7 +1438,7 @@ void displaytext(int x, int y, char *s) glListBase(0); // glPopAttrib (); } - +/* void writePrims( const int ypos, osg::Statistics& stats) { char clin[100]; // buffer to print @@ -1464,3 +1494,72 @@ void writePrims( const int ypos, osg::Statistics& stats) } displaytext(0,ypos-60,clin); } +*/ +int writePrims( const int ypos, osg::Statistics& stats) +{ + char clin[100]; // buffer to print + char ctmp[12]; + int i; // a counter + int npix=0; // offset from ypos + char intro[12]; // start of first line + static char *prtypes[]={"Total", + " Pt", " Ln", " Lstr", " LSTf", " Llop", // 1- 5 + " Tris", " TStr", " TSfl", " TFan", " TFnf", // 6-10 + " Quad", " QStr", " Pols", "", "", // 11-15 + "", "", "", "", ""}; + glColor3f(.9f,.9f,0.0f); + + if (stats.depth==1) sprintf(intro,"==> Bin %2d", stats._binNo); + else sprintf(intro," "); + sprintf(clin,"%s %d Prims %d Matxs %d Gsets %d nlts %d bins %d imps", + intro ,stats.nprims, stats.nummat, stats.numOpaque, stats.nlights, stats.nbins, stats.nimpostor); + displaytext(0,ypos-npix,clin); + npix+=12; + strcpy(clin," "); + for (i=0; i<=osg::Statistics::POLYGON; i++) { + if (i==0 || stats.primtypes[i]) { + strcat(clin, prtypes[i]); + } + } + displaytext(0,ypos-npix,clin); + npix+=12; + strcpy(clin,"GSet type: "); + for (i=0; i<=osg::Statistics::POLYGON; i++) { + if (stats.primtypes[i]) { + sprintf(ctmp,"%5d", stats.primtypes[i]); + strcat(clin, ctmp); + } + } + displaytext(0,ypos-npix,clin); + npix+=12; + strcpy(clin,"Prims: "); + for (i=0; i<=osg::Statistics::POLYGON; i++) { + if (stats.primtypes[i]) { + sprintf(ctmp,"%5d", stats.numprimtypes[i]); + strcat(clin, ctmp); + } + } + displaytext(0,ypos-npix,clin); + npix+=12; + strcpy(clin,"Triangles: "); + for (i=0; i<=osg::Statistics::POLYGON; i++) { + if (stats.primtypes[i]) { + sprintf(ctmp,"%5d", stats.primlens[i]); + strcat(clin, ctmp); + } + } + displaytext(0,ypos-npix,clin); + npix+=12; + strcpy(clin,"Vertices: "); + for (i=0; i<=osg::Statistics::POLYGON; i++) { + if (stats.primtypes[i]) { + sprintf(ctmp,"%5d", stats.primverts[i]); + strcat(clin, ctmp); + } + } + displaytext(0,ypos-npix,clin); + npix+=12; + if (stats.stattype!=osg::Statistics::STAT_PRIMSPERBIN) { + } + return npix; +} diff --git a/src/osgUtil/RenderBin.cpp b/src/osgUtil/RenderBin.cpp index 391863abf..1b7daaa22 100644 --- a/src/osgUtil/RenderBin.cpp +++ b/src/osgUtil/RenderBin.cpp @@ -162,19 +162,12 @@ void RenderBin::draw_local(osg::State& state,RenderLeaf*& previous) } // stats -void RenderBin::getStats(Statistics& primStats) -{ - for(RenderBinList::iterator itr = _bins.begin(); - itr!=_bins.end(); - ++itr) - { - primStats.nbins++; - itr->second->getStats(primStats); // gwm 19.08.01 - multi-pass rendering uses these bins too. - } - +bool RenderBin::getStats(osg::Statistics* primStats) +{ // different by return type - collects the stats in this renderrBin + bool somestats=false; for(RenderGraphList::iterator oitr=_renderGraphList.begin(); - oitr!=_renderGraphList.end(); - ++oitr) + oitr!=_renderGraphList.end(); + ++oitr) { for(RenderGraph::LeafList::iterator dw_itr = (*oitr)->_leaves.begin(); @@ -183,11 +176,55 @@ void RenderBin::getStats(Statistics& primStats) { RenderLeaf* rl = dw_itr->get(); Drawable* dw= rl->_drawable; - primStats.numOpaque++; // number of geosets - if (rl->_matrix.get()) primStats.nummat++; // number of matrices + primStats->addOpaque(); // number of geosets + if (rl->_matrix.get()) primStats->addMatrix(); // number of matrices if (dw) { // then tot up the types 1-14 - dw->getStats(primStats); // use sub-class to find the stats for each drawable + dw->getStats(*primStats); // use sub-class to find the stats for each drawable } } + somestats=true; } + return somestats; +} + +void RenderBin::getPrims(osg::Statistics* primStats) +{ + static int ndepth; + ndepth++; + for(RenderBinList::iterator itr = _bins.begin(); + itr!=_bins.end(); + ++itr) + { + primStats->addBins(1); + itr->second->getPrims(primStats); + } + getStats(primStats); + ndepth--; + +} + +bool RenderBin::getPrims(osg::Statistics* primStats, const int nbin) +{ // collect stats for array of bins, maximum nbin + // (which will be modified on next call if array of primStats is too small); + // return 1 for OK; + static int ndepth; + bool ok=false; + ndepth++; + int nb=primStats[0].getBins(); + if (nbsecond->getPrims(primStats, nbin)) ok = true; + } + ok=true; + ndepth--; + return ok; } diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index dcaea5654..01e1bc440 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -140,8 +140,8 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous) } // Statistics features -void RenderStage::getStats(Statistics& primStats) +bool RenderStage::getStats(Statistics* primStats) { - if (_renderStageLighting.valid()) primStats.nlights+=_renderStageLighting->_lightList.size(); - RenderBin::getStats(primStats); + if (_renderStageLighting.valid()) primStats->addLight(_renderStageLighting->_lightList.size()); + return RenderBin::getStats(primStats); }