4 #include "OSGConfigured.h"
5 #include "OSGSimpleGeometry.h"
6 #include "OSGGLUTWindow.h"
7 #include "OSGSimpleSceneManager.h"
8 #include "OSGSceneFileHandler.h"
10 #include "OSGDrawable.h"
11 #include "OSGSimpleStatisticsForeground.h"
12 #include "OSGStatElemTypes.h"
13 #include "OSGStatCollector.h"
15 #include <boost/bind.hpp>
17 #include "OSGTextureBaseChunk.h"
18 #include "OSGMaterialChunk.h"
19 #include "OSGSimpleSHLChunk.h"
21 #include "OSGStatStringElem.h"
22 #include "OSGSimplePool.h"
23 #include "OSGRenderTreeNode.h"
24 #include "OSGOcclusionCullingTreeBuilder.h"
26 #ifdef OSG_WITH_NVPERFSDK
27 #include <NVPerfSDK.h>
30 OSG::StatElemDesc
<OSG::StatStringElem
> GPUIdleStat("GPUIdle","GPUIdle",
31 OSG::StatElemDescBase::RESET_NEVER
);
32 OSG::StatElemDesc
<OSG::StatStringElem
> PSBusyStat("PSBusyStat","PSBusyStat",
33 OSG::StatElemDescBase::RESET_NEVER
);
34 OSG::StatElemDesc
<OSG::StatStringElem
> VSBusyStat("VSBusyStat","VSBusyStat",
35 OSG::StatElemDescBase::RESET_NEVER
);
36 OSG::StatElemDesc
<OSG::StatStringElem
> TextureWaitStat("TextureWait","TextureWait",
37 OSG::StatElemDescBase::RESET_NEVER
);
38 OSG::StatElemDesc
<OSG::StatStringElem
> OGLFPSStat("OGL FPS","OGL FPS",
39 OSG::StatElemDescBase::RESET_NEVER
);
41 OSG::StatElemDesc
<OSG::StatStringElem
> *nvStatElems
[] =
42 { &GPUIdleStat
, &PSBusyStat
, &VSBusyStat
, &TextureWaitStat
, &OGLFPSStat
,
47 OSG::SimpleSceneManagerRefPtr mgr
;
48 OSG::RenderActionRefPtr tact
= NULL
;
49 OSG::RenderActionRefPtr debugact
= NULL
;
52 OSG::NodeRecPtr scene
;
54 OSG::GLUTWindowRecPtr mainwin
;
55 OSG::GLUTWindowRecPtr debugwin
;
56 int mainwinid
= -1, debugwinid
= -1;
58 OSG::SimpleStatisticsForegroundRecPtr statfg
;
59 OSG::StatCollector
*collector
;
63 bool bGLFinish
= false;
67 #ifdef OSG_WITH_NVPERFSDK
68 const GLuint counterEntryCount
= 10;
69 const GLuint bufferEntryCount
= 100;
71 // A simple class to manage counters, sampling, and display of the information
77 // We're averaging these, so we'll need to initialize to zero
78 for (GLuint i
= 0; i
< counterEntryCount
; i
++) {
79 for (GLuint j
= 0; j
< bufferEntryCount
; j
++) {
80 m_counterValues
[i
][j
] = 0.0f
;
83 m_counterIndexArrayCount
= 0;
84 m_counterValuesRRIndex
= 0;
87 virtual size_t nCounters() const
89 return m_counterIndexArrayCount
;
92 virtual bool add(GLuint counterIndex
)
94 if (NVPMAddCounter(counterIndex
) == NVPM_OK
) {
95 m_counterIndexArray
[m_counterIndexArrayCount
++] = counterIndex
;
102 virtual bool add(const char *counterName
)
105 if (NVPMGetCounterIndex(const_cast<char *>(counterName
), &counterIndex
) == NVPM_OK
) {
106 return add(counterIndex
);
112 virtual bool removeAllCounters()
114 NVPMRemoveAllCounters();
116 while (m_counterIndexArrayCount
) {
117 m_counterIndexArray
[--m_counterIndexArrayCount
] = 0;
123 virtual bool sample()
125 GLuint counterIndex
, unused
;
126 UINT64 events
, cycles
;
128 // Sample the GPU counters
129 NVPMSample(NULL
, &unused
);
131 // Retrieve the current sample values
132 for (counterIndex
= 0;
133 counterIndex
< m_counterIndexArrayCount
;
136 NVPMGetCounterValue(m_counterIndexArray
[counterIndex
], 0, &events
, &cycles
);
138 m_counterValues
[counterIndex
][m_counterValuesRRIndex
] =
139 100.0f
* float(events
) / float(cycles
);
141 m_counterValuesRRIndex
++;
142 if (m_counterValuesRRIndex
>= bufferEntryCount
) {
143 m_counterValuesRRIndex
= 0;
149 virtual float value(const GLuint counterIndex
) const
152 GLfloat runningTotal
= 0.0f
;
153 for (entryIndex
= 0; entryIndex
< bufferEntryCount
; entryIndex
++) {
155 m_counterValues
[counterIndex
][entryIndex
] / float(bufferEntryCount
);
161 GLuint m_counterIndexArray
[counterEntryCount
];
162 GLuint m_counterIndexArrayCount
;
164 // Maintain a round-robin style buffer and display the average of the
165 // the last bufferEntryCount samples.
166 GLfloat m_counterValues
[counterEntryCount
][bufferEntryCount
];
167 GLuint m_counterValuesRRIndex
;
171 NVDataProvider
*nvDataProvider
= &g_nvDataProvider
;
173 bool runExperiment
= false;
180 if(glutGetWindow() == mainwinid
)
182 #ifdef OSG_WITH_NVPERFSDK
183 if(nvDataProvider
->nCounters())
185 nvDataProvider
->sample();
189 for(int i
= 0; nvStatElems
[i
] != NULL
; ++i
)
191 if(collector
!= NULL
)
193 sprintf(str
, "%s: %f", nvStatElems
[i
]->getDescription().c_str(),
194 nvDataProvider
->value(i
));
196 OSG::StatStringElem
*e
= dynamic_cast<OSG::StatStringElem
*>(
197 collector
->getElem(*nvStatElems
[i
]));
208 const char *expCounters
[] = {
209 "2D Bottleneck", "2D SOL",
210 "IDX Bottleneck", "IDX SOL",
211 "GEOM Bottleneck", "GEOM SOL",
212 "ZCULL Bottleneck", "ZCULL SOL",
213 "TEX Bottleneck", "TEX SOL",
214 "ROP Bottleneck", "ROP SOL",
215 "SHD Bottleneck", "SHD SOL",
216 "FB Bottleneck", "FB SOL",
217 "GPU Bottleneck", // Needs to be last
220 for(int i
= 0; expCounters
[i
] != NULL
; ++i
)
222 NVPMAddCounterByName(const_cast<char *>(expCounters
[i
]));
225 NVPMBeginExperiment(&nCount
);
227 FLOG(("NVPerfKitSDK: Running %d passes\n", nCount
));
229 for(int i
= 0; i
< nCount
; i
++)
237 UINT64 value
, cycles
;
239 for(int i
= 0; expCounters
[i
] != NULL
; ++i
)
241 NVPMGetCounterValueByName(const_cast<char *>(expCounters
[i
]), 0, &value
, &cycles
);
242 FLOG(("%s: %lld value, %lld cycles (%.4f%%)\n",
243 expCounters
[i
], value
, cycles
, value
* 100. / cycles
));
246 char buffer
[1000] = "";
248 NVPMGetGPUBottleneckName(value
, buffer
);
250 FLOG(("GPU Bottleneck: '%s'\n", buffer
));
252 for(int i
= 0; expCounters
[i
] != NULL
; ++i
)
254 //NVPMRemoveCounterByName(expCounters[i]);
257 runExperiment
= false;
262 else if(glutGetWindow() == debugwinid
)
264 // Use RenderAction to prevent new occlusion culling on debug output
265 debugwin
->render(debugact
);
269 // Redisplay both windows, if active
272 glutSetWindow(mainwinid
);
276 glutSetWindow(debugwinid
);
286 // react to size changes
287 void reshape(int w
, int h
)
289 if(glutGetWindow() == mainwinid
)
294 else if(glutGetWindow() == debugwinid
)
296 debugwin
->resize(w
,h
);
301 // react to mouse button presses
302 void mouse(int button
, int state
, int x
, int y
)
305 mgr
->mouseButtonRelease(button
, x
, y
);
307 mgr
->mouseButtonPress(button
, x
, y
);
312 // react to mouse motions with pressed buttons
313 void motion(int x
, int y
)
315 mgr
->mouseMove(x
, y
);
320 void initElements(void)
322 if(collector
!= NULL
)
324 collector
->clearElems();
327 // add optional elements
328 // collector->getElem(Drawable::statNTriangles);
333 void keyboard(unsigned char k
, int, int)
339 #ifdef OSG_WITH_NVPERFSDK
356 #ifdef OSG_OLD_RENDER_ACTION
359 mgr
->getAction()->setVolumeDrawing(
360 !mgr
->getAction()->getVolumeDrawing());
361 std::cerr
<< "Volume Drawing: "
362 << (mgr
->getAction()->getVolumeDrawing()?"on":"off")
368 OSG::RenderAction
*ract
=
369 dynamic_cast<OSG::RenderAction
*>(mgr
->getAction());
371 ract
->setZWriteTrans(!ract
->getZWriteTrans());
373 std::cerr
<< "Switch TransZWrite to "
374 << (ract
->getZWriteTrans()?"on":"off")
384 bool buseTrav
= mgr
->getUseTraversalAction();
385 buseTrav
= !buseTrav
;
386 mgr
->setUseTraversalAction(buseTrav
);
390 #ifdef OSG_OLD_RENDER_ACTION
392 fprintf(stderr
, "1) set s sorting to %d\n", act
->getStateSorting());
393 act
->setStateSorting(!act
->getStateSorting());
394 fprintf(stderr
, "2) set s sorting to %d\n", act
->getStateSorting());
404 OSG::UInt32 uiSId
= OSG::SimpleSHLChunk ::getStaticClassId() & 0x000003FF;
405 OSG::UInt32 uiTId
= OSG::TextureBaseChunk::getStaticClassId() & 0x000003FF;
406 OSG::UInt32 uiMId
= OSG::MaterialChunk ::getStaticClassId() & 0x000003FF;
409 OSG::UInt32 uiKeyGen
= (uiSId
) | (uiTId
<< 10) | (uiMId
<< 20);
411 tact
->setKeyGen(uiKeyGen
);
416 bGLFinish
= !bGLFinish
;
417 tact
->setUseGLFinish(bGLFinish
);
418 #ifdef OSG_OLD_RENDER_ACTION
419 act
->setUseGLFinish(bGLFinish
);
426 OSG::Real32 cov
= tact
->getOcclusionCullingCoveredThreshold();
428 tact
->setOcclusionCullingCoveredThreshold(cov
);
429 std::cout
<< "Covered Threshold now: " << cov
<< std::endl
;
435 OSG::Real32 cov1
= tact
->getOcclusionCullingCoveredThreshold();
437 tact
->setOcclusionCullingCoveredThreshold(cov1
);
438 std::cout
<< "Covered Threshold now: " << cov1
<< std::endl
;
444 OSG::UInt32 minFSize
= tact
->getOcclusionCullingMinimumFeatureSize();
446 tact
->setOcclusionCullingMinimumFeatureSize(minFSize
);
447 std::cout
<< "Minimum Feature Size now: " << minFSize
<< std::endl
;
453 OSG::UInt32 small1
= tact
->getOcclusionCullingMinimumFeatureSize();
455 tact
->setOcclusionCullingMinimumFeatureSize(small1
);
456 std::cout
<< "Minimum Feature Size now: " << small1
<< std::endl
;
462 OSG::UInt32 visT
= tact
->getOcclusionCullingVisibilityThreshold();
464 tact
->setOcclusionCullingVisibilityThreshold(visT
);
465 std::cout
<< "Visibility Threshold now: " << visT
<< std::endl
;
471 OSG::UInt32 visTa
= tact
->getOcclusionCullingVisibilityThreshold();
473 tact
->setOcclusionCullingVisibilityThreshold(visTa
);
474 std::cout
<< "Visibility Threshold now: " << visTa
<< std::endl
;
480 OSG::UInt32 numLev
= tact
->getScreenLODNumLevels();
482 tact
->setScreenLODNumLevels(numLev
);
483 std::cout
<< "LOD's in use now: " << numLev
<< std::endl
;
489 OSG::UInt32 numLeva
= tact
->getScreenLODNumLevels();
491 tact
->setScreenLODNumLevels(numLeva
);
492 std::cout
<< "LOD's in use now: " << numLeva
<< std::endl
;
498 OSG::UInt32 bfsz
= tact
->getOcclusionCullingQueryBufferSize();
500 tact
->setOcclusionCullingQueryBufferSize(bfsz
);
501 std::cout
<< "Query Buffer Size now: " << bfsz
<< std::endl
;
507 OSG::UInt32 bfsza
= tact
->getOcclusionCullingQueryBufferSize();
509 tact
->setOcclusionCullingQueryBufferSize(bfsza
);
510 std::cout
<< "Query Buffer Size now: " << bfsza
<< std::endl
;
516 OSG::UInt32 tcount
= tact
->getOcclusionCullingMinimumTriangleCount();
518 tact
->setOcclusionCullingMinimumTriangleCount(tcount
);
519 std::cout
<< "Minimum Triangle Count now: " << tcount
<< std::endl
;
525 OSG::UInt32 tcounta
= tact
->getOcclusionCullingMinimumTriangleCount();
527 tact
->setOcclusionCullingMinimumTriangleCount(tcounta
);
528 std::cout
<< "Minimum Triangle Count now: " << tcounta
<< std::endl
;
534 OSG::UInt32 mfsa
= 0;
535 OSG::Real32 sfta
= 0.0f
;
536 tact
->setOcclusionCullingMinimumFeatureSize(mfsa
);
537 tact
->setOcclusionCullingVisibilityThreshold(mfsa
);
538 tact
->setScreenLODCoverageThreshold(sfta
);
539 std::cout
<< "High Resolution Mode" << std::endl
;
545 OSG::UInt32 mfs
= 1000;
546 OSG::Real32 sft
= 0.15f
;
547 tact
->setOcclusionCullingMinimumFeatureSize(mfs
);
548 tact
->setOcclusionCullingVisibilityThreshold(mfs
);
549 tact
->setScreenLODCoverageThreshold(sft
);
550 std::cout
<< "Low Resolution Mode" << std::endl
;
556 OSG::Real32 cover
= tact
->getScreenLODCoverageThreshold();
558 tact
->setScreenLODCoverageThreshold(cover
);
559 std::cout
<< "ScreenLOD Coverage Threshold now: " << cover
<< std::endl
;
565 OSG::Real32 covera
= tact
->getScreenLODCoverageThreshold();
567 tact
->setScreenLODCoverageThreshold(covera
);
568 std::cout
<< "ScreenLOD Coverage Threshold now: " << covera
<< std::endl
;
574 OSG::Real32 user_dega
= tact
->getScreenLODDegradationFactor();
576 tact
->setScreenLODDegradationFactor(user_dega
);
577 std::cout
<< "ScreenLOD User Degradation Factor now: " << user_dega
<< std::endl
;
583 OSG::Real32 user_deg
= tact
->getScreenLODDegradationFactor();
585 tact
->setScreenLODDegradationFactor(user_deg
);
586 std::cout
<< "ScreenLOD User Degradation Factor now: " << user_deg
<< std::endl
;
592 OSG::Real32 coverb
= tact
->getScreenLODCoverageThreshold();
594 tact
->setScreenLODCoverageThreshold(coverb
);
595 std::cout
<< "ScreenLOD Coverage Threshold now: " << coverb
<< std::endl
;
601 tact
->setOcclusionCulling(false);
602 std::cout
<< "OCC Off" << std::endl
;
608 tact
->setOcclusionCulling(true);
609 std::cout
<< "OCC On" << std::endl
;
615 std::cout
<< "Freeze Occlusion result" << std::endl
;
618 mgr
->setUseTraversalAction(false);
620 // Render stuff that is visible and tested
621 mgr
->getWindow()->getPort(0)->setTravMask(0x5);
627 std::cout
<< "Unfreeze Occlusion result" << std::endl
;
630 mgr
->setUseTraversalAction(true);
632 mgr
->getWindow()->getPort(0)->setTravMask(0xffffffff);
638 std::string sss
= "out.osb";
639 OSG::SceneFileHandler::the()->write(scene
, sss
.c_str());
643 #ifdef OSG_WITH_NVPERFSDK
645 runExperiment
= true;
653 OSG::Action::ResultE
initMask(OSG::Node
*n
)
655 // Make Geometries render in main window, but nowhere else.
656 if(n
->getCore()->getType().isDerivedFrom(OSG::Geometry::getClassType()))
657 n
->setTravMask(0x800000);
659 return OSG::Action::Continue
;
662 int main(int argc
, char **argv
)
664 OSG::osgInit(argc
,argv
);
666 if(argc
> 1 && !strcmp(argv
[1],"-s"))
673 if(argc
> 1 && !strcmp(argv
[1],"-d"))
683 scene
= OSG::Node::create();
684 OSG::GroupUnrecPtr g
= OSG::Group::create();
688 for(OSG::UInt16 i
= 1; i
< argc
; ++i
)
689 scene
->addChild(OSG::SceneFileHandler::the()->read(argv
[i
]));
693 scene
= OSG::makeTorus(.5, 3, 16, 16);
697 glutInit(&argc
, argv
);
699 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
701 glutInitWindowSize(1024, 768);
702 mainwinid
= glutCreateWindow("OpenSG");
704 glutReshapeFunc(reshape
);
705 glutDisplayFunc(display
);
707 glutMouseFunc(mouse
);
708 glutMotionFunc(motion
);
709 glutKeyboardFunc(keyboard
);
711 OSG::GLUTWindowUnrecPtr mainwin
=OSG::GLUTWindow::create();
712 mainwin
->setGlutId(mainwinid
);
715 // create the SimpleSceneManager helper
716 mgr
= OSG::SimpleSceneManager::create();
718 // create the window and initial camera/viewport
719 mgr
->setWindow(mainwin
);
720 // tell the manager what to manage
721 mgr
->setRoot (scene
);
723 OSG::commitChanges();
725 // show the whole scene
728 mgr
->setUseTraversalAction(true);
730 tact
= OSG::RenderAction::create();
731 #ifdef OSG_OLD_RENDER_ACTION
732 act
= OSG::RenderAction::create();
734 debugact
= OSG::RenderAction::create();
735 tact
->setOcclusionCulling(true);
738 // Open the debug window
741 OSG::traverse(scene
, initMask
);
743 glutInitWindowSize(800, 400);
744 debugwinid
= glutCreateWindow("OpenSG Occlusion Debugging");
746 glutReshapeFunc(reshape
);
747 glutDisplayFunc(display
);
748 glutIdleFunc(display
);
749 glutKeyboardFunc(keyboard
);
751 debugwin
=OSG::GLUTWindow::create();
752 debugwin
->setGlutId(debugwinid
);
755 OSG::ViewportUnrecPtr vp
= mainwin
->getPort(0);
757 OSG::ViewportUnrecPtr newvp
= OSG::Viewport::create();
759 newvp
->setRight(0.5);
762 newvp
->setRoot(vp
->getRoot());
763 newvp
->setCamera(vp
->getCamera());
764 newvp
->setBackground(vp
->getBackground());
765 newvp
->setTravMask(0x1);
766 debugwin
->addPort(newvp
);
768 newvp
= OSG::Viewport::create();
773 newvp
->setRoot(vp
->getRoot());
774 newvp
->setCamera(vp
->getCamera());
775 newvp
->setBackground(vp
->getBackground());
776 newvp
->setTravMask(0x2);
777 debugwin
->addPort(newvp
);
779 tact
->setOcclusionCullingDebug(true);
780 tact
->setOcclusionDebugMasks(0x1, 0x2, 0x4);
783 // add the statistics forground
785 statfg
= OSG::SimpleStatisticsForeground::create();
788 statfg
->setColor(OSG::Color4f(0,1,0,0.7f
));
790 statfg
->addElement(OSG::RenderAction::statDrawTime
,
792 statfg
->addElement(OSG::RenderAction::statNMatrices
,
793 "Matrix Changes: %d");
794 statfg
->addElement(OSG::RenderAction::statNStates
,
795 "State Changes: %d");
797 statfg
->addElement(OSG::RenderPartition::statCullTestedNodes
,
798 "Cull-tested Nodes: %d");
799 statfg
->addElement(OSG::RenderPartition::statCulledNodes
,
802 statfg
->addElement(OSG::OcclusionCullingTreeBuilder::statNOccNodes
,
803 "Nodes in DrawTree: %d");
804 statfg
->addElement(OSG::OcclusionCullingTreeBuilder::statNOccTests
,
806 statfg
->addElement(OSG::OcclusionCullingTreeBuilder::statNOccInvisible
,
807 "Invisible Nodes: %d");
808 statfg
->addElement(OSG::OcclusionCullingTreeBuilder::statNOccSuccessTestPer
,
809 "OCC Success rate: %per%%");
810 statfg
->addElement(OSG::OcclusionCullingTreeBuilder::statNOccTriangles
,
811 "Triangles culled: %d");
813 collector
= statfg
->getCollector();
815 tact
->setStatCollector(collector
);
816 #ifdef OSG_OLD_RENDER_ACTION
817 act
->setStatCollector(collector
);
820 mgr
->setAction(tact
);
821 #ifdef OSG_OLD_RENDER_ACTION
822 mgr
->setAction( act
);
825 //tact->setOcclusionCullingMinimumFeatureSize(15);
826 //tact->setOcclusionCullingVisibilityThreshold(15);
827 //tact->setScreenLODCoverageThreshold(0.005);
831 mainwin
->getPort(0)->addForeground(statfg
);
834 #ifdef OSG_WITH_NVPERFSDK
838 if (status
!= NVPM_OK
) {
839 FFATAL(("NVPerfSDK failed to initialize - no GPU data will be available"));
843 nvDataProvider
->add("gpu_idle");
844 nvDataProvider
->add("pixel_shader_busy");
845 nvDataProvider
->add("vertex_shader_busy");
846 nvDataProvider
->add("shader_waits_for_texture");
847 if (!nvDataProvider
->add("OGL FPS"))
848 FLOG(("nvDataProvider::add: 'OGL FPS' failed!\n"));
850 statfg
->addElement(GPUIdleStat
);
851 statfg
->addElement(PSBusyStat
);
852 statfg
->addElement(VSBusyStat
);
853 statfg
->addElement(TextureWaitStat
);
854 statfg
->addElement(OGLFPSStat
);