Magnum::GL::TimeQuery class

Query for elapsed time.

Queries timestamp after all previous OpenGL calls have been processed. It can query either duration of sequence of commands or absolute timestamp. Example usage of both methods:

GL::TimeQuery q1{GL::TimeQuery::Target::TimeElapsed},
              q2{GL::TimeQuery::Target::TimeElapsed};

q1.begin();
// rendering...
q1.end();

q2.begin();
// another rendering...
q2.end();

UnsignedInt timeElapsed1 = q1.result<UnsignedInt>();
UnsignedInt timeElapsed2 = q2.result<UnsignedInt>();
GL::TimeQuery q1{GL::TimeQuery::Target::Timestamp},
              q2{GL::TimeQuery::Target::Timestamp},
              q3{GL::TimeQuery::Target::Timestamp};

q1.timestamp();
// rendering...
q2.timestamp();
// another rendering...
q3.timestamp();

UnsignedInt tmp = q2.result<UnsignedInt>();
UnsignedInt timeElapsed1 = tmp - q1.result<UnsignedInt>();
UnsignedInt timeElapsed2 = q3.result<UnsignedInt>() - tmp;

Using the latter results in fewer OpenGL calls when doing more measures. All times are reported in nanoseconds.

Preventing GPU frequency scaling

Note that GPUs are subject to the same frequency scaling as CPUs, and depending on the vendor and driver the variance may be so high that time measurements are useless. This is particlarly the case with Intel integrated GPUs, which heavily downclock for power saving, and do so independently on the CPU power mode. On Linux it's possible to tune the behavior using Intel GPU tools, available as a intel-gpu-tools package on ArchLinux and Ubuntu, and igt-gpu-tools on Fedora. Run the following as root:

intel_gpu_frequency --max

You can reset back to the default behavior with intel_gpu_frequency --defaults. Without these tools available, it's possible to achieve similar results using low-level tunables in /sys, by setting the min and max frequency to the same value, for example:

cat /sys/class/drm/card1/gt/gt0/rps_max_freq_mhz > /sys/class/drm/card1/gt/gt0/rps_min_freq_mhz

On systems that have multiple GPUs, pick cardN based on whether it has a gt/ subdirectory, NVidia GPUs for example don't have it. Discrete GPUs have additional tunables, see the official Intel docs for more information.

Base classes

class AbstractQuery
Base class for queries.

Public types

enum class Target: GLenum { TimeElapsed = GL_TIME_ELAPSED, Timestamp = GL_TIMESTAMP }
Query target.

Public static functions

static auto wrap(GLuint id, Target target, ObjectFlags flags = {}) -> TimeQuery
Wrap existing OpenGL time query object.

Constructors, destructors, conversion operators

TimeQuery(Target target) explicit
Constructor.
TimeQuery(NoCreateT) explicit noexcept
Construct without creating the underlying OpenGL object.
TimeQuery(const TimeQuery&) deleted
Copying is not allowed.
TimeQuery(TimeQuery&&) defaulted noexcept
Move constructor.

Public functions

auto operator=(const TimeQuery&) -> TimeQuery& deleted
Copying is not allowed.
auto operator=(TimeQuery&&) -> TimeQuery& defaulted noexcept
Move assignment.
void timestamp()
Query timestamp.

Enum documentation

enum class Magnum::GL::TimeQuery::Target: GLenum

Query target.

Enumerators
TimeElapsed

Elapsed time, in nanoseconds. Use result<UnsignedLong>() or result<Long>() to retrieve the result.

Timestamp

Timestamp, in nanoseconds. For use with timestamp() only, use result<UnsignedLong>() or result<Long>() to retrieve the result.

Function documentation

static TimeQuery Magnum::GL::TimeQuery::wrap(GLuint id, Target target, ObjectFlags flags = {})

Wrap existing OpenGL time query object.

Parameters
id OpenGL time query ID
target Query target
flags Object creation flags

The id is expected to be of an existing OpenGL query object. Unlike query created using constructor, the OpenGL object is by default not deleted on destruction, use flags for different behavior.

Magnum::GL::TimeQuery::TimeQuery(Target target) explicit

Constructor.

Creates new OpenGL query object. If ARB_direct_state_access (part of OpenGL 4.5) is not available, the query is created on first use.

Magnum::GL::TimeQuery::TimeQuery(NoCreateT) explicit noexcept

Construct without creating the underlying OpenGL object.

The constructed instance is equivalent to moved-from state. Useful in cases where you will overwrite the instance later anyway. Move another object over it to make it useful.

This function can be safely used for constructing (and later destructing) objects even without any OpenGL context being active. However note that this is a low-level and a potentially dangerous API, see the documentation of NoCreate for alternatives.

void Magnum::GL::TimeQuery::timestamp()

Query timestamp.

Use result<UnsignedLong>() or result<Long>() to retrieve the result.