1Name 2 3 AMD_interleaved_elements 4 5Name Strings 6 7 GL_AMD_interleaved_elements 8 9Contact 10 11 Graham Sellers (graham.sellers 'at' amd.com) 12 13Contributors 14 15 Sergey Leontyev, AMD 16 17Status 18 19 Shipping 20 21Version 22 23 Last Modified Date: 2 May 2013 24 Revision: 3 25 26Number 27 28 431 29 30Dependencies 31 32 This extension is written against version 4.3 of the Core Profile OpenGL 33 Specification, dated August 6, 2012. 34 35Overview 36 37 The glDrawElements function and its variants (instanced and indirect, 38 for example) allow OpenGL to draw indexed arrays of vertices. Since its 39 inception, OpenGL has supported unsigned bytes, unsigned shorts and 40 unsigned integers as index types. However, all enabled vertex arrays may 41 be represented by at most one shared index. 42 43 A common scenario in graphics rendering is that several faces share 44 a vertex where, for each face some properties of a vertex (position and 45 texture coordinates, for example) should be common but others must be 46 unique (colors, normals, and so on). Consider a mesh of a cube with 47 per-face normals, for example. There are 8 vertices and 6 normals, and 12 48 triangles (where each face of the cube is represented as two triangles). 49 To render this cube, we must compute the 24 unique permutations of 50 position and normal and build a new element list to index into it. In 51 fact, any advantage of indexed draw is lost here as the number of required 52 permutations is equal to the final vertex count required to draw the 53 object. 54 55 This extension allows OpenGL to process multi-component packed element 56 data. The maximum size of a vertex's index data is not increased, but the 57 facility to store 2 16-bit or 2 or 4 8-bit indices per vertex is introduced. 58 Each vertex attribute is given a swizzle property to allow its index to 59 be sourced from one of up to 4 channels of index data. This effectively 60 allows an application to supply multiple interleaved streams of index data 61 to OpenGL. Each vertex attribute is given a 'channel selector' to select 62 one of the up to 4 channels of vertex index information presented to 63 OpenGL. This enables the use-case described above and many more. 64 The swizzle parameter is also applied to vertex indices passed to shaders, 65 and updates to the definition of base vertex parameters and primitive 66 restart are applied. 67 68New Procedures and Functions 69 70 void VertexAttribParameteriAMD(uint index, enum pname, int param); 71 72New Tokens 73 74 Accepted by the <pname> parameter of VertexAttribParameteriAMD and 75 GetVertexAttrib{iv|dv|fv|Iiv|Iuiv|Ldv}: 76 77 VERTEX_ELEMENT_SWIZZLE_AMD 0x91A4 78 79 Selected by the <pname> parameter of ProgramParameteri and GetProgramiv: 80 81 VERTEX_ID_SWIZZLE_AMD 0x91A5 82 83 Accepted by the <param> parameter of VertexAttribParameteriAMD: 84 85 RED 0x1903 86 GREEN 0x1904 87 BLUE 0x1905 88 ALPHA 0x1906 89 90 Accepted by the <type> parameter of DrawElements, DrawElementsInstanced, 91 DrawElementsInstancedBaseInstance and DrawElementsIndirect: 92 93 RG8UI 0x8238 94 RG16UI 0x823A 95 RGBA8UI 0x8D7C 96 97IP Status 98 99 None. 100 101Additions to Chapter 7 of the OpenGL Core Profile Specification, Version 4.3, 102"Programs and Shaders" 103 104 Add to the parameters accepted by ProgramParameteri, p.82: 105 106 If <pname> is VERTEX_ID_SWIZZLE_AMD, <value> should be set to 107 RED, GREEN, BLUE or ALPHA to indicate that the first, second, third 108 or fourth component of the vertex element vector be propagated to the 109 gl_VertexID vertex shader input as described in subsection 11.1.3.9. 110 The initial value of VERTEX_ID_SWIZZLE_AMD is RED. 111 112Additions to Chapter 10 of the OpenGL Core Profile Specification, Version 4.3, 113"Vertex Specification and Drawing Commands" 114 115 Insert Subsection 10.3.2, "Vertex Attribute Parameters", renumber 116 subsequent sections: 117 118 Each vertex attribute possesses a set of parameters that control 119 its behavior. Parameters for a vertex attribute may be set by calling: 120 121 void VertexAttribParameteriAMD(uint index, 122 enum pname, 123 int param); 124 125 where <index> identifies the generic vertex attribute array whose parameter 126 to modify. If <pname> is VERTEX_ELEMENT_SWIZZLE_AMD, then <param> 127 specifies the component of the vertex element that is to be used to 128 source the vertex indices for the selected vertex attribute. Its value 129 may be RED, GREEN, BLUE or ALPHA to select the first, second, third or 130 fourth component of the vertex element. 131 132 In section 10.3.2, "Primitive Restart", modify the language describing 133 how the restart index is compared to the vertex element index, p.302 134 as follows: 135 136 When one of the Draw* commands transfers a set of generic attribute 137 array elements to the GL, if all present index channels in the passed 138 element index are equal to the primitive restart index, then the GL 139 does not process those elements as a vertex. Instead ... *include 140 remainder of section verbatim.* 141 142 In the description of DrawElementsOneInstance (p. 311), replace the 143 sentence beginning "The ith element transferred by..." with: 144 145 For each enabled vertex attribute, the ith element transferred by 146 DrawElementsOneInstance will be taken from that attribute's selected 147 channel of the element whose values are stored currently bound element 148 array buffer at offset indices + i. 149 150 Replace the paragraph explaining the <type> parameter to 151 DrawElementsOneIntance (p. 311): 152 153 <type> may be UNSIGNED_BYTE, UNSIGNED_SHORT or UNSIGNED_INT, 154 indicating that the index values are of GL type ubyte, ushort or uint, 155 respectively, RG8UI or RG16UI, indicating that the index values are pairs 156 of GL type ubyte or ushort, respectively, or RGBA8UI, indicating that 157 index values are quadruplets of GL type ubyte. ... 158 159 Modify the language describing the DrawElements*BaseVertex* functions 160 on p.314 as follows: 161 162 ... are equivalent to the commands with the same base name (without 163 the BaseVertex suffix), except that the ith element transferred by 164 the corresponding draw call will be taken from the selected channel 165 of the element vector indices[i] + <basevertex>. That is, the value of 166 <basevertex> is added to the vertex index after channel selection. 167 ... *include remainder of description verbatim.* 168 169 Add to the list of accepted values for the <pname> parameter to 170 GetVertexAttrib* in Section 10.6, "Vertex Array and Vertex Array Object 171 Queries", p. 317: 172 173 ... VERTEX_ELEMENT_SWIZZLE_AMD. 174 175Additions to Chapter 11 of the OpenGL Core Profile Specification, Version 4.3, 176"Programmable Vertex Processing" 177 178 In Subsection 11.1.3.9, "Shader Inputs", p.338, modify the description 179 of gl_VertexID as follows: 180 181 gl_VertexID holds the integer index i stored in the selected component 182 of the element implicitly passed by DrawArrays or one of the other drawing 183 commands defined in section 10.5. The component of the element data 184 stored in gl_VertexID may be specified by calling ProgramParameteri with 185 <pname> set to VERTEX_ID_SWIZZLE_AMD as specified in section 7.3. 186 187New State 188 189 Append to Table 23.4, "Vertex Array Object State (cont.)": 190 191 +------------------------------+----------+---------------------+----------------+---------------------------------------------+----------+ 192 | Get Value | Type | Get Command | Initial Value | Description | Sec | 193 +------------------------------+----------+---------------------+----------------+---------------------------------------------+----------+ 194 | VERTEX_ELEMENT_SWIZZLE_AMD | 16 * x E | GetVertexAttribiv | RED | Channel selector for vertex attribute index | 10.3.2 | 195 +------------------------------+----------+---------------------+----------------+---------------------------------------------+----------+ 196 197 Append to Table 23.39, "Program Object State (cont.)": 198 199 +------------------------+-------+---------------+----------------+------------------------------------+----------+ 200 | Get Value | Type | Get Command | Initial Value | Description | Sec | 201 +------------------------+-------+---------------+----------------+------------------------------------+----------+ 202 | VERTEX_ID_SWIZZLE_AMD | E | GetProgramiv | RED | Channel selector for gl_VertexID | 11.1.3.9 | 203 +------------------------+-------+---------------+----------------+------------------------------------+----------+ 204 205New Implementation Dependent State 206 207 None. 208 209Errors 210 211 INVALID_ENUM is generated by VertexAttribParameteri if <pname> is not an 212 accepted token. 213 214 INVALID_VALUE is generated by VertexAttribParameteri if <value> is not an 215 acceptable value for the specified value of <pname>. 216 217Examples 218 219 // Basic per-face normals 220 221 // Normal data 222 static const float normals[] = 223 { 224 0.0f, 0.0f, 1.0f, // Positive Z 225 0.0f, 0.0f, -1.0f, // Negative Z 226 0.0f, 1.0f, 0.0f, // Positive Y 227 0.0f, -1.0f, 0.0f, // Negative Y 228 1.0f, 0.0f, 0.0f, // Positive X 229 -1.0f, 0.0f, 0.0f, // Negative X 230 }; 231 232 // Position data 233 static const float positions[] = 234 { 235 -1.0f, -1.0f, -1.0f, 236 // <More data here> 237 1.0f, 1.0f, 1.0f 238 }; 239 240 // Put the above data into a buffer and bind them as separate vertex 241 // attributes. 242 GLuint vertex_buffer; 243 glGenBuffers(1, &vertex_buffer); 244 glBindBuffer(GL_ARRAY_BUFFER, sizeof(positions) + sizeof(normals), 245 NULL, GL_STATIC_DRAW); 246 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), positions); 247 glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions), 248 sizeof(normals), normals); 249 // ... etc. Set up vertex attributes. 250 251 // Index data 252 static const unsigned short indices[] = 253 { 254 0, 0, // vertex 0: position index, normal index 255 1, 0, // vertex 1: position index, normal index 256 2, 0, // vertex 2: position index, normal index 257 1, 0, // vertex 3: position index, normal index 258 2, 0, // ... six vertices, forming 259 3, 0, // ... two complete triangles, all using normals[0] 260 0, 1, 261 2, 1, 262 3, 1, 263 3, 1, 264 4, 1, // ... six more vertices, forming 265 2, 1, // ... two more triangles, all using normals[1] 266 // etc... 267 }; 268 269 GLuint index_buffer; 270 glGenBuffers(1, &index_buffer); 271 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); 272 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), 273 indices, GL_STATIC_DRAW); 274 275 // Okay... here's the new code. Set up vertex attribute 0 (position) to 276 // consume the RED channel of the vertex index and attribute 1 (normal) 277 // to consume the GREEN (second) channel of the vertex index. Then 278 // draw with GL_RG16UI (two channel, 16-bit unsigned int) as the index 279 // type. 280 glVertexAttribParameteriAMD(0, GL_VERTEX_ELEMENT_SWIZZLE_AMD, GL_RED); 281 glVertexAttribParameteriAMD(1, GL_VERTEX_ELEMENT_SWIZZLE_AMD, GL_GREEN); 282 283 glDrawElements(GL_TRIANGLES, 284 sizeof(indices) / (2 * sizeof(unsigned short)), 285 GL_RG16UI, 286 NULL); 287 288Issues 289 290 1) What is the effect of multi-channel vertex indices on gl_VertexID? 291 292 RESOLVED: The VERTEX_ID_SWIZZLE_AMD program parameter selects the 293 channel of vector element types to be passed to gl_VertexID. By 294 default, this is RED, which is backwards compatible with single-channel 295 types. 296 297 2) How does this interact with primitive-restart indices? 298 299 RESOLVED: If all present channels of the vertex index vector match the 300 restart index, then the element index is considered to match. 301 302 3) How does baseVertex affect this? 303 304 RESOLVED: The same base vertex value is added to each each vertex 305 element component after channel selection for each of the enabled 306 vertex attributes. This choice is primarily motivated by the behavior 307 of base vertex elements encoded in indirect draw commands. 308 309 4) Does this feature disable potential optimizations such as vertex 310 reuse? 311 312 RESOVLED: No, vertex reuse should continue to function correctly. 313 Each unique vector of indices should produce a unique set of vertex 314 shader outputs (modulo side effects) and will hit a naive vertex 315 reuse cache. Nothing precludes more advanced optimization strategies 316 from being implemented, however. 317 318 5) Is it possible to get at all two or four channels of the vertex index 319 using a built-in input to the vertex shader? 320 321 RESOLVED: No. A single channel selection is provided. Providing more 322 data could be implemented by introducing a new built-in integer vector 323 input to the shader, but we have chosen not to do at this time. 324 325 6) What is the value of missing channels? For example, if we render with 326 GL_RG16UI indices but set certain attributes to GL_BLUE or GL_ALPHA 327 swizzle, what index value is used for those channels? 328 329 RESOLVED: Zero. 330 331 7) Are the traditional GL_RED, GL_GREEN, GL_BLUE, and GL_ALPHA terms 332 appropriate for this use? 333 334 RESOLVED: Not really, but are they appropriate for normals? g-buffers? 335 Any other arbitrary data that might be in a buffer or texture? 336 It's not worth introducing new enumerants just for this - we'll use 337 R, G, B, A. 338 339Revision History 340 341 Rev. Date Author Changes 342 ---- -------- -------- ----------------------------------------- 343 344 3 05/02/2013 gsellers Shipping. Finalize spec ready for posting. 345 2 01/25/2013 gsellers Resolve issues 1, 2, 3. Polish spec. 346 1 01/17/2013 gsellers Initial draft 347 348