1Name 2 3 ARB_occlusion_query2 4 5Name Strings 6 7 GL_ARB_occlusion_query2 8 9Contributors 10 11 Aske Simon Christensen 12 Bill Licea-Kane 13 Cass Everitt 14 Jeff Bolz 15 Maurice Ribble 16 17Contact 18 19 Bill Licea-Kane (bill 'at' amd.com) 20 21Notice 22 23 Copyright (c) 2010-2013 The Khronos Group Inc. Copyright terms at 24 http://www.khronos.org/registry/speccopyright.html 25 26Specification Update Policy 27 28 Khronos-approved extension specifications are updated in response to 29 issues and bugs prioritized by the Khronos OpenGL Working Group. For 30 extensions which have been promoted to a core Specification, fixes will 31 first appear in the latest version of that core Specification, and will 32 eventually be backported to the extension document. This policy is 33 described in more detail at 34 https://www.khronos.org/registry/OpenGL/docs/update_policy.php 35 36Status 37 38 Complete. Approved by the ARB at the 2010/01/22 F2F meeting. 39 Approved by the Khronos Board of Promoters on March 10, 2010. 40 41Version 42 43 Date: March 21, 2010 44 Revision: 11 45 $Id$ 46 47Number 48 49 ARB Extension #80 50 51Dependencies 52 53 Written based on the wording of OpenGL Specification 54 Version 3.2 (Core Profile) - July 24, 2009 55 56 Version 3.2 (Compatibility Profile) interacts with this extension. 57 58 OpenGL 1.x is required. 59 60 ARB_occlusion_query interacts with this extension. 61 62 Conditional rendering interacts with this extension. 63 64Overview 65 66 This extension trivially adds a boolean occlusion query 67 to ARB_occlusion_query. 68 69 While the counter-based occlusion query provided by 70 ARB_occlusion_query is flexible, there is still value 71 to a simple boolean, which is often sufficient for applications. 72 73IP Status 74 75 There are no known claims. 76 77 HP claimed IP to a related extension, ARB_occlusion_query. 78 HP committed to releasing rights to this IP to the ARB if the 79 functionality is included in OpenGL (April 10, 2003). 80 ARB_occlusion_query was promoted to core OpenGL 1.5 (July 29, 2003). 81 82New Procedures and Functions 83 84 None 85 86New Tokens 87 88 Accepted by the <target> parameter of BeginQuery, EndQuery, 89 and GetQueryiv: 90 91 ANY_SAMPLES_PASSED 0x8C2F 92 93Additions to Chapter 2 of the OpenGL 3.2 Specification 94(OpenGL Operation) 95 962.14 97Asynchronous Queries 98 99p. 89-90, replace last sentence of first paragraph 100 101 Occlusion queries (see section 4.1.6) count the number of fragments 102 or samples that pass the depth test, 103| or set a boolean to true when fragments or samples pass the depth 104| test. 105 106p. 90, modify the last paragraph before "The command void EndQuery..." 107 108 BeginQuery sets the active query object name for the query type given by 109 target to id. If BeginQuery is called with an id of zero, if the active query object 110 name for target is non-zero 111| (for the targets SAMPLES_PASSED or ANY_SAMPLES PASSED, if the active query object 112| for either target is non-zero), 113 if id is the name of an existing query object whose 114 type does not match target, if id is the active query object name for any query type, 115 or if id is the active query object for condtional rendering (see section 2.15), the 116 error INVALID_OPERATION is generated. 117 1182.15 119Conditional Rendering 120 121p. 91 122 123Add clause prior to "all rendering commands between" 124 125 "or if the result (ANY_SAMPLES_PASSED) is false," 126 127Add clause prior to "such commands are not discarded." 128 129 "or if the result is true," 130 131p. 92 132 133Change last sentence of Section 2.15 134 135 The error 136 INVALID_OPERATION is generated if id is the name of a query object with a target 137 other than 138| SAMPLES_PASSED 139| or ANY_SAMPLES_PASSED, 140 or id is the name of a query currently in progress. 141 142Additions to Chapter 4 of the OpenGL 3.2 Specification 143(Per-Fragment Operations and the Frame Buffer) 144 145p. 192, Replace 4.1.6 146Occlusion Queries 147 148 Occlusion queries use query objects to track fragments or samples 149 that pass the depth test. An occlusion query can be started and 150 finished by calling BeginQuery and EndQuery, respectively, with a target 151 of 152| SAMPLES_PASSED or ANY_SAMPLES_PASSED. 153 154 When an occlusion query is started 155| with the target SAMPLES_PASSED, 156 the samples-passed count maintained by the GL is set to zero. While that 157 occlusion query is active, the samples-passed count is incremented for 158 each fragment that passes the depth test. If the value of SAMPLE_BUFFERS 159 is 0, then the samples-passed count is incremented by 1 for each fragment. 160 If the value of SAMPLE_BUFFERS is 1, then the samples-passed count is 161 incremented by the number of samples whose coverage bit is set. However, 162 implementations, at their discretion, may instead increase the samples-passed 163 count by the value of SAMPLES if any sample in the fragment is covered. 164 When an occlusion query finishes and all fragments generated by commands 165 issued prior to EndQuery have been generated, the samples-passed count is written 166 to the corresponding query object as the query result value, and the query result for 167 that object is marked as available. 168 169 If the samples-passed count overflows (exceeds the value 2^n - 1, where n is 170 the number of bits in the samples-passed count), its value becomes undefined. It is 171 recommended, but not required, that implementations handle this overflow case by 172 saturating at 2^n - 1 and incrementing no further. 173 174| When an occlusion query is started with the target ANY_SAMPLES_PASSED, 175| the samples-boolean state maintained by the GL is set to FALSE. While 176| that occlusion query is active, the samples-boolean state is set to 177| TRUE if any fragment or sample passes the depth test. When the 178| occlusion query finishes, the samples-boolean state of FALSE or TRUE 179| is written to the corresponding query object as the query result value, 180| and the query result for that object is marked as available. 181 182 183Additions to Chapter 6 of the OpenGL 3.2 Specification 184(State and State Requests) 185 1866.1.6 187Asynchronous Queries 188p. 255 189 190Modify the Sentence beginning with "Information about the query target can be..." 191 192 ...target idendifies the query target, and must be one of 193 | SAMPLES_PASSED or ANY_SAMPLES_PASSED 194 for occlusion queries... 195 196Modify the paragraph beginning with "For occlusion queries (SAMPLES_PASSED)..." 197 198 For occlusion queries 199| (SAMPLES_PASSED and ANY_SAMPLES_PASSED), the number of bits 200| depends on the target. For a target of ANY_SAMPLES_PASSED, if 201| the number of bits is non-zero, the minimum number of bits is 1. For a target 202| of SAMPLES_PASSED, 203 if the number of bits is non-zero, ... 204 205 206Dependencies 207 208Version 3.2 (Compatibility Profile) interacts with this extension. 209 210 Other than adjusting the page numbers referenced in the edits, there are no 211 further changes required for the Compatibility Profile specification. 212 213ARB_occlusion_query 214 215 If ARB_occlusion_query is not supported, then delete the enum 216 SAMPLES_PASSED and delete sections of text refering to 217 SAMPLES_PASSED, and incorporate all other enums, entry 218 points and state introduced by ARB_occlusion_query into 219 this extension. 220 221Conditional Rendering 222 223 If Conditional Rendering is not supported, delete edits to 224 section on Conditional Rendering. 225 226New State 227 228(table 6.33, p. 298) 229 230 Get Value Type Get Command Initial Value Description Sec Attribute 231 --------- ---- ----------- ------------- ----------- ------ --------- 232 QUERY_RESULT Z+ GetQueryObjectuiv 0 samples-passed count 6.1.6 - 233| FALSE or any-samples-passed 234| boolean value 235 236 237Usage Examples 238 239 Here is some rough sample code that illustrates how this extension 240 can be used. 241 242 GLuint queries[N]; 243 GLint sampleBoolean; 244 GLint available; 245 246 247 glGenQueries(N, queries); 248 ... 249 // before this point, render major occluders 250 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 251 glDepthMask(GL_FALSE); 252 // also disable texturing and any fancy shaders 253 for (i = 0; i < N; i++) { 254 glBeginQuery(GL_ANY_SAMPLES_PASSED, queries[i]); 255 // render bounding box for object i 256 glEndQuery(GL_ANY_SAMPLES_PASSED); 257 } 258 259 glFlush(); 260 261 // Do other work until "most" of the queries are back, to avoid 262 // wasting time spinning 263 i = N*3/4; // instead of N-1, to prevent the GPU from going idle 264 do { 265 DoSomeStuff(); 266 glGetQueryObjectiv(queries[i], 267 GL_QUERY_RESULT_AVAILABLE, 268 &available); 269 } while (!available); 270 271 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 272 glDepthMask(GL_TRUE); 273 // reenable other state, such as texturing 274 for (i = 0; i < N; i++) { 275 glGetQueryObjectuiv(queries[i], GL_QUERY_RESULT, 276 &sampleBoolean); 277 if (sampleBoolean != 0) { 278 // render object i 279 } 280 } 281 282 Here is some rough sample code for a simple multipass rendering 283 application that does not use occlusion queries. 284 285 for (i = 0; i < N; i++) { 286 // First rendering pass 287 glDisable(GL_BLEND); 288 glDepthFunc(GL_LESS); 289 glDepthMask(GL_TRUE); 290 // configure shader 0 291 // render object i 292 293 // Second rendering pass 294 glEnable(GL_BLEND); 295 glBlendFunc(...); 296 glDepthFunc(GL_EQUAL); 297 glDepthMask(GL_FALSE); 298 // configure shader 1 299 // render object i 300 } 301 302 Here is the previous example, enhanced using occlusion queries. 303 304 GLuint queries[N]; 305 GLuint sampleBoolean; 306 307 glGenQueries(N, queries); 308 ... 309 // First rendering pass plus almost-free visibility checks 310 glDisable(GL_BLEND); 311 glDepthFunc(GL_LESS); 312 glDepthMask(GL_TRUE); 313 // configure shader 0 314 for (i = 0; i < N; i++) { 315 glBeginQuery(GL_ANY_SAMPLES_PASSED, queries[i]); 316 // render object i 317 glEndQuery(GL_ANY_SAMPLES_PASSED); 318 } 319 320 // Second pass only on objects that were visible 321 glEnable(GL_BLEND); 322 glBlendFunc(...); 323 glDepthFunc(GL_EQUAL); 324 glDepthMask(GL_FALSE); 325 // configure shader 1 326 for (i = 0; i < N; i++) { 327 glGetQueryObjectuiv(queries[i], GL_QUERY_RESULT, 328 &sampleBoolean); 329 if (sampleBoolean != 0) { 330 // render object i 331 } 332 } 333 334 335Issues 336 337 1) Can an occlusion query with a target of SAMPLES_PASSED 338 be active at the same time as an occlusion query with a 339 target of ANY_SAMPLES_PASSED? 340 341 Resolved. No! Specifically, it is an error to BeginQuery for 342 the targets SAMPLES_PASSED or ANY_SAMPLES_PASSED if the active 343 query is non-zero for EITHER target. 344 345 2) How many query types are there? 346 347 Unresolved. 348 349 The spec says "There are two query types" (p. 89), and 350 list them as Transform Feedback Queries and Occlusion Queries. 351 352 The spec says "Each type of query supported by the GL has an active 353 query object name." (p. 90) 354 355 Table 6.47 Miscellaneous (p. 312) says there are 356 CURRENT_QUERY 3 x Z+. 357 358 I believe there are three: 359 360 Primitive Queries (target PRIMITIVES_GENERATED) 361 Transform Feedback Queries (target TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) 362 and 363 Occlusion Queries (target SAMPLES_PASSED or ANY_SAMPLES_PASSED) 364 365 It is probable that the spec should say "There are three query types" 366 and list them as Primitive Queries (section 2.17), Transform Feedback 367 Queries (section 2.16) and Occlusion Queries (section 4.1.6). 368 369 A separate bug will be posted for the core specification to clarify 370 Primitive Queries and Transform Feedback. 371 372 This extension currently assumes that the bug will be resolved and only 373 edits the Occlusion Queries type to expand it to two targets. 374 375 3) Can we limit the number of query objects active? 376 377 Unresolved. This draft doesn't. 378 379 But, yes, we can limit the number of query objects active. 380 The language to do so would be straightforward, but why? 381 382 There can only be ONE occlusion query active at a time. The query object 383 created (or re-used) at BeginQuery contains the state to save the 384 boolean. At EndQuery the boolean for the current query is copied to 385 the query object's state. 386 387 (Clearly, OES can make another choice. But not sure why right now.) 388 389 4) Currently, if a draw within BeginQuery/EndQuery passes a depth 390 test, and a subsequent draw later covers all the pixels, can an 391 implementation return false (assuming the application queried 392 the result after the subsequent draw)? 393 394 Unresolved. This draft defers the issue. 395 The language to allow this is non-trivial. 396 397 Please note, the typical application will: 398 399 * set the color/depth masks to true, and blend state 400 * draw the major occluders 401 * draw visible opaque objects (coarsly sorted if possible) 402 * set the color/depth masks to false 403 * draw proxies for geometry which *might* be visible, with occlusion queries 404 * set the color masks to true, and blend state 405 * draw any transparent objects (sorted if possible) 406 * swap 407 408 * set the color/depth masks to true, and blend state 409 * draw the major occluders 410 * test the queries that are available from the prior frame 411 * draw visible and newly visible opaque objects (coarsly sorted if possible) 412 * set the color/depth masks to false 413 * draw proxies for geometry which *might* be visible, with occlusion queries 414 * set the color masks to true, and blend state 415 * draw any transparent objects (sorted if possible) 416 * swap 417 418 This technique has the disadvantage that the newly exposed 419 geometry is one frame late, but this is generally not considered 420 an issue. The advantage that in general the results are available by 421 the time the query is tested. 422 423 Note that no opaque occluders follow the queries in a frame. 424 425 Another common variation is: 426 427 * set the color/depth masks to true, and blend state 428 * draw the major occluders 429 * draw the visible opaque objects (corsely sorted if possible) 430 with occlusion queries 431 * set the color/depth mask to false 432 * draw proxies for geometry which *might* be visible, with occlusion queries 433 * set the color masks to true, and blend state 434 * draw any transparent objects (sorted if possible) 435 * swap 436 437 * set the color/depth masks to true, and blend state 438 * draw the major occluders 439 * test the queries that are available from the prior frame 440 * draw the still visible and newly visible opaque objects (coarsely sorted if possible) 441 with occlusion queries 442 * set the color/depth mask to false 443 * draw proxies for geometry which *might* be visible, with occlusion queries 444 * set the color masks to true, and blend state 445 * draw any transparent objects (sorted if possible) 446 * swap 447 448 This technique still has the disadvantage that newly exposed 449 geometry is one frame late, but still not considered an issue. 450 The advantage is that in general the results are available by the 451 time the query is tested. 452 453 This technique also culls geometry that was visible as it gets 454 occluded. (Though there can be some "picket fence" issues 455 and the occlusion query for actual geometry and proxy geometry 456 can cycle between false-true.) 457 458 Note that opaque occluders follow the queries in a frame. 459 460 5) What is this extension called? 461 462 Resolved. 463 Earlier drafts were EXT_occlusion_query2. 464 This draft is ARB_occlusion_query2. 465 466 6) What should the enum be called? 467 468 Resolved. 469 ANY_SAMPLES_PASSED. 470 471 7) Do we need "state required" for occlusion query objects? 472 473 Resolved. No. 474 That listing of state required had been moved to asynchronous 475 queries Section 2.14. It has been excised from the occlusion 476 query section. 477 478 8) Can an occlusion query "morph" from SAMPLES_PASSED to 479 ANY_SAMPLES_PASSED? That is, can the sequence 480 BeginQuery( SAMPLES_PASSED )...EndQuery( ANY_SAMPLES_PASSED ) 481 (or vice-versa)? 482 483 Resolved. No. Note this falls naturally by leaving the 484 EndQuery error language alone. ("If the active query object 485 name for target is zero when EndQuery is called, the error 486 INVALID_OPERATION is generated.") 487 488Revision History 489 2010-03-21 490 11, pbrown 491 Minor typo/wording fixes. 492 493 2010-01-26 494 10, pbrown 495 Assign enum value for ANY_SAMPLES_PASSED, using same allocation from 496 OES_occlusion_query. Enums are functionally equivalent. 497 498 2010-01-21 499 9, wwlk 500 JUST update version, date 501 502 2010-01-20 503 8, wwlk 504 Update issue 1, add issues 7 and 8. 505 Update the spec language to make it clear that you can't 506 start an occlusion query if an occlusion query (of either type) is 507 already active. 508 Update the spec language to trivially clarify conditional rendering. 509 510 2009-12-10 511 7, Jon Leech 512 Remove ARB suffixes for core 3.3 spec inclusion. Fix equation 513 typos. 514 515 2009-11-13 516 6, wwlk 517 Updated name and name strings to match ARB_occlusion_query2 518 519 2009-10-22 520 5, wwlk 521 Renamed to ARB_occlusion_query2 (and changed EXT to ARB) 522 Renamed ENUM (and updated ENUMs throughout) to ANY_SAMPLES_PASSED 523 Misc typos (Synchronos, COmpatibility) 524 525 2009-10-02 526 4, wwlk 527 Updates from comments. 528 Renamed to EXT_occlusion_query_boolean 529 Renamed ENUM(s) 530 Elaborated on issue 4. 531 532 2009-09-29 533 3, wwlk 534 updates from comments. 535 Added issues 4,5,6. 536 537 2009-09-28 538 2, wwlk 539 minor typo, add conditional rendering 540 541 2009-09-28 542 1, wwlk 543 first draft 544