1 Name 2 3 ANGLE_instanced_arrays 4 5 Name Strings 6 7 GL_ANGLE_instanced_arrays 8 9 Contributors 10 11 Contributors to ARB_instanced_arrays 12 Nicolas Capens, TransGaming Inc. 13 James Helferty, TransGaming Inc. 14 Kenneth Russell, Google Inc. 15 Vangelis Kokkevis, Google Inc. 16 17 Contact 18 19 Daniel Koch, TransGaming Inc. (daniel 'at' transgaming.com) 20 21 Status 22 23 Implemented in ANGLE r976. 24 25 Version 26 27 Last Modified Date: February 8, 2012 28 Author Revision: 3 29 30 Number 31 32 OpenGL ES Extension #109 33 34 Dependencies 35 36 OpenGL ES 2.0 is required. 37 38 This extension is written against the OpenGL ES 2.0 Specification. 39 40 Overview 41 42 A common use case in GL for some applications is to be able to 43 draw the same object, or groups of similar objects that share 44 vertex data, primitive count and type, multiple times. This 45 extension provides a means of accelerating such use cases while 46 restricting the number of API calls, and keeping the amount of 47 duplicate data to a minimum. 48 49 This extension introduces an array "divisor" for generic 50 vertex array attributes, which when non-zero specifies that the 51 attribute is "instanced." An instanced attribute does not 52 advance per-vertex as usual, but rather after every <divisor> 53 conceptual draw calls. 54 55 (Attributes which aren't instanced are repeated in their entirety 56 for every conceptual draw call.) 57 58 By specifying transform data in an instanced attribute or series 59 of instanced attributes, vertex shaders can, in concert with the 60 instancing draw calls, draw multiple instances of an object with 61 one draw call. 62 63 IP Status 64 65 No known IP claims. 66 67 New Tokens 68 69 Accepted by the <pname> parameters of GetVertexAttribfv and 70 GetVertexAttribiv: 71 72 VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE 73 74 New Procedures and Functions 75 76 void DrawArraysInstancedANGLE(enum mode, int first, sizei count, 77 sizei primcount); 78 79 void DrawElementsInstancedANGLE(enum mode, sizei count, enum type, 80 const void *indices, sizei primcount); 81 82 void VertexAttribDivisorANGLE(uint index, uint divisor); 83 84 Additions to Chapter 2 of the OpenGL ES 2.0 Specification 85 (OpenGL ES Operation) 86 87 Modify section 2.8 (Vertex Arrays), p. 21 88 89 After description of EnableVertexAttribArray / DisableVertexAttribArray 90 add the following: 91 92 "The command 93 94 void VertexAttribDivisorANGLE(uint index, uint divisor); 95 96 modifies the rate at which generic vertex attributes advance when 97 rendering multiple instances of primitives in a single draw call 98 (see DrawArraysInstancedANGLE and DrawElementsInstancedANGLE below). 99 If <divisor> is zero, the attribute at slot <index> advances once 100 per vertex. If <divisor> is non-zero, the attribute advances once 101 per <divisor> instances of the primitives being rendered. 102 An attribute is referred to as "instanced" if its <divisor> value is 103 non-zero." 104 105 Replace the text describing DrawArrays and DrawElements in the 106 "Transferring Array Elements" subsection of 2.8, from the second paragraph 107 through the end of the section with the following: 108 109 "The command 110 111 void DrawArraysOneInstance( enum mode, int first, sizei count, int instance ); 112 113 does not exist in the GL, but is used to describe functionality in 114 the rest of this section. This function constructs a sequence of 115 geometric primitives by transferring elements <first> through <first> + 116 <count> - 1 of each enabled non-instanced array to the GL. <mode> 117 specifies what kind of primitives are constructed, as defined in section 118 2.6.1. 119 120 If an enabled vertex attribute array is instanced (it has a non-zero 121 attribute <divisor> as specified by VertexAttribDivisorANGLE), the element 122 that is transferred to the GL is given by: 123 124 floor( <instance> / <divisor> ). 125 126 If an array corresponding to a generic attribute required by a vertex shader 127 is not enabled, then the corresponding element is taken from the current 128 generic attribute state (see section 2.7). 129 130 If an array corresponding to a generic attribute required by a vertex shader 131 is enabled, the corresponding current generic attribute value is unaffected 132 by the execution of DrawArraysOneInstance. 133 134 Specifying <first> < 0 results in undefined behavior. Generating the error 135 INVALID_VALUE is recommended in this case. 136 137 The command 138 139 void DrawArrays( enum mode, int first, sizei count ); 140 141 is equivalent to the command sequence 142 143 DrawArraysOneInstance(mode, first, count, 0); 144 145 The command 146 147 void DrawArraysInstancedANGLE(enum mode, int first, sizei count, 148 sizei primcount); 149 150 behaves identically to DrawArrays except that <primcount> 151 instances of the range of elements are executed, and the 152 <instance> advances for each iteration. Instanced attributes that 153 have <divisor> N, (where N > 0, as specified by 154 VertexAttribDivisorANGLE) advance once every N instances. 155 156 It has the same effect as: 157 158 if (mode, count, or primcount is invalid) 159 generate appropriate error 160 else { 161 for (i = 0; i < primcount; i++) { 162 DrawArraysOneInstance(mode, first, count, i); 163 } 164 } 165 166 The command 167 168 void DrawElementsOneInstance( enum mode, sizei count, enum type, 169 void *indices, int instance ); 170 171 does not exist in the GL, but is used to describe functionality in 172 the rest of this section. This command constructs a sequence of 173 geometric primitives by successively transferring the <count> elements 174 whose indices are stored in the currently bound element array buffer 175 (see section 2.9.2) at the offset defined by <indices> to the GL. 176 The <i>-th element transferred by DrawElementsOneInstance will be taken 177 from element <indices>[i] of each enabled non-instanced array. 178 <type> must be one of UNSIGNED_BYTE, UNSIGNED_SHORT, or UNSIGNED_INT, 179 indicating that the index values are of GL type ubyte, ushort, or uint 180 respectively. <mode> specifies what kind of primitives are constructed, 181 as defined in section 2.6.1. 182 183 If an enabled vertex attribute array is instanced (it has a non-zero 184 attribute <divisor> as specified by VertexAttribDivisorANGLE), the element 185 that is transferred to the GL is given by: 186 187 floor( <instance> / <divisor> ); 188 189 If an array corresponding to a generic attribute required by a vertex 190 shader is not enabled, then the corresponding element is taken from the 191 current generic attribute state (see section 2.7). Otherwise, if an array 192 is enabled, the corresponding current generic attribute value is 193 unaffected by the execution of DrawElementsOneInstance. 194 195 The command 196 197 void DrawElements( enum mode, sizei count, enum type, 198 const void *indices); 199 200 behaves identically to DrawElementsOneInstance with the <instance> 201 parameter set to zero; the effect of calling 202 203 DrawElements(mode, count, type, indices); 204 205 is equivalent to the command sequence: 206 207 if (mode, count or type is invalid ) 208 generate appropriate error 209 else 210 DrawElementsOneInstance(mode, count, type, indices, 0); 211 212 The command 213 214 void DrawElementsInstancedANGLE(enum mode, sizei count, enum type, 215 const void *indices, sizei primcount); 216 217 behaves identically to DrawElements except that <primcount> 218 instances of the set of elements are executed and the instance 219 advances between each set. Instanced attributes are advanced as they do 220 during the execution of DrawArraysInstancedANGLE. It has the same effect as: 221 222 if (mode, count, primcount, or type is invalid ) 223 generate appropriate error 224 else { 225 for (int i = 0; i < primcount; i++) { 226 DrawElementsOneInstance(mode, count, type, indices, i); 227 } 228 } 229 230 If the number of supported generic vertex attributes (the value of 231 MAX_VERTEX_ATTRIBS) is <n>, then the client state required to implement 232 vertex arrays consists of <n> boolean values, <n> memory pointers, <n> 233 integer stride values, <n> symbolic constants representing array types, 234 <n> integers representing values per element, <n> boolean values 235 indicating normalization, and <n> integers representing vertex attribute 236 divisors. 237 238 In the initial state, the boolean values are each false, the memory 239 pointers are each NULL, the strides are each zero, the array types are 240 each FLOAT, the integers representing values per element are each four, 241 and the divisors are each zero." 242 243 Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization) 244 245 None 246 247 Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment 248 Operations and the Framebuffer) 249 250 None 251 252 Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions) 253 254 None 255 256 Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State 257 Requests) 258 259 In section 6.1.8, add VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE to the list of 260 pnames accepted by GetVertexAttribfv and GetVertexAttribiv. 261 262 Additions to the AGL/EGL/GLX/WGL Specifications 263 264 None 265 266 Dependencies on OES_element_index_uint 267 268 If OES_element_index_uint is not supported, removed all references 269 to UNSIGNED_INT indices and the associated GL data type uint in 270 the description of DrawElementsOneInstance. 271 272 Errors 273 274 INVALID_VALUE is generated by VertexAttribDivisorANGLE if <index> 275 is greater than or equal to MAX_VERTEX_ATTRIBS. 276 277 INVALID_ENUM is generated by DrawElementsInstancedANGLE if <type> is 278 not one of UNSIGNED_BYTE, UNSIGNED_SHORT or UNSIGNED_INT. 279 280 INVALID_VALUE is generated by DrawArraysInstancedANGLE if <first>, 281 <count>, or <primcount> is less than zero. 282 283 INVALID_ENUM is generated by DrawArraysInstancedANGLE or 284 DrawElementsInstancedANGLE if <mode> is not one of the modes described in 285 section 2.6.1. 286 287 INVALID_VALUE is generated by DrawElementsInstancedANGLE if <count> or 288 <primcount> is less than zero. 289 290 INVALID_OPERATION is generated by DrawArraysInstancedANGLE or 291 DrawElementsInstancedANGLE if there is not at least one enabled 292 vertex attribute array that has a <divisor> of zero and is bound to an 293 active generic attribute value in the program used for the draw command. 294 295 New State 296 297 Changes to table 6.7, p. 268 (Vertex Array Data) 298 299 Initial 300 Get Value Type Get Command Value Description Sec. 301 --------- ----- ----------- ------- ----------- ---- 302 VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 8*xZ+ GetVertexAttrib 0 Instance Divisor 2.8 303 304 Issues 305 306 1) Should vertex attribute zero be instance-able? 307 308 Resolved: Yes. 309 Discussion: In Direct3D 9 stream 0 must be specified as indexed data 310 and it cannot be instanced. In ANGLE we can work around this by 311 remapping any other stream that does have indexed data (ie a zero 312 attribute divisor) to stream 0 in D3D9. This works because the HLSL 313 vertex shader matches attributes against the stream by using the 314 shader semantic index. 315 316 2) Can all vertex attributes be instanced simultaneously? 317 318 Resolved: No 319 Discussion: In rare cases it is possible for no attribute to have a 320 divisor of 0, meaning that all attributes are instanced and none of 321 them are regularly indexed. This in turn means each instance can only 322 have a single position element, and so it only actually renders 323 something when rendering point primitives. This is not a very 324 meaningful way of using instancing (which is likely why D3D restricts 325 stream 0 to be indexed regularly for position data in the first place). 326 We could implement it by drawing these points one at a time (essentially 327 emulating instancing), but it would not be very efficient and there 328 seems to be little-to-no value in doing so. 329 330 If all of the enabled vertex attribute arrays that are bound to active 331 generic attributes in the program have a non-zero divisor, the draw 332 call should return INVALID_OPERATION. 333 334 3) Direct3D 9 only supports instancing for DrawIndexedPrimitive which 335 corresponds to DrawElementsInstanced. Should we support 336 DrawArraysInstanced? 337 338 Resolved: Yes 339 Discussion: This can be supported easily enough by simply manufacturing 340 a linear index buffer of sufficient size and using that to do indexed 341 D3D9 drawing. 342 343 4) How much data is needed in a buffer for an instanced attribute? 344 345 Resolved: Where stride is the value passed to VertexAttribPointer: 346 347 if stride > 0 348 size = stride * ceil(primcount / divisor); 349 else 350 size = elementsize * ceil(primcount / divisor); 351 352 Revision History 353 354 #3 February 8, 2012 dgkoch 355 - clarify Issue 3 and the error condition for no indexed attributes 356 #2 January 24, 2012 dgkoch 357 - fix typos, add clarifications, and more errors 358 #1 January 17, 2012 dgkoch 359 - initial GLES2 version from ARB_instanced_arrays 360