• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    EXT_timer_query
4
5Name Strings
6
7    GL_EXT_timer_query
8
9Contact
10
11    James Jones, NVIDIA Corporation (jajones 'at' nvidia.com)
12
13Contributors
14
15    Axel Mamode, Sony
16    Brian Paul, Tungsten Graphics
17    Pat Brown, NVIDIA
18    Remi Arnaud, Sony
19
20Status
21
22    Shipping (version 1.0)
23
24    Supported by NVIDIA Release 80 drivers.
25
26Version
27
28    Last Modified Date:         2013/06/25
29    Revision:                   3
30
31Number
32
33    319
34
35Dependencies
36
37    Written based on the wording of the OpenGL 2.0 specification.
38
39    OpenGL 1.5 is required.
40
41    This extension modifies ARB_occlusion_query and NV_occlusion_query.
42
43Overview
44
45    Applications can benefit from accurate timing information in a number of
46    different ways.  During application development, timing information can
47    help identify application or driver bottlenecks.  At run time,
48    applications can use timing information to dynamically adjust the amount
49    of detail in a scene to achieve constant frame rates.  OpenGL
50    implementations have historically provided little to no useful timing
51    information.  Applications can get some idea of timing by reading timers
52    on the CPU, but these timers are not synchronized with the graphics
53    rendering pipeline.  Reading a CPU timer does not guarantee the completion
54    of a potentially large amount of graphics work accumulated before the
55    timer is read, and will thus produce wildly inaccurate results.
56    glFinish() can be used to determine when previous rendering commands have
57    been completed, but will idle the graphics pipeline and adversely affect
58    application performance.
59
60    This extension provides a query mechanism that can be used to determine
61    the amount of time it takes to fully complete a set of GL commands, and
62    without stalling the rendering pipeline.  It uses the query object
63    mechanisms first introduced in the occlusion query extension, which allow
64    time intervals to be polled asynchronously by the application.
65
66Issues
67
68    What time interval is being measured?
69
70      RESOLVED:  The timer starts when all commands prior to BeginQuery() have
71      been fully executed.  At that point, everything that should be drawn by
72      those commands has been written to the framebuffer.  The timer stops
73      when all commands prior to EndQuery() have been fully executed.
74
75    What unit of time will time intervals be returned in?
76
77      RESOLVED:  Nanoseconds (10^-9 seconds).  This unit of measurement allows
78      for reasonably accurate timing of even small blocks of rendering
79      commands.  The granularity of the timer is implementation-dependent.  A
80      32-bit query counter can express intervals of up to approximately 4
81      seconds.
82
83    What should be the minimum number of counter bits for timer queries?
84
85      RESOLVED:  30 bits, which will allow timing sections that take up to 1
86      second to render.
87
88    How are counter results of more than 32 bits returned?
89
90      RESOLVED: Using the int64 and uint64 datatypes (introduced in OpenGL
91      3.2 and used by this extension as well), and corresponding
92      GetQueryObject entry points. These types hold integer values and have
93      a minimum bit width of 64.
94
95    Should the extension measure total time elapsed between the full
96    completion of the BeginQuery and EndQuery commands, or just time spent in
97    the graphics library?
98
99      RESOLVED:  This extension will measure the total time elapsed between
100      the full completion of these commands.  Future extensions may implement
101      a query to determine time elapsed at different stages of the graphics
102      pipeline.
103
104    This extension introduces a second query type supported by
105    BeginQuery/EndQuery.  Can multiple query types be active simultaneously?
106
107      RESOLVED:  Yes; an application may perform an occlusion query and a
108      timer query simultaneously.  An application can not perform multiple
109      occlusion queries or multiple timer queries simultaneously.  An
110      application also can not use the same query object for an occlusion
111      query and a timer query simultaneously.
112
113    Do query objects have a query type permanently associated with them?
114
115      RESOLVED:  No.  A single query object can be used to perform different
116      types of queries, but not at the same time.
117
118      Having a fixed type for each query object simplifies some aspects of the
119      implementation -- not having to deal with queries with different result
120      sizes, for example.  It would also mean that BeginQuery() with a query
121      object of the "wrong" type would result in an INVALID_OPERATION error.
122
123    How predictable/repeatable are the results returned by the timer query?
124
125      RESOLVED:  In general, the amount of time needed to render the same
126      primitives should be fairly constant.  But there may be many other
127      system issues (e.g., context switching on the CPU and GPU, virtual
128      memory page faults, memory cache behavior on the CPU and GPU) that can
129      cause times to vary wildly.
130
131      Note that modern GPUs are generally highly pipelined, and may be
132      processing different primitives in different pipeline stages
133      simultaneously.  In this extension, the timers start and stop when the
134      BeginQuery/EndQuery commands reach the bottom of the rendering pipeline.
135      What that means is that by the time the timer starts, the GL driver on
136      the CPU may have started work on GL commands issued after BeginQuery,
137      and the higher pipeline stages (e.g., vertex transformation) may have
138      started as well.
139
140   What should the new 64 bit integer type be called?
141
142      RESOLVED: The new types will be called GLint64/GLuint64  The new
143      command suffixes will be i64 and ui64.  These names clearly convey the
144      minimum size of the types.  These types are similar to the C99 standard
145      type int_least64_t, but we use names similar to the C99 optional type
146      int64_t for simplicity.
147
148      (note: previous versions of EXT_timer_query used GLint64EXT and and
149      GLuint64EXT. These types were later promoted to core in OpenGL 3.2,
150      and this extension was changed to use the core datatypes for
151      compatibility with changes to the OpenGL ES EXT_disjoint_timer_query
152      extension, which introduces the same query entry points, and would
153      have otherwise have had different function signatures).
154
155New Procedures and Functions
156
157     void GetQueryObjecti64vEXT(uint id, enum pname, int64 *params);
158     void GetQueryObjectui64vEXT(uint id, enum pname, uint64 *params);
159
160New Tokens
161
162    Accepted by the <target> parameter of BeginQuery, EndQuery, and
163    GetQueryiv:
164
165        TIME_ELAPSED_EXT                               0x88BF
166
167Additions to Chapter 2 of the OpenGL 2.0 Specification (OpenGL Operation)
168
169    (Modify table 2.1, Correspondence of command suffix letters to GL argument
170     types, p. 8) Add two new types and suffixes:
171
172    Letter Corresponding GL Type
173    ------ ---------------------
174    i64    int64
175    ui64   uint64
176
177    (Modify table 2.2, GL data types, p. 9) Add two new types:
178
179              Minimum
180    GL Type   Bit Width Description
181    --------- --------- ------------------------------------
182    int64     64        signed 2's complement binary integer
183    uint64    64        unsigned binary integer
184
185Additions to Chapter 3 of the OpenGL 2.0 Specification (Rasterization)
186
187    None.
188
189Additions to Chapter 4 of the OpenGL 2.0 Specification (Per-Fragment
190Operations and the Framebuffer)
191
192    (Replace Section 4.1.7, Occlusion Queries, p.204)
193
194    Section 4.1.7, Asynchronous Queries
195
196    Asynchronous queries provide a mechanism to return information about the
197    processing of a sequence of GL commands.  There are two query types
198    supported by the GL.  Occlusion queries (section 4.1.7.1) count the number
199    of fragments or samples that pass the depth test.  Timer queries (section
200    4.1.12) record the amount of time needed to fully process these commands.
201
202    The results of asynchronous queries are not returned by the GL immediately
203    after the completion of the last command in the set; subsequent commands
204    can be processed while the query results are not complete.  When
205    available, the query results are stored in an associated query object.
206    The commands described in section 6.1.12 provide mechanisms to determine
207    when query results are available and return the actual results of the
208    query.  The name space for query objects is the unsigned integers, with
209    zero reserved by the GL.
210
211    Each type of query supported by the GL has an active query object name.
212    If the active query object name for a query type is non-zero, the GL is
213    currently tracking the information corresponding to that query type and
214    the query results will be written into the corresponding query object.  If
215    the active query object for a query type name is zero, no such information
216    is being tracked.
217
218    A query object is created by calling
219
220        void BeginQuery(enum target, uint id);
221
222    with an unused name <id>.  <target> indicates the type of query to be
223    performed; valid values of <target> are defined in subsequent sections.
224    When a query object is created, the name <id> is marked as used and
225    associated with a new query object.
226
227    BeginQuery sets the active query object name for the query type given by
228    <target> to <id>.  If BeginQuery is called with an <id> of zero, if the
229    active query object name for <target> is non-zero, or if <id> is the
230    active query object name for any query type, the error INVALID_OPERATION
231    is generated.
232
233    The command
234
235        void EndQuery(enum target);
236
237    marks the end of the sequence of commands to be tracked for the query type
238    given by <target>.  The active query object for <target> is updated to
239    indicate that query results are not available, and the active query object
240    name for <target> is reset to zero.  When the commands issued prior to
241    EndQuery have completed and a final query result is available, the query
242    object active when EndQuery is called is updated by the GL.  The query
243    object is updated to indicate that the query results are available and to
244    contain the query result.  If the active query object name for <target> is
245    zero when EndQuery is called, the error INVALID_OPERATION is generated.
246
247    The command
248
249        void GenQueries(sizei n, uint *ids);
250
251    returns <n> previously unused query object names in <ids>. These names are
252    marked as used, but no object is associated with them until the first time
253    they are used by BeginQuery.
254
255    Query objects are deleted by calling
256
257        void DeleteQueries(sizei n, const uint *ids);
258
259    <ids> contains <n> names of query objects to be deleted. After a query
260    object is deleted, its name is again unused.  Unused names in <ids> are
261    silently ignored.
262
263    Calling either GenQueries or DeleteQueries while any query of any target
264    is active causes an INVALID_OPERATION error to be generated.
265
266    Query objects contain two pieces of state:  a single bit indicating
267    whether a query result is available, and an integer containing the query
268    result value.  The number of bits used to represent the query result is
269    implementation-dependent.  In the initial state of a query object, the
270    result is available and its value is zero.
271
272    The necessary state for each query type is an unsigned integer holding the
273    active query object name (zero if no query object is active), and any
274    state necessary to keep the current results of an asynchronous query in
275    progress.
276
277    Section 4.1.7.1, Occlusion Queries
278
279    Occlusion queries use query objects to track the number of fragments or
280    samples that pass the depth test.  An occlusion query can be started and
281    finished by calling BeginQuery and EndQuery, respectively, with a <target>
282    of SAMPLES_PASSED.
283
284    When an occlusion query starts, the samples-passed count maintained by the
285    GL is set to zero.  When an occlusion query is active, the samples-passed
286    count is incremented for each fragment that passes the depth test.  If the
287    value of SAMPLE BUFFERS is 0, then the samples-passed count is incremented
288    by 1 for each fragment. If the value of SAMPLE BUFFERS is 1, then the
289    samples-passed count is incremented by the number of samples whose
290    coverage bit is set. However, implementations, at their discretion, may
291    instead increase the samples-passed count by the value of SAMPLES if any
292    sample in the fragment is covered.  When an occlusion query finishes and
293    all fragments generated by the commands issued prior to EndQuery have been
294    generated, the samples-passed count is written to the corresponding query
295    object as the query result value, and the query result for that object is
296    marked as available.
297
298    If the samples-passed count overflows, (i.e., exceeds the value 2^n - 1,
299    where n is the number of bits in the samples-passed count), its value
300    becomes undefined.  It is recommended, but not required, that
301    implementations handle this overflow case by saturating at 2^n - 1 and
302    incrementing no further.
303
304    (Add new Section 4.1.12, Timer Queries, p.212)
305
306    Timer queries use query objects (section 4.1.7) to track the amount of
307    time needed to fully complete a set of GL commands.  A timer query can be
308    started and finished by calling BeginQuery and EndQuery, respectively,
309    with a <target> of TIME_ELAPSED_EXT.
310
311    When BeginQuery and EndQuery are called with a <target> of
312    TIME_ELAPSED_EXT, the GL prepares to start and stop the timer used for
313    timer queries.  The timer is started or stopped when the effects from all
314    previous commands on the GL client and server state and the framebuffer
315    have been fully realized.  The BeginQuery and EndQuery commands may return
316    before the timer is actually started or stopped.  When the timer query
317    timer is finally stopped, the elapsed time (in nanoseconds) is written to
318    the corresponding query object as the query result value, and the query
319    result for that object is marked as available.
320
321    If the elapsed time overflows the number of bits, <n>, available to hold
322    elapsed time, its value becomes undefined.  It is recommended, but not
323    required, that implementations handle this overflow case by saturating at
324    2^n - 1.
325
326Additions to Chapter 5 of the OpenGL 2.0 Specification (Special Functions)
327
328    None.
329
330Additions to Chapter 6 of the OpenGL 2.0 Specification (State and State
331Requests)
332
333    (Replace Section 6.1.12, Occlusion Queries, p. 254)
334
335    Section 6.1.12, Asynchronous Queries
336
337    The command
338
339      boolean IsQuery(uint id);
340
341    returns TRUE if <id> is the name of a query object. If <id> is zero, or if
342    <id> is a non-zero value that is not the name of a query object, IsQuery
343    returns FALSE.
344
345    Information about a query target can be queried with the command
346
347      void GetQueryiv(enum target, enum pname, int *params);
348
349    <target> identifies the query target and can be SAMPLES_PASSED for
350    occlusion queries or TIME_ELAPSED_EXT for timer queries.
351
352    If <pname> is CURRENT_QUERY, the name of the currently active query for
353    <target>, or zero if no query is active, will be placed in <params>.
354
355    If <pname> is QUERY_COUNTER_BITS, the implementation-dependent number of
356    bits used to hold the query result for <target> will be placed in params.
357    The number of query counter bits may be zero, in which case the counter
358    contains no useful information.
359
360    For occlusion queries (SAMPLES_PASSED), if the number of bits is non-zero,
361    the minimum number of bits allowed is a function of the implementation's
362    maximum viewport dimensions (MAX_VIEWPORT_DIMS).  The counter must be able
363    to represent at least two overdraws for every pixel in the viewport.  The
364    formula to compute the allowable minimum value (where n is the minimum
365    number of bits) is:
366
367      n = min(32, ceil(log_2(maxViewportWidth * maxViewportHeight * 2))).
368
369    For timer queries (TIME_ELAPSED_EXT), if the minimum number if bits is
370    non-zero, it must be at least 30.
371
372    The state of a query object can be queried with the commands
373
374      void GetQueryObjectiv(uint id, enum pname, int *params);
375      void GetQueryObjectuiv(uint id, enum pname, uint *params);
376      void GetQueryObjecti64vEXT(uint id, enum pname, int64 *params);
377      void GetQueryObjectui64vEXT(uint id, enum pname, uint64 *params);
378    If <id> is not the name of a query object, or if the query object named by
379    <id> is currently active, then an INVALID_OPERATION error is generated.
380
381    If <pname> is QUERY_RESULT, then the query object's result value is
382    returned as a single integer in <params>.  If the value is so large in
383    magnitude that it cannot be represented with the requested type, then the
384    nearest value representable using the requested type is returned.  If the
385    number of query counter bits for any <target> is zero, then the result is
386    returned as a single integer with a value of 0.
387
388    There may be an indeterminate delay before the above query returns. If
389    <pname> is QUERY_RESULT_AVAILABLE, FALSE is returned if such a delay would
390    be required, TRUE is returned otherwise. It must always be true that if
391    any query object returns a result available of TRUE, all queries of the
392    same type issued prior to that query must also return TRUE.
393
394    Querying the state for any given query object forces the corresponding
395    query to complete within a finite amount of time.
396
397    If multiple queries are issued using the same object name prior to calling
398    GetQueryObject[u]iv, the result and availability information returned will
399    always be from the last query issued.  The results from any queries before
400    the last one will be lost if they are not retrieved before starting a new
401    query on the same <target> and <id>.
402
403GLX Protocol (Modification to the GLX 1.3 Protocol Encoding Specification)
404
405    Add to Section 1.4 (p.2), Common Types
406
407        INT64       A 64-bit signed integer value.
408
409        CARD64      A 64-bit unsigned integer value.
410
411    Two new non-rendering GL commands are added.  These commands are sent
412    seperately (i.e., not as part of a glXRender or glXRenderLarge request),
413    using the glXVendorPrivateWithReply request:
414
415        GetQueryObjecti64vEXT
416            1           CARD8           opcode (X assigned)
417            1           1328            GLX opcode (glXVendorPrivateWithReply)
418            2           4               request length
419            4           GLX_CONTEXT_TAG context tag
420            4           CARD32          id
421            4           ENUM            pname
422          =>
423            1           1               reply
424            1                           unused
425            2           CARD16          sequence number
426            4           m               reply length, m=(n==1?0:n)
427            4                           unused
428            4           CARD32          n
429
430            if (n=1) this follows:
431
432            8           INT64           params
433            8                           unused
434
435            otherwise this follows:
436
437            16                          unused
438            n*8         LISTofINT64     params
439
440        GetQueryObjectui64vEXT
441            1           CARD8           opcode (X assigned)
442            1           1329            GLX opcode (glXVendorPrivateWithReply)
443            2           4               request length
444            4           GLX_CONTEXT_TAG context tag
445            4           CARD32          id
446            4           ENUM            pname
447          =>
448            1           1               reply
449            1                           unused
450            2           CARD16          sequence number
451            4           m               reply length, m=(n==1?0:n)
452            4                           unused
453            4           CARD32          n
454
455           if (n=1) this follows:
456
457            8           CARD64          params
458            8                           unused
459
460            otherwise this follows:
461
462            16                          unused
463            n*8         CARD64          params
464
465Errors
466
467    All existing errors for query objects apply unchanged from the
468    ARB_occlusion_query spec, except the modification below:
469
470    The error INVALID_ENUM is generated if BeginQueryARB, EndQueryARB, or
471    GetQueryivARB is called where <target> is not SAMPLES_PASSED or
472    TIME_ELAPSED_EXT.
473
474    The error INVALID_OPERATION is generated if GetQueryObjecti64vEXT or
475    GetQueryObjectui64vEXT is called where <id> is not the name of a query
476    object.
477
478    The error INVALID_OPERATION is generated if GetQueryObjecti64vEXT or
479    GetQueryObjectui64vEXT is called where <id> is the name of a currently
480    active query object.
481
482    The error INVALID_ENUM is generated if GetQueryObjecti64vEXT or
483    GetQueryObjectui64vEXT is called where <pname> is not QUERY_RESULT or
484    QUERY_RESULT_AVAILABLE.
485
486New State
487
488   (table 6.37, p 298) Update the occlusion query / query object state to
489   cover timer queries:
490
491    Get Value               Type  Get Command       Init. Value  Description                Sec    Attribute
492    ----------------------  ----  ----------------  -----------  -------------------------  -----  ---------
493    CURRENT_QUERY           2xZ+  GetQueryiv        0            Active query object name   4.1.7  -
494                                                                   (occlusion and timer)
495    QUERY_RESULT            2xZ+  GetQueryObjectiv  0            Query object result        4.1.7  -
496                                                                   (samples passed or
497                                                                    time elapsed)
498    QUERY_RESULT_AVAILABLE  2xB   GetQueryObjectiv  TRUE         Query object result        4.1.7  -
499                                                                   available?
500
501New Implementation Dependent State
502
503   (table 6.34, p. 295) Update the occlusion query / query object state to
504   cover timer queries:
505
506    Get Value               Type Get Command  Minimum Value  Description                  Sec     Attribute
507    --------------------    ---- -----------  -------------  --------------------------   ------  ---------
508    QUERY_COUNTER_BITS      2xZ+ GetQueryiv   see 6.1.12     Asynchronous query counter   6.1.12  -
509                                                             bits (occlusion and timer
510                                                             queries)
511
512Dependencies on ARB_occlusion_query and NV_occlusion_query
513
514    If ARB_occlusion_query or NV_occlusion_query is supported, the previous
515    spec edits are considered to apply to the nearly identical language in
516    these extension specifications.  Note that the functionality provided by
517    these extensions is included in OpenGL versions 1.5 and greater.
518
519Usage Examples
520
521    Here is some rough sample code that demonstrates the intended usage
522    of this extension.
523
524        GLint queries[N];
525        GLint available = 0;
526        // timer queries can contain more than 32 bits of data, so always
527        // query them using the 64 bit types to avoid overflow
528        GLuint64 timeElapsed = 0;
529
530        // Create a query object.
531        glGenQueries(N, queries);
532
533        // Start query 1
534        glBeginQuery(GL_TIME_ELAPSED_EXT, queries[0]);
535
536        // Draw object 1
537        ....
538
539        // End query 1
540        glEndQuery(GL_TIME_ELAPSED_EXT);
541
542        ...
543
544        // Start query N
545        glBeginQuery(GL_TIME_ELAPSED_EXT, queries[N-1]);
546
547        // Draw object N
548        ....
549
550        // End query N
551        glEndQuery(GL_TIME_ELAPSED_EXT);
552
553        // Wait for all results to become available
554        while (!available) {
555            glGetQueryObjectiv(queries[N-1], GL_QUERY_RESULT_AVAILABLE, &available);
556        }
557
558        for (i = 0; i < N; i++) {
559            // See how much time the rendering of object i took in nanoseconds.
560            glGetQueryObjectui64vEXT(queries[i], GL_QUERY_RESULT, &timeElapsed);
561
562            // Do something useful with the time.  Note that care should be
563            // taken to use all significant bits of the result, not just the
564            // least significant 32 bits.
565            AdjustObjectLODBasedOnDrawTime(i, timeElapsed);
566        }
567
568    This example is sub-optimal in that it stalls at the end of every
569    frame to wait for query results.  Ideally, the collection of results
570    would be delayed one frame to minimize the amount of time spent
571    waiting for the GPU to finish rendering.
572
573Revision History
574
575    Version 3, June 25, 2013 (Jon Leech) - replace int64EXT / uint64EXT with
576    core int64/uint64 types, for compatibility with EXT_disjoint_timer_query
577    (Bug 10449).
578