blob: a461b8253ce6bf64f3fcd5838a72e42680f5a5a1 [file] [log] [blame]
Name Strings
Graham Sellers (graham.sellers 'at'
Sergey Leontyev, AMD
Last Modified Date: 2 May 2013
Revision: 3
This extension is written against version 4.3 of the Core Profile OpenGL
Specification, dated August 6, 2012.
The glDrawElements function and its variants (instanced and indirect,
for example) allow OpenGL to draw indexed arrays of vertices. Since its
inception, OpenGL has supported unsigned bytes, unsigned shorts and
unsigned integers as index types. However, all enabled vertex arrays may
be represented by at most one shared index.
A common scenario in graphics rendering is that several faces share
a vertex where, for each face some properties of a vertex (position and
texture coordinates, for example) should be common but others must be
unique (colors, normals, and so on). Consider a mesh of a cube with
per-face normals, for example. There are 8 vertices and 6 normals, and 12
triangles (where each face of the cube is represented as two triangles).
To render this cube, we must compute the 24 unique permutations of
position and normal and build a new element list to index into it. In
fact, any advantage of indexed draw is lost here as the number of required
permutations is equal to the final vertex count required to draw the
This extension allows OpenGL to process multi-component packed element
data. The maximum size of a vertex's index data is not increased, but the
facility to store 2 16-bit or 2 or 4 8-bit indices per vertex is introduced.
Each vertex attribute is given a swizzle property to allow its index to
be sourced from one of up to 4 channels of index data. This effectively
allows an application to supply multiple interleaved streams of index data
to OpenGL. Each vertex attribute is given a 'channel selector' to select
one of the up to 4 channels of vertex index information presented to
OpenGL. This enables the use-case described above and many more.
The swizzle parameter is also applied to vertex indices passed to shaders,
and updates to the definition of base vertex parameters and primitive
restart are applied.
New Procedures and Functions
void VertexAttribParameteriAMD(uint index, enum pname, int param);
New Tokens
Accepted by the <pname> parameter of VertexAttribParameteriAMD and
Selected by the <pname> parameter of ProgramParameteri and GetProgramiv:
Accepted by the <param> parameter of VertexAttribParameteriAMD:
RED 0x1903
GREEN 0x1904
BLUE 0x1905
ALPHA 0x1906
Accepted by the <type> parameter of DrawElements, DrawElementsInstanced,
DrawElementsInstancedBaseInstance and DrawElementsIndirect:
RG8UI 0x8238
RG16UI 0x823A
IP Status
Additions to Chapter 7 of the OpenGL Core Profile Specification, Version 4.3,
"Programs and Shaders"
Add to the parameters accepted by ProgramParameteri, p.82:
If <pname> is VERTEX_ID_SWIZZLE_AMD, <value> should be set to
RED, GREEN, BLUE or ALPHA to indicate that the first, second, third
or fourth component of the vertex element vector be propagated to the
gl_VertexID vertex shader input as described in subsection
The initial value of VERTEX_ID_SWIZZLE_AMD is RED.
Additions to Chapter 10 of the OpenGL Core Profile Specification, Version 4.3,
"Vertex Specification and Drawing Commands"
Insert Subsection 10.3.2, "Vertex Attribute Parameters", renumber
subsequent sections:
Each vertex attribute possesses a set of parameters that control
its behavior. Parameters for a vertex attribute may be set by calling:
void VertexAttribParameteriAMD(uint index,
enum pname,
int param);
where <index> identifies the generic vertex attribute array whose parameter
to modify. If <pname> is VERTEX_ELEMENT_SWIZZLE_AMD, then <param>
specifies the component of the vertex element that is to be used to
source the vertex indices for the selected vertex attribute. Its value
may be RED, GREEN, BLUE or ALPHA to select the first, second, third or
fourth component of the vertex element.
In section 10.3.2, "Primitive Restart", modify the language describing
how the restart index is compared to the vertex element index, p.302
as follows:
When one of the Draw* commands transfers a set of generic attribute
array elements to the GL, if all present index channels in the passed
element index are equal to the primitive restart index, then the GL
does not process those elements as a vertex. Instead ... *include
remainder of section verbatim.*
In the description of DrawElementsOneInstance (p. 311), replace the
sentence beginning "The ith element transferred by..." with:
For each enabled vertex attribute, the ith element transferred by
DrawElementsOneInstance will be taken from that attribute's selected
channel of the element whose values are stored currently bound element
array buffer at offset indices + i.
Replace the paragraph explaining the <type> parameter to
DrawElementsOneIntance (p. 311):
indicating that the index values are of GL type ubyte, ushort or uint,
respectively, RG8UI or RG16UI, indicating that the index values are pairs
of GL type ubyte or ushort, respectively, or RGBA8UI, indicating that
index values are quadruplets of GL type ubyte. ...
Modify the language describing the DrawElements*BaseVertex* functions
on p.314 as follows:
... are equivalent to the commands with the same base name (without
the BaseVertex suffix), except that the ith element transferred by
the corresponding draw call will be taken from the selected channel
of the element vector indices[i] + <basevertex>. That is, the value of
<basevertex> is added to the vertex index after channel selection.
... *include remainder of description verbatim.*
Add to the list of accepted values for the <pname> parameter to
GetVertexAttrib* in Section 10.6, "Vertex Array and Vertex Array Object
Queries", p. 317:
Additions to Chapter 11 of the OpenGL Core Profile Specification, Version 4.3,
"Programmable Vertex Processing"
In Subsection, "Shader Inputs", p.338, modify the description
of gl_VertexID as follows:
gl_VertexID holds the integer index i stored in the selected component
of the element implicitly passed by DrawArrays or one of the other drawing
commands defined in section 10.5. The component of the element data
stored in gl_VertexID may be specified by calling ProgramParameteri with
<pname> set to VERTEX_ID_SWIZZLE_AMD as specified in section 7.3.
New State
Append to Table 23.4, "Vertex Array Object State (cont.)":
| Get Value | Type | Get Command | Initial Value | Description | Sec |
| VERTEX_ELEMENT_SWIZZLE_AMD | 16 * x E | GetVertexAttribiv | RED | Channel selector for vertex attribute index | 10.3.2 |
Append to Table 23.39, "Program Object State (cont.)":
| Get Value | Type | Get Command | Initial Value | Description | Sec |
| VERTEX_ID_SWIZZLE_AMD | E | GetProgramiv | RED | Channel selector for gl_VertexID | |
New Implementation Dependent State
INVALID_ENUM is generated by VertexAttribParameteri if <pname> is not an
accepted token.
INVALID_VALUE is generated by VertexAttribParameteri if <value> is not an
acceptable value for the specified value of <pname>.
// Basic per-face normals
// Normal data
static const float normals[] =
0.0f, 0.0f, 1.0f, // Positive Z
0.0f, 0.0f, -1.0f, // Negative Z
0.0f, 1.0f, 0.0f, // Positive Y
0.0f, -1.0f, 0.0f, // Negative Y
1.0f, 0.0f, 0.0f, // Positive X
-1.0f, 0.0f, 0.0f, // Negative X
// Position data
static const float positions[] =
-1.0f, -1.0f, -1.0f,
// <More data here>
1.0f, 1.0f, 1.0f
// Put the above data into a buffer and bind them as separate vertex
// attributes.
GLuint vertex_buffer;
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, sizeof(positions) + sizeof(normals),
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), positions);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions),
sizeof(normals), normals);
// ... etc. Set up vertex attributes.
// Index data
static const unsigned short indices[] =
0, 0, // vertex 0: position index, normal index
1, 0, // vertex 1: position index, normal index
2, 0, // vertex 2: position index, normal index
1, 0, // vertex 3: position index, normal index
2, 0, // ... six vertices, forming
3, 0, // ... two complete triangles, all using normals[0]
0, 1,
2, 1,
3, 1,
3, 1,
4, 1, // ... six more vertices, forming
2, 1, // ... two more triangles, all using normals[1]
// etc...
GLuint index_buffer;
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices),
indices, GL_STATIC_DRAW);
// Okay... here's the new code. Set up vertex attribute 0 (position) to
// consume the RED channel of the vertex index and attribute 1 (normal)
// to consume the GREEN (second) channel of the vertex index. Then
// draw with GL_RG16UI (two channel, 16-bit unsigned int) as the index
// type.
sizeof(indices) / (2 * sizeof(unsigned short)),
1) What is the effect of multi-channel vertex indices on gl_VertexID?
RESOLVED: The VERTEX_ID_SWIZZLE_AMD program parameter selects the
channel of vector element types to be passed to gl_VertexID. By
default, this is RED, which is backwards compatible with single-channel
2) How does this interact with primitive-restart indices?
RESOLVED: If all present channels of the vertex index vector match the
restart index, then the element index is considered to match.
3) How does baseVertex affect this?
RESOLVED: The same base vertex value is added to each each vertex
element component after channel selection for each of the enabled
vertex attributes. This choice is primarily motivated by the behavior
of base vertex elements encoded in indirect draw commands.
4) Does this feature disable potential optimizations such as vertex
RESOVLED: No, vertex reuse should continue to function correctly.
Each unique vector of indices should produce a unique set of vertex
shader outputs (modulo side effects) and will hit a naive vertex
reuse cache. Nothing precludes more advanced optimization strategies
from being implemented, however.
5) Is it possible to get at all two or four channels of the vertex index
using a built-in input to the vertex shader?
RESOLVED: No. A single channel selection is provided. Providing more
data could be implemented by introducing a new built-in integer vector
input to the shader, but we have chosen not to do at this time.
6) What is the value of missing channels? For example, if we render with
GL_RG16UI indices but set certain attributes to GL_BLUE or GL_ALPHA
swizzle, what index value is used for those channels?
7) Are the traditional GL_RED, GL_GREEN, GL_BLUE, and GL_ALPHA terms
appropriate for this use?
RESOLVED: Not really, but are they appropriate for normals? g-buffers?
Any other arbitrary data that might be in a buffer or texture?
It's not worth introducing new enumerants just for this - we'll use
R, G, B, A.
Revision History
Rev. Date Author Changes
---- -------- -------- -----------------------------------------
3 05/02/2013 gsellers Shipping. Finalize spec ready for posting.
2 01/25/2013 gsellers Resolve issues 1, 2, 3. Polish spec.
1 01/17/2013 gsellers Initial draft