1Name 2 3 ARB_instanced_arrays 4 5Name Strings 6 7 GL_ARB_instanced_arrays 8 9Contributors 10 11 Michael Gold, NVIDIA 12 James Helferty, TransGaming Inc. 13 Daniel Koch, TransGaming Inc. 14 John Rosasco, Apple 15 Mark Kilgard, NVIDIA 16 Piers Daniell, NVIDIA 17 18Contact 19 20 James Helferty, TransGaming Inc. (james 'at' transgaming.com) 21 Daniel Koch, TransGaming Inc. (daniel 'at' transgaming.com) 22 23Notice 24 25 Copyright (c) 2008-2013 The Khronos Group Inc. Copyright terms at 26 http://www.khronos.org/registry/speccopyright.html 27 28Specification Update Policy 29 30 Khronos-approved extension specifications are updated in response to 31 issues and bugs prioritized by the Khronos OpenGL Working Group. For 32 extensions which have been promoted to a core Specification, fixes will 33 first appear in the latest version of that core Specification, and will 34 eventually be backported to the extension document. This policy is 35 described in more detail at 36 https://www.khronos.org/registry/OpenGL/docs/update_policy.php 37 38Status 39 40 Approved by the ARB on July 11, 2008. 41 42Version 43 44 Last Modified Date: August 8, 2013 45 Author Revision: 7 46 47 EXT_direct_state_access interacton added with revision 7. 48 49Number 50 51 ARB Extension #49 52 53Dependencies 54 55 OpenGL 1.1 is required. 56 57 This extension is written against the OpenGL 2.1 Specification. 58 59 ARB_draw_instanced affects the definition of this extension. 60 61 EXT_draw_instanced affects the definition of this extension. 62 63 EXT_gpu_shader4 affects the definition of this extension. 64 65Overview 66 67 A common use case in GL for some applications is to be able to 68 draw the same object, or groups of similar objects that share 69 vertex data, primitive count and type, multiple times. This 70 extension provides a means of accelerating such use cases while 71 restricting the number of API calls, and keeping the amount of 72 duplicate data to a minimum. 73 74 In particular, this extension specifies an alternative to the 75 read-only shader variable introduced by ARB_draw_instanced. It 76 uses the same draw calls introduced by that extension, but 77 redefines them so that a vertex shader can instead use vertex 78 array attributes as a source of instance data. 79 80 This extension introduces an array "divisor" for generic 81 vertex array attributes, which when non-zero specifies that the 82 attribute is "instanced." An instanced attribute does not 83 advance per-vertex as usual, but rather after every <divisor> 84 conceptual draw calls. 85 86 (Attributes which aren't instanced are repeated in their entirety 87 for every conceptual draw call.) 88 89 By specifying transform data in an instanced attribute or series 90 of instanced attributes, vertex shaders can, in concert with the 91 instancing draw calls, draw multiple instances of an object with 92 one draw call. 93 94IP Status 95 96 No known IP claims. 97 98New Tokens 99 100 Accepted by the <pname> parameters of GetVertexAttribdv, 101 GetVertexAttribfv, and GetVertexAttribiv: 102 103 VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE 104 105New Procedures and Functions 106 107 void VertexAttribDivisorARB(uint index, uint divisor); 108 109 When EXT_direct_state_access is present: 110 111 void VertexArrayVertexAttribDivisorEXT(uint vaobj, uint index, uint divisor); 112 113Additions to Chapter 2 of the OpenGL 2.1 Specification 114(OpenGL Operation) 115 116 Modify section 2.8 (Vertex Arrays), p. 23 117 118 (remove modifications to section 2.8 made by ARB_draw_instanced 119 and EXT_draw_instanced, and replace everything from the second 120 paragraph, p. 27 through the second paragraph, p. 30) 121 The internal counter <instanceID> is a 32-bit integer value which 122 may be read by a vertex program as <vertex.instance>, as described 123 in section 2.X.3.2, or vertex shader as <gl_InstanceIDARB>, as 124 described in section 2.15.4.2. The value of this counter is 125 always zero, except as noted. 126 127 The command 128 129 void VertexAttribDivisorARB(uint index, uint divisor); 130 131 modifies the rate at which generic vertex attributes advance when 132 rendering multiple instances of primitives in a single draw call. 133 If <divisor> is zero, the attribute at slot <index> advances once 134 per vertex. If <divisor> is non-zero, the attribute advances once 135 per <divisor> instances of the set(s) of vertices being rendered. 136 An attribute is referred to as <instanced> if its <divisor> value 137 is non-zero. 138 139 The function 140 141 void ArrayElementInstanced( int i, int instance ); 142 143 does not exist in the GL, but is used to describe functionality in 144 the rest of this section. This function transfers the <i>th 145 element of every enabled, non-instanced array and the 146 floor(<instance>/<divisor>)'th element of every enabled instanced 147 array to the GL. The effect of ArrayElementInstanced(i) is the 148 same as the effect of the command sequence 149 150 if (normal array enabled) 151 Normal3[type]v(normal array element i); 152 if (color array enabled) 153 Color[size][type]v(color array element i); 154 if (secondary color array enabled) 155 SecondaryColor3[type]v(secondary color array element i); 156 if (fog coordinate array enabled) 157 FogCoord[type]v(fog coordinate array element i); 158 for (j = 0; j < textureUnits; j++) { 159 if (texture coordinate set j array enabled) 160 MultiTexCoord[size][type]v(TEXTURE0 + j, texture coordinate set j array element i); 161 } 162 if (color index array enabled) 163 Index[type]v(color index array element i); 164 if (edge flag array enabled) 165 EdgeFlagv(edge flag array element i); 166 for (j = 1; j < genericAttributes; j++) { 167 if (generic vertex attribute j array enabled) { 168 if (VERTEX_ATTRIB_ARRAY_DIVISOR_ARB[j] > 0) 169 k = floor(instance / VERTEX_ATTRIB_ARRAY_DIVISOR_ARB[j]); 170 else 171 k = i; 172 if (generic vertex attribute j array normalization flag is set, and 173 type is not FLOAT or DOUBLE) 174 VertexAttrib[size]N[type]v(j, generic vertex attribute j array element k); 175 else 176 VertexAttrib[size][type]v(j, generic vertex attribute j array element k); 177 } 178 } 179 if (generic attribute array 0 enabled) { 180 if (VERTEX_ATTRIB_ARRAY_DIVISOR_ARB[0] > 0) 181 k = floor(instance / VERTEX_ATTRIB_ARRAY_DIVISOR_ARB[0]); 182 else 183 k = i; 184 if (generic vertex attribute 0 array normalization flag is set, and 185 type is not FLOAT or DOUBLE) 186 VertexAttrib[size]N[type]v(0, generic vertex attribute 0 array element k); 187 else 188 VertexAttrib[size][type]v(0, generic vertex attribute 0 array element k); 189 } else if (vertex array enabled) { 190 Vertex[size][type]v(vertex array element i); 191 } 192 193 where <textureUnits> and <genericAttributes> give the number of 194 texture coordinate sets and generic vertex attributes supported by 195 the implementation, respectively. "[size]" and "[type]" 196 correspond to the size and type of the corresponding array. For 197 generic vertex attributes, it is assumed that a complete set of 198 vertex attribute commands exists, even though not all such 199 functions are provided by the GL. 200 201 The command 202 203 void ArrayElement( int i ); 204 205 behaves identically to ArrayElementInstanced with the instance 206 set to zero; it is equivalent to calling 207 208 ArrayElementInstanced(i, 0); 209 210 Changes made to array data between the execution of Begin and the 211 corresponding execution of End may affect calls to ArrayElement 212 that are made within the same Begin/End period in non-sequential 213 ways. That is, a call to ArrayElement that precedes a change to 214 array data may access the changed data, and a call that follows a 215 change to array data may access original data. 216 217 Specifying i < 0 results in undefined behavior. Generating the 218 error INVALID VALUE is recommended in this case. 219 220 The function 221 222 void DrawArraysOneInstance( enum mode, int first, sizei count, int instance ); 223 224 does not exist in the GL, but is used to describe functionality in 225 the rest of this section. This function constructs a sequence of 226 geometric primitives using elements <first> through <first> + 227 <count> - 1 of each enabled, non-instanced array and the 228 <instance>th element of each enabled, instanced array. <mode> 229 specifies what kind of primitives are constructed; it accepts the 230 same token values as the mode parameter of the Begin command. The 231 effect of 232 233 DrawArraysOneInstance (mode, first, count, int instance); 234 235 is the same as the effect of the command sequence 236 237 Begin(mode); 238 for (int i = 0; i < count ; i++) 239 ArrayElementInstanced(first+ i, instance); 240 End(); 241 242 with one exception: the current normal coordinates, color, 243 secondary color, color index, edge flag, fog coordinate, texture 244 coordinates, and generic attributes are each indeterminate after 245 execution of DrawArraysOneInstance, if the corresponding array is 246 enabled. Current values corresponding to disabled arrays are not 247 modified by the execution of DrawArraysOneInstance. 248 249 Specifying first < 0 results in undefined behavior. Generating 250 the error INVALID_VALUE is recommended in this case. 251 252 The command 253 254 void DrawArrays( enum mode, int first, sizei count ); 255 256 behaves identically to DrawArraysOneInstance with the instance 257 set to zero; the effect of calling 258 259 DrawArrays(mode, first, count); 260 261 is equivalent to the command sequence: 262 263 if (mode or count is invalid ) 264 generate appropriate error 265 else 266 DrawArraysOneInstance(mode, first, count, 0); 267 268 The command 269 270 void DrawArraysInstancedARB(enum mode, int first, sizei count, 271 sizei primcount); 272 273 behaves identically to DrawArrays except that <primcount> 274 instances of the range of elements are executed, the value of 275 <instanceID> advances for each iteration, and the instanced 276 elements advance per instance depending on the value of the divisor 277 for that vertex attribute set with VertexAttribDivisorARB. It has the 278 same effect as: 279 280 if (mode or count is invalid) 281 generate appropriate error 282 else { 283 for (i = 0; i < primcount; i++) { 284 instanceID = i; 285 DrawArraysOneInstance(mode, first, count, i); 286 } 287 instanceID = 0; 288 } 289 290 The command 291 292 void MultiDrawArrays( enum mode, int *first, 293 sizei *count, sizei primcount ); 294 295 behaves identically to DrawArraysInstancedARB except that 296 <primcount> separate ranges of elements are specified instead, 297 all elements are treated as though they are not instanced, 298 and the value of <instanceID> stays at 0. It has the same 299 effect as: 300 301 if (mode is invalid) 302 generate appropriate error 303 else { 304 for (i = 0; i < primcount; i++) { 305 if (count[i] > 0) 306 DrawArraysOneInstance(mode, first[i], count[i], 0); 307 } 308 } 309 310 The function 311 312 void DrawElementsOneInstance( enum mode, sizei count, enum type, 313 void *indices ); 314 315 does not exist in the GL, but is used to describe functionality in 316 the rest of this section. This function constructs a sequence of 317 geometric primitives using the <count> elements whose indices are 318 stored in indices. <type> must be one of UNSIGNED_BYTE, 319 UNSIGNED_SHORT, or UNSIGNED_INT, indicating that the values in 320 <indices> are indices of GL type ubyte, ushort, or uint 321 respectively. <mode> specifies what kind of primitives are 322 constructed; it accepts the same token values as the mode 323 parameter of the Begin command. The effect of 324 325 DrawElementsOneInstance (mode, count, type, indices); 326 327 is the same as the effect of the command sequence 328 329 Begin(mode); 330 for (int i = 0; i < count ; i++) 331 ArrayElementInstanced(indices[i], instance); 332 End(); 333 334 with one exception: the current normal coordinates, color, 335 secondary color, color index, edge flag, fog coordinate, texture 336 coordinates, and generic attributes are each indeterminate after 337 execution of DrawElementsOneInstance, if the corresponding array is 338 enabled. Current values corresponding to disabled arrays are not 339 modified by the execution of DrawElementsOneInstance. 340 341 The command 342 343 void DrawElements( enum mode, sizei count, enum type, 344 void *indices ); 345 346 behaves identically to DrawElementsOneInstance with the instance 347 paremeter set to zero; the effect of calling 348 349 DrawElements(mode, count, type, indices); 350 351 is equivalent to the command sequence: 352 353 if (mode, count or type is invalid ) 354 generate appropriate error 355 else 356 DrawElementsOneInstance(mode, count, type, indices, 0); 357 358 The command 359 360 void DrawElementsInstancedARB(enum mode, sizei count, enum type, 361 const void *indices, sizei primcount); 362 363 behaves identically to DrawElements except that <primcount> 364 instances of the set of elements are executed, the value of 365 <instanceID> advances between each set, and the instance 366 advances between each set. It has the same effect as: 367 368 if (mode, count, or type is invalid ) 369 generate appropriate error 370 else { 371 for (int i = 0; i < primcount; i++) { 372 instanceID = i; 373 DrawElementsOneInstance(mode, count, type, indices, i); 374 } 375 instanceID = 0; 376 } 377 378 The command 379 380 void MultiDrawElements( enum mode, sizei *count, 381 enum type, void **indices, sizei primcount ); 382 383 behaves identically to DrawElementsInstancedARB except that 384 <primcount> separate sets of elements are specified instead, all 385 elements are treated as though they are not instanced, and the 386 value of <instanceID> stays at 0. It has the same effect as: 387 388 if (mode, count, or type is invalid ) 389 generate appropriate error 390 else { 391 for (int i = 0; i < primcount; i++) 392 DrawElementsOneInstance(mode, count[i], type, indices[i], 0); 393 } 394 395 The command 396 397 void DrawRangeElements( enum mode, uint start, 398 uint end, sizei count, enum type, void *indices ); 399 400 is a restricted form of DrawElements. ... 401 402 Modify section 2.8 (Vertex Arrays), p. 23 403 404 (remove section before final paragraph, p. 30, that was added by 405 ARB_draw_instanced and EXT_draw_instanced) 406 407 Modify section 2.8 (Vertex Arrays), p. 33 408 409 (in the list of client state required to implement vertex arrays add) 410 ... <n> integers representing vertex attribute divisors, ... 411 412 (in the list of initial state add) 413 ... the divisors are each zero, ... 414 415Additions to Chapter 5 of the OpenGL 2.1 Specification 416(Special Functions) 417 418 The error INVALID_OPERATION is generated if DrawArraysInstancedARB 419 or DrawElementsInstancedARB is called during display list 420 compilation. 421 422Additions to Chapter 6 of the OpenGL 2.1 Specification (State and State 423Requests) 424 425 In section 6.1.14, add to the list of pnames accepted by 426 GetVertexAttrib*v: VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 427 428************************************************************************ 429 430Additions to the AGL/EGL/GLX/WGL Specifications 431 432 None 433 434Dependencies on OpenGL 1.4 435 436 If OpenGL 1.4 is not supported, all discussion of MultiDrawArrays 437 and MultiDrawElements should be removed from section 2.8. 438 439Dependencies on ARB_draw_instanced 440 441 If neither ARB_draw_instanced nor EXT_draw_instanced is supported, 442 all references to instanceID should be removed from section 2.8. 443 444 If ARB_draw_instanced is not supported, all references to gl_InstanceIDARB 445 should be removed from section 2.8. This extension will introduce 446 the following additional New Procedures and Functions: 447 448 void DrawArraysInstancedARB(enum mode, int first, sizei count, 449 sizei primcount); 450 void DrawElementsInstancedARB(enum mode, sizei count, enum type, 451 const void *indices, sizei primcount); 452 453Dependencies on EXT_draw_instanced 454 455 If EXT_draw_instanced is supported, then DrawArraysInstancedEXT 456 is aliased to DrawArraysInstancedARB, and DrawElementsInstancedEXT 457 is aliased to DrawElementsInstancedARB. 458 459 If neither ARB_draw_instanced nor EXT_draw_instanced is supported, 460 all references to instanceID should be removed from section 2.8. 461 462Dependencies on EXT_gpu_shader4 463 464 If EXT_gpu_shader4 is not supported, all references to gl_InstanceID 465 should be removed from section 2.8. 466 467Dependencies on EXT_direct_state_access 468 469 When EXT_direct_state_access is present, add a new entry point that takes a 470 vertex array object handle: 471 472 void VertexArrayVertexAttribDivisorEXT(uint vaobj, uint index, uint divisor); 473 474 This command behaves identically to glVertexAttribDivisorEXT 475 except it modifies the state of the vertex array object named 476 by its initial vaobj parameter (rather than the currently bound 477 vertex array object). The vertex array object named by vaobj must 478 be generated by GenVertexArrays (and not since deleted); otherwise 479 an INVALID_OPERATION error is generated. 480 481 GetVertexArrayIntegeri_vEXT must accept VERTEX_ATTRIB_ARRAY_DIVISOR_ARB to return 482 the vertex array object's vertex attrib array divisor state. 483 484Errors 485 486 INVALID_VALUE is generated by VertexAttribDivisorARB if <index> 487 is greater than or equal to MAX_VERTEX_ATTRIBS. 488 489 INVALID_ENUM is generated by DrawElementsInstancedARB if <type> is 490 not one of UNSIGNED_BYTE, UNSIGNED_SHORT or UNSIGNED_INT. 491 492 INVALID_VALUE is generated by DrawArraysInstancedARB if <first> is 493 less than zero. 494 495New State 496 497 Changes to table 6.7, p. 268 (Vertex Array Data) 498 499 Initial 500 Get Value Type Get Command Value Description Sec. Attribute 501 --------- ---- ----------- ------- ----------- ---- --------- 502 VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 16+ xZ+ GetVertexAttrib 0 Instance Divisor 2.8 vertex-array 503 504Issues 505 506 1) Should legacy arrays be supported, or only generic vertex 507 attribs? 508 509 Resolved: It is possible to render instanced objects which use 510 legacy array types but only the generic arrays may have a 511 divisor. 512 513 2) Should generic attrib zero be instance-able? 514 515 Resolved: Yes. This was added in revision 5 of the spec. 516 517 Prior to revision 5 of this spec, attempting to call 518 VertexAttribDivisorARB with attrib=0 generated INVALID_VALUE. 519 It was originally thought that this implied issuing a vertex at 520 lower frequency than the associated attribs (due to the special 521 properties of vertex attribute zero in GL 2.x and the compatibility 522 profiles). That would be true if the immediate-mode model of 523 instancing was to make an attribute call only once every <N> vertices 524 for instanced attributes -- you wouldn't want to specify a new vertex 525 once every <N> vertices! But that's not the model -- the frequency 526 <N> is only used to translate an incoming array element <i> into an 527 attribute index <k>. Immediate mode calls are still specified as 528 happening for every vertex. Given this definition, it is not 529 necessary to do anything differently for attribute zero. 530 531 3) How is ArrayElement affected by this extension? 532 533 Resolved: Arrays with a non-zero divisor return the first 534 element of the array, as if instanceID is fixed at zero. This 535 allows legacy varray draw calls to give instancing behavior 536 but are still defined in terms of ArrayElement. 537 538 4) Should DrawArraysInstanced and DrawElementsInstanced be compiled 539 into display lists? 540 541 Resolved: No, calling these during display list compilation 542 generate INVALID_OPERATION. This matches EXT_draw_instanced 543 and ARB_draw_instanced. 544 545 5) Is it useful to have instancing for the MultiDraw* functions? 546 547 Resolved: We will follow the lead of EXT_draw_instanced and 548 ARB_draw_instanced in not extending these functions. 549 550 6) This extension must elaborate on the definition of functions 551 added by ARB_draw_instanced. How do we do this in a manner such 552 that both extensions may coexist? 553 554 Resolved: This extension is specified so that it applies on 555 top of ARB_draw_instanced and EXT_draw_instanced. As a 556 result, some portions modified by those extensions are 557 replaced in this extension. In the event that those 558 extensions are not supported, this extension reintroduces 559 the draw calls from ARB_draw_instanced. 560 561 7) How should EXT_direct_state_access interact with this extension? 562 563 Resolved: Add glVertexArrayVertexAttribDivisorEXT selector-free 564 vertex array object command and glGetVertexArrayIntegeri_vEXT 565 query must accept VERTEX_ATTRIB_ARRAY_DIVISOR_ARB to return the 566 vertex array object's vertex attrib array divisor state. 567 568 The DSA interaction was added July 2013. If implementations 569 respond to a wglGetProcAddress, etc. query for 570 "glVertexArrayVertexAttribDivisorEXT" with a NULL pointer, 571 the DSA functionality is not available. 572 573Revision History 574 575 #7 August 6, 2013 mjk 576 - Add EXT_direct_state_access interaction 577 #6 February 11, 2010 dgkoch 578 - sync language with GL3.3, add required and initial state for divisors 579 #5 January 13, 2010 dgkoch 580 - update spec so that specifying a divisor on vertex attrib 0 is legal (5796) 581 - update resolution of Issue 2 appropriately. 582 #4 January 1, 2010, Jon Leech 583 - Correct Errors section to match spec body 584 #3 July 8, 2008, jhelferty 585 - expanded Overview 586 - changed name of GLSL instance ID variable to follow naming conventions, 587 and match ARB_draw_instanced. 588 - made dependencies and interactions more explicit 589 #2 May 14 2008, jhelferty 590 - changed pname to VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 591 - added dependencies on ARB_draw_instanced 592 - update to GL 2.1 language 593 #1 May 12 2008, dgkoch 594 - copied from NVX_instanced_arrays and renamed. removed original revision history 595