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