aboutsummaryrefslogtreecommitdiff
path: root/extensions
diff options
context:
space:
mode:
authorJamie Madill <jmadill@chromium.org>2013-09-24 14:07:39 -0400
committerJamie Madill <jmadill@chromium.org>2013-09-24 14:21:28 -0400
commitba615196a8f60c73eef978e723ccbd85deea0687 (patch)
treefc7e834e3fc73d31131ee4bd61a0e4d910797d12 /extensions
parent5d2e95949f770a34758ac7dbe38aff1473177daa (diff)
downloadangle-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.txt1182
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