diff options
author | Jamie Madill <jmadill@chromium.org> | 2013-09-24 14:07:39 -0400 |
---|---|---|
committer | Jamie Madill <jmadill@chromium.org> | 2013-09-24 14:21:28 -0400 |
commit | ba615196a8f60c73eef978e723ccbd85deea0687 (patch) | |
tree | fc7e834e3fc73d31131ee4bd61a0e4d910797d12 /extensions | |
parent | 5d2e95949f770a34758ac7dbe38aff1473177daa (diff) | |
download | angle-ba615196a8f60c73eef978e723ccbd85deea0687.tar.gz |
Normalize line endings of tracked files in the repository.
TRAC #23896
Signed-off-by: Shannon Woods
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/ANGLE_timer_query.txt | 1182 |
1 files changed, 591 insertions, 591 deletions
diff --git a/extensions/ANGLE_timer_query.txt b/extensions/ANGLE_timer_query.txt index 3cc38582..c1371ad8 100644 --- a/extensions/ANGLE_timer_query.txt +++ b/extensions/ANGLE_timer_query.txt @@ -1,591 +1,591 @@ -Name
-
- ANGLE_timer_query
-
-Name Strings
-
- GL_ANGLE_timer_query
-
-Contributors
-
- Contributors to ARB_occlusion_query
- Contributors to EXT_timer_query
- Contributors to ARB_timer_query
- Ben Vanik, Google Inc.
- Daniel Koch, TransGaming Inc.
-
-Contact
-
- Ben Vanik, Google Inc. (benvanik 'at' google 'dot' com)
-
-Status
-
- Draft
-
-Version
-
- Last Modified Date: Apr 28, 2011
- Author Revision: 1
-
-Number
-
- OpenGL ES Extension #??
-
-Dependencies
-
- OpenGL ES 2.0 is required.
-
- The extension is written against the OpenGL ES 2.0 specification.
-
-Overview
-
- Applications can benefit from accurate timing information in a number of
- different ways. During application development, timing information can
- help identify application or driver bottlenecks. At run time,
- applications can use timing information to dynamically adjust the amount
- of detail in a scene to achieve constant frame rates. OpenGL
- implementations have historically provided little to no useful timing
- information. Applications can get some idea of timing by reading timers
- on the CPU, but these timers are not synchronized with the graphics
- rendering pipeline. Reading a CPU timer does not guarantee the completion
- of a potentially large amount of graphics work accumulated before the
- timer is read, and will thus produce wildly inaccurate results.
- glFinish() can be used to determine when previous rendering commands have
- been completed, but will idle the graphics pipeline and adversely affect
- application performance.
-
- This extension provides a query mechanism that can be used to determine
- the amount of time it takes to fully complete a set of GL commands, and
- without stalling the rendering pipeline. It uses the query object
- mechanisms first introduced in the occlusion query extension, which allow
- time intervals to be polled asynchronously by the application.
-
-IP Status
-
- No known IP claims.
-
-New Procedures and Functions
-
- void GenQueriesANGLE(sizei n, uint *ids);
- void DeleteQueriesANGLE(sizei n, const uint *ids);
- boolean IsQueryANGLE(uint id);
- void BeginQueryANGLE(enum target, uint id);
- void EndQueryANGLE(enum target);
- void QueryCounterANGLE(uint id, enum target);
- void GetQueryivANGLE(enum target, enum pname, int *params);
- void GetQueryObjectivANGLE(uint id, enum pname, int *params);
- void GetQueryObjectuivANGLE(uint id, enum pname, uint *params);
- void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params);
- void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params);
-
-New Tokens
-
- Accepted by the <pname> parameter of GetQueryivANGLE:
-
- QUERY_COUNTER_BITS_ANGLE 0x8864
- CURRENT_QUERY_ANGLE 0x8865
-
- Accepted by the <pname> parameter of GetQueryObjectivANGLE,
- GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, and
- GetQueryObjectui64vANGLE:
-
- QUERY_RESULT_ANGLE 0x8866
- QUERY_RESULT_AVAILABLE_ANGLE 0x8867
-
- Accepted by the <target> parameter of BeginQueryANGLE, EndQueryANGLE, and
- GetQueryivANGLE:
-
- TIME_ELAPSED_ANGLE 0x88BF
-
- Accepted by the <target> parameter of GetQueryivANGLE and
- QueryCounterANGLE:
-
- TIMESTAMP_ANGLE 0x8E28
-
-Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation)
-
- (Modify table 2.1, Correspondence of command suffix letters to GL argument)
- Add two new types:
-
- Letter Corresponding GL Type
- ------ ---------------------
- i64 int64ANGLE
- ui64 uint64ANGLE
-
- (Modify table 2.2, GL data types) Add two new types:
-
- GL Type Minimum Bit Width Description
- ------- ----------------- -----------------------------
- int64ANGLE 64 Signed 2's complement integer
- uint64ANGLE 64 Unsigned binary integer
-
-Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)
-
- Add a new section 5.3 "Timer Queries":
-
- "5.3 Timer Queries
-
- Timer queries use query objects to track the amount of time needed to
- fully complete a set of GL commands, or to determine the current time
- of the GL.
-
- Timer queries are associated with query objects. The command
-
- void GenQueriesANGLE(sizei n, uint *ids);
-
- returns <n> previously unused query object names in <ids>. These
- names are marked as used, but no object is associated with them until
- the first time they are used by BeginQueryANGLE. Query objects contain
- one piece of state, an integer result value. This result value is
- initialized to zero when the object is created. Any positive integer
- except for zero (which is reserved for the GL) is a valid query
- object name.
-
- Query objects are deleted by calling
-
- void DeleteQueriesANGLE(sizei n, const uint *ids);
-
- <ids> contains <n> names of query objects to be deleted. After a
- query object is deleted, its name is again unused. Unused names in
- <ids> are silently ignored.
- If an active query object is deleted its name immediately becomes unused,
- but the underlying object is not deleted until it is no longer active.
-
- A timer query can be started and finished by calling
-
- void BeginQueryANGLE(enum target, uint id);
- void EndQueryANGLE(enum target);
-
- where <target> is TIME_ELAPSED_ANGLE. If BeginQueryANGLE is called
- with an unused <id>, that name is marked as used and associated with
- a new query object.
-
- If BeginQueryANGLE is called with an <id> of zero, if the active query
- object name for <target> is non-zero, if <id> is the name of an existing
- query object whose type does not match <target>, or if <id> is the active
- query object name for any query type, the error INVALID_OPERATION is
- generated. If EndQueryANGLE is called while no query with the same target
- is in progress, an INVALID_OPERATION error is generated.
-
- When BeginQueryANGLE and EndQueryANGLE are called with a <target> of
- TIME_ELAPSED_ANGLE, the GL prepares to start and stop the timer used for
- timer queries. The timer is started or stopped when the effects from all
- previous commands on the GL client and server state and the framebuffer
- have been fully realized. The BeginQueryANGLE and EndQueryANGLE commands
- may return before the timer is actually started or stopped. When the timer
- query timer is finally stopped, the elapsed time (in nanoseconds) is
- written to the corresponding query object as the query result value, and
- the query result for that object is marked as available.
-
- If the elapsed time overflows the number of bits, <n>, available to hold
- elapsed time, its value becomes undefined. It is recommended, but not
- required, that implementations handle this overflow case by saturating at
- 2^n - 1.
-
- The necessary state is a single bit indicating whether an timer
- query is active, the identifier of the currently active timer
- query, and a counter keeping track of the time that has passed.
-
- When the command
-
- void QueryCounterANGLE(uint id, enum target);
-
- is called with <target> TIMESTAMP_ANGLE, the GL records the current time
- into the corresponding query object. The time is recorded after all
- previous commands on the GL client and server state and the framebuffer
- have been fully realized. When the time is recorded, the query result for
- that object is marked available. QueryCounterANGLE timer queries can be
- used within a BeginQueryANGLE / EndQueryANGLE block where the <target> is
- TIME_ELAPSED_ANGLE and it does not affect the result of that query object.
- The error INVALID_OPERATION is generated if the <id> is already in use
- within a BeginQueryANGLE/EndQueryANGLE block."
-
-Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
-Requests)
-
- Add a new section 6.1.9 "Timer Queries":
-
- "The command
-
- boolean IsQueryANGLE(uint id);
-
- returns TRUE if <id> is the name of a query object. If <id> is zero,
- or if <id> is a non-zero value that is not the name of a query
- object, IsQueryANGLE returns FALSE.
-
- Information about a query target can be queried with the command
-
- void GetQueryivANGLE(enum target, enum pname, int *params);
-
- <target> identifies the query target and can be TIME_ELAPSED_ANGLE or
- TIMESTAMP_ANGLE for timer queries.
-
- If <pname> is CURRENT_QUERY_ANGLE, the name of the currently active query
- for <target>, or zero if no query is active, will be placed in <params>.
-
- If <pname> is QUERY_COUNTER_BITS_ANGLE, the implementation-dependent number
- of bits used to hold the query result for <target> will be placed in
- <params>. The number of query counter bits may be zero, in which case
- the counter contains no useful information.
-
- For timer queries (TIME_ELAPSED_ANGLE and TIMESTAMP_ANGLE), if the number
- of bits is non-zero, the minimum number of bits allowed is 30 which
- will allow at least 1 second of timing.
-
- The state of a query object can be queried with the commands
-
- void GetQueryObjectivANGLE(uint id, enum pname, int *params);
- void GetQueryObjectuivANGLE(uint id, enum pname, uint *params);
- void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params);
- void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params);
-
- If <id> is not the name of a query object, or if the query object
- named by <id> is currently active, then an INVALID_OPERATION error is
- generated.
-
- If <pname> is QUERY_RESULT_ANGLE, then the query object's result
- value is returned as a single integer in <params>. If the value is so
- large in magnitude that it cannot be represented with the requested type,
- then the nearest value representable using the requested type is
- returned. If the number of query counter bits for target is zero, then
- the result is returned as a single integer with the value zero.
-
- There may be an indeterminate delay before the above query returns. If
- <pname> is QUERY_RESULT_AVAILABLE_ANGLE, FALSE is returned if such a delay
- would be required; otherwise TRUE is returned. It must always be true
- that if any query object returns a result available of TRUE, all queries
- of the same type issued prior to that query must also return TRUE.
-
- Querying the state for a given timer query forces that timer query to
- complete within a finite amount of time.
-
- If multiple queries are issued on the same target and id prior to
- calling GetQueryObject[u]i[64]vANGLE, the result returned will always be
- from the last query issued. The results from any queries before the
- last one will be lost if the results are not retrieved before starting
- a new query on the same <target> and <id>."
-
-Errors
-
- The error INVALID_VALUE is generated if GenQueriesANGLE is called where
- <n> is negative.
-
- The error INVALID_VALUE is generated if DeleteQueriesANGLE is called
- where <n> is negative.
-
- The error INVALID_OPERATION is generated if BeginQueryANGLE is called
- when a query of the given <target> is already active.
-
- The error INVALID_OPERATION is generated if EndQueryANGLE is called
- when a query of the given <target> is not active.
-
- The error INVALID_OPERATION is generated if BeginQueryANGLE is called
- where <id> is zero.
-
- The error INVALID_OPERATION is generated if BeginQueryANGLE is called
- where <id> is the name of a query currently in progress.
-
- The error INVALID_OPERATION is generated if BeginQueryANGLE is called
- where <id> is the name of an existing query object whose type does not
- match <target>.
-
- The error INVALID_ENUM is generated if BeginQueryANGLE or EndQueryANGLE
- is called where <target> is not TIME_ELAPSED_ANGLE.
-
- The error INVALID_ENUM is generated if GetQueryivANGLE is called where
- <target> is not TIME_ELAPSED_ANGLE or TIMESTAMP_ANGLE.
-
- The error INVALID_ENUM is generated if GetQueryivANGLE is called where
- <pname> is not QUERY_COUNTER_BITS_ANGLE or CURRENT_QUERY_ANGLE.
-
- The error INVALID_ENUM is generated if QueryCounterANGLE is called where
- <target> is not TIMESTAMP_ANGLE.
-
- The error INVALID_OPERATION is generated if QueryCounterANGLE is called
- on a query object that is already in use inside a
- BeginQueryANGLE/EndQueryANGLE.
-
- The error INVALID_OPERATION is generated if GetQueryObjectivANGLE,
- GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or
- GetQueryObjectui64vANGLE is called where <id> is not the name of a query
- object.
-
- The error INVALID_OPERATION is generated if GetQueryObjectivANGLE,
- GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or
- GetQueryObjectui64vANGLE is called where <id> is the name of a currently
- active query object.
-
- The error INVALID_ENUM is generated if GetQueryObjectivANGLE,
- GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or
- GetQueryObjectui64vANGLE is called where <pname> is not
- QUERY_RESULT_ANGLE or QUERY_RESULT_AVAILABLE_ANGLE.
-
-New State
-
- (Add a new table 6.xx, "Query Operations")
-
- Get Value Type Get Command Initial Value Description Sec
- --------- ---- ----------- ------------- ----------- ------
- - B - FALSE query active 5.3
- CURRENT_QUERY_ANGLE Z+ GetQueryivANGLE 0 active query ID 5.3
- QUERY_RESULT_ANGLE Z+ GetQueryObjectuivANGLE, 0 samples-passed count 5.3
- GetQueryObjectui64vANGLE
- QUERY_RESULT_AVAILABLE_ANGLE B GetQueryObjectivANGLE FALSE query result available 5.3
-
-New Implementation Dependent State
-
- (Add the following entry to table 6.18):
-
- Get Value Type Get Command Minimum Value Description Sec
- -------------------------- ---- ----------- ------------- ---------------- ------
- QUERY_COUNTER_BITS_ANGLE Z+ GetQueryivANGLE see 6.1.9 Number of bits in 6.1.9
- query counter
-
-Examples
-
- (1) Here is some rough sample code that demonstrates the intended usage
- of this extension.
-
- GLint queries[N];
- GLint available = 0;
- // timer queries can contain more than 32 bits of data, so always
- // query them using the 64 bit types to avoid overflow
- GLuint64ANGLE timeElapsed = 0;
-
- // Create a query object.
- glGenQueriesANGLE(N, queries);
-
- // Start query 1
- glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[0]);
-
- // Draw object 1
- ....
-
- // End query 1
- glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE);
-
- ...
-
- // Start query N
- glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[N-1]);
-
- // Draw object N
- ....
-
- // End query N
- glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE);
-
- // Wait for all results to become available
- while (!available) {
- glGetQueryObjectivANGLE(queries[N-1], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available);
- }
-
- for (i = 0; i < N; i++) {
- // See how much time the rendering of object i took in nanoseconds.
- glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeElapsed);
-
- // Do something useful with the time. Note that care should be
- // taken to use all significant bits of the result, not just the
- // least significant 32 bits.
- AdjustObjectLODBasedOnDrawTime(i, timeElapsed);
- }
-
- This example is sub-optimal in that it stalls at the end of every
- frame to wait for query results. Ideally, the collection of results
- would be delayed one frame to minimize the amount of time spent
- waiting for the GPU to finish rendering.
-
- (2) This example is basically the same as the example above but uses
- QueryCounter instead.
-
- GLint queries[N+1];
- GLint available = 0;
- // timer queries can contain more than 32 bits of data, so always
- // query them using the 64 bit types to avoid overflow
- GLuint64ANGLE timeStart, timeEnd, timeElapsed = 0;
-
- // Create a query object.
- glGenQueriesANGLE(N+1, queries);
-
- // Query current timestamp 1
- glQueryCounterANGLE(queries[0], GL_TIMESTAMP_ANGLE);
-
- // Draw object 1
- ....
-
- // Query current timestamp N
- glQueryCounterANGLE(queries[N-1], GL_TIMESTAMP_ANGLE);
-
- // Draw object N
- ....
-
- // Query current timestamp N+1
- glQueryCounterANGLE(queries[N], GL_TIMESTAMP_ANGLE);
-
- // Wait for all results to become available
- while (!available) {
- glGetQueryObjectivANGLE(queries[N], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available);
- }
-
- for (i = 0; i < N; i++) {
- // See how much time the rendering of object i took in nanoseconds.
- glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeStart);
- glGetQueryObjectui64vANGLE(queries[i+1], GL_QUERY_RESULT_ANGLE, &timeEnd);
- timeElapsed = timeEnd - timeStart;
-
- // Do something useful with the time. Note that care should be
- // taken to use all significant bits of the result, not just the
- // least significant 32 bits.
- AdjustObjectLODBasedOnDrawTime(i, timeElapsed);
- }
-
-Issues from EXT_timer_query
-
- (1) What time interval is being measured?
-
- RESOLVED: The timer starts when all commands prior to BeginQuery() have
- been fully executed. At that point, everything that should be drawn by
- those commands has been written to the framebuffer. The timer stops
- when all commands prior to EndQuery() have been fully executed.
-
- (2) What unit of time will time intervals be returned in?
-
- RESOLVED: Nanoseconds (10^-9 seconds). This unit of measurement allows
- for reasonably accurate timing of even small blocks of rendering
- commands. The granularity of the timer is implementation-dependent. A
- 32-bit query counter can express intervals of up to approximately 4
- seconds.
-
- (3) What should be the minimum number of counter bits for timer queries?
-
- RESOLVED: 30 bits, which will allow timing sections that take up to 1
- second to render.
-
- (4) How are counter results of more than 32 bits returned?
-
- RESOLVED: Via two new datatypes, int64ANGLE and uint64ANGLE, and their
- corresponding GetQueryObject entry points. These types hold integer
- values and have a minimum bit width of 64.
-
- (5) Should the extension measure total time elapsed between the full
- completion of the BeginQuery and EndQuery commands, or just time
- spent in the graphics library?
-
- RESOLVED: This extension will measure the total time elapsed between
- the full completion of these commands. Future extensions may implement
- a query to determine time elapsed at different stages of the graphics
- pipeline.
-
- (6) If multiple query types are supported, can multiple query types be
- active simultaneously?
-
- RESOLVED: Yes; an application may perform a timer query and another
- type of query simultaneously. An application can not perform multiple
- timer queries or multiple queries of other types simultaneously. An
- application also can not use the same query object for another query
- and a timer query simultaneously.
-
- (7) Do query objects have a query type permanently associated with them?
-
- RESOLVED: No. A single query object can be used to perform different
- types of queries, but not at the same time.
-
- Having a fixed type for each query object simplifies some aspects of the
- implementation -- not having to deal with queries with different result
- sizes, for example. It would also mean that BeginQuery() with a query
- object of the "wrong" type would result in an INVALID_OPERATION error.
-
- UPDATE: This resolution was relevant for EXT_timer_query and OpenGL 2.0.
- Since EXT_transform_feedback has since been incorporated into the core,
- the resolution is that BeginQuery will generate error INVALID_OPERATION
- if <id> represents a query object of a different type.
-
- (8) How predictable/repeatable are the results returned by the timer
- query?
-
- RESOLVED: In general, the amount of time needed to render the same
- primitives should be fairly constant. But there may be many other
- system issues (e.g., context switching on the CPU and GPU, virtual
- memory page faults, memory cache behavior on the CPU and GPU) that can
- cause times to vary wildly.
-
- Note that modern GPUs are generally highly pipelined, and may be
- processing different primitives in different pipeline stages
- simultaneously. In this extension, the timers start and stop when the
- BeginQuery/EndQuery commands reach the bottom of the rendering pipeline.
- What that means is that by the time the timer starts, the GL driver on
- the CPU may have started work on GL commands issued after BeginQuery,
- and the higher pipeline stages (e.g., vertex transformation) may have
- started as well.
-
- (9) What should the new 64 bit integer type be called?
-
- RESOLVED: The new types will be called GLint64ANGLE/GLuint64ANGLE. The new
- command suffixes will be i64 and ui64. These names clearly convey the
- minimum size of the types. These types are similar to the C99 standard
- type int_least64_t, but we use names similar to the C99 optional type
- int64_t for simplicity.
-
-Issues from ARB_timer_query
-
- (10) What about tile-based implementations? The effects of a command are
- not complete until the frame is completely rendered. Timing recorded
- before the frame is complete may not be what developers expect. Also
- the amount of time needed to render the same primitives is not
- consistent, which conflicts with issue (8) above. The time depends on
- how early or late in the scene it is placed.
-
- RESOLVED: The current language supports tile-based rendering okay as it
- is written. Developers are warned that using timers on tile-based
- implementation may not produce results they expect since rendering is not
- done in a linear order. Timing results are calculated when the frame is
- completed and may depend on how early or late in the scene it is placed.
-
- (11) Can the GL implementation use different clocks to implement the
- TIME_ELAPSED and TIMESTAMP queries?
-
- RESOLVED: Yes, the implemenation can use different internal clocks to
- implement TIME_ELAPSED and TIMESTAMP. If different clocks are
- used it is possible there is a slight discrepancy when comparing queries
- made from TIME_ELAPSED and TIMESTAMP; they may have slight
- differences when both are used to measure the same sequence. However, this
- is unlikely to affect real applications since comparing the two queries is
- not expected to be useful.
-
-Issues
-
- (12) What should we call this extension?
-
- RESOLVED: ANGLE_timer_query
-
- (13) Why is this done as a separate extension instead of just supporting
- ARB_timer_query?
-
- ARB_timer_query is written against OpenGL 3.2, which includes a lot of
- the required support for dealing with query objects. None of these
- functions or tokens exist in OpenGL ES, and as such have to be added in
- this specification.
-
- (14) How does this extension differ from ARB_timer_query?
-
- This extension contains most ARB_timer_query behavior unchanged as well
- as a subset of the query support required to use it from the core
- OpenGL 3.2 spec. It omits the glGetInteger(TIMESTAMP) functionality used to
- query the current time on the GPU, but the behavior for all remaining
- functionality taken from ARB_timer_query is the same.
-
- (15) Are query objects shareable between multiple contexts?
-
- RESOLVED: No. Query objects are lightweight and we normally share
- large data across contexts. Also, being able to share query objects
- across contexts is not particularly useful. In order to do the async
- query across contexts, a query on one context would have to be finished
- before the other context could query it.
-
-Revision History
-
- Revision 1, 2011/04/28
- - copied from revision 9 of ARB_timer_query and revision 7 of
- ARB_occlusion_query
- - removed language that was clearly not relevant to ES2
- - rebased changes against the OpenGL ES 2.0 specification
+Name + + ANGLE_timer_query + +Name Strings + + GL_ANGLE_timer_query + +Contributors + + Contributors to ARB_occlusion_query + Contributors to EXT_timer_query + Contributors to ARB_timer_query + Ben Vanik, Google Inc. + Daniel Koch, TransGaming Inc. + +Contact + + Ben Vanik, Google Inc. (benvanik 'at' google 'dot' com) + +Status + + Draft + +Version + + Last Modified Date: Apr 28, 2011 + Author Revision: 1 + +Number + + OpenGL ES Extension #?? + +Dependencies + + OpenGL ES 2.0 is required. + + The extension is written against the OpenGL ES 2.0 specification. + +Overview + + Applications can benefit from accurate timing information in a number of + different ways. During application development, timing information can + help identify application or driver bottlenecks. At run time, + applications can use timing information to dynamically adjust the amount + of detail in a scene to achieve constant frame rates. OpenGL + implementations have historically provided little to no useful timing + information. Applications can get some idea of timing by reading timers + on the CPU, but these timers are not synchronized with the graphics + rendering pipeline. Reading a CPU timer does not guarantee the completion + of a potentially large amount of graphics work accumulated before the + timer is read, and will thus produce wildly inaccurate results. + glFinish() can be used to determine when previous rendering commands have + been completed, but will idle the graphics pipeline and adversely affect + application performance. + + This extension provides a query mechanism that can be used to determine + the amount of time it takes to fully complete a set of GL commands, and + without stalling the rendering pipeline. It uses the query object + mechanisms first introduced in the occlusion query extension, which allow + time intervals to be polled asynchronously by the application. + +IP Status + + No known IP claims. + +New Procedures and Functions + + void GenQueriesANGLE(sizei n, uint *ids); + void DeleteQueriesANGLE(sizei n, const uint *ids); + boolean IsQueryANGLE(uint id); + void BeginQueryANGLE(enum target, uint id); + void EndQueryANGLE(enum target); + void QueryCounterANGLE(uint id, enum target); + void GetQueryivANGLE(enum target, enum pname, int *params); + void GetQueryObjectivANGLE(uint id, enum pname, int *params); + void GetQueryObjectuivANGLE(uint id, enum pname, uint *params); + void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params); + void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params); + +New Tokens + + Accepted by the <pname> parameter of GetQueryivANGLE: + + QUERY_COUNTER_BITS_ANGLE 0x8864 + CURRENT_QUERY_ANGLE 0x8865 + + Accepted by the <pname> parameter of GetQueryObjectivANGLE, + GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, and + GetQueryObjectui64vANGLE: + + QUERY_RESULT_ANGLE 0x8866 + QUERY_RESULT_AVAILABLE_ANGLE 0x8867 + + Accepted by the <target> parameter of BeginQueryANGLE, EndQueryANGLE, and + GetQueryivANGLE: + + TIME_ELAPSED_ANGLE 0x88BF + + Accepted by the <target> parameter of GetQueryivANGLE and + QueryCounterANGLE: + + TIMESTAMP_ANGLE 0x8E28 + +Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation) + + (Modify table 2.1, Correspondence of command suffix letters to GL argument) + Add two new types: + + Letter Corresponding GL Type + ------ --------------------- + i64 int64ANGLE + ui64 uint64ANGLE + + (Modify table 2.2, GL data types) Add two new types: + + GL Type Minimum Bit Width Description + ------- ----------------- ----------------------------- + int64ANGLE 64 Signed 2's complement integer + uint64ANGLE 64 Unsigned binary integer + +Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions) + + Add a new section 5.3 "Timer Queries": + + "5.3 Timer Queries + + Timer queries use query objects to track the amount of time needed to + fully complete a set of GL commands, or to determine the current time + of the GL. + + Timer queries are associated with query objects. The command + + void GenQueriesANGLE(sizei n, uint *ids); + + returns <n> previously unused query object names in <ids>. These + names are marked as used, but no object is associated with them until + the first time they are used by BeginQueryANGLE. Query objects contain + one piece of state, an integer result value. This result value is + initialized to zero when the object is created. Any positive integer + except for zero (which is reserved for the GL) is a valid query + object name. + + Query objects are deleted by calling + + void DeleteQueriesANGLE(sizei n, const uint *ids); + + <ids> contains <n> names of query objects to be deleted. After a + query object is deleted, its name is again unused. Unused names in + <ids> are silently ignored. + If an active query object is deleted its name immediately becomes unused, + but the underlying object is not deleted until it is no longer active. + + A timer query can be started and finished by calling + + void BeginQueryANGLE(enum target, uint id); + void EndQueryANGLE(enum target); + + where <target> is TIME_ELAPSED_ANGLE. If BeginQueryANGLE is called + with an unused <id>, that name is marked as used and associated with + a new query object. + + If BeginQueryANGLE is called with an <id> of zero, if the active query + object name for <target> is non-zero, if <id> is the name of an existing + query object whose type does not match <target>, or if <id> is the active + query object name for any query type, the error INVALID_OPERATION is + generated. If EndQueryANGLE is called while no query with the same target + is in progress, an INVALID_OPERATION error is generated. + + When BeginQueryANGLE and EndQueryANGLE are called with a <target> of + TIME_ELAPSED_ANGLE, the GL prepares to start and stop the timer used for + timer queries. The timer is started or stopped when the effects from all + previous commands on the GL client and server state and the framebuffer + have been fully realized. The BeginQueryANGLE and EndQueryANGLE commands + may return before the timer is actually started or stopped. When the timer + query timer is finally stopped, the elapsed time (in nanoseconds) is + written to the corresponding query object as the query result value, and + the query result for that object is marked as available. + + If the elapsed time overflows the number of bits, <n>, available to hold + elapsed time, its value becomes undefined. It is recommended, but not + required, that implementations handle this overflow case by saturating at + 2^n - 1. + + The necessary state is a single bit indicating whether an timer + query is active, the identifier of the currently active timer + query, and a counter keeping track of the time that has passed. + + When the command + + void QueryCounterANGLE(uint id, enum target); + + is called with <target> TIMESTAMP_ANGLE, the GL records the current time + into the corresponding query object. The time is recorded after all + previous commands on the GL client and server state and the framebuffer + have been fully realized. When the time is recorded, the query result for + that object is marked available. QueryCounterANGLE timer queries can be + used within a BeginQueryANGLE / EndQueryANGLE block where the <target> is + TIME_ELAPSED_ANGLE and it does not affect the result of that query object. + The error INVALID_OPERATION is generated if the <id> is already in use + within a BeginQueryANGLE/EndQueryANGLE block." + +Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State +Requests) + + Add a new section 6.1.9 "Timer Queries": + + "The command + + boolean IsQueryANGLE(uint id); + + returns TRUE if <id> is the name of a query object. If <id> is zero, + or if <id> is a non-zero value that is not the name of a query + object, IsQueryANGLE returns FALSE. + + Information about a query target can be queried with the command + + void GetQueryivANGLE(enum target, enum pname, int *params); + + <target> identifies the query target and can be TIME_ELAPSED_ANGLE or + TIMESTAMP_ANGLE for timer queries. + + If <pname> is CURRENT_QUERY_ANGLE, the name of the currently active query + for <target>, or zero if no query is active, will be placed in <params>. + + If <pname> is QUERY_COUNTER_BITS_ANGLE, the implementation-dependent number + of bits used to hold the query result for <target> will be placed in + <params>. The number of query counter bits may be zero, in which case + the counter contains no useful information. + + For timer queries (TIME_ELAPSED_ANGLE and TIMESTAMP_ANGLE), if the number + of bits is non-zero, the minimum number of bits allowed is 30 which + will allow at least 1 second of timing. + + The state of a query object can be queried with the commands + + void GetQueryObjectivANGLE(uint id, enum pname, int *params); + void GetQueryObjectuivANGLE(uint id, enum pname, uint *params); + void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params); + void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params); + + If <id> is not the name of a query object, or if the query object + named by <id> is currently active, then an INVALID_OPERATION error is + generated. + + If <pname> is QUERY_RESULT_ANGLE, then the query object's result + value is returned as a single integer in <params>. If the value is so + large in magnitude that it cannot be represented with the requested type, + then the nearest value representable using the requested type is + returned. If the number of query counter bits for target is zero, then + the result is returned as a single integer with the value zero. + + There may be an indeterminate delay before the above query returns. If + <pname> is QUERY_RESULT_AVAILABLE_ANGLE, FALSE is returned if such a delay + would be required; otherwise TRUE is returned. It must always be true + that if any query object returns a result available of TRUE, all queries + of the same type issued prior to that query must also return TRUE. + + Querying the state for a given timer query forces that timer query to + complete within a finite amount of time. + + If multiple queries are issued on the same target and id prior to + calling GetQueryObject[u]i[64]vANGLE, the result returned will always be + from the last query issued. The results from any queries before the + last one will be lost if the results are not retrieved before starting + a new query on the same <target> and <id>." + +Errors + + The error INVALID_VALUE is generated if GenQueriesANGLE is called where + <n> is negative. + + The error INVALID_VALUE is generated if DeleteQueriesANGLE is called + where <n> is negative. + + The error INVALID_OPERATION is generated if BeginQueryANGLE is called + when a query of the given <target> is already active. + + The error INVALID_OPERATION is generated if EndQueryANGLE is called + when a query of the given <target> is not active. + + The error INVALID_OPERATION is generated if BeginQueryANGLE is called + where <id> is zero. + + The error INVALID_OPERATION is generated if BeginQueryANGLE is called + where <id> is the name of a query currently in progress. + + The error INVALID_OPERATION is generated if BeginQueryANGLE is called + where <id> is the name of an existing query object whose type does not + match <target>. + + The error INVALID_ENUM is generated if BeginQueryANGLE or EndQueryANGLE + is called where <target> is not TIME_ELAPSED_ANGLE. + + The error INVALID_ENUM is generated if GetQueryivANGLE is called where + <target> is not TIME_ELAPSED_ANGLE or TIMESTAMP_ANGLE. + + The error INVALID_ENUM is generated if GetQueryivANGLE is called where + <pname> is not QUERY_COUNTER_BITS_ANGLE or CURRENT_QUERY_ANGLE. + + The error INVALID_ENUM is generated if QueryCounterANGLE is called where + <target> is not TIMESTAMP_ANGLE. + + The error INVALID_OPERATION is generated if QueryCounterANGLE is called + on a query object that is already in use inside a + BeginQueryANGLE/EndQueryANGLE. + + The error INVALID_OPERATION is generated if GetQueryObjectivANGLE, + GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or + GetQueryObjectui64vANGLE is called where <id> is not the name of a query + object. + + The error INVALID_OPERATION is generated if GetQueryObjectivANGLE, + GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or + GetQueryObjectui64vANGLE is called where <id> is the name of a currently + active query object. + + The error INVALID_ENUM is generated if GetQueryObjectivANGLE, + GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or + GetQueryObjectui64vANGLE is called where <pname> is not + QUERY_RESULT_ANGLE or QUERY_RESULT_AVAILABLE_ANGLE. + +New State + + (Add a new table 6.xx, "Query Operations") + + Get Value Type Get Command Initial Value Description Sec + --------- ---- ----------- ------------- ----------- ------ + - B - FALSE query active 5.3 + CURRENT_QUERY_ANGLE Z+ GetQueryivANGLE 0 active query ID 5.3 + QUERY_RESULT_ANGLE Z+ GetQueryObjectuivANGLE, 0 samples-passed count 5.3 + GetQueryObjectui64vANGLE + QUERY_RESULT_AVAILABLE_ANGLE B GetQueryObjectivANGLE FALSE query result available 5.3 + +New Implementation Dependent State + + (Add the following entry to table 6.18): + + Get Value Type Get Command Minimum Value Description Sec + -------------------------- ---- ----------- ------------- ---------------- ------ + QUERY_COUNTER_BITS_ANGLE Z+ GetQueryivANGLE see 6.1.9 Number of bits in 6.1.9 + query counter + +Examples + + (1) Here is some rough sample code that demonstrates the intended usage + of this extension. + + GLint queries[N]; + GLint available = 0; + // timer queries can contain more than 32 bits of data, so always + // query them using the 64 bit types to avoid overflow + GLuint64ANGLE timeElapsed = 0; + + // Create a query object. + glGenQueriesANGLE(N, queries); + + // Start query 1 + glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[0]); + + // Draw object 1 + .... + + // End query 1 + glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE); + + ... + + // Start query N + glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[N-1]); + + // Draw object N + .... + + // End query N + glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE); + + // Wait for all results to become available + while (!available) { + glGetQueryObjectivANGLE(queries[N-1], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available); + } + + for (i = 0; i < N; i++) { + // See how much time the rendering of object i took in nanoseconds. + glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeElapsed); + + // Do something useful with the time. Note that care should be + // taken to use all significant bits of the result, not just the + // least significant 32 bits. + AdjustObjectLODBasedOnDrawTime(i, timeElapsed); + } + + This example is sub-optimal in that it stalls at the end of every + frame to wait for query results. Ideally, the collection of results + would be delayed one frame to minimize the amount of time spent + waiting for the GPU to finish rendering. + + (2) This example is basically the same as the example above but uses + QueryCounter instead. + + GLint queries[N+1]; + GLint available = 0; + // timer queries can contain more than 32 bits of data, so always + // query them using the 64 bit types to avoid overflow + GLuint64ANGLE timeStart, timeEnd, timeElapsed = 0; + + // Create a query object. + glGenQueriesANGLE(N+1, queries); + + // Query current timestamp 1 + glQueryCounterANGLE(queries[0], GL_TIMESTAMP_ANGLE); + + // Draw object 1 + .... + + // Query current timestamp N + glQueryCounterANGLE(queries[N-1], GL_TIMESTAMP_ANGLE); + + // Draw object N + .... + + // Query current timestamp N+1 + glQueryCounterANGLE(queries[N], GL_TIMESTAMP_ANGLE); + + // Wait for all results to become available + while (!available) { + glGetQueryObjectivANGLE(queries[N], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available); + } + + for (i = 0; i < N; i++) { + // See how much time the rendering of object i took in nanoseconds. + glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeStart); + glGetQueryObjectui64vANGLE(queries[i+1], GL_QUERY_RESULT_ANGLE, &timeEnd); + timeElapsed = timeEnd - timeStart; + + // Do something useful with the time. Note that care should be + // taken to use all significant bits of the result, not just the + // least significant 32 bits. + AdjustObjectLODBasedOnDrawTime(i, timeElapsed); + } + +Issues from EXT_timer_query + + (1) What time interval is being measured? + + RESOLVED: The timer starts when all commands prior to BeginQuery() have + been fully executed. At that point, everything that should be drawn by + those commands has been written to the framebuffer. The timer stops + when all commands prior to EndQuery() have been fully executed. + + (2) What unit of time will time intervals be returned in? + + RESOLVED: Nanoseconds (10^-9 seconds). This unit of measurement allows + for reasonably accurate timing of even small blocks of rendering + commands. The granularity of the timer is implementation-dependent. A + 32-bit query counter can express intervals of up to approximately 4 + seconds. + + (3) What should be the minimum number of counter bits for timer queries? + + RESOLVED: 30 bits, which will allow timing sections that take up to 1 + second to render. + + (4) How are counter results of more than 32 bits returned? + + RESOLVED: Via two new datatypes, int64ANGLE and uint64ANGLE, and their + corresponding GetQueryObject entry points. These types hold integer + values and have a minimum bit width of 64. + + (5) Should the extension measure total time elapsed between the full + completion of the BeginQuery and EndQuery commands, or just time + spent in the graphics library? + + RESOLVED: This extension will measure the total time elapsed between + the full completion of these commands. Future extensions may implement + a query to determine time elapsed at different stages of the graphics + pipeline. + + (6) If multiple query types are supported, can multiple query types be + active simultaneously? + + RESOLVED: Yes; an application may perform a timer query and another + type of query simultaneously. An application can not perform multiple + timer queries or multiple queries of other types simultaneously. An + application also can not use the same query object for another query + and a timer query simultaneously. + + (7) Do query objects have a query type permanently associated with them? + + RESOLVED: No. A single query object can be used to perform different + types of queries, but not at the same time. + + Having a fixed type for each query object simplifies some aspects of the + implementation -- not having to deal with queries with different result + sizes, for example. It would also mean that BeginQuery() with a query + object of the "wrong" type would result in an INVALID_OPERATION error. + + UPDATE: This resolution was relevant for EXT_timer_query and OpenGL 2.0. + Since EXT_transform_feedback has since been incorporated into the core, + the resolution is that BeginQuery will generate error INVALID_OPERATION + if <id> represents a query object of a different type. + + (8) How predictable/repeatable are the results returned by the timer + query? + + RESOLVED: In general, the amount of time needed to render the same + primitives should be fairly constant. But there may be many other + system issues (e.g., context switching on the CPU and GPU, virtual + memory page faults, memory cache behavior on the CPU and GPU) that can + cause times to vary wildly. + + Note that modern GPUs are generally highly pipelined, and may be + processing different primitives in different pipeline stages + simultaneously. In this extension, the timers start and stop when the + BeginQuery/EndQuery commands reach the bottom of the rendering pipeline. + What that means is that by the time the timer starts, the GL driver on + the CPU may have started work on GL commands issued after BeginQuery, + and the higher pipeline stages (e.g., vertex transformation) may have + started as well. + + (9) What should the new 64 bit integer type be called? + + RESOLVED: The new types will be called GLint64ANGLE/GLuint64ANGLE. The new + command suffixes will be i64 and ui64. These names clearly convey the + minimum size of the types. These types are similar to the C99 standard + type int_least64_t, but we use names similar to the C99 optional type + int64_t for simplicity. + +Issues from ARB_timer_query + + (10) What about tile-based implementations? The effects of a command are + not complete until the frame is completely rendered. Timing recorded + before the frame is complete may not be what developers expect. Also + the amount of time needed to render the same primitives is not + consistent, which conflicts with issue (8) above. The time depends on + how early or late in the scene it is placed. + + RESOLVED: The current language supports tile-based rendering okay as it + is written. Developers are warned that using timers on tile-based + implementation may not produce results they expect since rendering is not + done in a linear order. Timing results are calculated when the frame is + completed and may depend on how early or late in the scene it is placed. + + (11) Can the GL implementation use different clocks to implement the + TIME_ELAPSED and TIMESTAMP queries? + + RESOLVED: Yes, the implemenation can use different internal clocks to + implement TIME_ELAPSED and TIMESTAMP. If different clocks are + used it is possible there is a slight discrepancy when comparing queries + made from TIME_ELAPSED and TIMESTAMP; they may have slight + differences when both are used to measure the same sequence. However, this + is unlikely to affect real applications since comparing the two queries is + not expected to be useful. + +Issues + + (12) What should we call this extension? + + RESOLVED: ANGLE_timer_query + + (13) Why is this done as a separate extension instead of just supporting + ARB_timer_query? + + ARB_timer_query is written against OpenGL 3.2, which includes a lot of + the required support for dealing with query objects. None of these + functions or tokens exist in OpenGL ES, and as such have to be added in + this specification. + + (14) How does this extension differ from ARB_timer_query? + + This extension contains most ARB_timer_query behavior unchanged as well + as a subset of the query support required to use it from the core + OpenGL 3.2 spec. It omits the glGetInteger(TIMESTAMP) functionality used to + query the current time on the GPU, but the behavior for all remaining + functionality taken from ARB_timer_query is the same. + + (15) Are query objects shareable between multiple contexts? + + RESOLVED: No. Query objects are lightweight and we normally share + large data across contexts. Also, being able to share query objects + across contexts is not particularly useful. In order to do the async + query across contexts, a query on one context would have to be finished + before the other context could query it. + +Revision History + + Revision 1, 2011/04/28 + - copied from revision 9 of ARB_timer_query and revision 7 of + ARB_occlusion_query + - removed language that was clearly not relevant to ES2 + - rebased changes against the OpenGL ES 2.0 specification |