double GpuTimer::elapsed() { glQueryCounter(inflightPairs.back().endQuery, GL_TIMESTAMP); // Query just issued is not going to be available just yet. // We'll return the oldest available result. // On startup, there won't be any available. if (inflightPairs.size() == 1) return 0.; // Check if a previously issued query is available. Since startQuery // is issued before endQuery, we check endQuery only. QueryPair qp = inflightPairs.front(); GLuint queryAvailable = GL_FALSE; glGetQueryObjectuiv(qp.endQuery, GL_QUERY_RESULT_AVAILABLE, &queryAvailable); if (queryAvailable) { availablePairs.push(qp); inflightPairs.pop(); GLuint64 startTime, endTime; glGetQueryObjectui64v(qp.startQuery, GL_QUERY_RESULT, &startTime); glGetQueryObjectui64v(qp.endQuery, GL_QUERY_RESULT, &endTime); double duration = double(endTime-startTime) * 0.001 * 0.001; // Milliseconds. return duration; } return 0.; }
bool GPUTimer::updateResults() { if( !glExt::ARB_timer_query ) return false; if( _numQueries == 0 ) { _time = 0; return true; } // Make sure that last query is available GLint available; glGetQueryObjectiv( _queryPool[_numQueries * 2 - 1], GL_QUERY_RESULT_AVAILABLE, &available ); if( !available ) return false; // Accumulate time GLuint64 timeStart = 0, timeEnd = 0, timeAccum = 0; for( uint32 i = 0; i < _numQueries; ++i ) { glGetQueryObjectui64v( _queryPool[i * 2], GL_QUERY_RESULT, &timeStart ); glGetQueryObjectui64v( _queryPool[i * 2 + 1], GL_QUERY_RESULT, &timeEnd ); timeAccum += timeEnd - timeStart; } _time = (float)((double)timeAccum / 1000000.0); return true; }
int main(int /*argc*/, char ** /*argv*/) { BaseApp app; ProgramObject program; auto mainWindow = app.getMainWindow(); std::string prefix = app.getResourceDir() + "Shaders/Examples/e06_ModelLoader/"; PerspectiveCamera cam; OrbitManipulator manipulator(&cam); manipulator.setupCallbacks(app); NodeShared root; GLuint query[2]; app.addInitCallback([&]() { auto vs = compileShader(GL_VERTEX_SHADER, Loader::text(prefix + "phong.vert")); auto fs = compileShader(GL_FRAGMENT_SHADER, Loader::text(prefix + "phong.frag")); program = createProgram(vs, fs); root = Loader::scene(app.getResourceDir() + "Models/sponza/sponza.fbx"); glCreateQueries(GL_TIMESTAMP, 2, query); SDL_GL_SetSwapInterval(0); }); app.addResizeCallback([&](int w, int h) { glViewport(0, 0, w, h); cam.setAspect(float(w) / float(h)); }); app.addDrawCallback([&]() { glQueryCounter(query[0], GL_TIMESTAMP); glClearColor(0.2, 0.2, 0.2, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); //bunny program.use(); program.setMatrix4fv("p", value_ptr(cam.getProjection())); program.setMatrix4fv("v", value_ptr(cam.getView())); drawNode(program, root); glQueryCounter(query[1], GL_TIMESTAMP); GLuint64 time1, time2; glGetQueryObjectui64v(query[0], GL_QUERY_RESULT, &time1); glGetQueryObjectui64v(query[1], GL_QUERY_RESULT, &time2); std::string s = "fps: " + std::to_string(1e9 / (time2 - time1)) + " (" + std::to_string(ImGui::GetIO().Framerate) + ")"; label(s, 0, 0, 300, 100); }); return app.run(); }
GLuint64 OpenGLTimer::GetElapsedTime() { GLint stopTimerAvailable = 0; while (!stopTimerAvailable) { glGetQueryObjectiv(endQuery, GL_QUERY_RESULT_AVAILABLE, &stopTimerAvailable); } glGetQueryObjectui64v(startQuery, GL_QUERY_RESULT, &startTime); glGetQueryObjectui64v(endQuery, GL_QUERY_RESULT, &endTime); elapsedTime = (endTime - startTime) / 1000000.0; return elapsedTime; }
void GLTimerQuery::finalize() { mFinalized = true; GLuint64 timeStart; GLuint64 timeEnd; glGetQueryObjectui64v(mQueryStartObj, GL_QUERY_RESULT, &timeStart); glGetQueryObjectui64v(mQueryEndObj, GL_QUERY_RESULT, &timeEnd); mTimeDelta = (timeEnd - timeStart) / 1000000.0f; }
int stopGPUTimer(GPUtimer* timer, float* times, int maxTimes) { // NVG_NOTUSED(times); // NVG_NOTUSED(maxTimes); GLint available = 1; int n = 0; if (!timer->supported) return 0; glEndQuery(GL_TIME_ELAPSED); while (available && timer->ret <= timer->cur) { // check for results if there are any glGetQueryObjectiv(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT_AVAILABLE, &available); if (available) { GLuint64 timeElapsed = 0; glGetQueryObjectui64v(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT, &timeElapsed); timer->ret++; if (n < maxTimes) { times[n] = (float)((double)timeElapsed * 1e-9); n++; } } } return n; }
const Renderer::ProfileInfo& OpenGLRenderer::popDebugGroup() { #ifdef RW_GRAPHICS_STATS if (ogl_ext_KHR_debug) { glPopDebugGroup(); currentDebugDepth--; RW_ASSERT(currentDebugDepth >= 0); ProfileInfo& prof = profileInfo[currentDebugDepth]; glQueryCounter(debugQuery, GL_TIMESTAMP); GLuint64 current_time; glGetQueryObjectui64v(debugQuery, GL_QUERY_RESULT, ¤t_time); prof.duration = current_time - prof.timerStart; // Add counters to the parent group if (currentDebugDepth > 0) { ProfileInfo& p = profileInfo[currentDebugDepth - 1]; p.draws += prof.draws; p.buffers += prof.buffers; p.primitives += prof.primitives; p.textures += prof.textures; p.uploads += prof.uploads; } return prof; } #endif return profileInfo[0]; }
// call after swap buffers void wzPerfFrame() { if (!perfStarted) { return; // not started yet } ASSERT(queryActive == PERF_COUNT, "Missing wfPerfEnd() call"); PERF_STORE store; for (int i = 0; i < PERF_COUNT; i++) { glGetQueryObjectui64v(perfpos[i], GL_QUERY_RESULT, &store.counters[i]); } glErrors(); perfList.append(store); perfStarted = false; // Make a screenshot to document sample content time_t aclock; struct tm *t; time(&aclock); /* Get time in seconds */ t = localtime(&aclock); /* Convert time to struct */ ssprintf(screendump_filename, "screenshots/wz2100-perf-sample-%02d-%04d%02d%02d_%02d%02d%02d-%s.png", perfList.size() - 1, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, getLevelName()); screendump_required = true; GL_DEBUG("Performance sample complete"); }
double gl_query_time(GLuint q[][2]) { double measures[64]; GLint stopTimerAvailable = 0; while (!stopTimerAvailable) glGetQueryObjectiv(q[number_of_tests - 1][1], GL_QUERY_RESULT_AVAILABLE, &stopTimerAvailable); double best_time = 99999999999.9; for (int i = 0; i < number_of_tests; ++i) { GLuint64 start, stop; glGetQueryObjectui64v(q[i][0], GL_QUERY_RESULT, &start); glGetQueryObjectui64v(q[i][1], GL_QUERY_RESULT, &stop); measures[i] = (stop - start) / 1000.0; glDeleteQueries(2, q[i]); } return average_best(measures, number_of_tests); }
static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query, void *data, DWORD size, DWORD flags) { struct wined3d_timestamp_query *tq = query->extendedData; struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_context *context; GLuint available; GLuint64 timestamp; HRESULT res; TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags); if (!tq->context) query->state = QUERY_CREATED; if (query->state == QUERY_CREATED) { /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves. */ TRACE("Query wasn't yet started, returning S_OK.\n"); timestamp = 0; fill_query_data(data, size, ×tamp, sizeof(timestamp)); return S_OK; } if (tq->context->tid != GetCurrentThreadId()) { FIXME("%p Wrong thread, returning 1.\n", query); timestamp = 1; fill_query_data(data, size, ×tamp, sizeof(timestamp)); return S_OK; } context = context_acquire(query->device, tq->context->current_rt); GL_EXTCALL(glGetQueryObjectuiv(tq->id, GL_QUERY_RESULT_AVAILABLE, &available)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE)"); TRACE("available %#x.\n", available); if (available) { if (size) { GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT, ×tamp)); checkGLcall("glGetQueryObjectui64v(GL_QUERY_RESULT)"); TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); fill_query_data(data, size, ×tamp, sizeof(timestamp)); } res = S_OK; } else { res = S_FALSE; } context_release(context); return res; }
GLuint64 Query::get64(const GLenum pname) const { GLuint64 value = 0; glGetQueryObjectui64v(id(), pname, &value); return value; }
uint64_t kit::GLTimer::end() { glEndQuery(GL_TIME_ELAPSED); uint64_t timenano = 0; glGetQueryObjectui64v(m_glHandle, GL_QUERY_RESULT, &timenano); return timenano;// / 1,000,000.0; }
GLuint64 Query::getResult() { if (!resultRead) { glGetQueryObjectui64v(id, GL_QUERY_RESULT, &result); resultRead = true; } return result; }
void Profiler::endFrame() { if (m_frameEntries != m_lastEntries) { m_lastEntries = m_frameEntries; m_resetDelay = CONFIG_DELAY; } if (m_resetDelay) { m_resetDelay--; for (size_t i = 0; i < m_entries.size(); i++){ m_entries[i].numTimes = 0; m_entries[i].cpuTimes = 0; m_entries[i].gpuTimes = 0; } m_numFrames = 0; } if (m_numFrames > FRAME_DELAY){ for (size_t i = 0; i < m_frameEntries; i++){ Entry& entry = m_entries[i]; if (entry.splitter) continue; GLint available = 0; GLuint queryFrame = (m_numFrames + 1) % FRAME_DELAY; glGetQueryObjectiv(entry.queries[queryFrame + FRAME_DELAY], GL_QUERY_RESULT_AVAILABLE,&available); if (available) { GLuint64 beginTime; GLuint64 endTime; glGetQueryObjectui64v(entry.queries[queryFrame], GL_QUERY_RESULT,&beginTime); glGetQueryObjectui64v(entry.queries[queryFrame + FRAME_DELAY], GL_QUERY_RESULT,&endTime); // nanoseconds to microseconds GLuint64 gpuNano = endTime - beginTime; double gpu = double(gpuNano) / 1000.0; entry.gpuTimes += gpu; entry.cpuTimes += entry.deltas[queryFrame]; entry.numTimes ++; } } } m_numFrames++; }
double GPUClock::getElapsedTime() { if(!mStopped) return -1; GLuint64 result; glGetQueryObjectui64v(mQuery, GL_QUERY_RESULT, &result); return ((double)result) / 1000000000; }
// Collect Queries results void VSProfileLib::CollectQueryResults() { #if VSPL_PROFILE == VSPL_PROFILE_CPU_AND_GPU int siz; section *sec; int availableEnd = 0; GLuint64 timeStart=0, timeEnd = 0; unsigned long long int aux = 0; for (int l = 0; l < sTotalLevels; ++l) { siz = sLevels[l].sec.size(); for(int cur = 0; cur < siz; ++cur) { sec = &(sLevels[l].sec[cur]); if (sec->profileGL) { sec->totalQueryTime = 0; aux = 0; for (unsigned int j = 0; j < sec->queriesGL[sFrontBuffer].size(); ++j) { glGetQueryObjectui64v(sec->queriesGL[sFrontBuffer][j].queries[0], GL_QUERY_RESULT, &timeStart); glGetQueryObjectui64v(sec->queriesGL[sFrontBuffer][j].queries[1], GL_QUERY_RESULT, &timeEnd); aux += (timeEnd - timeStart); glDeleteQueries(2, sec->queriesGL[sFrontBuffer][j].queries); } sec->totalQueryTime += aux; sec->queriesGL[sFrontBuffer].clear(); } } } // SWAP QUERY BUFFERS if (sBackBuffer) { sBackBuffer = 0; sFrontBuffer = 1; } else { sBackBuffer = 1; sFrontBuffer = 0; } #endif }
template<> UnsignedLong AbstractQuery::result<UnsignedLong>() { UnsignedLong result; #ifndef MAGNUM_TARGET_GLES glGetQueryObjectui64v(_id, GL_QUERY_RESULT, &result); #elif !defined(CORRADE_TARGET_NACL) glGetQueryObjectui64vEXT(_id, GL_QUERY_RESULT_EXT, &result); #else CORRADE_ASSERT_UNREACHABLE(); #endif return result; }
uint64_t OGLSOStatisticsQuery::NumPrimitivesWritten() { GLuint available = 0; while (!available) { glGetQueryObjectuiv(primitive_written_query_, GL_QUERY_RESULT_AVAILABLE, &available); } GLuint64 ret; glGetQueryObjectui64v(primitive_written_query_, GL_QUERY_RESULT, &ret); return ret; }
uint64_t OGLSOStatisticsQuery::PrimitivesGenerated() { GLuint available = 0; while (!available) { glGetQueryObjectuiv(primitive_generated_query_, GL_QUERY_RESULT_AVAILABLE, &available); } GLuint64 ret; glGetQueryObjectui64v(primitive_generated_query_, GL_QUERY_RESULT, &ret); return ret; }
double OGLTimerQuery::TimeElapsed() { GLuint available = 0; while (!available) { glGetQueryObjectuiv(query_, GL_QUERY_RESULT_AVAILABLE, &available); } GLuint64 ret; glGetQueryObjectui64v(query_, GL_QUERY_RESULT, &ret); return static_cast<uint64_t>(ret) * 1e-9; }
template<> UnsignedLong AbstractQuery::result<UnsignedLong>() { CORRADE_ASSERT(!target, "AbstractQuery::result(): the query is currently running", {}); /** @todo Re-enable when extension loader is available for ES */ UnsignedLong result; #ifndef MAGNUM_TARGET_GLES glGetQueryObjectui64v(_id, GL_QUERY_RESULT, &result); #else CORRADE_INTERNAL_ASSERT(false); //glGetQueryObjectui64vEXT(_id, GL_QUERY_RESULT, &result); #endif return result; }
u32 GPU_Profile::read_diff_timers(u32 start_timer, u32 stop_timer) { #ifdef GLSL4_API if(!start_timer || !stop_timer) return -1; int stopTimerAvailable = 0; while (!stopTimerAvailable) glGetQueryObjectiv(stop_timer, GL_QUERY_RESULT_AVAILABLE, &stopTimerAvailable); u64 start, stop = 0; // Note: timers have a precision of the ns, so you need 64 bits value to avoid overflow! glGetQueryObjectui64v(start_timer, GL_QUERY_RESULT, &start); glGetQueryObjectui64v(stop_timer, GL_QUERY_RESULT, &stop); // delete timer glDeleteQueries(1, &start_timer); glDeleteQueries(1, &stop_timer); return (stop-start)/1000; #else return 0; #endif }
GLuint64 getResultSync() { if (thisQueryActive) return 0; GLuint64 result; GLint isReady = GL_FALSE; while (isReady == GL_FALSE) glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &isReady); glGetQueryObjectui64v(query, GL_QUERY_RESULT, &result); return result; }
void calcFPS(float &dt) { static float t0=0.0; static float t1=0.0; static char title[256]; static int frames=0; float t = (float)glfwGetTime(); dt = t - t0; t0 = t; t1 += dt; if(t1 > 0.25) { float fps = (float)frames / t1; GLuint64 timeStamp[7]; for(int i=0; i<7; ++i) glGetQueryObjectui64v(queryID[i], GL_QUERY_RESULT, &timeStamp[i]); double geom = (timeStamp[1] - timeStamp[0]) / 1000000.0; double down = (timeStamp[2] - timeStamp[1]) / 1000000.0; double ao = (timeStamp[3] - timeStamp[2]) / 1000000.0; double up = (timeStamp[4] - timeStamp[3]) / 1000000.0; double blur = (timeStamp[5] - timeStamp[4]) / 1000000.0; double comp = (timeStamp[6] - timeStamp[5]) / 1000000.0; double tot = (timeStamp[6] - timeStamp[0]) / 1000000.0; sprintf(title, "Fullres: %i, FPS: %2.1f, time(ms): geom %2.2f, down %2.2f, ao %2.2f, up %2.2f, blur %2.2f, comp %2.2f tot %2.2f", (int)fullres, fps, geom, down, ao, up, blur, comp, tot); glfwSetWindowTitle(title); t1 = 0.0; frames = 0; } ++frames; }
static BOOL wined3d_timestamp_query_ops_poll(struct wined3d_query *query) { struct wined3d_timestamp_query *tq = query->extendedData; struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_context *context; GLuint available; GLuint64 timestamp; BOOL ret; if (!gl_info->supported[ARB_TIMER_QUERY]) { TRACE("Faking timestamp.\n"); QueryPerformanceCounter((LARGE_INTEGER *)&tq->timestamp); return TRUE; } if (tq->context->tid != GetCurrentThreadId()) { FIXME("%p Wrong thread, returning 1.\n", query); tq->timestamp = 1; return TRUE; } context = context_acquire(device, context_get_rt_surface(tq->context)); GL_EXTCALL(glGetQueryObjectuiv(tq->id, GL_QUERY_RESULT_AVAILABLE, &available)); checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE)"); TRACE("available %#x.\n", available); if (available) { GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT, ×tamp)); checkGLcall("glGetQueryObjectui64v(GL_QUERY_RESULT)"); TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); tq->timestamp = timestamp; ret = TRUE; } else { ret = FALSE; } context_release(context); return ret; }
void whitgl_profile_end_frame() { glEndQuery(GL_TIME_ELAPSED); if(!_first) { GLuint* query_array = !_front ? _front_queries : _back_queries; int done = 0; while (!done) { glGetQueryObjectiv(query_array[next_gpu_event-1], GL_QUERY_RESULT_AVAILABLE, &done); } whitgl_int i; for(i=0; i<next_gpu_event; i++) { GLuint64 timer; glGetQueryObjectui64v(query_array[i], GL_QUERY_RESULT, &timer); gpu_events[i].total += timer / 1000000000.0; } } _front = !_front; _first = false; _frame_total += whitgl_sys_get_time()-_frame_start; _frames++; if(_frames >= FRAMES_TO_COUNT) { whitgl_float target = 1.0/60.0; _frames -= FRAMES_TO_COUNT; whitgl_int i; whitgl_float average_gpu = 0; for(i=0; i<next_gpu_event; i++) { whitgl_float event_avg = gpu_events[i].total/FRAMES_TO_COUNT; average_gpu += event_avg; if(_should_report) WHITGL_LOG("%.1f%% %s", (event_avg/target)*100, gpu_events[i].name); gpu_events[i] = whitgl_profile_event_zero; } whitgl_float average_total = _frame_total/FRAMES_TO_COUNT; whitgl_float average_update = _frame_update/FRAMES_TO_COUNT; if(_should_report) WHITGL_LOG("update %.2f%% gpu %.2f%% total %.2f%%", (average_update/target)*100, (average_gpu/target)*100, (average_total/target)*100); _frame_update = 0; _frame_total = 0; } }
void TimerQuery::update() { if(!m_has_data ) { return; } if( m_query == 0 ) { glGenQueries( 1, &m_query ); } GLuint64 result; glGetQueryObjectui64v( m_query, GL_QUERY_RESULT, &result ); m_sample_sum += result; m_samples++; m_has_data = false; }
bool getResult(GLuint64 *result) { if (thisQueryActive) return false; GLint isReady = GL_FALSE; glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &isReady); if (isReady != GL_TRUE) return false; glGetQueryObjectui64v(query, GL_QUERY_RESULT, result); if (glGetError() == GL_INVALID_OPERATION) return false; return true; }
void OpenGLRenderer::pushDebugGroup(const std::string& title) { #ifdef RW_GRAPHICS_STATS if (ogl_ext_KHR_debug) { glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, title.c_str()); ProfileInfo& prof = profileInfo[currentDebugDepth]; prof.buffers = prof.draws = prof.textures = prof.uploads = prof.primitives = 0; glQueryCounter(debugQuery, GL_TIMESTAMP); glGetQueryObjectui64v(debugQuery, GL_QUERY_RESULT, &prof.timerStart); currentDebugDepth++; RW_ASSERT(currentDebugDepth < MAX_DEBUG_DEPTH); } #else RW_UNUSED(title); #endif }
static enum piglit_result cpu_gather_query(bool exact, uint32_t expected, uint64_t *cpu_result) { *cpu_result = 0; glBindBuffer(GL_QUERY_BUFFER, 0); if (result_type == GL_INT) glGetQueryObjectiv(query, GL_QUERY_RESULT, (GLint*)cpu_result); else if (result_type == GL_UNSIGNED_INT) glGetQueryObjectuiv(query, GL_QUERY_RESULT, (GLuint*)cpu_result); else glGetQueryObjectui64v(query, GL_QUERY_RESULT, cpu_result); glBindBuffer(GL_QUERY_BUFFER, qbo); return (exact ? *cpu_result == expected : *cpu_result >= expected) ? PIGLIT_PASS : PIGLIT_FAIL; }