1Name 2 3 EXT_occlusion_query_boolean 4 5Name Strings 6 7 GL_EXT_occlusion_query_boolean 8 9Contributors 10 11 All those who have contributed to the definition of occlusion 12 query functionality in the OpenGL ARB and OpenGL ES workgroups, 13 upon which this extension spec is entirely dependent. 14 15Contact 16 17 Benj Lipchak, Apple (lipchak 'at' apple.com) 18 19Status 20 21 Complete 22 23Version 24 25 Date: July 22, 2011 26 Revision: 2 27 28Number 29 30 OpenGL ES Extension #100 31 32Dependencies 33 34 Written based on the wording of the OpenGL ES 2.0.25 Full Specification 35 (November 2, 2010). 36 37Overview 38 39 This extension defines a mechanism whereby an application can 40 query whether any pixels (or, more precisely, samples) are drawn 41 by a primitive or group of primitives. 42 43 The primary purpose of such a query (hereafter referred to as an 44 "occlusion query") is to determine the visibility of an object. 45 Typically, the application will render the major occluders in the 46 scene, then perform an occlusion query for each detail object in 47 the scene. On subsequent frames, the previous results of the 48 occlusion queries can be used to decide whether to draw an object 49 or not. 50 51New Procedures and Functions 52 53 void GenQueriesEXT(sizei n, uint *ids); 54 void DeleteQueriesEXT(sizei n, const uint *ids); 55 boolean IsQueryEXT(uint id); 56 void BeginQueryEXT(enum target, uint id); 57 void EndQueryEXT(enum target); 58 void GetQueryivEXT(enum target, enum pname, int *params); 59 void GetQueryObjectuivEXT(uint id, enum pname, uint *params); 60 61New Tokens 62 63 Accepted by the <target> parameter of BeginQueryEXT, EndQueryEXT, 64 and GetQueryivEXT: 65 66 ANY_SAMPLES_PASSED_EXT 0x8C2F 67 ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A 68 69 Accepted by the <pname> parameter of GetQueryivEXT: 70 71 CURRENT_QUERY_EXT 0x8865 72 73 Accepted by the <pname> parameter of GetQueryObjectivEXT and 74 GetQueryObjectuivEXT: 75 76 QUERY_RESULT_EXT 0x8866 77 QUERY_RESULT_AVAILABLE_EXT 0x8867 78 79Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation) 80 81 Add a new section "Asynchronous Queries" between sections 2.12 and 2.13 82 and renumber subsequent sections: 83 84 "2.13 Asynchronous Queries 85 86 Asynchronous queries provide a mechanism to return information about the 87 processing of a sequence of GL commands. There is one query type 88 supported by the GL. Occlusion queries (see section 4.1.6) set a boolean 89 to true when any fragments or samples pass the depth test. 90 91 The results of asynchronous queries are not returned by the GL immediately 92 after the completion of the last command in the set; subsequent commands 93 can be processed while the query results are not complete. When available, 94 the query results are stored in an associated query object. The commands 95 described in section 6.1.6 provide mechanisms to determine when query 96 results are available and return the actual results of the query. The 97 name space for query objects is the unsigned integers, with zero reserved 98 by the GL. 99 100 Each type of query supported by the GL has an active query object name. If 101 the active query object name for a query type is non-zero, the GL is 102 currently tracking the information corresponding to that query type and the 103 query results will be written into the corresponding query object. If the 104 active query object for a query type name is zero, no such information is 105 being tracked. 106 107 A query object is created and made active by calling 108 109 void BeginQueryEXT(enum target, uint id); 110 111 <target> indicates the type of query to be performed; valid values of 112 <target> are defined in subsequent sections. If the query object name <id> 113 has not been created, the name is marked as used and associated with a new 114 query object of the type specified by <target>. Otherwise <id> must be the 115 name of an existing query object of that type. 116 117 BeginQueryEXT fails and an INVALID_OPERATION error is generated if <id> 118 is not a name returned from a previous call to GenQueriesEXT, or if such 119 a name has since been deleted with DeleteQueriesEXT. 120 121 BeginQueryEXT sets the active query object name for the query type given 122 by <target> to <id>. If BeginQueryEXT is called with an <id> of zero, if 123 the active query object name for <target> is non-zero (for the targets 124 ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if the 125 active query for either target is non-zero), if <id> is the name of an 126 existing query object whose type does not match <target>, or if <id> is the 127 active query object name for any query type, the error INVALID_OPERATION is 128 generated. 129 130 The command 131 132 void EndQueryEXT(enum target); 133 134 marks the end of the sequence of commands to be tracked for the query type 135 given by <target>. The active query object for <target> is updated to 136 indicate that query results are not available, and the active query object 137 name for <target> is reset to zero. When the commands issued prior to 138 EndQueryEXT have completed and a final query result is available, the 139 query object active when EndQueryEXT is called is updated by the GL. The 140 query object is updated to indicate that the query results are available 141 and to contain the query result. If the active query object name for 142 <target> is zero when EndQueryEXT is called, the error INVALID_OPERATION 143 is generated. 144 145 The command 146 147 void GenQueriesEXT(sizei n, uint *ids); 148 149 returns <n> previously unused query object names in <ids>. These names are 150 marked as used, for the purposes of GenQueriesEXT only, but no object is 151 associated with them until the first time they are used by BeginQueryEXT. 152 153 Query objects are deleted by calling 154 155 void DeleteQueriesEXT(sizei n, const uint *ids); 156 157 <ids> contains <n> names of query objects to be deleted. After a query 158 object is deleted, its name is again unused. Unused names in <ids> are 159 silently ignored, as is the value zero. If an active query object is 160 deleted its name immediately becomes unused, but the underlying object is 161 not deleted until it is no longer active (see section C.1). 162 163 Query objects contain two pieces of state: a single bit indicating whether 164 a query result is available, and an integer containing the query result 165 value. The number of bits used to represent the query result is 166 implementation-dependent and may vary by query object type. In the initial 167 state of a query object, the result is available and its value is zero. 168 169 The necessary state for each query type is an unsigned integer holding the 170 active query object name (zero if no query object is active), and any state 171 necessary to keep the current results of an asynchronous query in progress. 172 Only a single type of occlusion query can be active at one time, so the 173 required state for occlusion queries is shared." 174 175Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization) 176 177 None 178 179Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment 180Operations and the Frame Buffer) 181 182 Add a new section "Occlusion Queries" between sections 4.1.5 and 183 4.1.6 and renumber subsequent sections: 184 185 "4.1.6 Occlusion Queries 186 187 Occlusion queries use query objects to track the number of fragments or 188 samples that pass the depth test. An occlusion query can be started and 189 finished by calling BeginQueryEXT and EndQueryEXT, respectively, with a 190 target of ANY_SAMPLES_PASSED_EXT or ANY_SAMPLES_PASSED_CONSERVATIVE_EXT. 191 192 When an occlusion query is started with the target 193 ANY_SAMPLES_PASSED_EXT, the samples-boolean state maintained by the GL is 194 set to FALSE. While that occlusion query is active, the samples-boolean 195 state is set to TRUE if any fragment or sample passes the depth test. When 196 the occlusion query finishes, the samples-boolean state of FALSE or TRUE is 197 written to the corresponding query object as the query result value, and 198 the query result for that object is marked as available. If the target of 199 the query is ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, an implementation may 200 choose to use a less precise version of the test which can additionally set 201 the samples-boolean state to TRUE in some other implementation dependent 202 cases." 203 204Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions) 205 206 None 207 208Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and 209State Requests) 210 211 Add a new section "Asynchronous Queries" between sections 6.1.5 and 212 6.1.6 and renumber subsequent sections: 213 214 "6.1.6 Asynchronous Queries 215 216 The command 217 218 boolean IsQueryEXT(uint id); 219 220 returns TRUE if <id> is the name of a query object. If <id> is zero, 221 or if <id> is a non-zero value that is not the name of a query 222 object, IsQueryEXT returns FALSE. 223 224 Information about a query target can be queried with the command 225 226 void GetQueryivEXT(enum target, enum pname, int *params); 227 228 <target> identifies the query target, and must be one of 229 ANY_SAMPLES_PASSED_EXT or ANY_SAMPLES_PASSED_CONSERVATIVE_EXT. 230 231 <pname> must be CURRENT_QUERY_EXT. The name of the currently active 232 query for <target>, or zero if no query is active, will be placed in 233 <params>. 234 235 The state of a query object can be queried with the command 236 237 void GetQueryObjectuivEXT(uint id, enum pname, uint *params); 238 239 If <id> is not the name of a query object, or if the query object 240 named by <id> is currently active, then an INVALID_OPERATION error is 241 generated. <pname> must be QUERY_RESULT_EXT or QUERY_RESULT_AVAILABLE_EXT. 242 243 If <pname> is QUERY_RESULT_EXT, then the query object's result value 244 is returned as a single integer in <params>. If the value is so large in 245 magnitude that it cannot be represented with the requested type, then the 246 nearest value representable using the requested type is returned. 247 248 There may be an indeterminate delay before the above query returns. If 249 <pname> is QUERY_RESULT_AVAILABLE_EXT, FALSE is returned if such a delay 250 would be required; otherwise TRUE is returned. It must always be true that 251 if any query object returns a result available of TRUE, all queries of the 252 same type issued prior to that query must also return TRUE. 253 254 Querying the state for any given query object forces that occlusion query 255 to complete within a finite amount of time. Repeatedly querying the 256 QUERY_RESULT_AVAILABLE_EXT state for any given query object is guaranteed 257 to return true eventually. Note that multiple queries to the same occlusion 258 object may result in a significant performance loss. For better performance 259 it is recommended to wait N frames before querying this state. N is 260 implementation dependent but is generally between one and three. 261 262 If multiple queries are issued using the same object name prior to calling 263 GetQueryObjectuivEXT, the result and availability information returned 264 will always be from the last query issued. The results from any queries 265 before the last one will be lost if they are not retrieved before starting 266 a new query on the same <target> and <id>." 267 268Additions to Appendix C of the OpenGL ES 2.0 Specification (Shared Object and 269Multiple Contexts) 270 271 Change the first sentence of the first paragraph of section C.1.2 to read: 272 273 "When a buffer, texture, renderbuffer, or query is deleted, ..." 274 275 Add the following sentence to the end of section C.1.2: 276 277 "A query object is in use so long as it is the active query object for a 278 query type and index, as described in section 2.13." 279 280Errors 281 282 The error INVALID_OPERATION is generated if BeginQueryEXT is called 283 where <id> is not a name returned from a previous call to GenQueriesEXT, 284 or if such a name has since been deleted with DeleteQueriesEXT. 285 286 The error INVALID_OPERATION is generated if BeginQueryEXT is called 287 where <id> is zero. 288 289 The error INVALID_OPERATION is generated if BeginQueryEXT is called 290 where <id> is the name of an existing query object whose type does not 291 match <target>. 292 293 The error INVALID_OPERATION is generated if BeginQueryEXT is called 294 where <id> is the active query object name for any query type. 295 296 The error INVALID_OPERATION is generated if BeginQueryEXT is called 297 when the active query object name for either ANY_SAMPLES_PASSED_EXT or 298 ANY_SAMPLES_PASSED_CONSERVATIVE_EXT is non-zero. 299 300 The error INVALID_OPERATION is generated if EndQueryEXT is called 301 when the active query object name for <target> is zero. 302 303 The error INVALID_OPERATION is generated if GetQueryObjectuivEXT is 304 called where <id> is not the name of a query object. 305 306 The error INVALID_OPERATION is generated if GetQueryObjectuivEXT is 307 called where <id> is the name of a currently active query object. 308 309 The error INVALID_VALUE is generated if GenQueriesEXT is called where 310 <n> is negative. 311 312 The error INVALID_VALUE is generated if DeleteQueriesEXT is called 313 where <n> is negative. 314 315 The error INVALID_ENUM is generated if BeginQueryEXT, EndQueryEXT, 316 or GetQueryivEXT is called where <target> is not 317 ANY_SAMPLES_PASSED_EXT or ANY_SAMPLES_PASSED_CONSERVATIVE_EXT. 318 319 The error INVALID_ENUM is generated if GetQueryivEXT is called where 320 <pname> is not CURRENT_QUERY_EXT. 321 322 The error INVALID_ENUM is generated if GetQueryObjectuivEXT is called 323 where <pname> is not QUERY_RESULT_EXT or QUERY_RESULT_AVAILABLE_EXT. 324 325New State 326 327(table 6.18, p. 233) 328 329 Int'l 330 Get Value Type Get Command Value Description Sec 331 -------------------------- ---- -------------------- ----- ---------------------- ----- 332 - B - FALSE query active 4.1.6 333 CURRENT_QUERY_EXT Z+ GetQueryivEXT 0 active query ID 4.1.6 334 QUERY_RESULT_EXT B GetQueryObjectuivEXT FALSE samples-passed 4.1.6 335 QUERY_RESULT_AVAILABLE_EXT B GetQueryObjectuivEXT FALSE query result available 4.1.6 336 337Issues 338 339 (1) What should the enum be called? 340 341 RESOLVED: The enum should be called ANY_SAMPLES_PASSED as in 342 ARB_occlusion_query2 to retain compatibility between the two 343 extensions. 344 345 (2) Can application-provided names be used as query object names? 346 347 ARB_occlusion_query allows application-provided names, but this 348 was later removed in core OpenGL. 349 350 RESOLVED: No, we will follow core OpenGL on this. 351 352 (3) Should calling GenQueries or DeleteQueries when a query is 353 active produce an error? 354 355 This behavior is in ARB_occlusion_query but was 356 removed in OpenGL 3.0. 357 358 RESOLVED: Not an error. Calling DeleteQueries marks the name 359 as no longer used, but the object is not deleted until it is no 360 longer in use (i.e. no longer active). 361 362 (4) What is the interaction with multisample? 363 364 RESOLVED: The query result is set to true if at least one 365 sample passes the depth test. 366 367 (5) Exactly what stage in the pipeline are we counting samples at? 368 369 RESOLVED: We are counting immediately after _both_ the depth and 370 stencil tests, i.e., samples that pass both. Note that the depth 371 test comes after the stencil test, so to say that it is the 372 number that pass the depth test is sufficient; though it is often 373 conceptually helpful to think of the depth and stencil tests as 374 being combined, because the depth test's result impacts the 375 stencil operation used. 376 377 (6) Is it guaranteed that occlusion queries return in order? 378 379 RESOLVED: Yes. 380 381 If occlusion test X occurred before occlusion query Y, and the driver 382 informs the app that occlusion query Y is done, the app can infer that 383 occlusion query X is also done. 384 385 (7) Will polling a query for QUERY_RESULT_AVAILABLE without a Flush 386 possibly cause an infinite loop? 387 388 RESOLVED: No. 389 390 (8) Should there be a "target" parameter to BeginQuery? 391 392 RESOLVED: Yes. This distinguishes the boolean queries 393 defined by this extension (and ARB_occlusion_query2) from 394 the counter queries defined by ARB_occlusion_query. 395 396 (9) Are query objects shareable between multiple contexts? 397 398 RESOLVED: No. Query objects are lightweight and we normally share 399 large data across contexts. Also, being able to share query objects 400 across contexts is not particularly useful. In order to do the async 401 query across contexts, a query on one context would have to be finished 402 before the other context could query it. 403 404 (10) Should there be a limit on how many queries can be outstanding? 405 406 RESOLVED: No. If an implementation has an internal limit, it can 407 flush the pipeline when it runs out. 408 409 (11) Can an implementation sometimes return a conservative result, 410 i.e. return true even though no samples were drawn? 411 412 RESOLVED: Yes, but only when explicitly enabled by the 413 application. 414 415 Allowing such results with no restrictions effectively makes 416 the functionality of the extension optional, which decreases 417 its value. Precise restrictions are presumably hard to 418 specify. 419 420 One situation where this restriction could be relevant is if 421 an implementation performs a conservative early depth test at 422 a lower precision and wants to base the occlusion query result 423 on that whenever the early depth test can be used. 424 425 (12) Should the restrictions in issue 11 be explicitly enabled 426 by the application in order to be in effect? 427 428 RESOLVED: Yes. 429 430 The restrictions could be enabled by a hint call or by using 431 a different enum in the BeginQuery call. 432 433 This would enable the application to choose whether it wants a 434 precise (but possibly slow) version or an approximate (but 435 possibly faster) version. 436 437 (13) Can the restrictions in issue 18 be applied nondeterministically? 438 439 An implementation might benefit from taking the decision of 440 whether to apply a particular restriction on a case by case 441 basis. Some of these decisions could depend on 442 nondeterministic effects such as memory bus timing. 443 444 RESOLVED: No. This would violate the GL repeatability 445 principle. 446 447 (14) How does an application request that the result is allowed to 448 be conservative (as defined in issue 11)? 449 450 RESOLVED: It is specified as a separate query target, 451 ANY_SAMPLES_PASSED_CONSERVATIVE. 452 453 454Revision History 455 456 Date: 5/03/2011 457 Revision: 1 (Benj Lipchak) 458 - Initial draft based on XXX_occlusion_query_boolean 459 460 Date: 7/22/2011 461 Revision: 2 (Benj Lipchak) 462 - Rename from APPLE to EXT 463