changed: auto add updateData callback to stages so that stagedata can be updated...
[opensg.git] / Source / WindowSystem / GLUT / testOcclusionCulling.cpp
blobddaff5fb2e984163ed7b29cca4a03d9747d75673
2 #include "OSGGLUT.h"
3 #include "OSGConfig.h"
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,
43 NULL };
45 #endif
47 OSG::SimpleSceneManagerRefPtr mgr;
48 OSG::RenderActionRefPtr tact = NULL;
49 OSG::RenderActionRefPtr debugact = NULL;
51 // create the scene
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;
61 bool show = true;
62 bool debug = false;
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
72 class NVDataProvider
74 public:
75 NVDataProvider()
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;
96 return true;
97 } else {
98 return false;
102 virtual bool add(const char *counterName)
104 GLuint counterIndex;
105 if (NVPMGetCounterIndex(const_cast<char *>(counterName), &counterIndex) == NVPM_OK) {
106 return add(counterIndex);
107 } else {
108 return false;
112 virtual bool removeAllCounters()
114 NVPMRemoveAllCounters();
116 while (m_counterIndexArrayCount) {
117 m_counterIndexArray[--m_counterIndexArrayCount] = 0;
120 return true;
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;
134 counterIndex++)
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;
146 return true;
149 virtual float value(const GLuint counterIndex) const
151 GLuint entryIndex;
152 GLfloat runningTotal = 0.0f;
153 for (entryIndex = 0; entryIndex < bufferEntryCount; entryIndex++) {
154 runningTotal +=
155 m_counterValues[counterIndex][entryIndex] / float(bufferEntryCount);
157 return runningTotal;
160 protected:
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;
169 } g_nvDataProvider;
171 NVDataProvider *nvDataProvider = &g_nvDataProvider;
173 bool runExperiment = false;
175 #endif
177 // redraw the window
178 void display(void)
180 if(glutGetWindow() == mainwinid)
182 #ifdef OSG_WITH_NVPERFSDK
183 if(nvDataProvider->nCounters())
185 nvDataProvider->sample();
187 OSG::Char8 str[40];
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]));
199 e->set(str);
204 if(runExperiment)
206 int nCount;
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
218 NULL };
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++)
231 NVPMBeginPass(i);
232 mgr->redraw();
233 NVPMEndPass(i);
235 NVPMEndExperiment();
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;
259 #endif
260 mgr->redraw();
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
270 void redisplay(void)
272 glutSetWindow(mainwinid);
273 glutPostRedisplay();
274 if(debugwinid > 0)
276 glutSetWindow(debugwinid);
277 glutPostRedisplay();
281 void idle(void)
283 redisplay();
286 // react to size changes
287 void reshape(int w, int h)
289 if(glutGetWindow() == mainwinid)
291 mgr->resize(w,h);
292 glutPostRedisplay();
294 else if(glutGetWindow() == debugwinid)
296 debugwin->resize(w,h);
297 glutPostRedisplay();
301 // react to mouse button presses
302 void mouse(int button, int state, int x, int y)
304 if (state)
305 mgr->mouseButtonRelease(button, x, y);
306 else
307 mgr->mouseButtonPress(button, x, y);
309 redisplay();
312 // react to mouse motions with pressed buttons
313 void motion(int x, int y)
315 mgr->mouseMove(x, y);
317 redisplay();
320 void initElements(void)
322 if(collector != NULL)
324 collector->clearElems();
327 // add optional elements
328 // collector->getElem(Drawable::statNTriangles);
332 // react to keys
333 void keyboard(unsigned char k, int, int)
335 switch(k)
337 case 27:
339 #ifdef OSG_WITH_NVPERFSDK
340 NVPMShutdown();
341 #endif
342 mgr = NULL;
344 tact = NULL;
345 debugact = NULL;
347 scene = NULL;
348 mainwin = NULL;
349 debugwin = NULL;
350 statfg = NULL;
352 OSG::osgExit();
353 exit(0);
356 #ifdef OSG_OLD_RENDER_ACTION
357 case 'v':
359 mgr->getAction()->setVolumeDrawing(
360 !mgr->getAction()->getVolumeDrawing());
361 std::cerr << "Volume Drawing: "
362 << (mgr->getAction()->getVolumeDrawing()?"on":"off")
363 << std::endl;
366 case 'z':
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")
375 << std::endl;
378 break;
379 #endif
381 case 'r':
383 initElements();
384 bool buseTrav = mgr->getUseTraversalAction();
385 buseTrav = !buseTrav;
386 mgr->setUseTraversalAction(buseTrav);
388 break;
390 #ifdef OSG_OLD_RENDER_ACTION
391 case 'n':
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());
395 break;
396 #endif
398 case 'k':
399 tact->setKeyGen(0);
400 break;
402 case 's':
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);
413 break;
415 case 'g':
416 bGLFinish = !bGLFinish;
417 tact->setUseGLFinish(bGLFinish);
418 #ifdef OSG_OLD_RENDER_ACTION
419 act->setUseGLFinish(bGLFinish);
420 #endif
421 break;
424 case 'C':
426 OSG::Real32 cov = tact->getOcclusionCullingCoveredThreshold();
427 cov+=0.1f;
428 tact->setOcclusionCullingCoveredThreshold(cov);
429 std::cout << "Covered Threshold now: " << cov << std::endl;
431 break;
433 case 'c':
435 OSG::Real32 cov1 = tact->getOcclusionCullingCoveredThreshold();
436 cov1-=0.1f;
437 tact->setOcclusionCullingCoveredThreshold(cov1);
438 std::cout << "Covered Threshold now: " << cov1 << std::endl;
440 break;
442 case 'M':
444 OSG::UInt32 minFSize = tact->getOcclusionCullingMinimumFeatureSize();
445 minFSize+=1;
446 tact->setOcclusionCullingMinimumFeatureSize(minFSize);
447 std::cout << "Minimum Feature Size now: " << minFSize << std::endl;
449 break;
451 case 'm':
453 OSG::UInt32 small1 = tact->getOcclusionCullingMinimumFeatureSize();
454 small1-=1;
455 tact->setOcclusionCullingMinimumFeatureSize(small1);
456 std::cout << "Minimum Feature Size now: " << small1 << std::endl;
458 break;
460 case 'I':
462 OSG::UInt32 visT = tact->getOcclusionCullingVisibilityThreshold();
463 visT+=1;
464 tact->setOcclusionCullingVisibilityThreshold(visT);
465 std::cout << "Visibility Threshold now: " << visT << std::endl;
467 break;
469 case 'i':
471 OSG::UInt32 visTa = tact->getOcclusionCullingVisibilityThreshold();
472 visTa-=1;
473 tact->setOcclusionCullingVisibilityThreshold(visTa);
474 std::cout << "Visibility Threshold now: " << visTa << std::endl;
476 break;
478 case 'l':
480 OSG::UInt32 numLev = tact->getScreenLODNumLevels();
481 numLev-=1;
482 tact->setScreenLODNumLevels(numLev);
483 std::cout << "LOD's in use now: " << numLev << std::endl;
485 break;
487 case 'L':
489 OSG::UInt32 numLeva = tact->getScreenLODNumLevels();
490 numLeva+=1;
491 tact->setScreenLODNumLevels(numLeva);
492 std::cout << "LOD's in use now: " << numLeva << std::endl;
494 break;
496 case 'B':
498 OSG::UInt32 bfsz = tact->getOcclusionCullingQueryBufferSize();
499 bfsz+=200;
500 tact->setOcclusionCullingQueryBufferSize(bfsz);
501 std::cout << "Query Buffer Size now: " << bfsz << std::endl;
503 break;
505 case 'b':
507 OSG::UInt32 bfsza = tact->getOcclusionCullingQueryBufferSize();
508 bfsza-=200;
509 tact->setOcclusionCullingQueryBufferSize(bfsza);
510 std::cout << "Query Buffer Size now: " << bfsza << std::endl;
512 break;
514 case 't':
516 OSG::UInt32 tcount = tact->getOcclusionCullingMinimumTriangleCount();
517 tcount-=50;
518 tact->setOcclusionCullingMinimumTriangleCount(tcount);
519 std::cout << "Minimum Triangle Count now: " << tcount << std::endl;
521 break;
523 case 'T':
525 OSG::UInt32 tcounta = tact->getOcclusionCullingMinimumTriangleCount();
526 tcounta+=50;
527 tact->setOcclusionCullingMinimumTriangleCount(tcounta);
528 std::cout << "Minimum Triangle Count now: " << tcounta << std::endl;
530 break;
532 case 'H':
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;
541 break;
543 case 'h':
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;
552 break;
554 case 'P':
556 OSG::Real32 cover = tact->getScreenLODCoverageThreshold();
557 cover+=0.001f;
558 tact->setScreenLODCoverageThreshold(cover);
559 std::cout << "ScreenLOD Coverage Threshold now: " << cover << std::endl;
561 break;
563 case 'p':
565 OSG::Real32 covera = tact->getScreenLODCoverageThreshold();
566 covera-=0.001f;
567 tact->setScreenLODCoverageThreshold(covera);
568 std::cout << "ScreenLOD Coverage Threshold now: " << covera << std::endl;
570 break;
572 case 'D':
574 OSG::Real32 user_dega = tact->getScreenLODDegradationFactor();
575 user_dega+=0.01f;
576 tact->setScreenLODDegradationFactor(user_dega);
577 std::cout << "ScreenLOD User Degradation Factor now: " << user_dega << std::endl;
579 break;
581 case 'd':
583 OSG::Real32 user_deg = tact->getScreenLODDegradationFactor();
584 user_deg-=0.01f;
585 tact->setScreenLODDegradationFactor(user_deg);
586 std::cout << "ScreenLOD User Degradation Factor now: " << user_deg << std::endl;
588 break;
590 case 'N':
592 OSG::Real32 coverb = tact->getScreenLODCoverageThreshold();
593 coverb=0.0;
594 tact->setScreenLODCoverageThreshold(coverb);
595 std::cout << "ScreenLOD Coverage Threshold now: " << coverb << std::endl;
597 break;
599 case 'o':
601 tact->setOcclusionCulling(false);
602 std::cout << "OCC Off" << std::endl;
604 break;
606 case 'O':
608 tact->setOcclusionCulling(true);
609 std::cout << "OCC On" << std::endl;
611 break;
613 case 'f':
615 std::cout << "Freeze Occlusion result" << std::endl;
617 //initElements();
618 mgr->setUseTraversalAction(false);
620 // Render stuff that is visible and tested
621 mgr->getWindow()->getPort(0)->setTravMask(0x5);
623 break;
625 case 'F':
627 std::cout << "Unfreeze Occlusion result" << std::endl;
629 //initElements();
630 mgr->setUseTraversalAction(true);
632 mgr->getWindow()->getPort(0)->setTravMask(0xffffffff);
634 break;
636 case 'W':
638 std::string sss = "out.osb";
639 OSG::SceneFileHandler::the()->write(scene, sss.c_str());
641 break;
643 #ifdef OSG_WITH_NVPERFSDK
644 case 'e':
645 runExperiment = true;
646 break;
647 #endif
650 redisplay();
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"))
668 show = false;
669 argv++;
670 argc--;
673 if(argc > 1 && !strcmp(argv[1],"-d"))
675 debug = true;
676 argv++;
677 argc--;
681 if(argc > 1)
683 scene = OSG::Node::create();
684 OSG::GroupUnrecPtr g = OSG::Group::create();
686 scene->setCore(g);
688 for(OSG::UInt16 i = 1; i < argc; ++i)
689 scene->addChild(OSG::SceneFileHandler::the()->read(argv[i]));
691 else
693 scene = OSG::makeTorus(.5, 3, 16, 16);
696 // GLUT init
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);
706 glutIdleFunc(idle);
707 glutMouseFunc(mouse);
708 glutMotionFunc(motion);
709 glutKeyboardFunc(keyboard);
711 OSG::GLUTWindowUnrecPtr mainwin=OSG::GLUTWindow::create();
712 mainwin->setGlutId(mainwinid);
713 mainwin->init();
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
726 mgr->showAll();
728 mgr->setUseTraversalAction(true);
730 tact = OSG::RenderAction::create();
731 #ifdef OSG_OLD_RENDER_ACTION
732 act = OSG::RenderAction::create();
733 #endif
734 debugact = OSG::RenderAction::create();
735 tact->setOcclusionCulling(true);
738 // Open the debug window
739 if(debug)
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);
753 debugwin->init();
755 OSG::ViewportUnrecPtr vp = mainwin->getPort(0);
757 OSG::ViewportUnrecPtr newvp = OSG::Viewport::create();
758 newvp->setLeft(0);
759 newvp->setRight(0.5);
760 newvp->setBottom(0);
761 newvp->setTop(1);
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();
769 newvp->setLeft(0.5);
770 newvp->setRight(1);
771 newvp->setBottom(0);
772 newvp->setTop(1);
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();
787 statfg->setSize(25);
788 statfg->setColor(OSG::Color4f(0,1,0,0.7f));
790 statfg->addElement(OSG::RenderAction::statDrawTime,
791 "Draw FPS: %r.3f");
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,
800 "Culled Nodes: %d");
802 statfg->addElement(OSG::OcclusionCullingTreeBuilder::statNOccNodes,
803 "Nodes in DrawTree: %d");
804 statfg->addElement(OSG::OcclusionCullingTreeBuilder::statNOccTests,
805 "Occ Tests: %d");
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);
818 #endif
820 mgr->setAction(tact);
821 #ifdef OSG_OLD_RENDER_ACTION
822 mgr->setAction( act);
823 #endif
825 //tact->setOcclusionCullingMinimumFeatureSize(15);
826 //tact->setOcclusionCullingVisibilityThreshold(15);
827 //tact->setScreenLODCoverageThreshold(0.005);
829 if(show)
831 mainwin->getPort(0)->addForeground(statfg);
834 #ifdef OSG_WITH_NVPERFSDK
835 NVPMRESULT status;
837 status = NVPMInit();
838 if (status != NVPM_OK) {
839 FFATAL(("NVPerfSDK failed to initialize - no GPU data will be available"));
841 else
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);
856 #endif
858 // GLUT main loop
859 glutMainLoop();
861 return 0;