static float draw(GLuint *q, int iters) { float start_time, end_time; glUseProgram(prog); glUniform1i(iters_loc, iters); start_time = get_time(); if (test == TIMESTAMP) { glQueryCounter(q[0], GL_TIMESTAMP); } else { glBeginQuery(GL_TIME_ELAPSED, q[0]); } piglit_draw_rect(-1, -1, 2, 2); if (test == TIMESTAMP) { glQueryCounter(q[1], GL_TIMESTAMP); } else { glEndQuery(GL_TIME_ELAPSED); } /* This glFinish() is important, since this is used in a * timing loop. */ glFinish(); end_time = get_time(); return end_time - start_time; }
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(); }
void Query::begin() { glBeginQuery(target, id); if (target == GL_TIME_ELAPSED) { glQueryCounter(id, GL_TIMESTAMP); } }
void GLTimerQuery::begin() { glQueryCounter(mQueryStartObj, GL_TIMESTAMP); setActive(true); mEndIssued = false; }
void GLTimerQuery::end() { glQueryCounter(mQueryEndObj, GL_TIMESTAMP); mEndIssued = true; mFinalized = false; }
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]; }
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.; }
void beginProfile(trace::Call &call, bool isDraw) { /* Create call query */ CallQuery query; query.isDraw = isDraw; query.call = call.no; query.sig = call.sig; query.program = glretrace::currentContext ? glretrace::currentContext->activeProgram : 0; /* GPU profiling only for draw calls */ if (isDraw) { glGenQueries(3, query.ids); if (retrace::profilingGpuTimes) { if (supportsTimestamp) { glQueryCounter(query.ids[0], GL_TIMESTAMP); } glBeginQuery(GL_TIME_ELAPSED, query.ids[1]); } if (retrace::profilingPixelsDrawn) { glBeginQuery(GL_SAMPLES_PASSED, query.ids[2]); } } callQueries.push_back(query); /* CPU profiling for all calls */ if (retrace::profilingCpuTimes) { callQueries.back().cpuStart = os::getTime(); } }
enum piglit_result piglit_display(void) { int test_pass = 1; GLuint query; GLint result; piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Guaranteed to be random, see: http://xkcd.com/221 */ query = 3243; test_pass &= is_query_matches(query, 0, "with un-generated name"); glGenQueries(1, &query); test_pass &= is_query_matches(query, 0, "after glGenQueries"); glQueryCounter(query, GL_TIMESTAMP); test_pass &= is_query_matches(query, 1, "after glQueryCounter"); /* Do a little drawing at least */ glColor3ub(0x00, 0xff, 0x00); piglit_draw_rect(0, 0, piglit_width, piglit_height); glGetQueryObjectiv(query, GL_QUERY_RESULT, &result); test_pass &= is_query_matches(query, 1, "after glGetQueryObjectiv"); glDeleteQueries(1, &query); test_pass &= is_query_matches(query, 0, "after glDeleteQueries"); piglit_present_results(); return test_pass ? PIGLIT_PASS : PIGLIT_FAIL; }
void GPUTimer::beginQuery( uint32 frameID ) { if( !glExt::ARB_timer_query ) return; ASSERT( !_activeQuery ); if( _queryFrame != frameID ) { if( !updateResults() ) return; _queryFrame = frameID; _numQueries = 0; } // Create new query pair if necessary uint32 queryObjs[2]; if( _numQueries++ * 2 == _queryPool.size() ) { glGenQueries( 2, queryObjs ); _queryPool.push_back( queryObjs[0] ); _queryPool.push_back( queryObjs[1] ); } else { queryObjs[0] = _queryPool[(_numQueries - 1) * 2]; } _activeQuery = true; glQueryCounter( queryObjs[0], GL_TIMESTAMP ); }
void Profile::time(std::string name) { assert(!CHECKERROR); if (ready) { //create query struct for "name" if there isn't one QueryMap::iterator q = queries.find(name); if (q == queries.end()) { std::pair<QueryMap::iterator, bool> ret; ret = queries.insert(make_pair(name, Query())); q = ret.first; } //if "name" has already been set after begin(), ignore this call if (q->second.timeDiff > 0) return; //attach this timediff to "name" q->second.timeDiff = current; queryOrder.push_back(q->first); //move to the next query CHECKERROR; glQueryCounter(getNextQuery(), GL_TIMESTAMP); //NOTE: if this causes an error it's probably because you're using AMD //my guess is AMD won't allow two querys at the same time even of differing types CHECKERROR; } }
// Create a new profile section void VSProfileLib::createNewSection(std::string &name, pTime w, bool profileGL) { section s; #if VSPL_PROFILE == VSPL_PROFILE_CPU_AND_GPU s.profileGL = profileGL; #else s.profileGL = false; #endif s.parent = (sCurrLevel > 0 ? sLevels[sCurrLevel-1].cursor : -1); s.name = name; s.calls = 1; s.totalTime = 0; s.totalQueryTime = 0; sLevels[sCurrLevel].cursor++; if (profileGL) { pair p; glGenQueries(2, p.queries); glQueryCounter(p.queries[0], GL_TIMESTAMP); s.queriesGL[sBackBuffer].push_back(p); } GetTicks(&(s.startTime)); s.wastedTime = s.startTime - w; sLevels[sCurrLevel].sec.push_back(s); }
void GPUTimer::endQuery() { if( _activeQuery ) { glQueryCounter( _queryPool[_numQueries * 2 - 1], GL_TIMESTAMP ); _activeQuery = false; } }
inline Profiler::Slot Profiler::beginSection( const char* name, GPUInterface* gpuif ) { GLuint queryFrame = m_numFrames % FRAME_DELAY; Slot slot = m_frameEntries++; if (slot >= m_entries.size()){ grow((unsigned int)(m_entries.size() * 2)); if (gpuif){ gpuif->TimerGrow( getRequiredTimers() ); } } if (m_entries[slot].name != name || m_entries[slot].gpuif != gpuif ) { m_entries[slot].name = name; m_entries[slot].gpuif = gpuif; m_resetDelay = CONFIG_DELAY; } int level = m_level++; m_entries[slot].level = level; m_entries[slot].splitter = false; #ifdef SUPPORT_NVTOOLSEXT { nvtxEventAttributes_t eventAttrib = {0}; eventAttrib.version = NVTX_VERSION; eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; eventAttrib.colorType = NVTX_COLOR_ARGB; unsigned char color[4]; color[0] = 255; color[1] = 0; color[2] = slot % 2 ? 127 : 255; color[3] = 255; color[2] -= level * 16; color[3] -= level * 16; eventAttrib.color = *(uint32_t*)(color); eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII; eventAttrib.message.ascii = name; nvtxRangePushEx(&eventAttrib); } #endif if (gpuif){ gpuif->TimerSetup( getTimerIdx(slot,queryFrame,true) ); } else{ glQueryCounter(m_entries[slot].queries[queryFrame],GL_TIMESTAMP); } m_entries[slot].deltas[queryFrame] = -getMicroSeconds(); return slot; }
void GPUTimer::endQuery() { #if !defined (PLATFORM_ES2) if( _activeQuery ) { glQueryCounter( _queryPool[_numQueries * 2 - 1], GL_TIMESTAMP ); _activeQuery = false; } #endif }
void scene_buildings::gpu_draw(base::frame_context * const ctx){ base::hptimer timer; timer.start(); if (base::cfg().no_cull){ glDisable(GL_CULL_FACE); } glUseProgram(_prg); // this is only needed on AMD cards due to driver bug wich needs // to have attr0 array anabled //base::set_attr0_vbo_amd_wa(); glQueryCounter(ctx->_time_queries[0], GL_TIMESTAMP); glUniformMatrix4fv(_prg_mvp, 1, GL_FALSE, glm::value_ptr(ctx->_mvp)); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indices_vbo); glUniform1i(_prg_tb_blocks, 0); glActiveTexture(GL_TEXTURE0); // bind scene texture buffers for (uint32 i = 0; i < _tiles.size(); i++){ int x = _tiles[i]._tile_pos.x; int y = _tiles[i]._tile_pos.y; glUniform2i(_prg_tile_offset, x,y); glUniform1ui(_prg_total_count, _tiles[i]._blocks_count); glBindTexture(GL_TEXTURE_BUFFER, _tiles[i]._blocks_tb); glDrawElementsInstanced(GL_TRIANGLES, 10 * 3 * base::cfg().blocks_per_idc, GL_UNSIGNED_INT, 0, (_tiles[i]._blocks_count + base::cfg().blocks_per_idc - 1) / base::cfg().blocks_per_idc); } ctx->_cpu_render_time = timer.elapsed_time(); glQueryCounter(ctx->_time_queries[1], GL_TIMESTAMP); }
PIGLIT_GL_TEST_CONFIG_END static GLint64 get_gpu_time_via_query(GLuint q) { GLint64 time; glQueryCounter(q, GL_TIMESTAMP); glGetQueryObjecti64v(q, GL_QUERY_RESULT, &time); return time; }
void MetricBackend_opengl::beginQuery(QueryBoundary boundary) { // GPU related if (glQueriesNeeded[boundary]) { std::array<GLuint, QUERY_LIST_END> query; glGenQueries(QUERY_LIST_END, query.data()); if (metrics[METRIC_GPU_START].profiled[boundary] || (metrics[METRIC_GPU_DURATION].profiled[boundary] && supportsTimestamp)) { glQueryCounter(query[QUERY_GPU_START], GL_TIMESTAMP); } if (metrics[METRIC_GPU_DURATION].profiled[boundary] && !supportsTimestamp) { glBeginQuery(GL_TIME_ELAPSED, query[QUERY_GPU_DURATION]); } if (metrics[METRIC_GPU_PIXELS].profiled[boundary]) { glBeginQuery(GL_SAMPLES_PASSED, query[QUERY_OCCLUSION]); } queries[boundary].push(std::move(query)); } // CPU related if (metrics[METRIC_CPU_START].profiled[boundary] || metrics[METRIC_CPU_DURATION].profiled[boundary]) { cpuStart[boundary] = getCurrentTime(); if (metrics[METRIC_CPU_START].profiled[boundary]) { int64_t time = cpuStart[boundary] * cpuTimeScale - baseTime; data[METRIC_CPU_START][boundary]->addData(boundary, time); } } if (metrics[METRIC_CPU_VSIZE_START].profiled[boundary] || metrics[METRIC_CPU_VSIZE_DURATION].profiled[boundary]) { vsizeStart[boundary] = os::getVsize(); if (metrics[METRIC_CPU_VSIZE_START].profiled[boundary]) { int64_t time = vsizeStart[boundary]; data[METRIC_CPU_VSIZE_START][boundary]->addData(boundary, time); } } if (metrics[METRIC_CPU_RSS_START].profiled[boundary] || metrics[METRIC_CPU_RSS_DURATION].profiled[boundary]) { rssStart[boundary] = os::getRss(); if (metrics[METRIC_CPU_RSS_START].profiled[boundary]) { int64_t time = rssStart[boundary]; data[METRIC_CPU_RSS_START][boundary]->addData(boundary, time); } } queryInProgress[boundary] = true; // DRAWCALL is a CALL if (boundary == QUERY_BOUNDARY_DRAWCALL) beginQuery(QUERY_BOUNDARY_CALL); }
bool render() { glm::ivec2 WindowSize(this->getWindowSize()); glm::mat4 Projection = glm::perspective(glm::pi<float>() * 0.25f, 4.0f / 3.0f, 0.1f, 100.0f); glm::mat4 Model = glm::mat4(1.0f); glm::mat4 MVP = Projection * this->view() * Model; glQueryCounter(QueryName[query::BEGIN], GL_TIMESTAMP); glViewport(0, 0, WindowSize.x, WindowSize.y); glClearBufferfv(GL_COLOR, 0, &glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)[0]); glUseProgram(ProgramName); glUniformMatrix4fv(UniformMVP, 1, GL_FALSE, &MVP[0][0]); glBindVertexArray(VertexArrayName); glDrawArrays(GL_TRIANGLES, 0, VertexCount); glQueryCounter(QueryName[query::END], GL_TIMESTAMP); GLint AvailableBegin = GL_FALSE; glGetQueryObjectiv(QueryName[query::BEGIN], GL_QUERY_RESULT_AVAILABLE, &AvailableBegin); GLint AvailableEnd = GL_FALSE; glGetQueryObjectiv(QueryName[query::END], GL_QUERY_RESULT_AVAILABLE, &AvailableEnd); // The OpenGL implementations will wait for the query if it's not available GLint64 TimeBegin = 0, TimeEnd = 0; glGetQueryObjecti64v(QueryName[query::BEGIN], GL_QUERY_RESULT, &TimeBegin); glGetQueryObjecti64v(QueryName[query::END], GL_QUERY_RESULT, &TimeEnd); //glGetInteger64v(GL_TIMESTAMP, &TimeBegin); //glGetInteger64v(GL_TIMESTAMP, &TimeEnd); fprintf(stdout, "%d, %d / Time stamp: %f ms \r", AvailableBegin, AvailableEnd, (TimeEnd - TimeBegin) / 1000.f / 1000.f); return TimeEnd - TimeBegin > 0; }
void GPU_Profile::create_timer() { u32 timer = 0; #ifdef GLSL4_API glGenQueries(1, &timer); glQueryCounter(timer, GL_TIMESTAMP); #endif datas.push_back(ProfileInfo(timer, frame, draw)); #ifdef ENABLE_MARKER dump(true); #endif }
void Profile::begin() { assert(!CHECKERROR); if (ready) { ready = false; } if (queries.size()) { //if the last query is done, they are all done GLint available; glGetQueryObjectiv(queryObjs[current-1], GL_QUERY_RESULT_AVAILABLE, &available); if (available) { //get the results timeStamps.resize(queryObjs.size()); for (int i = 0; i < (int)queryObjs.size(); ++i) { CHECKERROR; GLuint64 result; glGetQueryObjectui64vEXT(queryObjs[i], GL_QUERY_RESULT, &result); timeStamps[i] = result; CHECKERROR; } //append the differences to the samples list for (QueryMap::iterator it = queries.begin(); it != queries.end(); ++it) { if (it->second.timeDiff < 1) continue; GLuint64 timediff = timeStamps[it->second.timeDiff] - timeStamps[it->second.timeDiff-1]; it->second.times.push_back(timediff); if (it->second.times.size() > PROFILE_SAMPLES) it->second.times.pop_front(); it->second.timeDiff = -1; } //start the next set of samples ready = true; restartQueries(); } } else ready = true; if (ready) { glQueryCounter(getNextQuery(), GL_TIMESTAMP); } }
// accumulates the time spent in the section void VSProfileLib::accumulate() { section *s; pTime t,t2; GetTicks(&t); s = &(sLevels[sCurrLevel].sec[sLevels[sCurrLevel].cursor]); if (s->profileGL) { glQueryCounter(s->queriesGL[sBackBuffer][s->queriesGL[sBackBuffer].size()-1].queries[1], GL_TIMESTAMP); } // to measure wasted time when accumulating GetTicks(&t2); s->wastedTime += (t2-t); s->totalTime += (t - s->startTime); }
// updates a profile section void VSProfileLib::updateSection(int cur, pTime w) { section *s; s = &(sLevels[sCurrLevel].sec[cur]); s->calls++; sLevels[sCurrLevel].cursor = cur; if (s->profileGL) { pair p; glGenQueries(2, p.queries); glQueryCounter(p.queries[0], GL_TIMESTAMP); s->queriesGL[sBackBuffer].push_back(p); } GetTicks(&s->startTime); s->wastedTime += s->startTime - w; }
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 }
void MetricBackend_opengl::endQuery(QueryBoundary boundary) { if (queryInProgress[boundary]) { // CPU related if (metrics[METRIC_CPU_DURATION].profiled[boundary]) { cpuEnd[boundary] = getCurrentTime(); int64_t time = (cpuEnd[boundary] - cpuStart[boundary]) * cpuTimeScale; data[METRIC_CPU_DURATION][boundary]->addData(boundary, time); } if (metrics[METRIC_CPU_VSIZE_DURATION].profiled[boundary]) { vsizeEnd[boundary] = os::getVsize(); int64_t time = vsizeEnd[boundary] - vsizeStart[boundary]; data[METRIC_CPU_VSIZE_DURATION][boundary]->addData(boundary, time); } if (metrics[METRIC_CPU_RSS_DURATION].profiled[boundary]) { rssEnd[boundary] = os::getRss(); int64_t time = rssEnd[boundary] - rssStart[boundary]; data[METRIC_CPU_RSS_DURATION][boundary]->addData(boundary, time); } // GPU related if (glQueriesNeeded[boundary]) { std::array<GLuint, QUERY_LIST_END> &query = queries[boundary].back(); if (metrics[METRIC_GPU_DURATION].profiled[boundary] && supportsTimestamp) { // GL_TIME_ELAPSED cannot be used in nested queries // so prefer this if timestamps are supported glQueryCounter(query[QUERY_GPU_DURATION], GL_TIMESTAMP); } if (metrics[METRIC_GPU_PIXELS].profiled[boundary]) { glEndQuery(GL_SAMPLES_PASSED); } } queryInProgress[boundary] = false; } // DRAWCALL is a CALL if (boundary == QUERY_BOUNDARY_DRAWCALL) endQuery(QUERY_BOUNDARY_CALL); // clear queries after each frame if (boundary == QUERY_BOUNDARY_FRAME && glQueriesNeededAnyBoundary) { processQueries(); } }
void beginProfile(trace::Call &call, bool isDraw) { glretrace::Context *currentContext = glretrace::getCurrentContext(); /* Create call query */ CallQuery query; query.isDraw = isDraw; query.call = call.no; query.sig = call.sig; query.program = currentContext ? currentContext->activeProgram : 0; glGenQueries(NUM_QUERIES, query.ids); /* GPU profiling only for draw calls */ if (isDraw) { if (retrace::profilingGpuTimes) { if (supportsTimestamp) { glQueryCounter(query.ids[GPU_START], GL_TIMESTAMP); } glBeginQuery(GL_TIME_ELAPSED, query.ids[GPU_DURATION]); } if (retrace::profilingPixelsDrawn) { glBeginQuery(GL_SAMPLES_PASSED, query.ids[OCCLUSION]); } } callQueries.push_back(query); /* CPU profiling for all calls */ if (retrace::profilingCpuTimes) { CallQuery& query = callQueries.back(); query.cpuStart = getCurrentTime(); } if (retrace::profilingMemoryUsage) { CallQuery& query = callQueries.back(); query.vsizeStart = os::getVsize(); query.rssStart = os::getRss(); } }
static void getCurrentTimes(int64_t& cpuTime, int64_t& gpuTime) { GLuint query; if (retrace::profilingGpuTimes && supportsTimestamp) { glGenQueries(1, &query); glQueryCounter(query, GL_TIMESTAMP); glGetQueryObjecti64vEXT(query, GL_QUERY_RESULT, &gpuTime); } else { gpuTime = 0; } if (retrace::profilingCpuTimes) { cpuTime = os::getTime(); } else { cpuTime = 0; } if (retrace::profilingGpuTimes && supportsTimestamp) { glDeleteQueries(1, &query); } }
inline void Profiler::endSection( Slot slot ) { GLuint queryFrame = m_numFrames % FRAME_DELAY; m_entries[slot].deltas[queryFrame] += getMicroSeconds(); if (m_entries[slot].gpuif){ m_entries[slot].gpuif->TimerSetup( getTimerIdx(slot,queryFrame,false) ); } else{ glQueryCounter(m_entries[slot].queries[queryFrame + FRAME_DELAY],GL_TIMESTAMP); #if NV_TIMER_FLUSH glFlush(); #endif } #ifdef SUPPORT_NVTOOLSEXT nvtxRangePop(); #endif m_level--; }
static HRESULT wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags) { struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; TRACE("query %p, flags %#x.\n", query, flags); if (gl_info->supported[ARB_TIMER_QUERY]) { struct wined3d_timestamp_query *tq = query->extendedData; struct wined3d_context *context; if (flags & WINED3DISSUE_BEGIN) { WARN("Ignoring WINED3DISSUE_BEGIN with a TIMESTAMP query.\n"); } if (flags & WINED3DISSUE_END) { if (tq->context) context_free_timestamp_query(tq); context = context_acquire(query->device, NULL); context_alloc_timestamp_query(context, tq); GL_EXTCALL(glQueryCounter(tq->id, GL_TIMESTAMP)); checkGLcall("glQueryCounter()"); context_release(context); } } else { ERR("Timestamp queries not supported.\n"); } if (flags & WINED3DISSUE_END) query->state = QUERY_SIGNALLED; return WINED3D_OK; }
void GpuTimer::start() { QueryPair qp; if (availablePairs.empty()) { glGenQueries(1, &qp.startQuery); glGenQueries(1, &qp.endQuery); } else { qp = availablePairs.front(); availablePairs.pop(); // Reuse old OpenGL ids, no need for additional glGenQueries. } inflightPairs.push(qp); // Create a fence and insert it into the command stream. This fence will be signaled // when the GPU has completed all previously issued commands. glWaitSync will defer // subsequently issued commands (without blocking CPU) until the fence signals. // This prevents overlapped execution of OpenGL calls and should make timing measurements // more precise. For more, see e.g. OpenGL Insights. GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glWaitSync(sync, 0, GL_TIMEOUT_IGNORED); glDeleteSync(sync); // Flag for deletion. glQueryCounter(qp.startQuery, GL_TIMESTAMP); }