Created
August 23, 2021 15:20
-
-
Save rbnelr/d9ac1831b9e5a7fddfa864d70c2f2416 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if RENDERER_PROFILING | |
template <int N=4> | |
struct TimerZone { | |
int next = 0; // next timer to be used for measurement | |
int count = 0; // number of timers 'buffered', ie measurement was started by result not read yet | |
GLuint queries[N]; | |
TimerZone () { | |
glGenQueries(N, queries); | |
// could check the timer res here, but not sure what to do if it ever overflowed, just ignore since it's only for profiling anyway | |
//GLint bits; | |
//glGetQueryiv(GL_TIME_ELAPSED, GL_QUERY_COUNTER_BITS, &bits); | |
} | |
~TimerZone () { | |
glDeleteQueries(N, queries); | |
} | |
// always call end() after start() and never call read_seconds inbetween | |
void start () { | |
glBeginQuery(GL_TIME_ELAPSED, queries[next]); | |
} | |
void end () { | |
glEndQuery(GL_TIME_ELAPSED); | |
next = (next + 1) % N; | |
count++; | |
} | |
// try to read oldest timing | |
// returns false if it is still not ready to be read | |
// returns true if result was ready, result in out_seconds | |
// in case that a result takes so long to be readable (or you don't read them) | |
// timers will start to be reused, thus overwriting results | |
// in the case that this happend count will become larger than N and this function will return 'fake' 0 results | |
bool read_seconds (float* out_seconds) { | |
if (count == 0) return false; | |
if (count > N) { | |
// we overflowed our buffer, so this sample is overwritten, return 0 dummy value | |
count--; // pop timing | |
*out_seconds = 0; | |
return true; | |
} | |
int idx = (next + N - count) % N; | |
ZoneScoped; | |
GLint avail; | |
glGetQueryObjectiv(queries[idx], GL_QUERY_RESULT_AVAILABLE, &avail); | |
if (avail == 0) return false; | |
count--; // pop timing | |
uint64_t elapsed_ns = 99; | |
glGetQueryObjectui64v(queries[idx], GL_QUERY_RESULT, &elapsed_ns); | |
*out_seconds = (float)elapsed_ns * (1.0f / NSEC); | |
return true; | |
} | |
}; | |
struct TimerZoneScoped { | |
TimerZone<>& zone; | |
TimerZoneScoped (TimerZone<>& zone): zone{zone} { | |
zone.start(); | |
} | |
~TimerZoneScoped () { | |
zone.end(); | |
} | |
}; | |
#define OGL_TIMER(name) TimerZone<> name | |
#define OGL_TIMER_ZONE(zone) TimerZoneScoped __scoped_glzone_##__COUNTER__(zone) | |
#else | |
#define OGL_TIMER(name) | |
#define OGL_TIMER_ZONE(zone) | |
#endif | |
// somewhere start of frame | |
TimerZone<> timer_rt; | |
float seconds; | |
while (timer_rt.read_seconds(&seconds)) | |
histo_rt.push_timing(seconds); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment