static void completeCallQuery(CallQuery& query) { /* Get call start and duration */ int64_t gpuStart = 0, gpuDuration = 0, cpuDuration = 0, pixels = 0, vsizeDuration = 0, rssDuration = 0; if (query.isDraw) { if (retrace::profilingGpuTimes) { if (supportsTimestamp) { /* Use ARB queries in case EXT not present */ glGetQueryObjecti64v(query.ids[GPU_START], GL_QUERY_RESULT, &gpuStart); glGetQueryObjecti64v(query.ids[GPU_DURATION], GL_QUERY_RESULT, &gpuDuration); } else { glGetQueryObjecti64vEXT(query.ids[GPU_DURATION], GL_QUERY_RESULT, &gpuDuration); } } if (retrace::profilingPixelsDrawn) { if (supportsTimestamp) { glGetQueryObjecti64v(query.ids[OCCLUSION], GL_QUERY_RESULT, &pixels); } else if (supportsElapsed) { glGetQueryObjecti64vEXT(query.ids[OCCLUSION], GL_QUERY_RESULT, &pixels); } else { uint32_t pixels32; glGetQueryObjectuiv(query.ids[OCCLUSION], GL_QUERY_RESULT, &pixels32); pixels = static_cast<int64_t>(pixels32); } } } else { pixels = -1; } if (retrace::profilingCpuTimes) { double cpuTimeScale = 1.0E9 / getTimeFrequency(); cpuDuration = (query.cpuEnd - query.cpuStart) * cpuTimeScale; query.cpuStart *= cpuTimeScale; } if (retrace::profilingMemoryUsage) { vsizeDuration = query.vsizeEnd - query.vsizeStart; rssDuration = query.rssEnd - query.rssStart; } glDeleteQueries(NUM_QUERIES, query.ids); /* Add call to profile */ retrace::profiler.addCall(query.call, query.sig->name, query.program, pixels, gpuStart, gpuDuration, query.cpuStart, cpuDuration, query.vsizeStart, vsizeDuration, query.rssStart, rssDuration); }
void MetricBackend_opengl::beginPass() { if (curPass == 1) { for (int i = 0; i < QUERY_BOUNDARY_LIST_END; i++) { for (auto &m : metrics) { if (m.enabled[i]) m.profiled[i] = true; } } // profile frames in first pass if (twoPasses) { if (!supportsTimestamp) { metrics[METRIC_GPU_DURATION].profiled[QUERY_BOUNDARY_DRAWCALL] = false; metrics[METRIC_GPU_DURATION].profiled[QUERY_BOUNDARY_CALL] = false; } metrics[METRIC_GPU_PIXELS].profiled[QUERY_BOUNDARY_DRAWCALL] = false; metrics[METRIC_GPU_PIXELS].profiled[QUERY_BOUNDARY_CALL] = false; } } else if (curPass == 2) { for (int i = 0; i < QUERY_BOUNDARY_LIST_END; i++) { for (auto &m : metrics) { m.profiled[i] = false; } } // profile calls/draw calls in second pass if (!supportsTimestamp) { if (metrics[METRIC_GPU_DURATION].enabled[QUERY_BOUNDARY_DRAWCALL]) { metrics[METRIC_GPU_DURATION].profiled[QUERY_BOUNDARY_DRAWCALL] = true; } if (metrics[METRIC_GPU_DURATION].enabled[QUERY_BOUNDARY_CALL]) { metrics[METRIC_GPU_DURATION].profiled[QUERY_BOUNDARY_CALL] = true; } } if (metrics[METRIC_GPU_PIXELS].enabled[QUERY_BOUNDARY_DRAWCALL]) { metrics[METRIC_GPU_PIXELS].profiled[QUERY_BOUNDARY_DRAWCALL] = true; } if (metrics[METRIC_GPU_PIXELS].enabled[QUERY_BOUNDARY_CALL]) { metrics[METRIC_GPU_PIXELS].profiled[QUERY_BOUNDARY_CALL] = true; } } // setup times cpuTimeScale = 1.0E9 / getTimeFrequency(); baseTime = getCurrentTime() * cpuTimeScale; }
void initContext() { glretrace::Context *currentContext = glretrace::getCurrentContext(); /* Ensure we have adequate extension support */ assert(currentContext); supportsTimestamp = currentContext->hasExtension("GL_ARB_timer_query"); supportsElapsed = currentContext->hasExtension("GL_EXT_timer_query") || supportsTimestamp; supportsOcclusion = currentContext->hasExtension("GL_ARB_occlusion_query"); supportsDebugOutput = currentContext->hasExtension("GL_ARB_debug_output"); supportsARBShaderObjects = currentContext->hasExtension("GL_ARB_shader_objects"); /* Check for timer query support */ if (retrace::profilingGpuTimes) { if (!supportsTimestamp && !supportsElapsed) { std::cout << "Error: Cannot run profile, GL_ARB_timer_query or GL_EXT_timer_query extensions are not supported." << std::endl; exit(-1); } GLint bits = 0; glGetQueryiv(GL_TIME_ELAPSED, GL_QUERY_COUNTER_BITS, &bits); if (!bits) { std::cout << "Error: Cannot run profile, GL_QUERY_COUNTER_BITS == 0." << std::endl; exit(-1); } } /* Check for occlusion query support */ if (retrace::profilingPixelsDrawn && !supportsOcclusion) { std::cout << "Error: Cannot run profile, GL_ARB_occlusion_query extension is not supported." << std::endl; exit(-1); } /* Setup debug message call back */ if (retrace::debug && supportsDebugOutput) { glretrace::Context *currentContext = glretrace::getCurrentContext(); glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); glDebugMessageCallbackARB(&debugOutputCallback, currentContext); if (DEBUG_OUTPUT_SYNCHRONOUS) { glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); } } /* Sync the gpu and cpu start times */ if (retrace::profilingCpuTimes || retrace::profilingGpuTimes) { if (!retrace::profiler.hasBaseTimes()) { double cpuTimeScale = 1.0E9 / getTimeFrequency(); GLint64 currentTime = getCurrentTime() * cpuTimeScale; retrace::profiler.setBaseCpuTime(currentTime); retrace::profiler.setBaseGpuTime(currentTime); } } if (retrace::profilingMemoryUsage) { GLint64 currentVsize, currentRss; getCurrentVsize(currentVsize); retrace::profiler.setBaseVsizeUsage(currentVsize); getCurrentRss(currentRss); retrace::profiler.setBaseRssUsage(currentRss); } }
/* * Called the first time a context is made current. */ void initContext() { glretrace::Context *currentContext = glretrace::getCurrentContext(); assert(currentContext); /* Ensure we have adequate extension support */ glprofile::Profile currentProfile = currentContext->actualProfile(); supportsTimestamp = currentProfile.versionGreaterOrEqual(glprofile::API_GL, 3, 3) || currentContext->hasExtension("GL_ARB_timer_query"); supportsElapsed = currentContext->hasExtension("GL_EXT_timer_query") || supportsTimestamp; supportsOcclusion = currentProfile.versionGreaterOrEqual(glprofile::API_GL, 1, 5); supportsARBShaderObjects = currentContext->hasExtension("GL_ARB_shader_objects"); currentContext->KHR_debug = currentContext->hasExtension("GL_KHR_debug"); if (currentContext->KHR_debug) { glGetIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH, ¤tContext->maxDebugMessageLength); assert(currentContext->maxDebugMessageLength > 0); } #ifdef __APPLE__ // GL_TIMESTAMP doesn't work on Apple. GL_TIME_ELAPSED still does however. // http://lists.apple.com/archives/mac-opengl/2014/Nov/threads.html#00001 supportsTimestamp = false; #endif /* Check for timer query support */ if (retrace::profilingGpuTimes) { if (!supportsTimestamp && !supportsElapsed) { std::cout << "error: cannot profile, GL_ARB_timer_query or GL_EXT_timer_query extensions are not supported." << std::endl; exit(-1); } GLint bits = 0; glGetQueryiv(GL_TIME_ELAPSED, GL_QUERY_COUNTER_BITS, &bits); if (!bits) { std::cout << "error: cannot profile, GL_QUERY_COUNTER_BITS == 0." << std::endl; exit(-1); } } /* Check for occlusion query support */ if (retrace::profilingPixelsDrawn && !supportsOcclusion) { std::cout << "error: cannot profile, GL_ARB_occlusion_query extension is not supported (" << currentProfile << ")" << std::endl; exit(-1); } /* Setup debug message call back */ if (retrace::debug) { if (currentContext->KHR_debug) { if (currentProfile.desktop()) { glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); glDebugMessageCallback(&debugOutputCallback, currentContext); } else { glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); glDebugMessageCallbackKHR(&debugOutputCallback, currentContext); } if (DEBUG_OUTPUT_SYNCHRONOUS) { glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); } } else if (currentContext->hasExtension("GL_ARB_debug_output")) { glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); glDebugMessageCallbackARB(&debugOutputCallback, currentContext); if (DEBUG_OUTPUT_SYNCHRONOUS) { glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); } } } /* Sync the gpu and cpu start times */ if (retrace::profilingCpuTimes || retrace::profilingGpuTimes) { if (!retrace::profiler.hasBaseTimes()) { double cpuTimeScale = 1.0E9 / getTimeFrequency(); GLint64 currentTime = getCurrentTime() * cpuTimeScale; retrace::profiler.setBaseCpuTime(currentTime); retrace::profiler.setBaseGpuTime(currentTime); } } if (retrace::profilingMemoryUsage) { GLint64 currentVsize, currentRss; getCurrentVsize(currentVsize); retrace::profiler.setBaseVsizeUsage(currentVsize); getCurrentRss(currentRss); retrace::profiler.setBaseRssUsage(currentRss); } }