Katana Plug-in APIs 0.1

OpenGLTiming.h

00001 // Copyright (c) 2017 The Foundry Visionmongers Ltd. All Rights Reserved.
00002 
00003 #ifndef INCLUDED_UTIL_OPENGLTIMING_H
00004 #define INCLUDED_UTIL_OPENGLTIMING_H
00005 
00006 #ifdef USEGLTIMING
00007 
00008 #include "GL/glew.h"
00009 
00010 #include <string>
00011 #include <cstdio>
00012 #include <cstdlib>
00013 #include <cstring>
00014 
00015 // requires trailing semi-colon
00016 #define GLTIMING_FRAMESCOPE() \
00017     static int _gpuTimingFrameCount = 0; printf("GL GPU timing: frame %i\n", _gpuTimingFrameCount++)
00018 #define GLTIMING_STATICVAR() \
00019     static UTIL::OpenGL::GPUTimingStats _gpuTimingStats
00020 #define GLTIMING_SCOPED(_autovar,_layerName) \
00021     UTIL::OpenGL::GPUTiming _autovar(&_gpuTimingStats,_layerName)
00022 
00023 namespace UTIL
00024 {
00025     namespace OpenGL
00026     {
00027         struct GPUTimingStats
00028         {
00029             GPUTimingStats()
00030             {
00031                 _queries[0]      = _queries[1] = 0;
00032                 _writeQueryIndex = 0;
00033                 _lastFrameTimeMS = 0.0f;
00034                 _minFrameTimeMS  = 0.0f;
00035                 _maxFrameTimeMS  = 0.0f;
00036                 _avgFrameTimeMS  = 0.0f;
00037                 _numFrameTimes =  0;
00038 
00039                 glGenQueries(2, _queries);
00040                 glBeginQuery(GL_TIME_ELAPSED, _queries[_writeQueryIndex]);
00041                 glEndQuery(GL_TIME_ELAPSED);
00042                 ++_writeQueryIndex;
00043             }
00044 
00045             GLuint _queries[2];
00046             int    _writeQueryIndex;
00047             float  _lastFrameTimeMS;
00048             float  _minFrameTimeMS;
00049             float  _maxFrameTimeMS;
00050             float  _avgFrameTimeMS;
00051             int    _numFrameTimes;
00052         };
00053 
00054         class GPUTiming
00055         {
00056         public:
00057             explicit GPUTiming(GPUTimingStats *context, const std::string &layerName)
00058                 :
00059                 _layerName(layerName)
00060             {
00061                 if (!GLEW_ARB_timer_query)
00062                 {
00063                     return;
00064                 }
00065                 _context = context;
00066                 glBeginQuery(GL_TIME_ELAPSED, _context->_queries[_context->_writeQueryIndex]);
00067             }
00068 
00069             ~GPUTiming()
00070             {
00071                 if (!GLEW_ARB_timer_query)
00072                 {
00073                     return;
00074                 }
00075                 glEndQuery(GL_TIME_ELAPSED);
00076                 // wait
00077                 GLint available = 0;
00078                 const int readQueryIndex = (_context->_writeQueryIndex + 1) % 2;
00079                 while (!available) {
00080                     glGetQueryObjectiv(_context->_queries[readQueryIndex], GL_QUERY_RESULT_AVAILABLE, &available);
00081                 }
00082 
00083                 GLuint64 timeElapsedNS = 0;
00084                 glGetQueryObjectui64v(_context->_queries[readQueryIndex], GL_QUERY_RESULT, &timeElapsedNS);
00085 
00086                 _context->_lastFrameTimeMS = timeElapsedNS / 1024.f / 1024.f;
00087                 if (_context->_lastFrameTimeMS < _context->_minFrameTimeMS) {
00088                     _context->_minFrameTimeMS = _context->_lastFrameTimeMS;
00089                 }
00090                 if (_context->_lastFrameTimeMS > _context->_maxFrameTimeMS) {
00091                     _context->_maxFrameTimeMS = _context->_lastFrameTimeMS;
00092                 }
00093                 _context->_avgFrameTimeMS = (_context->_lastFrameTimeMS + _context->_numFrameTimes * _context->_avgFrameTimeMS) / (_context->_numFrameTimes + 1);
00094                 _context->_writeQueryIndex = readQueryIndex;
00095                 ++_context->_numFrameTimes;
00096                 printf("%s: Last %.2fms: Min %.2fms: Max %.2fms: Avg %.2fms\n",
00097                     _layerName.c_str(),
00098                     _context->_lastFrameTimeMS,
00099                     _context->_minFrameTimeMS,
00100                     _context->_maxFrameTimeMS,
00101                     _context->_avgFrameTimeMS);
00102                 do_csv_export();
00103             }
00104 
00105         private:
00106             void do_csv_export()
00107             {
00108                 const char *csvPath = getenv("GL_TIMING_CSV");
00109                 if (0 == csvPath) {
00110                     return;
00111                 }
00112                 const char *csvLayerFilter = getenv("GL_TIMING_CSV_FILTER");
00113                 if (0 != csvLayerFilter) {
00114                     // only accept layers that are an exact match
00115                     if (0 != strcmp(csvLayerFilter, _layerName.c_str())) {
00116                         return;
00117                     }
00118                 }
00119                 FILE *csv = fopen(csvPath, "a");
00120                 if (0 == csv) {
00121                     return;
00122                 }
00123                 fprintf(csv, "%s,%i,%f,%f,%f,%f\n",
00124                     _layerName.c_str(),
00125                     _context->_numFrameTimes,
00126                     _context->_avgFrameTimeMS,
00127                     _context->_lastFrameTimeMS,
00128                     _context->_minFrameTimeMS,
00129                     _context->_maxFrameTimeMS);
00130                 fclose(csv);
00131             }
00132 
00133         private:
00134             GPUTimingStats *_context;
00135             std::string     _layerName;
00136         };
00137 
00138     }  // namespace OpenGL
00139 }  // namespace UTIL
00140 
00141 #else  // USEGLTRACEMARKERS
00142 
00143 // requires trailing semi-colon, boils away both arguments
00144 #define GLTIMING_FRAMESCOPE() ((void)0)
00145 #define GLTIMING_STATICVAR() ((void)0)
00146 #define GLTIMING_SCOPED(_autovar,_msg) ((void)0)
00147 
00148 #endif  // USEGLTRACEMARKERS
00149 
00150 #endif  // INCLUDED_UTIL_OPENGLTIMING_H
 All Classes Functions Variables Typedefs Enumerations Enumerator