|
1 Name |
|
2 |
|
3 ANGLE_timer_query |
|
4 |
|
5 Name Strings |
|
6 |
|
7 GL_ANGLE_timer_query |
|
8 |
|
9 Contributors |
|
10 |
|
11 Contributors to ARB_occlusion_query |
|
12 Contributors to EXT_timer_query |
|
13 Contributors to ARB_timer_query |
|
14 Ben Vanik, Google Inc. |
|
15 Daniel Koch, TransGaming Inc. |
|
16 |
|
17 Contact |
|
18 |
|
19 Ben Vanik, Google Inc. (benvanik 'at' google 'dot' com) |
|
20 |
|
21 Status |
|
22 |
|
23 Draft |
|
24 |
|
25 Version |
|
26 |
|
27 Last Modified Date: Apr 28, 2011 |
|
28 Author Revision: 1 |
|
29 |
|
30 Number |
|
31 |
|
32 OpenGL ES Extension #?? |
|
33 |
|
34 Dependencies |
|
35 |
|
36 OpenGL ES 2.0 is required. |
|
37 |
|
38 The extension is written against the OpenGL ES 2.0 specification. |
|
39 |
|
40 Overview |
|
41 |
|
42 Applications can benefit from accurate timing information in a number of |
|
43 different ways. During application development, timing information can |
|
44 help identify application or driver bottlenecks. At run time, |
|
45 applications can use timing information to dynamically adjust the amount |
|
46 of detail in a scene to achieve constant frame rates. OpenGL |
|
47 implementations have historically provided little to no useful timing |
|
48 information. Applications can get some idea of timing by reading timers |
|
49 on the CPU, but these timers are not synchronized with the graphics |
|
50 rendering pipeline. Reading a CPU timer does not guarantee the completion |
|
51 of a potentially large amount of graphics work accumulated before the |
|
52 timer is read, and will thus produce wildly inaccurate results. |
|
53 glFinish() can be used to determine when previous rendering commands have |
|
54 been completed, but will idle the graphics pipeline and adversely affect |
|
55 application performance. |
|
56 |
|
57 This extension provides a query mechanism that can be used to determine |
|
58 the amount of time it takes to fully complete a set of GL commands, and |
|
59 without stalling the rendering pipeline. It uses the query object |
|
60 mechanisms first introduced in the occlusion query extension, which allow |
|
61 time intervals to be polled asynchronously by the application. |
|
62 |
|
63 IP Status |
|
64 |
|
65 No known IP claims. |
|
66 |
|
67 New Procedures and Functions |
|
68 |
|
69 void GenQueriesANGLE(sizei n, uint *ids); |
|
70 void DeleteQueriesANGLE(sizei n, const uint *ids); |
|
71 boolean IsQueryANGLE(uint id); |
|
72 void BeginQueryANGLE(enum target, uint id); |
|
73 void EndQueryANGLE(enum target); |
|
74 void QueryCounterANGLE(uint id, enum target); |
|
75 void GetQueryivANGLE(enum target, enum pname, int *params); |
|
76 void GetQueryObjectivANGLE(uint id, enum pname, int *params); |
|
77 void GetQueryObjectuivANGLE(uint id, enum pname, uint *params); |
|
78 void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params); |
|
79 void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params); |
|
80 |
|
81 New Tokens |
|
82 |
|
83 Accepted by the <pname> parameter of GetQueryivANGLE: |
|
84 |
|
85 QUERY_COUNTER_BITS_ANGLE 0x8864 |
|
86 CURRENT_QUERY_ANGLE 0x8865 |
|
87 |
|
88 Accepted by the <pname> parameter of GetQueryObjectivANGLE, |
|
89 GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, and |
|
90 GetQueryObjectui64vANGLE: |
|
91 |
|
92 QUERY_RESULT_ANGLE 0x8866 |
|
93 QUERY_RESULT_AVAILABLE_ANGLE 0x8867 |
|
94 |
|
95 Accepted by the <target> parameter of BeginQueryANGLE, EndQueryANGLE, and |
|
96 GetQueryivANGLE: |
|
97 |
|
98 TIME_ELAPSED_ANGLE 0x88BF |
|
99 |
|
100 Accepted by the <target> parameter of GetQueryivANGLE and |
|
101 QueryCounterANGLE: |
|
102 |
|
103 TIMESTAMP_ANGLE 0x8E28 |
|
104 |
|
105 Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation) |
|
106 |
|
107 (Modify table 2.1, Correspondence of command suffix letters to GL argument) |
|
108 Add two new types: |
|
109 |
|
110 Letter Corresponding GL Type |
|
111 ------ --------------------- |
|
112 i64 int64ANGLE |
|
113 ui64 uint64ANGLE |
|
114 |
|
115 (Modify table 2.2, GL data types) Add two new types: |
|
116 |
|
117 GL Type Minimum Bit Width Description |
|
118 ------- ----------------- ----------------------------- |
|
119 int64ANGLE 64 Signed 2's complement integer |
|
120 uint64ANGLE 64 Unsigned binary integer |
|
121 |
|
122 Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions) |
|
123 |
|
124 Add a new section 5.3 "Timer Queries": |
|
125 |
|
126 "5.3 Timer Queries |
|
127 |
|
128 Timer queries use query objects to track the amount of time needed to |
|
129 fully complete a set of GL commands, or to determine the current time |
|
130 of the GL. |
|
131 |
|
132 Timer queries are associated with query objects. The command |
|
133 |
|
134 void GenQueriesANGLE(sizei n, uint *ids); |
|
135 |
|
136 returns <n> previously unused query object names in <ids>. These |
|
137 names are marked as used, but no object is associated with them until |
|
138 the first time they are used by BeginQueryANGLE. Query objects contain |
|
139 one piece of state, an integer result value. This result value is |
|
140 initialized to zero when the object is created. Any positive integer |
|
141 except for zero (which is reserved for the GL) is a valid query |
|
142 object name. |
|
143 |
|
144 Query objects are deleted by calling |
|
145 |
|
146 void DeleteQueriesANGLE(sizei n, const uint *ids); |
|
147 |
|
148 <ids> contains <n> names of query objects to be deleted. After a |
|
149 query object is deleted, its name is again unused. Unused names in |
|
150 <ids> are silently ignored. |
|
151 If an active query object is deleted its name immediately becomes unused, |
|
152 but the underlying object is not deleted until it is no longer active. |
|
153 |
|
154 A timer query can be started and finished by calling |
|
155 |
|
156 void BeginQueryANGLE(enum target, uint id); |
|
157 void EndQueryANGLE(enum target); |
|
158 |
|
159 where <target> is TIME_ELAPSED_ANGLE. If BeginQueryANGLE is called |
|
160 with an unused <id>, that name is marked as used and associated with |
|
161 a new query object. |
|
162 |
|
163 If BeginQueryANGLE is called with an <id> of zero, if the active query |
|
164 object name for <target> is non-zero, if <id> is the name of an existing |
|
165 query object whose type does not match <target>, or if <id> is the active |
|
166 query object name for any query type, the error INVALID_OPERATION is |
|
167 generated. If EndQueryANGLE is called while no query with the same target |
|
168 is in progress, an INVALID_OPERATION error is generated. |
|
169 |
|
170 When BeginQueryANGLE and EndQueryANGLE are called with a <target> of |
|
171 TIME_ELAPSED_ANGLE, the GL prepares to start and stop the timer used for |
|
172 timer queries. The timer is started or stopped when the effects from all |
|
173 previous commands on the GL client and server state and the framebuffer |
|
174 have been fully realized. The BeginQueryANGLE and EndQueryANGLE commands |
|
175 may return before the timer is actually started or stopped. When the timer |
|
176 query timer is finally stopped, the elapsed time (in nanoseconds) is |
|
177 written to the corresponding query object as the query result value, and |
|
178 the query result for that object is marked as available. |
|
179 |
|
180 If the elapsed time overflows the number of bits, <n>, available to hold |
|
181 elapsed time, its value becomes undefined. It is recommended, but not |
|
182 required, that implementations handle this overflow case by saturating at |
|
183 2^n - 1. |
|
184 |
|
185 The necessary state is a single bit indicating whether an timer |
|
186 query is active, the identifier of the currently active timer |
|
187 query, and a counter keeping track of the time that has passed. |
|
188 |
|
189 When the command |
|
190 |
|
191 void QueryCounterANGLE(uint id, enum target); |
|
192 |
|
193 is called with <target> TIMESTAMP_ANGLE, the GL records the current time |
|
194 into the corresponding query object. The time is recorded after all |
|
195 previous commands on the GL client and server state and the framebuffer |
|
196 have been fully realized. When the time is recorded, the query result for |
|
197 that object is marked available. QueryCounterANGLE timer queries can be |
|
198 used within a BeginQueryANGLE / EndQueryANGLE block where the <target> is |
|
199 TIME_ELAPSED_ANGLE and it does not affect the result of that query object. |
|
200 The error INVALID_OPERATION is generated if the <id> is already in use |
|
201 within a BeginQueryANGLE/EndQueryANGLE block." |
|
202 |
|
203 Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State |
|
204 Requests) |
|
205 |
|
206 Add a new section 6.1.9 "Timer Queries": |
|
207 |
|
208 "The command |
|
209 |
|
210 boolean IsQueryANGLE(uint id); |
|
211 |
|
212 returns TRUE if <id> is the name of a query object. If <id> is zero, |
|
213 or if <id> is a non-zero value that is not the name of a query |
|
214 object, IsQueryANGLE returns FALSE. |
|
215 |
|
216 Information about a query target can be queried with the command |
|
217 |
|
218 void GetQueryivANGLE(enum target, enum pname, int *params); |
|
219 |
|
220 <target> identifies the query target and can be TIME_ELAPSED_ANGLE or |
|
221 TIMESTAMP_ANGLE for timer queries. |
|
222 |
|
223 If <pname> is CURRENT_QUERY_ANGLE, the name of the currently active query |
|
224 for <target>, or zero if no query is active, will be placed in <params>. |
|
225 |
|
226 If <pname> is QUERY_COUNTER_BITS_ANGLE, the implementation-dependent number |
|
227 of bits used to hold the query result for <target> will be placed in |
|
228 <params>. The number of query counter bits may be zero, in which case |
|
229 the counter contains no useful information. |
|
230 |
|
231 For timer queries (TIME_ELAPSED_ANGLE and TIMESTAMP_ANGLE), if the number |
|
232 of bits is non-zero, the minimum number of bits allowed is 30 which |
|
233 will allow at least 1 second of timing. |
|
234 |
|
235 The state of a query object can be queried with the commands |
|
236 |
|
237 void GetQueryObjectivANGLE(uint id, enum pname, int *params); |
|
238 void GetQueryObjectuivANGLE(uint id, enum pname, uint *params); |
|
239 void GetQueryObjecti64vANGLE(uint id, enum pname, int64 *params); |
|
240 void GetQueryObjectui64vANGLE(uint id, enum pname, uint64 *params); |
|
241 |
|
242 If <id> is not the name of a query object, or if the query object |
|
243 named by <id> is currently active, then an INVALID_OPERATION error is |
|
244 generated. |
|
245 |
|
246 If <pname> is QUERY_RESULT_ANGLE, then the query object's result |
|
247 value is returned as a single integer in <params>. If the value is so |
|
248 large in magnitude that it cannot be represented with the requested type, |
|
249 then the nearest value representable using the requested type is |
|
250 returned. If the number of query counter bits for target is zero, then |
|
251 the result is returned as a single integer with the value zero. |
|
252 |
|
253 There may be an indeterminate delay before the above query returns. If |
|
254 <pname> is QUERY_RESULT_AVAILABLE_ANGLE, FALSE is returned if such a delay |
|
255 would be required; otherwise TRUE is returned. It must always be true |
|
256 that if any query object returns a result available of TRUE, all queries |
|
257 of the same type issued prior to that query must also return TRUE. |
|
258 |
|
259 Querying the state for a given timer query forces that timer query to |
|
260 complete within a finite amount of time. |
|
261 |
|
262 If multiple queries are issued on the same target and id prior to |
|
263 calling GetQueryObject[u]i[64]vANGLE, the result returned will always be |
|
264 from the last query issued. The results from any queries before the |
|
265 last one will be lost if the results are not retrieved before starting |
|
266 a new query on the same <target> and <id>." |
|
267 |
|
268 Errors |
|
269 |
|
270 The error INVALID_VALUE is generated if GenQueriesANGLE is called where |
|
271 <n> is negative. |
|
272 |
|
273 The error INVALID_VALUE is generated if DeleteQueriesANGLE is called |
|
274 where <n> is negative. |
|
275 |
|
276 The error INVALID_OPERATION is generated if BeginQueryANGLE is called |
|
277 when a query of the given <target> is already active. |
|
278 |
|
279 The error INVALID_OPERATION is generated if EndQueryANGLE is called |
|
280 when a query of the given <target> is not active. |
|
281 |
|
282 The error INVALID_OPERATION is generated if BeginQueryANGLE is called |
|
283 where <id> is zero. |
|
284 |
|
285 The error INVALID_OPERATION is generated if BeginQueryANGLE is called |
|
286 where <id> is the name of a query currently in progress. |
|
287 |
|
288 The error INVALID_OPERATION is generated if BeginQueryANGLE is called |
|
289 where <id> is the name of an existing query object whose type does not |
|
290 match <target>. |
|
291 |
|
292 The error INVALID_ENUM is generated if BeginQueryANGLE or EndQueryANGLE |
|
293 is called where <target> is not TIME_ELAPSED_ANGLE. |
|
294 |
|
295 The error INVALID_ENUM is generated if GetQueryivANGLE is called where |
|
296 <target> is not TIME_ELAPSED_ANGLE or TIMESTAMP_ANGLE. |
|
297 |
|
298 The error INVALID_ENUM is generated if GetQueryivANGLE is called where |
|
299 <pname> is not QUERY_COUNTER_BITS_ANGLE or CURRENT_QUERY_ANGLE. |
|
300 |
|
301 The error INVALID_ENUM is generated if QueryCounterANGLE is called where |
|
302 <target> is not TIMESTAMP_ANGLE. |
|
303 |
|
304 The error INVALID_OPERATION is generated if QueryCounterANGLE is called |
|
305 on a query object that is already in use inside a |
|
306 BeginQueryANGLE/EndQueryANGLE. |
|
307 |
|
308 The error INVALID_OPERATION is generated if GetQueryObjectivANGLE, |
|
309 GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or |
|
310 GetQueryObjectui64vANGLE is called where <id> is not the name of a query |
|
311 object. |
|
312 |
|
313 The error INVALID_OPERATION is generated if GetQueryObjectivANGLE, |
|
314 GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or |
|
315 GetQueryObjectui64vANGLE is called where <id> is the name of a currently |
|
316 active query object. |
|
317 |
|
318 The error INVALID_ENUM is generated if GetQueryObjectivANGLE, |
|
319 GetQueryObjectuivANGLE, GetQueryObjecti64vANGLE, or |
|
320 GetQueryObjectui64vANGLE is called where <pname> is not |
|
321 QUERY_RESULT_ANGLE or QUERY_RESULT_AVAILABLE_ANGLE. |
|
322 |
|
323 New State |
|
324 |
|
325 (Add a new table 6.xx, "Query Operations") |
|
326 |
|
327 Get Value Type Get Command Initial Value Description Sec |
|
328 --------- ---- ----------- ------------- ----------- ------ |
|
329 - B - FALSE query active 5.3 |
|
330 CURRENT_QUERY_ANGLE Z+ GetQueryivANGLE 0 active query ID 5.3 |
|
331 QUERY_RESULT_ANGLE Z+ GetQueryObjectuivANGLE, 0 samples-passed count 5.3 |
|
332 GetQueryObjectui64vANGLE |
|
333 QUERY_RESULT_AVAILABLE_ANGLE B GetQueryObjectivANGLE FALSE query result available 5.3 |
|
334 |
|
335 New Implementation Dependent State |
|
336 |
|
337 (Add the following entry to table 6.18): |
|
338 |
|
339 Get Value Type Get Command Minimum Value Description Sec |
|
340 -------------------------- ---- ----------- ------------- ---------------- ------ |
|
341 QUERY_COUNTER_BITS_ANGLE Z+ GetQueryivANGLE see 6.1.9 Number of bits in 6.1.9 |
|
342 query counter |
|
343 |
|
344 Examples |
|
345 |
|
346 (1) Here is some rough sample code that demonstrates the intended usage |
|
347 of this extension. |
|
348 |
|
349 GLint queries[N]; |
|
350 GLint available = 0; |
|
351 // timer queries can contain more than 32 bits of data, so always |
|
352 // query them using the 64 bit types to avoid overflow |
|
353 GLuint64ANGLE timeElapsed = 0; |
|
354 |
|
355 // Create a query object. |
|
356 glGenQueriesANGLE(N, queries); |
|
357 |
|
358 // Start query 1 |
|
359 glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[0]); |
|
360 |
|
361 // Draw object 1 |
|
362 .... |
|
363 |
|
364 // End query 1 |
|
365 glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE); |
|
366 |
|
367 ... |
|
368 |
|
369 // Start query N |
|
370 glBeginQueryANGLE(GL_TIME_ELAPSED_ANGLE, queries[N-1]); |
|
371 |
|
372 // Draw object N |
|
373 .... |
|
374 |
|
375 // End query N |
|
376 glEndQueryANGLE(GL_TIME_ELAPSED_ANGLE); |
|
377 |
|
378 // Wait for all results to become available |
|
379 while (!available) { |
|
380 glGetQueryObjectivANGLE(queries[N-1], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available); |
|
381 } |
|
382 |
|
383 for (i = 0; i < N; i++) { |
|
384 // See how much time the rendering of object i took in nanoseconds. |
|
385 glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeElapsed); |
|
386 |
|
387 // Do something useful with the time. Note that care should be |
|
388 // taken to use all significant bits of the result, not just the |
|
389 // least significant 32 bits. |
|
390 AdjustObjectLODBasedOnDrawTime(i, timeElapsed); |
|
391 } |
|
392 |
|
393 This example is sub-optimal in that it stalls at the end of every |
|
394 frame to wait for query results. Ideally, the collection of results |
|
395 would be delayed one frame to minimize the amount of time spent |
|
396 waiting for the GPU to finish rendering. |
|
397 |
|
398 (2) This example is basically the same as the example above but uses |
|
399 QueryCounter instead. |
|
400 |
|
401 GLint queries[N+1]; |
|
402 GLint available = 0; |
|
403 // timer queries can contain more than 32 bits of data, so always |
|
404 // query them using the 64 bit types to avoid overflow |
|
405 GLuint64ANGLE timeStart, timeEnd, timeElapsed = 0; |
|
406 |
|
407 // Create a query object. |
|
408 glGenQueriesANGLE(N+1, queries); |
|
409 |
|
410 // Query current timestamp 1 |
|
411 glQueryCounterANGLE(queries[0], GL_TIMESTAMP_ANGLE); |
|
412 |
|
413 // Draw object 1 |
|
414 .... |
|
415 |
|
416 // Query current timestamp N |
|
417 glQueryCounterANGLE(queries[N-1], GL_TIMESTAMP_ANGLE); |
|
418 |
|
419 // Draw object N |
|
420 .... |
|
421 |
|
422 // Query current timestamp N+1 |
|
423 glQueryCounterANGLE(queries[N], GL_TIMESTAMP_ANGLE); |
|
424 |
|
425 // Wait for all results to become available |
|
426 while (!available) { |
|
427 glGetQueryObjectivANGLE(queries[N], GL_QUERY_RESULT_AVAILABLE_ANGLE, &available); |
|
428 } |
|
429 |
|
430 for (i = 0; i < N; i++) { |
|
431 // See how much time the rendering of object i took in nanoseconds. |
|
432 glGetQueryObjectui64vANGLE(queries[i], GL_QUERY_RESULT_ANGLE, &timeStart); |
|
433 glGetQueryObjectui64vANGLE(queries[i+1], GL_QUERY_RESULT_ANGLE, &timeEnd); |
|
434 timeElapsed = timeEnd - timeStart; |
|
435 |
|
436 // Do something useful with the time. Note that care should be |
|
437 // taken to use all significant bits of the result, not just the |
|
438 // least significant 32 bits. |
|
439 AdjustObjectLODBasedOnDrawTime(i, timeElapsed); |
|
440 } |
|
441 |
|
442 Issues from EXT_timer_query |
|
443 |
|
444 (1) What time interval is being measured? |
|
445 |
|
446 RESOLVED: The timer starts when all commands prior to BeginQuery() have |
|
447 been fully executed. At that point, everything that should be drawn by |
|
448 those commands has been written to the framebuffer. The timer stops |
|
449 when all commands prior to EndQuery() have been fully executed. |
|
450 |
|
451 (2) What unit of time will time intervals be returned in? |
|
452 |
|
453 RESOLVED: Nanoseconds (10^-9 seconds). This unit of measurement allows |
|
454 for reasonably accurate timing of even small blocks of rendering |
|
455 commands. The granularity of the timer is implementation-dependent. A |
|
456 32-bit query counter can express intervals of up to approximately 4 |
|
457 seconds. |
|
458 |
|
459 (3) What should be the minimum number of counter bits for timer queries? |
|
460 |
|
461 RESOLVED: 30 bits, which will allow timing sections that take up to 1 |
|
462 second to render. |
|
463 |
|
464 (4) How are counter results of more than 32 bits returned? |
|
465 |
|
466 RESOLVED: Via two new datatypes, int64ANGLE and uint64ANGLE, and their |
|
467 corresponding GetQueryObject entry points. These types hold integer |
|
468 values and have a minimum bit width of 64. |
|
469 |
|
470 (5) Should the extension measure total time elapsed between the full |
|
471 completion of the BeginQuery and EndQuery commands, or just time |
|
472 spent in the graphics library? |
|
473 |
|
474 RESOLVED: This extension will measure the total time elapsed between |
|
475 the full completion of these commands. Future extensions may implement |
|
476 a query to determine time elapsed at different stages of the graphics |
|
477 pipeline. |
|
478 |
|
479 (6) If multiple query types are supported, can multiple query types be |
|
480 active simultaneously? |
|
481 |
|
482 RESOLVED: Yes; an application may perform a timer query and another |
|
483 type of query simultaneously. An application can not perform multiple |
|
484 timer queries or multiple queries of other types simultaneously. An |
|
485 application also can not use the same query object for another query |
|
486 and a timer query simultaneously. |
|
487 |
|
488 (7) Do query objects have a query type permanently associated with them? |
|
489 |
|
490 RESOLVED: No. A single query object can be used to perform different |
|
491 types of queries, but not at the same time. |
|
492 |
|
493 Having a fixed type for each query object simplifies some aspects of the |
|
494 implementation -- not having to deal with queries with different result |
|
495 sizes, for example. It would also mean that BeginQuery() with a query |
|
496 object of the "wrong" type would result in an INVALID_OPERATION error. |
|
497 |
|
498 UPDATE: This resolution was relevant for EXT_timer_query and OpenGL 2.0. |
|
499 Since EXT_transform_feedback has since been incorporated into the core, |
|
500 the resolution is that BeginQuery will generate error INVALID_OPERATION |
|
501 if <id> represents a query object of a different type. |
|
502 |
|
503 (8) How predictable/repeatable are the results returned by the timer |
|
504 query? |
|
505 |
|
506 RESOLVED: In general, the amount of time needed to render the same |
|
507 primitives should be fairly constant. But there may be many other |
|
508 system issues (e.g., context switching on the CPU and GPU, virtual |
|
509 memory page faults, memory cache behavior on the CPU and GPU) that can |
|
510 cause times to vary wildly. |
|
511 |
|
512 Note that modern GPUs are generally highly pipelined, and may be |
|
513 processing different primitives in different pipeline stages |
|
514 simultaneously. In this extension, the timers start and stop when the |
|
515 BeginQuery/EndQuery commands reach the bottom of the rendering pipeline. |
|
516 What that means is that by the time the timer starts, the GL driver on |
|
517 the CPU may have started work on GL commands issued after BeginQuery, |
|
518 and the higher pipeline stages (e.g., vertex transformation) may have |
|
519 started as well. |
|
520 |
|
521 (9) What should the new 64 bit integer type be called? |
|
522 |
|
523 RESOLVED: The new types will be called GLint64ANGLE/GLuint64ANGLE. The new |
|
524 command suffixes will be i64 and ui64. These names clearly convey the |
|
525 minimum size of the types. These types are similar to the C99 standard |
|
526 type int_least64_t, but we use names similar to the C99 optional type |
|
527 int64_t for simplicity. |
|
528 |
|
529 Issues from ARB_timer_query |
|
530 |
|
531 (10) What about tile-based implementations? The effects of a command are |
|
532 not complete until the frame is completely rendered. Timing recorded |
|
533 before the frame is complete may not be what developers expect. Also |
|
534 the amount of time needed to render the same primitives is not |
|
535 consistent, which conflicts with issue (8) above. The time depends on |
|
536 how early or late in the scene it is placed. |
|
537 |
|
538 RESOLVED: The current language supports tile-based rendering okay as it |
|
539 is written. Developers are warned that using timers on tile-based |
|
540 implementation may not produce results they expect since rendering is not |
|
541 done in a linear order. Timing results are calculated when the frame is |
|
542 completed and may depend on how early or late in the scene it is placed. |
|
543 |
|
544 (11) Can the GL implementation use different clocks to implement the |
|
545 TIME_ELAPSED and TIMESTAMP queries? |
|
546 |
|
547 RESOLVED: Yes, the implemenation can use different internal clocks to |
|
548 implement TIME_ELAPSED and TIMESTAMP. If different clocks are |
|
549 used it is possible there is a slight discrepancy when comparing queries |
|
550 made from TIME_ELAPSED and TIMESTAMP; they may have slight |
|
551 differences when both are used to measure the same sequence. However, this |
|
552 is unlikely to affect real applications since comparing the two queries is |
|
553 not expected to be useful. |
|
554 |
|
555 Issues |
|
556 |
|
557 (12) What should we call this extension? |
|
558 |
|
559 RESOLVED: ANGLE_timer_query |
|
560 |
|
561 (13) Why is this done as a separate extension instead of just supporting |
|
562 ARB_timer_query? |
|
563 |
|
564 ARB_timer_query is written against OpenGL 3.2, which includes a lot of |
|
565 the required support for dealing with query objects. None of these |
|
566 functions or tokens exist in OpenGL ES, and as such have to be added in |
|
567 this specification. |
|
568 |
|
569 (14) How does this extension differ from ARB_timer_query? |
|
570 |
|
571 This extension contains most ARB_timer_query behavior unchanged as well |
|
572 as a subset of the query support required to use it from the core |
|
573 OpenGL 3.2 spec. It omits the glGetInteger(TIMESTAMP) functionality used to |
|
574 query the current time on the GPU, but the behavior for all remaining |
|
575 functionality taken from ARB_timer_query is the same. |
|
576 |
|
577 (15) Are query objects shareable between multiple contexts? |
|
578 |
|
579 RESOLVED: No. Query objects are lightweight and we normally share |
|
580 large data across contexts. Also, being able to share query objects |
|
581 across contexts is not particularly useful. In order to do the async |
|
582 query across contexts, a query on one context would have to be finished |
|
583 before the other context could query it. |
|
584 |
|
585 Revision History |
|
586 |
|
587 Revision 1, 2011/04/28 |
|
588 - copied from revision 9 of ARB_timer_query and revision 7 of |
|
589 ARB_occlusion_query |
|
590 - removed language that was clearly not relevant to ES2 |
|
591 - rebased changes against the OpenGL ES 2.0 specification |