blob: 8aa747c43d154c057e7fa8188e8808cf664b14ad [file] [log] [blame]
Name
AMD_query_buffer_object
Name Strings
GL_AMD_query_buffer_object
Contact
Daniel Rakos (daniel.rakos 'at' amd.com)
Contributors
Daniel Rakos, AMD
Graham Sellers, AMD
Christophe Riccio, AMD
Status
Shipping in Catalyst 12.6
Version
Last Modified Date: 03/07/2016
Author Revision: 6
Number
420
Dependencies
OpenGL 1.5 is required.
This extension is written against the OpenGL 4.2 (core) specification.
Overview
Statistics about the operation of the OpenGL pipeline, such as the number
of samples that passed the depth test, the elapsed time between two events
or the number of vertices written to a transform feedback buffer may
be retrieved from the GL through query objects. The current value of a
query object may be retrieved by the application through the OpenGL API.
Should the result returned by the API be required for use in a shader,
it must be passed back to the GL via a program uniform or some other
mechanism. This requires a round-trip from the GPU to the CPU and back.
This extension introduces a mechanism whereby the current value of a query
result may be retrieved into a buffer object instead of client memory.
This allows the query result to be made available to a shader without a
round-trip to the CPU for example by subsequently using the buffer object
as a uniform buffer, texture buffer or other data store visible to the
shader. This functionality may also be used to place the results of
many query objects into a single, large buffer and then map or otherwise
read back the entire buffer at a later point in time, avoiding a per-query
CPU-GPU synchronization event.
The result of any query object type supported by the GL implementation
may be retrieved into a buffer object. The implementation will determine
the most efficient method of copying the query result to the buffer.
New Procedures and Functions
None.
New Tokens
Accepted by the <pname> parameter of GetQueryObjectiv, GetQueryObjectuiv,
GetQueryObjecti64v and GetQueryObjectui64v:
QUERY_RESULT_NO_WAIT_AMD 0x9194
Accepted by the <target> parameters of BindBuffer, BufferData,
BufferSubData, MapBuffer, UnmapBuffer, MapBufferRange, GetBufferSubData,
GetBufferParameteriv
and GetBufferPointerv:
QUERY_BUFFER_AMD 0x9192
Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv,
and GetDoublev:
QUERY_BUFFER_BINDING_AMD 0x9193
Additions to Chapter 2 of the OpenGL 4.2 (core) Specification (OpenGL Operation)
Modify Section 2.9, Buffer Objects
Add to Table 2.8: Buffer object binding targets (p. 43)
+---------------------+--------------------------+-------------------------+
| Target name | Purpose | Described in section(s) |
+---------------------+--------------------------+-------------------------+
| QUERY_BUFFER_AMD | Query result buffer | 6.1.7 |
+---------------------+--------------------------+-------------------------+
Additions to Chapter 3 of the OpenGL 3.2 (core) Specification (Rasterization)
None.
Additions to Chapter 4 of the OpenGL 3.2 (core) Specification (Per-Fragment Operations and the Frame Buffer)
None.
Additions to Chapter 5 of the OpenGL 3.2 (core) Specification (Special Functions)
None.
Additions to Chapter 6 of the OpenGL 3.2 (core) Specification (State and State Requests)
Modify Section 6.1.7, Asynchronous Queries
Add new paragraph before the third paragraph on p. 358
Initially, zero is bound for the QUERY_BUFFER_AMD, indicating that
<params> is a pointer into client memory. However, if a non-zero buffer
object is bound as the current query result buffer, then <params> is
treated as an offset into the designated buffer object.
Replace last sentence of the third paragraph on p. 358
beginning with "The state of a query object can be queried with ..."
pname must be QUERY_RESULT, QUERY_RESULT_NO_WAIT_AMD
or QUERY_RESULT_AVAILABLE.
Add new paragraph before the last paragraph on p. 358
If <pname> is QUERY_RESULT_NO_WAIT_AMD, then the query object's
result value is returned as a single integer in <params> if the result
is available at the time of the state query. If the result is not
available then the destination memory location is not overwritten.
Additions to the AGL/GLX/WGL Specifications
None.
GLX Protocol
None.
Errors
INVALID_OPERATION is generated by GetQueryObjectiv, GetQueryObjectuiv,
GetQueryObjecti64v, or GetQueryObjectui64v if the command would cause data
to be written beyond the bounds of the buffer currently currently bound
to the QUERY_BUFFER_AMD target.
New State
Append to Table 6.41, "Query Object State"
+----------------------------+-------+-------------------+---------------+-------------------------------------------+-------+
| Get Value | Type | Get Command | Initial Value | Description | Sec. |
+----------------------------+-------+-------------------+---------------+-------------------------------------------+-------+
| QUERY_BUFFER_BINDING_AMD | Z+ | GetIntegeriv | 0 | Query result buffer binding. | 6.1.7 |
+----------------------------+-------+-------------------+---------------+-------------------------------------------+-------+
New Implementation Dependent State
None.
Usage Examples
Convenient macro definition for specifying buffer offsets:
#define BUFFER_OFFSET(i) ((void*)NULL + (i))
Example 1: Using occlusion query result in shader
// Create a buffer object for the query result
glGenBuffers(1, &queryBuffer);
glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
glBufferData(GL_QUERY_BUFFER_AMD, sizeof(GLuint),
NULL, GL_DYNAMIC_COPY);
// Perform occlusion query
glBeginQuery(GL_SAMPLES_PASSED, queryId)
...
glEndQuery(GL_SAMPLES_PASSED);
// Get query results to buffer object
glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
glGetQueryObjectuiv(queryId, GL_QUERY_RESULT, BUFFER_OFFSET(0));
// Bind query result buffer as uniform buffer
glBindBufferBase(GL_UNIFORM_BUFFER, 0, queryBuffer);
...
--- Shader ---
...
uniform queryResult {
uint samplesPassed;
};
...
void main() {
...
if (samplesPassed > threshold) {
// complex processing
...
} else {
// simplified processing
...
}
...
}
Example 2: Using occlusion query result in shader only if result is available
// Create a buffer object for the query result
glGenBuffers(1, &queryBuffer);
glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
glBufferData(GL_QUERY_BUFFER_AMD, 2 * sizeof(GLuint),
NULL, GL_DYNAMIC_COPY);
// Perform occlusion query
glBeginQuery(GL_SAMPLES_PASSED, queryId)
...
glEndQuery(GL_SAMPLES_PASSED);
// Get query availability and result (if available) to buffer object
glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
glGetQueryObjectuiv(queryId, GL_QUERY_RESULT_AVAILABLE, BUFFER_OFFSET(0));
glGetQueryObjectuiv(queryId, GL_QUERY_RESULT_NO_WAIT_AMD, BUFFER_OFFSET(4));
// Bind query result buffer as uniform buffer
glBindBufferBase(GL_UNIFORM_BUFFER, 0, queryBuffer);
...
--- Shader ---
...
uniform queryResult {
uint resultAvailable;
uint samplesPassed;
};
...
void main() {
...
if (resultAvailable) {
if (samplesPassed > threshold) {
// complex processing
...
} else {
// simplified processing
...
}
} else {
// default processing if no query result is available
...
}
...
}
Example 3: Using a default value and QUERY_RESULT_NO_WAIT_AMD
// Create a buffer object for the query result
// Store a default value in the buffer that will be used
// if the query results are not available
glGenBuffers(1, &queryBuffer);
glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
GLuint defaultValue = 42;
glBufferData(GL_QUERY_BUFFER_AMD, sizeof(GLuint),
&defaultValue, GL_DYNAMIC_COPY);
// Perform occlusion query
glBeginQuery(GL_SAMPLES_PASSED, queryId)
...
glEndQuery(GL_SAMPLES_PASSED);
// Get query results to buffer object with no wait
// Default value remains untouched if results are not available
glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
glGetQueryObjectuiv(queryId, GL_QUERY_RESULT_NO_WAIT_AMD, BUFFER_OFFSET(0));
...
Example 4: Using transform feedback query result to fill indirect draw buffer
// Create a buffer object for the indirect draw command
glGenBuffers(1, &drawIndirectBuffer);
// Initialize draw command
DrawArraysIndirectCommand cmd = { ... };
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawIndirectBuffer);
glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand),
&cmd, GL_DYNAMIC_COPY);
// Perform transform feedback query
glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, queryId)
...
glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
// Write query result to the primCount field of the indirect draw command
glBindBuffer(GL_QUERY_BUFFER_AMD, drawIndirectBuffer);
glGetQueryObjectuiv(queryId, GL_QUERY_RESULT,
BUFFER_OFFSET(offsetof(DrawArraysIndirectCommand, primCount)));
// Execute the indirect draw command
glDrawArraysIndirect(GL_TRIANGLES, BUFFER_OFFSET(0));
...
Issues
1) What is QUERY_RESULT_NO_WAIT_AMD useful for?
RESOLVED: The application may decide that it does not want to wait for the
result of the query object if it's not available at the time. This is not
a problem without this extension as the application can always query the
availability using QUERY_RESULT_AVAILABLE and decide to actually get the
results using QUERY_RESULT only if the result is available. However, when
using query buffers, QUERY_RESULT_AVAILABLE and QUERY_RESULT alone cannot
provide the same flexibility for shader based decision making as the
results are either always available (if QUERY_RESULT was used) or never.
QUERY_RESULT_NO_WAIT_AMD provides a way to query the result only if it's
available. Combined with QUERY_RESULT_AVAILABLE, the shader can decide
to use the result or not based on the availability (see usage example 2).
2) Should QUERY_RESULT_NO_WAIT_AMD be accepted by GetQueryObjectiv,
GetQueryObjectuiv, GetQueryObjecti64v and GetQueryObjectui64v in case
there is no buffer bound to QUERY_BUFFER_AMD?
RESOLVED: YES, for completeness.
3) Is there any guarantee that GetQueryObject* will not wait for the
query results to become available if <pname> is QUERY_RESULT_NO_WAIT_AMD?
RESOLVED: There is no need to have such guarantee. An implementation may
choose to wait for the results even in case of QUERY_RESULT_NO_WAIT_AMD,
however, that may incur a potential performance hit in case the application
expects it to not wait.
4) Should the INVALID_OPERATION error be generated if a GetQueryObject*
command would access data outside the rage of the bound query buffer?
RESOLVED: YES. This requires considering the value of <params> and the
size of the type of the written value to determine the maximum addressed
byte for the state query command.
Note: This follows the precedence of the language introduced by
ARB_pixel_buffer_object.
5) Should we support 64 bit versions of the state query commands
(GetQueryObjecti64v and GetQueryObjectui64v)?
RESOLVED: YES, both for completeness and to support timer queries. In this
case a 64 bit integer value is written to the buffer.
6) Should the extension support all query types supported by the current
GL implementation?
RESOLVED: YES. There is not much value in providing additional capability
queries that would allow the application to find out which query object
types are supported. Also, the GL implementation can always choose to
implement the functionality in software for query types that cannot be
supported in hardware.
7) Is there any precedence that the pointer parameter of a glGet* command
is treated as an offset into a bound buffer object?
RESOLVED: YES, glGetTexImage accepts an offset into the pixel pack buffer
in case a pixel pack buffer is bound. As pixel buffer objects are part of
the core specification since version 2.1, no precedence is introduced by
this extension.
8) What should be written to the query buffer when QUERY_RESULT_NO_WAIT_AMD
is used but the results are not available?
DISCUSSION: Leaving the written value undefined is an option, however
in many cases the application can benefit from having a default value in
the query buffer if the results are not available. The following options
were considered to support such use cases:
a. Write a predefined fixed value to the buffer.
b. Write a user specified value to the buffer.
c. Don't write anything to the buffer, leave the current value
untouched.
The problem with option a. is that it may be difficult to select such
a predefined value that would not potentially conflict with a valid
value. Option b. could be fine, however it requires new API to specify
this default value. Thus, option c. is considered to most preferable.
RESOLVED: Nothing, the current value in the specified offset of the
query buffer is leaved untouched.
Revision History
Rev. Date Author Changes
---- -------- -------- ---------------------------------------------
6 03/07/2016 drakos Fixed typo in example #4
5 06/01/2012 gsellers Minor cleanup. Shipped and ready for posting.
4 03/21/2012 drakos Removed undefined behavior when using
QUERY_RESULT_NO_WAIT and added issue #8
based on Graham's comments
3 03/12/2012 drakos Assigned enums
2 03/07/2012 drakos Clarified issues #4 and #5
Added issue #7 based on Christophe's comments
1 02/28/2012 drakos Initial revision