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