Query Object

From OpenGL.org
Revision as of 11:11, 18 August 2012 by Alfonse (Talk | contribs) (Query scope)

Jump to: navigation, search
Query Object
Core in version 1.5
ARB extension ARB_occlusion_query

Query Objects are OpenGL Objects that are used for asynchronous queries of certain kinds of information.


Query objects follow the general OpenGL Object. They have glGenQueries and glDeleteQueries. However, unlike most other OpenGL Objects, there is no glBindQuery or similar function.

Many kinds of query operations require a scope. The scope of the query is bound by a pair of begin/end functions, such that the query returns some information about the execution of all commands within that scope.

Like textures, query objects have different types, represented by the target​ parameter taken by many query object functions. Query objects represent a single integer value which can be queried. The different types determine what the value being queried means and where it comes from:

  • GL_SAMPLES_PASSED​: The number of samples that pass the depth test for all rendering commands within the scope of the query.
  • GL_ANY_SAMPLES_PASSED​: GL_FALSE if none of the scoped rendering commands generate samples that pass the depth test; otherwise, the value is GL_TRUE. This requires OpenGL 3.3 or ARB_occlusion_query2.
  • GL_ANY_SAMPLES_PASSED_CONSERVATIVE​: As GL_ANY_SAMPLES_PASSED, except that the implementation may use a less accurate algorithm, which may be faster, but at the cost of more more false positives. This requires OpenGL 4.3 or ARB_ES3_compatibility.
  • GL_PRIMITIVES_GENERATED: Records the number of primitives sent to a Geometry Shader output stream (or by stream 0 if no GS is active) by scoped rendering commands. This requires OpenGL 3.0; multiple streams requires 4.0 or ARB_transform_feedback3.
  • GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: Records the number of primitives written by a Geometry Shader stream to a Transform Feedback object (or by stream 0 if no GS is active) by scoped rendering commands. This requires OpenGL 3.0; multiple streams requires 4.0 or ARB_transform_feedback3.
  • GL_TIME_ELAPSED​: Records the time that it takes for the GPU to execute all of the scoped commands. The timer starts when all commands before the scope have completed, and the timer ends when the last scoped command has completed.
  • GL_TIMESTAMP: Records the current time of the GPU.

Query scope

The result of query objects is usually based on data created from multiple rendering commands. As such, the commands that the query operates over is denoted by a begin/end pair of functions:

glBeginQuery(GLenum target​, GLuint id​);
glEndQuery(GLenum target​);

The only target​ not accepted by these functions is GL_TIMESTAMP.

Some targets are indexed, meaning that the target has some number of slots for query operations. These kinds of targets can use glBeginQueryIndexed and glEndQueryIndexed, which take an index that the function will begin a query on. glBeginQuery is defined as calling glBeginQueryIndexed with an index​ of 0.

Targets that allow for a non-zero index are:

  • GL_PRIMITIVES_GENERATED​: The maximum index is GL_MAX_VERTEX_STREAMS. Requires OpenGL 4.0 or ARB_transform_feedback3.
  • GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: The maximum index is GL_MAX_VERTEX_STREAMS. Requires OpenGL 4.0 or ARB_transform_feedback3.

Query retrieval

The purpose of query objects is to represent asynchronous queries of values. Thus, even after a query's scope has ended, the queried value may not be available.

To detect whether they queried value is available, use this function:

glGetQueryObject[ui64v](GLuint id​, GLenum pname​, GLint * params​);

Where id​ is the query object and pname​ is GL_QUERY_RESULT_AVAILABLE. This will return GL_FALSE​ if the query has not completed, and GL_TRUE​ otherwise.

To get the actual value, the same function is used with GL_QUERY_RESULT. If the value is too large for the bitdepth of the function (ie: an integer requires 48-bits to store, but the user uses the 32-bit version of the function), then the value returned will be the value that is closest to the actual value of the query.

Query precision

All query objects represent a single integer value. However, each type of query object has a different precision for this value. While you can query the integer value at 32 and 64-bit precision, the OpenGL implementation only provides so much precision for these values.

The precision for a query can be acquired by calling glGetQuery with GL_QUERY_COUNTER_BITS as the second parameter. OpenGL defines the minimum precision for each query type as follows:

Query type Minimum precision

* In OpenGL 3.3, the minimum precision required is a function of the maximum viewport width and height. Specifically, the precision is required to be at least enough to hold a counter that is twice the maximum width and height, thus supporting 2x multisampling at the largest buffer size.

Note that implementations are allowed to return 0 for any of these values. This means that the query type contains no actual information, and the implementation does not really support it..

Occlusion queries

Query Object
Core in version 4.5
Core ARB extension ARB_occlusion_query2

All of the "SAMPLES_PASSED" query types are referred to collectively as "occlusion queries". These represent ways to detect whether an object is visible.

Note that the sample count is based only on the depth test. The stencil test, alpha test, or fragment shader discard is irrelevant with queries.

When using Multisampling, the implementation is allowed to decide how to count the individual samples within a pixel area. The implementation may count only the samples within a triangle's area (if the triangle only covers part of a pixel), or it may count all of the samples if the triangle covers any of them in a pixel.

The GL_ANY_SAMPLES_PASSED_CONSERVATIVE​​ may be faster than GL_ANY_SAMPLES_PASSED​​. However, it may also be less accurate. If it is, it will only be such that it gives more false positives than the more accurate method.

The result of an occlusion query can be used as the condition for Conditional Rendering.

Timer queries

Calling glGetInteger64v with GL_TIMESTAMP will return the GPU timestamp when all previously given commands have issued, but not necessarily completed. As such, when coupled with an asynchronous timestamp timer query, one can determine the latency between when commands are issued and when they complete.

Primitive queries