• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    ARB_query_buffer_object
4
5Name Strings
6
7    GL_ARB_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
19Notice
20
21    Copyright (c) 2013 The Khronos Group Inc. Copyright terms at
22        http://www.khronos.org/registry/speccopyright.html
23
24Specification Update Policy
25
26    Khronos-approved extension specifications are updated in response to
27    issues and bugs prioritized by the Khronos OpenGL Working Group. For
28    extensions which have been promoted to a core Specification, fixes will
29    first appear in the latest version of that core Specification, and will
30    eventually be backported to the extension document. This policy is
31    described in more detail at
32        https://www.khronos.org/registry/OpenGL/docs/update_policy.php
33
34Status
35
36    Complete. Approved by the ARB on June 3, 2013.
37    Ratified by the Khronos Board of Promoters on July 19, 2013.
38
39Version
40
41    Last Modified Date: 7 March 2016
42    Author Revision: 3
43
44Number
45
46    ARB Extension #148
47
48Dependencies
49
50    OpenGL 1.5 is required.
51
52    This extension is written against the OpenGL 4.3 (core) specification.
53
54Overview
55
56    Statistics about the operation of the OpenGL pipeline, such as the number
57    of samples that passed the depth test, the elapsed time between two events
58    or the number of vertices written by transform feedback can be retrieved
59    from the GL through query objects. The result of a query object is
60    acquired by the application through the OpenGL API into a client provided
61    memory location. Should the result returned by the API be required for use
62    in a shader, it must be passed back to the GL via a program uniform or
63    some other mechanism. This requires a round-trip from the GPU to the CPU
64    and back.
65
66    This extension introduces a mechanism whereby the result of a query object
67    may be retrieved into a buffer object instead of client memory. This allows
68    the query rsult to be made available to a shader without a round-trip to
69    the CPU for example by subsequently using the buffer object as a uniform
70    buffer, texture buffer or other data store visible to the shader. This
71    functionality may also be used to place the results of many query objects
72    into a single, large buffer and then map or otherwise read back the entire
73    buffer at a later point in time, avoiding a per-query object CPU-GPU
74    synchronization event.
75
76    The extension allows acquiring the result of any query object type
77    supported by the GL implementation into a buffer object. The implementation
78    will determine the most efficient method of copying the query result to the
79    buffer.
80
81New Procedures and Functions
82
83    None.
84
85New Tokens
86
87    Accepted by the <pname> parameter of GetQueryObjectiv, GetQueryObjectuiv,
88    GetQueryObjecti64v and GetQueryObjectui64v:
89
90        QUERY_RESULT_NO_WAIT                            0x9194
91
92    Accepted by the <target> parameter of BindBuffer, BufferData,
93    BufferSubData, MapBuffer, UnmapBuffer, MapBufferRange, GetBufferSubData,
94    GetBufferParameteriv, GetBufferParameteri64v, GetBufferPointerv,
95    ClearBufferSubData, and the <readtarget> and <writetarget> parameters of
96    CopyBufferSubData:
97
98        QUERY_BUFFER                                    0x9192
99
100    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv,
101    and GetDoublev:
102
103        QUERY_BUFFER_BINDING                            0x9193
104
105    Accepted in the <barriers> bitfield in MemoryBarrier:
106
107        QUERY_BUFFER_BARRIER_BIT                        0x00008000
108
109Additions to Chapter 4 of the OpenGL Core Profile Specification, Version 4.3,
110"Event Model"
111
112    Modify Section 4.2.1, "Query Object Queries"
113
114    Add new paragraph after the fist paragraph on p. 44 ending with
115    "... <id> is the name of a query object."
116
117        Initially, zero is bound to the QUERY_BUFFER binding point, indicating
118    that <params> is a pointer into client memory. However, if a non-zero
119    buffer object is bound as the current query result buffer (see section
120    6.1), then <params> is treated as an offset into the designated buffer
121    object.
122
123    Add new paragraph after the third paragraph on p. 44 ending with
124    "... finite amount of time."
125
126        If <pname> is QUERY_RESULT_NO_WAIT, then the query object's result
127    value is returned as a single integer in <params> if the result is
128    available at the time of the state query. If the result is not available
129    then the destination memory location is not overwritten.
130
131Additions to Chapter 6 of the OpenGL Core Profile Specification, Version 4.3,
132"Buffer Objects"
133
134    Modify Section 6.1, "Creating and Binding Buffer Objects"
135
136    Add to Table 6.1: "Buffer object binding targets"
137
138    +--------------------+--------------------------+-------------------------+
139    | Target name        | Purpose                  | Described in section(s) |
140    +--------------------+--------------------------+-------------------------+
141    | QUERY_BUFFER       | Query result buffer      | 4.2.1                   |
142    +--------------------+--------------------------+-------------------------+
143
144Additions to Chapter 7 of the OpenGL Core Profile Specification, Version 4.3,
145"Programs and Shaders"
146
147    Modify Section 7.12, "Shader Memory Access"
148
149    Add to the list of MemoryBarrier <barriers> bullets, p. 138
150
151      * QUERY_BUFFER_BARRIER_BIT: Writes of buffer objects via the QUERY_BUFFER
152        binding (see section 4.2.1) after the barrier will reflect data written
153        by shaders prior to the barrier. Additionally, buffer object writes
154        issued after the barrier will wait on the completion of all shader
155        writes initiated prior to the barrier.
156
157Additions to the AGL/GLX/WGL Specifications
158
159    None.
160
161GLX Protocol
162
163    None.
164
165Errors
166
167  Replace second error case for QueryObject* with the following:
168
169    An INVALID_ENUM error is generated if <pname> is not QUERY_RESULT,
170    QUERY_RESULT_NO_WAIT or QUERY_RESULT_AVAILABLE.
171
172  Add error case for QueryObject* as follows:
173
174    An INVALID_OPERATION error is generated if the command would cause data
175    to be written beyond the bounds of the buffer currently bound to the
176    QUERY_BUFFER target.
177
178New State
179
180    Append to Table 23.73, "Miscellaneous"
181
182    +----------------------+------+--------------+---------------+------------------------------+-------+
183    | Get Value            | Type | Get Command  | Initial Value | Description                  | Sec.  |
184    +----------------------+------+--------------+---------------+------------------------------+-------+
185    | QUERY_BUFFER_BINDING | Z+   | GetIntegeriv | 0             | Query result buffer binding. | 4.2.1 |
186    +----------------------+------+--------------+---------------+------------------------------+-------+
187
188New Implementation Dependent State
189
190    None.
191
192Usage Examples
193
194    Convenient macro definition for specifying buffer offsets:
195
196        #define BUFFER_OFFSET(i)    ((void*)NULL + (i))
197
198    Example 1: Using occlusion query result in shader
199
200        // Create a buffer object for the query result
201        glGenBuffers(1, &queryBuffer);
202        glBindBuffer(GL_QUERY_BUFFER, queryBuffer);
203        glBufferData(GL_QUERY_BUFFER, sizeof(GLuint),
204                     NULL, GL_DYNAMIC_COPY);
205
206        // Perform occlusion query
207        glBeginQuery(GL_SAMPLES_PASSED, queryId)
208        ...
209        glEndQuery(GL_SAMPLES_PASSED);
210
211        // Get query results to buffer object
212        glBindBuffer(GL_QUERY_BUFFER, queryBuffer);
213        glGetQueryObjectuiv(queryId, GL_QUERY_RESULT, BUFFER_OFFSET(0));
214
215        // Bind query result buffer as uniform buffer
216        glBindBufferBase(GL_UNIFORM_BUFFER, 0, queryBuffer);
217        ...
218
219        --- Shader ---
220
221        ...
222        uniform queryResult {
223            uint samplesPassed;
224        };
225        ...
226        void main() {
227            ...
228            if (samplesPassed > threshold) {
229                // complex processing
230                ...
231            } else {
232                // simplified processing
233                ...
234            }
235            ...
236        }
237
238    Example 2: Using occlusion query result in shader only if result is available
239
240        // Create a buffer object for the query result
241        glGenBuffers(1, &queryBuffer);
242        glBindBuffer(GL_QUERY_BUFFER, queryBuffer);
243        glBufferData(GL_QUERY_BUFFER, 2 * sizeof(GLuint),
244                     NULL, GL_DYNAMIC_COPY);
245
246        // Perform occlusion query
247        glBeginQuery(GL_SAMPLES_PASSED, queryId)
248        ...
249        glEndQuery(GL_SAMPLES_PASSED);
250
251        // Get query availability and result (if available) to buffer object
252        glBindBuffer(GL_QUERY_BUFFER, queryBuffer);
253        glGetQueryObjectuiv(queryId, GL_QUERY_RESULT_AVAILABLE, BUFFER_OFFSET(0));
254        glGetQueryObjectuiv(queryId, GL_QUERY_RESULT_NO_WAIT, BUFFER_OFFSET(4));
255
256        // Bind query result buffer as uniform buffer
257        glBindBufferBase(GL_UNIFORM_BUFFER, 0, queryBuffer);
258        ...
259
260        --- Shader ---
261
262        ...
263        uniform queryResult {
264            uint resultAvailable;
265            uint samplesPassed;
266        };
267        ...
268        void main() {
269            ...
270            if (resultAvailable) {
271                if (samplesPassed > threshold) {
272                    // complex processing
273                    ...
274                } else {
275                    // simplified processing
276                    ...
277                }
278            } else {
279                // default processing if no query result is available
280                ...
281            }
282            ...
283        }
284
285    Example 3: Using a default value and QUERY_RESULT_NO_WAIT
286
287        // Create a buffer object for the query result
288        // Store a default value in the buffer that will be used
289        // if the query results are not available
290        glGenBuffers(1, &queryBuffer);
291        glBindBuffer(GL_QUERY_BUFFER, queryBuffer);
292        GLuint defaultValue = 42;
293        glBufferData(GL_QUERY_BUFFER, sizeof(GLuint),
294                     &defaultValue, GL_DYNAMIC_COPY);
295
296        // Perform occlusion query
297        glBeginQuery(GL_SAMPLES_PASSED, queryId)
298        ...
299        glEndQuery(GL_SAMPLES_PASSED);
300
301        // Get query results to buffer object with no wait
302        // Default value remains untouched if results are not available
303        glBindBuffer(GL_QUERY_BUFFER, queryBuffer);
304        glGetQueryObjectuiv(queryId, GL_QUERY_RESULT_NO_WAIT, BUFFER_OFFSET(0));
305        ...
306
307    Example 4: Using transform feedback query result to fill indirect draw buffer
308
309        // Create a buffer object for the indirect draw command
310        glGenBuffers(1, &drawIndirectBuffer);
311
312        // Initialize draw command
313        DrawArraysIndirectCommand cmd = { ... };
314        glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawIndirectBuffer);
315        glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand),
316                     &cmd, GL_DYNAMIC_COPY);
317
318        // Perform transform feedback query
319        glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, queryId)
320        ...
321        glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
322
323        // Write query result to the primCount field of the indirect draw command
324        glBindBuffer(GL_QUERY_BUFFER, drawIndirectBuffer);
325        glGetQueryObjectuiv(queryId, GL_QUERY_RESULT,
326                            BUFFER_OFFSET(offsetof(DrawArraysIndirectCommand, primCount)));
327
328        // Execute the indirect draw command
329        glDrawArraysIndirect(GL_TRIANGLES, BUFFER_OFFSET(0));
330        ...
331
332Issues
333
334    1) What is QUERY_RESULT_NO_WAIT useful for?
335
336    RESOLVED: The application may decide that it does not want to wait for the
337    result of the query object if it's not available at the time. This is not
338    a problem without this extension as the application can always query the
339    availability using QUERY_RESULT_AVAILABLE and decide to actually get the
340    results using QUERY_RESULT only if the result is available. However, when
341    using query buffers, QUERY_RESULT_AVAILABLE and QUERY_RESULT alone cannot
342    provide the same flexibility for shader based decision making as the
343    results are either always available (if QUERY_RESULT was used) or never.
344    QUERY_RESULT_NO_WAIT provides a way to query the result only if it's
345    available. Combined with QUERY_RESULT_AVAILABLE, the shader can decide
346    to use the result or not based on the availability (see usage example 2).
347
348    2) Should QUERY_RESULT_NO_WAIT be accepted by GetQueryObject* in case
349    there is no buffer bound to QUERY_BUFFER?
350
351    RESOLVED: YES, for completeness.
352
353    3) Is there any guarantee that GetQueryObject* will not wait for the
354    query results to become available if <pname> is QUERY_RESULT_NO_WAIT?
355
356    RESOLVED: There is no need to have such guarantee. An implementation may
357    choose to wait for the results even in case of QUERY_RESULT_NO_WAIT,
358    however, that may incur a potential performance hit in case the
359    application expects it to not wait.
360
361    4) Should the INVALID_OPERATION error be generated if a GetQueryObject*
362    command would access data outside the range of the bound query buffer?
363
364    RESOLVED: YES. This requires considering the value of <params> and the
365    size of the type of the written value to determine the maximum addressed
366    byte for the state query command.
367
368    Note: This follows the precedence of the language introduced by
369    ARB_pixel_buffer_object.
370
371    5) Should we support 64 bit versions of the state query commands
372    (GetQueryObjecti64v and GetQueryObjectui64v)?
373
374    RESOLVED: YES, both for completeness and to support timer queries. In this
375    case a 64 bit integer value is written to the buffer.
376
377    6) Should the extension support all query types supported by the current
378    GL implementation?
379
380    RESOLVED: YES. There is not much value in providing additional capability
381    queries that would allow the application to find out which query object
382    types are supported. Also, the GL implementation can always choose to
383    implement the functionality through a GPU-CPU rount-trip for query types
384    that cannot be resolved to a buffer by the hardware.
385
386    7) Is there any precedence that the pointer parameter of a glGet* command
387    is treated as an offset into a bound buffer object?
388
389    RESOLVED: YES, glGetTexImage accepts an offset into the pixel pack buffer
390    in case a pixel pack buffer is bound. As pixel buffer objects are part of
391    the core specification since version 2.1, no precedence is introduced by
392    this extension.
393
394    8) What should be written to the query buffer when QUERY_RESULT_NO_WAIT
395    is used but the results are not available?
396
397    DISCUSSION: Leaving the written value undefined is an option, however
398    in many cases the application can benefit from having a defined value in
399    the query buffer if the results are not available. The following options
400    were considered to support such use cases:
401
402        a. Write a predefined fixed value to the buffer.
403        b. Write a user specified value to the buffer.
404        c. Don't write anything to the buffer.
405
406    The problem with option a. is that it may be difficult to select such
407    a predefined value that would not potentially conflict with a valid
408    value. Option b. could be fine, however it requires new API to specify
409    this default value. Thus, option c. is considered to most preferable.
410
411    RESOLVED: Nothing, the current value in the specified offset of the
412    query buffer is left untouched.
413
414    9) How does ARB_query_buffer_object differ from AMD_query_buffer_object?
415
416    RESOLVED: This extension introduced a new barrier bit accepted by
417    MemoryBarrier that controls the relative ordering of shader buffer writes
418    and query buffer writes.
419
420Revision History
421
422    Rev.    Date      Author    Changes
423    ----  --------    --------  ----------------------------------------------
424
425      3   03/07/2016  drakos    Fixed typo in example #4
426      2   04/02/2013  drakos    Added missing function names to the list of
427                                functions accepting QUERY_BUFFER as parameter
428      1   03/08/2013  drakos    Initial draft based on AMD_query_buffer_object
429                                Removed suffixes
430                                Updated spec language to GL 4.3
431                                Added QUERY_BUFFER_BARRIER_BIT
432