|
Katana Plug-in APIs 0.1
|
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
1.7.3