Name
ARB_occlusion_query2
Name Strings
GL_ARB_occlusion_query2
Contributors
Aske Simon Christensen
Bill Licea-Kane
Cass Everitt
Jeff Bolz
Maurice Ribble
Contact
Bill Licea-Kane (bill 'at' amd.com)
Notice
Copyright (c) 2010-2013 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Status
Complete. Approved by the ARB at the 2010/01/22 F2F meeting.
Approved by the Khronos Board of Promoters on March 10, 2010.
Version
Date: March 21, 2010
Revision: 11
$Id$
Number
ARB Extension #80
Dependencies
Written based on the wording of OpenGL Specification
Version 3.2 (Core Profile) - July 24, 2009
Version 3.2 (Compatibility Profile) interacts with this extension.
OpenGL 1.x is required.
ARB_occlusion_query interacts with this extension.
Conditional rendering interacts with this extension.
Overview
This extension trivially adds a boolean occlusion query
to ARB_occlusion_query.
While the counter-based occlusion query provided by
ARB_occlusion_query is flexible, there is still value
to a simple boolean, which is often sufficient for applications.
IP Status
There are no known claims.
HP claimed IP to a related extension, ARB_occlusion_query.
HP committed to releasing rights to this IP to the ARB if the
functionality is included in OpenGL (April 10, 2003).
ARB_occlusion_query was promoted to core OpenGL 1.5 (July 29, 2003).
New Procedures and Functions
None
New Tokens
Accepted by the parameter of BeginQuery, EndQuery,
and GetQueryiv:
ANY_SAMPLES_PASSED 0x8C2F
Additions to Chapter 2 of the OpenGL 3.2 Specification
(OpenGL Operation)
2.14
Asynchronous Queries
p. 89-90, replace last sentence of first paragraph
Occlusion queries (see section 4.1.6) count the number of fragments
or samples that pass the depth test,
| or set a boolean to true when fragments or samples pass the depth
| test.
p. 90, modify the last paragraph before "The command void EndQuery..."
BeginQuery sets the active query object name for the query type given by
target to id. If BeginQuery is called with an id of zero, if the active query object
name for target is non-zero
| (for the targets SAMPLES_PASSED or ANY_SAMPLES PASSED, if the active query object
| for either target is non-zero),
if id is the name of an existing query object whose
type does not match target, if id is the active query object name for any query type,
or if id is the active query object for condtional rendering (see section 2.15), the
error INVALID_OPERATION is generated.
2.15
Conditional Rendering
p. 91
Add clause prior to "all rendering commands between"
"or if the result (ANY_SAMPLES_PASSED) is false,"
Add clause prior to "such commands are not discarded."
"or if the result is true,"
p. 92
Change last sentence of Section 2.15
The error
INVALID_OPERATION is generated if id is the name of a query object with a target
other than
| SAMPLES_PASSED
| or ANY_SAMPLES_PASSED,
or id is the name of a query currently in progress.
Additions to Chapter 4 of the OpenGL 3.2 Specification
(Per-Fragment Operations and the Frame Buffer)
p. 192, Replace 4.1.6
Occlusion Queries
Occlusion queries use query objects to track fragments or samples
that pass the depth test. An occlusion query can be started and
finished by calling BeginQuery and EndQuery, respectively, with a target
of
| SAMPLES_PASSED or ANY_SAMPLES_PASSED.
When an occlusion query is started
| with the target SAMPLES_PASSED,
the samples-passed count maintained by the GL is set to zero. While that
occlusion query is active, the samples-passed count is incremented for
each fragment that passes the depth test. If the value of SAMPLE_BUFFERS
is 0, then the samples-passed count is incremented by 1 for each fragment.
If the value of SAMPLE_BUFFERS is 1, then the samples-passed count is
incremented by the number of samples whose coverage bit is set. However,
implementations, at their discretion, may instead increase the samples-passed
count by the value of SAMPLES if any sample in the fragment is covered.
When an occlusion query finishes and all fragments generated by commands
issued prior to EndQuery have been generated, the samples-passed count 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 samples-passed count overflows (exceeds the value 2^n - 1, where n is
the number of bits in the samples-passed count), its value becomes undefined. It is
recommended, but not required, that implementations handle this overflow case by
saturating at 2^n - 1 and incrementing no further.
| When an occlusion query is started with the target ANY_SAMPLES_PASSED,
| the samples-boolean state maintained by the GL is set to FALSE. While
| that occlusion query is active, the samples-boolean state is set to
| TRUE if any fragment or sample passes the depth test. When the
| occlusion query finishes, the samples-boolean state of FALSE or TRUE
| is written to the corresponding query object as the query result value,
| and the query result for that object is marked as available.
Additions to Chapter 6 of the OpenGL 3.2 Specification
(State and State Requests)
6.1.6
Asynchronous Queries
p. 255
Modify the Sentence beginning with "Information about the query target can be..."
...target idendifies the query target, and must be one of
| SAMPLES_PASSED or ANY_SAMPLES_PASSED
for occlusion queries...
Modify the paragraph beginning with "For occlusion queries (SAMPLES_PASSED)..."
For occlusion queries
| (SAMPLES_PASSED and ANY_SAMPLES_PASSED), the number of bits
| depends on the target. For a target of ANY_SAMPLES_PASSED, if
| the number of bits is non-zero, the minimum number of bits is 1. For a target
| of SAMPLES_PASSED,
if the number of bits is non-zero, ...
Dependencies
Version 3.2 (Compatibility Profile) interacts with this extension.
Other than adjusting the page numbers referenced in the edits, there are no
further changes required for the Compatibility Profile specification.
ARB_occlusion_query
If ARB_occlusion_query is not supported, then delete the enum
SAMPLES_PASSED and delete sections of text refering to
SAMPLES_PASSED, and incorporate all other enums, entry
points and state introduced by ARB_occlusion_query into
this extension.
Conditional Rendering
If Conditional Rendering is not supported, delete edits to
section on Conditional Rendering.
New State
(table 6.33, p. 298)
Get Value Type Get Command Initial Value Description Sec Attribute
--------- ---- ----------- ------------- ----------- ------ ---------
QUERY_RESULT Z+ GetQueryObjectuiv 0 samples-passed count 6.1.6 -
| FALSE or any-samples-passed
| boolean value
Usage Examples
Here is some rough sample code that illustrates how this extension
can be used.
GLuint queries[N];
GLint sampleBoolean;
GLint available;
glGenQueries(N, queries);
...
// before this point, render major occluders
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
// also disable texturing and any fancy shaders
for (i = 0; i < N; i++) {
glBeginQuery(GL_ANY_SAMPLES_PASSED, queries[i]);
// render bounding box for object i
glEndQuery(GL_ANY_SAMPLES_PASSED);
}
glFlush();
// Do other work until "most" of the queries are back, to avoid
// wasting time spinning
i = N*3/4; // instead of N-1, to prevent the GPU from going idle
do {
DoSomeStuff();
glGetQueryObjectiv(queries[i],
GL_QUERY_RESULT_AVAILABLE,
&available);
} while (!available);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
// reenable other state, such as texturing
for (i = 0; i < N; i++) {
glGetQueryObjectuiv(queries[i], GL_QUERY_RESULT,
&sampleBoolean);
if (sampleBoolean != 0) {
// render object i
}
}
Here is some rough sample code for a simple multipass rendering
application that does not use occlusion queries.
for (i = 0; i < N; i++) {
// First rendering pass
glDisable(GL_BLEND);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
// configure shader 0
// render object i
// Second rendering pass
glEnable(GL_BLEND);
glBlendFunc(...);
glDepthFunc(GL_EQUAL);
glDepthMask(GL_FALSE);
// configure shader 1
// render object i
}
Here is the previous example, enhanced using occlusion queries.
GLuint queries[N];
GLuint sampleBoolean;
glGenQueries(N, queries);
...
// First rendering pass plus almost-free visibility checks
glDisable(GL_BLEND);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
// configure shader 0
for (i = 0; i < N; i++) {
glBeginQuery(GL_ANY_SAMPLES_PASSED, queries[i]);
// render object i
glEndQuery(GL_ANY_SAMPLES_PASSED);
}
// Second pass only on objects that were visible
glEnable(GL_BLEND);
glBlendFunc(...);
glDepthFunc(GL_EQUAL);
glDepthMask(GL_FALSE);
// configure shader 1
for (i = 0; i < N; i++) {
glGetQueryObjectuiv(queries[i], GL_QUERY_RESULT,
&sampleBoolean);
if (sampleBoolean != 0) {
// render object i
}
}
Issues
1) Can an occlusion query with a target of SAMPLES_PASSED
be active at the same time as an occlusion query with a
target of ANY_SAMPLES_PASSED?
Resolved. No! Specifically, it is an error to BeginQuery for
the targets SAMPLES_PASSED or ANY_SAMPLES_PASSED if the active
query is non-zero for EITHER target.
2) How many query types are there?
Unresolved.
The spec says "There are two query types" (p. 89), and
list them as Transform Feedback Queries and Occlusion Queries.
The spec says "Each type of query supported by the GL has an active
query object name." (p. 90)
Table 6.47 Miscellaneous (p. 312) says there are
CURRENT_QUERY 3 x Z+.
I believe there are three:
Primitive Queries (target PRIMITIVES_GENERATED)
Transform Feedback Queries (target TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)
and
Occlusion Queries (target SAMPLES_PASSED or ANY_SAMPLES_PASSED)
It is probable that the spec should say "There are three query types"
and list them as Primitive Queries (section 2.17), Transform Feedback
Queries (section 2.16) and Occlusion Queries (section 4.1.6).
A separate bug will be posted for the core specification to clarify
Primitive Queries and Transform Feedback.
This extension currently assumes that the bug will be resolved and only
edits the Occlusion Queries type to expand it to two targets.
3) Can we limit the number of query objects active?
Unresolved. This draft doesn't.
But, yes, we can limit the number of query objects active.
The language to do so would be straightforward, but why?
There can only be ONE occlusion query active at a time. The query object
created (or re-used) at BeginQuery contains the state to save the
boolean. At EndQuery the boolean for the current query is copied to
the query object's state.
(Clearly, OES can make another choice. But not sure why right now.)
4) Currently, if a draw within BeginQuery/EndQuery passes a depth
test, and a subsequent draw later covers all the pixels, can an
implementation return false (assuming the application queried
the result after the subsequent draw)?
Unresolved. This draft defers the issue.
The language to allow this is non-trivial.
Please note, the typical application will:
* set the color/depth masks to true, and blend state
* draw the major occluders
* draw visible opaque objects (coarsly sorted if possible)
* set the color/depth masks to false
* draw proxies for geometry which *might* be visible, with occlusion queries
* set the color masks to true, and blend state
* draw any transparent objects (sorted if possible)
* swap
* set the color/depth masks to true, and blend state
* draw the major occluders
* test the queries that are available from the prior frame
* draw visible and newly visible opaque objects (coarsly sorted if possible)
* set the color/depth masks to false
* draw proxies for geometry which *might* be visible, with occlusion queries
* set the color masks to true, and blend state
* draw any transparent objects (sorted if possible)
* swap
This technique has the disadvantage that the newly exposed
geometry is one frame late, but this is generally not considered
an issue. The advantage that in general the results are available by
the time the query is tested.
Note that no opaque occluders follow the queries in a frame.
Another common variation is:
* set the color/depth masks to true, and blend state
* draw the major occluders
* draw the visible opaque objects (corsely sorted if possible)
with occlusion queries
* set the color/depth mask to false
* draw proxies for geometry which *might* be visible, with occlusion queries
* set the color masks to true, and blend state
* draw any transparent objects (sorted if possible)
* swap
* set the color/depth masks to true, and blend state
* draw the major occluders
* test the queries that are available from the prior frame
* draw the still visible and newly visible opaque objects (coarsely sorted if possible)
with occlusion queries
* set the color/depth mask to false
* draw proxies for geometry which *might* be visible, with occlusion queries
* set the color masks to true, and blend state
* draw any transparent objects (sorted if possible)
* swap
This technique still has the disadvantage that newly exposed
geometry is one frame late, but still not considered an issue.
The advantage is that in general the results are available by the
time the query is tested.
This technique also culls geometry that was visible as it gets
occluded. (Though there can be some "picket fence" issues
and the occlusion query for actual geometry and proxy geometry
can cycle between false-true.)
Note that opaque occluders follow the queries in a frame.
5) What is this extension called?
Resolved.
Earlier drafts were EXT_occlusion_query2.
This draft is ARB_occlusion_query2.
6) What should the enum be called?
Resolved.
ANY_SAMPLES_PASSED.
7) Do we need "state required" for occlusion query objects?
Resolved. No.
That listing of state required had been moved to asynchronous
queries Section 2.14. It has been excised from the occlusion
query section.
8) Can an occlusion query "morph" from SAMPLES_PASSED to
ANY_SAMPLES_PASSED? That is, can the sequence
BeginQuery( SAMPLES_PASSED )...EndQuery( ANY_SAMPLES_PASSED )
(or vice-versa)?
Resolved. No. Note this falls naturally by leaving the
EndQuery error language alone. ("If the active query object
name for target is zero when EndQuery is called, the error
INVALID_OPERATION is generated.")
Revision History
2010-03-21
11, pbrown
Minor typo/wording fixes.
2010-01-26
10, pbrown
Assign enum value for ANY_SAMPLES_PASSED, using same allocation from
OES_occlusion_query. Enums are functionally equivalent.
2010-01-21
9, wwlk
JUST update version, date
2010-01-20
8, wwlk
Update issue 1, add issues 7 and 8.
Update the spec language to make it clear that you can't
start an occlusion query if an occlusion query (of either type) is
already active.
Update the spec language to trivially clarify conditional rendering.
2009-12-10
7, Jon Leech
Remove ARB suffixes for core 3.3 spec inclusion. Fix equation
typos.
2009-11-13
6, wwlk
Updated name and name strings to match ARB_occlusion_query2
2009-10-22
5, wwlk
Renamed to ARB_occlusion_query2 (and changed EXT to ARB)
Renamed ENUM (and updated ENUMs throughout) to ANY_SAMPLES_PASSED
Misc typos (Synchronos, COmpatibility)
2009-10-02
4, wwlk
Updates from comments.
Renamed to EXT_occlusion_query_boolean
Renamed ENUM(s)
Elaborated on issue 4.
2009-09-29
3, wwlk
updates from comments.
Added issues 4,5,6.
2009-09-28
2, wwlk
minor typo, add conditional rendering
2009-09-28
1, wwlk
first draft