• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    AMD_query_buffer_object
4
5Name Strings
6
7    GL_AMD_query_buffer_object
8
9Contact
10
11    Daniel Rakos (daniel.rakos 'at' amd.com)
12
13Contributors
14
15    Daniel Rakos, AMD
16    Graham Sellers, AMD
17    Christophe Riccio, AMD
18
19Status
20
21    Shipping in Catalyst 12.6
22
23Version
24
25    Last Modified Date:         03/07/2016
26    Author Revision:            6
27
28Number
29
30    420
31
32Dependencies
33
34    OpenGL 1.5 is required.
35
36    This extension is written against the OpenGL 4.2 (core) specification.
37
38Overview
39
40    Statistics about the operation of the OpenGL pipeline, such as the number
41    of samples that passed the depth test, the elapsed time between two events
42    or the number of vertices written to a transform feedback buffer may
43    be retrieved from the GL through query objects. The current value of a
44    query object may be retrieved by the application through the OpenGL API.
45    Should the result returned by the API be required for use in a shader,
46    it must be passed back to the GL via a program uniform or some other
47    mechanism. This requires a round-trip from the GPU to the CPU and back.
48
49    This extension introduces a mechanism whereby the current value of a query
50    result may be retrieved into a buffer object instead of client memory.
51    This allows the query result to be made available to a shader without a
52    round-trip to the CPU for example by subsequently using the buffer object
53    as a uniform buffer, texture buffer or other data store visible to the
54    shader. This functionality may also be used to place the results of
55    many query objects into a single, large buffer and then map or otherwise
56    read back the entire buffer at a later point in time, avoiding a per-query
57    CPU-GPU synchronization event.
58
59    The result of any query object type supported by the GL implementation
60    may be retrieved into a buffer object. The implementation will determine
61    the most efficient method of copying the query result to the buffer.
62
63New Procedures and Functions
64
65    None.
66
67New Tokens
68
69    Accepted by the <pname> parameter of GetQueryObjectiv, GetQueryObjectuiv,
70    GetQueryObjecti64v and GetQueryObjectui64v:
71
72        QUERY_RESULT_NO_WAIT_AMD                        0x9194
73
74    Accepted by the <target> parameters of BindBuffer, BufferData,
75    BufferSubData, MapBuffer, UnmapBuffer, MapBufferRange, GetBufferSubData,
76    GetBufferParameteriv
77    and GetBufferPointerv:
78
79        QUERY_BUFFER_AMD                                0x9192
80
81    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv,
82    and GetDoublev:
83
84        QUERY_BUFFER_BINDING_AMD                        0x9193
85
86Additions to Chapter 2 of the OpenGL 4.2 (core) Specification (OpenGL Operation)
87
88    Modify Section 2.9, Buffer Objects
89
90    Add to Table 2.8: Buffer object binding targets (p. 43)
91
92    +---------------------+--------------------------+-------------------------+
93    | Target name         | Purpose                  | Described in section(s) |
94    +---------------------+--------------------------+-------------------------+
95    | QUERY_BUFFER_AMD    | Query result buffer      | 6.1.7                   |
96    +---------------------+--------------------------+-------------------------+
97
98Additions to Chapter 3 of the OpenGL 3.2 (core) Specification (Rasterization)
99
100    None.
101
102Additions to Chapter 4 of the OpenGL 3.2 (core) Specification (Per-Fragment Operations and the Frame Buffer)
103
104    None.
105
106Additions to Chapter 5 of the OpenGL 3.2 (core) Specification (Special Functions)
107
108    None.
109
110Additions to Chapter 6 of the OpenGL 3.2 (core) Specification (State and State Requests)
111
112  Modify Section 6.1.7, Asynchronous Queries
113
114  Add new paragraph before the third paragraph on p. 358
115
116        Initially, zero is bound for the QUERY_BUFFER_AMD, indicating that
117    <params> is a pointer into client memory. However, if a non-zero buffer
118    object is bound as the current query result buffer, then <params> is
119    treated as an offset into the designated buffer object.
120
121  Replace last sentence of the third paragraph on p. 358
122  beginning with "The state of a query object can be queried with ..."
123
124    pname must be QUERY_RESULT, QUERY_RESULT_NO_WAIT_AMD
125    or QUERY_RESULT_AVAILABLE.
126
127  Add new paragraph before the last paragraph on p. 358
128
129        If <pname> is QUERY_RESULT_NO_WAIT_AMD, then the query object's
130    result value is returned as a single integer in <params> if the result
131    is available at the time of the state query. If the result is not
132    available then the destination memory location is not overwritten.
133
134Additions to the AGL/GLX/WGL Specifications
135
136    None.
137
138GLX Protocol
139
140    None.
141
142Errors
143
144    INVALID_OPERATION is generated by GetQueryObjectiv, GetQueryObjectuiv,
145    GetQueryObjecti64v, or GetQueryObjectui64v if the command would cause data
146    to be written beyond the bounds of the buffer currently currently bound
147    to the QUERY_BUFFER_AMD target.
148
149New State
150
151    Append to Table 6.41, "Query Object State"
152
153    +----------------------------+-------+-------------------+---------------+-------------------------------------------+-------+
154    | Get Value                  | Type  | Get Command       | Initial Value | Description                               | Sec.  |
155    +----------------------------+-------+-------------------+---------------+-------------------------------------------+-------+
156    | QUERY_BUFFER_BINDING_AMD   | Z+    | GetIntegeriv      | 0             | Query result buffer binding.              | 6.1.7 |
157    +----------------------------+-------+-------------------+---------------+-------------------------------------------+-------+
158
159New Implementation Dependent State
160
161    None.
162
163Usage Examples
164
165    Convenient macro definition for specifying buffer offsets:
166
167        #define BUFFER_OFFSET(i)    ((void*)NULL + (i))
168
169    Example 1: Using occlusion query result in shader
170
171        // Create a buffer object for the query result
172        glGenBuffers(1, &queryBuffer);
173        glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
174        glBufferData(GL_QUERY_BUFFER_AMD, sizeof(GLuint),
175                     NULL, GL_DYNAMIC_COPY);
176
177        // Perform occlusion query
178        glBeginQuery(GL_SAMPLES_PASSED, queryId)
179        ...
180        glEndQuery(GL_SAMPLES_PASSED);
181
182        // Get query results to buffer object
183        glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
184        glGetQueryObjectuiv(queryId, GL_QUERY_RESULT, BUFFER_OFFSET(0));
185
186        // Bind query result buffer as uniform buffer
187        glBindBufferBase(GL_UNIFORM_BUFFER, 0, queryBuffer);
188        ...
189
190        --- Shader ---
191
192        ...
193        uniform queryResult {
194            uint samplesPassed;
195        };
196        ...
197        void main() {
198            ...
199            if (samplesPassed > threshold) {
200                // complex processing
201                ...
202            } else {
203                // simplified processing
204                ...
205            }
206            ...
207        }
208
209    Example 2: Using occlusion query result in shader only if result is available
210
211        // Create a buffer object for the query result
212        glGenBuffers(1, &queryBuffer);
213        glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
214        glBufferData(GL_QUERY_BUFFER_AMD, 2 * sizeof(GLuint),
215                     NULL, GL_DYNAMIC_COPY);
216
217        // Perform occlusion query
218        glBeginQuery(GL_SAMPLES_PASSED, queryId)
219        ...
220        glEndQuery(GL_SAMPLES_PASSED);
221
222        // Get query availability and result (if available) to buffer object
223        glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
224        glGetQueryObjectuiv(queryId, GL_QUERY_RESULT_AVAILABLE, BUFFER_OFFSET(0));
225        glGetQueryObjectuiv(queryId, GL_QUERY_RESULT_NO_WAIT_AMD, BUFFER_OFFSET(4));
226
227        // Bind query result buffer as uniform buffer
228        glBindBufferBase(GL_UNIFORM_BUFFER, 0, queryBuffer);
229        ...
230
231        --- Shader ---
232
233        ...
234        uniform queryResult {
235            uint resultAvailable;
236            uint samplesPassed;
237        };
238        ...
239        void main() {
240            ...
241            if (resultAvailable) {
242                if (samplesPassed > threshold) {
243                    // complex processing
244                    ...
245                } else {
246                    // simplified processing
247                    ...
248                }
249            } else {
250                // default processing if no query result is available
251                ...
252            }
253            ...
254        }
255
256    Example 3: Using a default value and QUERY_RESULT_NO_WAIT_AMD
257
258        // Create a buffer object for the query result
259        // Store a default value in the buffer that will be used
260        // if the query results are not available
261        glGenBuffers(1, &queryBuffer);
262        glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
263        GLuint defaultValue = 42;
264        glBufferData(GL_QUERY_BUFFER_AMD, sizeof(GLuint),
265                     &defaultValue, GL_DYNAMIC_COPY);
266
267        // Perform occlusion query
268        glBeginQuery(GL_SAMPLES_PASSED, queryId)
269        ...
270        glEndQuery(GL_SAMPLES_PASSED);
271
272        // Get query results to buffer object with no wait
273        // Default value remains untouched if results are not available
274        glBindBuffer(GL_QUERY_BUFFER_AMD, queryBuffer);
275        glGetQueryObjectuiv(queryId, GL_QUERY_RESULT_NO_WAIT_AMD, BUFFER_OFFSET(0));
276        ...
277
278    Example 4: Using transform feedback query result to fill indirect draw buffer
279
280        // Create a buffer object for the indirect draw command
281        glGenBuffers(1, &drawIndirectBuffer);
282
283        // Initialize draw command
284        DrawArraysIndirectCommand cmd = { ... };
285        glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawIndirectBuffer);
286        glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand),
287                     &cmd, GL_DYNAMIC_COPY);
288
289        // Perform transform feedback query
290        glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, queryId)
291        ...
292        glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
293
294        // Write query result to the primCount field of the indirect draw command
295        glBindBuffer(GL_QUERY_BUFFER_AMD, drawIndirectBuffer);
296        glGetQueryObjectuiv(queryId, GL_QUERY_RESULT,
297                            BUFFER_OFFSET(offsetof(DrawArraysIndirectCommand, primCount)));
298
299        // Execute the indirect draw command
300        glDrawArraysIndirect(GL_TRIANGLES, BUFFER_OFFSET(0));
301        ...
302
303Issues
304
305    1) What is QUERY_RESULT_NO_WAIT_AMD useful for?
306
307    RESOLVED: The application may decide that it does not want to wait for the
308    result of the query object if it's not available at the time. This is not
309    a problem without this extension as the application can always query the
310    availability using QUERY_RESULT_AVAILABLE and decide to actually get the
311    results using QUERY_RESULT only if the result is available. However, when
312    using query buffers, QUERY_RESULT_AVAILABLE and QUERY_RESULT alone cannot
313    provide the same flexibility for shader based decision making as the
314    results are either always available (if QUERY_RESULT was used) or never.
315    QUERY_RESULT_NO_WAIT_AMD provides a way to query the result only if it's
316    available. Combined with QUERY_RESULT_AVAILABLE, the shader can decide
317    to use the result or not based on the availability (see usage example 2).
318
319    2) Should QUERY_RESULT_NO_WAIT_AMD be accepted by GetQueryObjectiv,
320    GetQueryObjectuiv, GetQueryObjecti64v and GetQueryObjectui64v in case
321    there is no buffer bound to QUERY_BUFFER_AMD?
322
323    RESOLVED: YES, for completeness.
324
325    3) Is there any guarantee that GetQueryObject* will not wait for the
326    query results to become available if <pname> is QUERY_RESULT_NO_WAIT_AMD?
327
328    RESOLVED: There is no need to have such guarantee. An implementation may
329    choose to wait for the results even in case of QUERY_RESULT_NO_WAIT_AMD,
330    however, that may incur a potential performance hit in case the application
331    expects it to not wait.
332
333    4) Should the INVALID_OPERATION error be generated if a GetQueryObject*
334    command would access data outside the rage of the bound query buffer?
335
336    RESOLVED: YES. This requires considering the value of <params> and the
337    size of the type of the written value to determine the maximum addressed
338    byte for the state query command.
339
340    Note: This follows the precedence of the language introduced by
341    ARB_pixel_buffer_object.
342
343    5) Should we support 64 bit versions of the state query commands
344    (GetQueryObjecti64v and GetQueryObjectui64v)?
345
346    RESOLVED: YES, both for completeness and to support timer queries. In this
347    case a 64 bit integer value is written to the buffer.
348
349    6) Should the extension support all query types supported by the current
350    GL implementation?
351
352    RESOLVED: YES. There is not much value in providing additional capability
353    queries that would allow the application to find out which query object
354    types are supported. Also, the GL implementation can always choose to
355    implement the functionality in software for query types that cannot be
356    supported in hardware.
357
358    7) Is there any precedence that the pointer parameter of a glGet* command
359    is treated as an offset into a bound buffer object?
360
361    RESOLVED: YES, glGetTexImage accepts an offset into the pixel pack buffer
362    in case a pixel pack buffer is bound. As pixel buffer objects are part of
363    the core specification since version 2.1, no precedence is introduced by
364    this extension.
365
366    8) What should be written to the query buffer when QUERY_RESULT_NO_WAIT_AMD
367    is used but the results are not available?
368
369    DISCUSSION: Leaving the written value undefined is an option, however
370    in many cases the application can benefit from having a default value in
371    the query buffer if the results are not available. The following options
372    were considered to support such use cases:
373
374        a. Write a predefined fixed value to the buffer.
375        b. Write a user specified value to the buffer.
376        c. Don't write anything to the buffer, leave the current value
377           untouched.
378
379    The problem with option a. is that it may be difficult to select such
380    a predefined value that would not potentially conflict with a valid
381    value. Option b. could be fine, however it requires new API to specify
382    this default value. Thus, option c. is considered to most preferable.
383
384    RESOLVED: Nothing, the current value in the specified offset of the
385    query buffer is leaved untouched.
386
387
388Revision History
389
390    Rev.    Date      Author    Changes
391    ----  --------    --------  ---------------------------------------------
392
393      6   03/07/2016  drakos    Fixed typo in example #4
394      5   06/01/2012  gsellers  Minor cleanup. Shipped and ready for posting.
395      4   03/21/2012  drakos    Removed undefined behavior when using
396                                QUERY_RESULT_NO_WAIT and added issue #8
397                                based on Graham's comments
398      3   03/12/2012  drakos    Assigned enums
399      2   03/07/2012  drakos    Clarified issues #4 and #5
400                                Added issue #7 based on Christophe's comments
401      1   02/28/2012  drakos    Initial revision
402