blob: 8d116300480b416396c056daa03017d3fc4ec60c [file] [log] [blame]
Name
ARB_base_instance
Name Strings
GL_ARB_base_instance
Contact
Graham Sellers, AMD (graham.sellers 'at' amd.com)
Contributors
Daniel Koch, NVIDIA
Notice
Copyright (c) 2011-2013 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Status
Complete. Approved by the ARB on 2011/06/20.
Approved by the Khronos Promoters on 2011/07/29.
Version
Last Modified Date: June 13, 2014
Author Revision: 7
Number
ARB Extension #107
Dependencies
This extension is written against the OpenGL Specification, Version 4.1
(Core Profile).
OpenGL 3.1 or ARB_draw_instanced is required.
Overview
This extension allows the offset within buffer objects used for instanced
rendering to be specified. This is congruent with the <first> parameter
in glDrawArrays and the <basevertex> parameter in glDrawElements. When
instanced rendering is performed (for example, through
glDrawArraysInstanced), instanced vertex attributes whose vertex attribute
divisors are non-zero are fetched from enabled vertex arrays per-instance
rather than per-vertex. However, in unextended OpenGL, there is no way to
define the offset into those arrays from which the attributes are fetched.
This extension adds that offset in the form of a <baseinstance> parameter
to several new procedures.
The <baseinstance> parameter is added to the index of the array element,
after division by the vertex attribute divisor. This allows several sets of
instanced vertex attribute data to be stored in a single vertex array, and
the base offset of that data to be specified for each draw. Further, this
extension exposes the <baseinstance> parameter as the final and previously
undefined structure member of the draw-indirect data structure.
IP Status
None.
New Procedures and Functions
void DrawArraysInstancedBaseInstance(enum mode,
int first,
sizei count,
sizei primcount,
uint baseinstance);
void DrawElementsInstancedBaseInstance(enum mode,
sizei count,
enum type,
const void *indices,
sizei primcount,
uint baseinstance);
void DrawElementsInstancedBaseVertexBaseInstance(enum mode,
sizei count,
enum type,
const void *indices,
sizei primcount,
int basevertex,
uint baseinstance);
New Tokens
None.
Modifications to Chapter 2 of the the OpenGL 4.1 (Core Profile) Specification
(OpenGL Operation)
Modification to Section 2.8.3, "Drawing Commands"
Modify the definition of DrawArraysOneInstance on p.33.
The command
void DrawArraysOneInstance(enum mode,
int first,
sizei count,
int instance,
uint baseinstance);
does not exist in the GL, but is used to describe functionality in the rest
of this section. This command constructs a sequence of geometric primitives
by transferring elements <first> through <first> + <count> - 1 of each
enabled array to the GL. <mode> specifies what kind of primitives are
constructed, as defined in section 2.6.1. If <mode> is not a valid primitive
type, an INVALID_ENUM error is generated. If <count> is negative, an
INVALID_VALUE error is generated.
For any vertex attribute whose divisor is non-zero as set by
VertexAttribDivisor, the value <baseinstance> is used to determine the element
of the enabled instanced attribute arrays that will be transferred for all
vertices transferred by this function.
If an array corresponding to a generic attribute required by a vertex
shader is not enabled, then the corresponding element is taken from the
current generic attribute state (see section 2.7).
If an array corresponding to a generic attribute required by a vertex
shader is enabled, the corresponding current generic attribute value is
unaffected by the execution of DrawArraysOneInstance.
Specifying <first> < 0 results in undefined behavior. Generating the
error INVALID_VALUE is recommended in this case.
The command
void DrawArrays( enum mode, int first, sizei count );
is equivalent to the command sequence
DrawArraysOneInstance(mode, first, count, 0, 0);
Replace the description of DrawArraysInstanced with the following (p.35):
The command
void DrawArraysInstancedBaseInstance(enum mode,
int first,
sizei count,
sizei primcount,
uint baseinstance);
behaves identically to DrawArrays, except that <primcount> instances of the
range of elements are executed and the value of <instanceID> advances for
each iteration. Those attributes that have divisor N where N is other than
zero (as specified by VertexAttribDivisor) advance once every N instances.
Additionally, the first element within those instanced vertex attributes
is specified in <baseinstance>. Thus, the element transferred from instanced
vertex attributes is given by:
(<instanceID> / <divisor>) + <baseinstance>
DrawArraysInstancedBaseInstance has the same effect as:
if (<mode> or <count> is invalid)
generate appropriate error
else {
for (i = 0; i < <primcount>; i++) {
instanceID = i;
DrawArraysOneInstance(<mode>, <first>, <count>, i, <baseinstance>);
}
instanceID = 0;
}
The command
void DrawArraysInstanced(enum mode,
int first,
sizei count,
sizei primcount);
Is equivalent to calling DrawArraysInstancedBaseInstance with <baseinstance>
set to zero.
Update the definition of DrawArraysIndirect as follows (p.35):
The command
void DrawArraysIndirect(enum mode,
const void *indirect);
has the same effect as:
typedef struct {
uint count;
uint primCount;
uint first;
uint baseInstance;
} DrawArraysIndirectCommand;
const DrawArraysIndirectCommand *cmd =
(const DrawArraysIndirectCommand *)indirect;
DrawArraysInstancedBaseInstance(mode,
cmd->first,
cmd->count,
cmd->primCount,
cmd->baseInstance);
Remove the sentence "Results are undefined if reservedMustBeZero is non-
zero, but must not lead to GL interruption or termination."
Update the definition of DrawElementsOneInstance, p.36:
The command
void DrawElementsOneInstance(enum mode,
sizei count,
enum type,
const void *indices,
int instance,
uint baseinstance);
does not exist in the GL ... <retain the remainder of the description>
If an enabled vertex attribute array is instanced (it has a non-zero
attribute divisor as specified by VertexAttribDivisor), the element that is
transferred to the GL is given by:
floor(<instance> / <divisor>) + <baseinstance>
Update the text describing DrawElements:
The command
void DrawElements(enum mode,
sizei count,
enum type,
const void *indices);
behaves identically to DrawElementsOneInstance with the <instance> and
<baseinstance> parameters set to zero; the effect of calling
DrawElements(mode, count, type, indices);
is equivalent to the command sequence:
if (<mode>, <count> or <type> is invalid)
generate appropriate error
else
DrawElementsOneInstance(mode, count, type, indices, 0, 0);
Replace the description of DrawElementsInstanced with the following (p.37)
The command
void DrawElementsInstancedBaseInstance(enum mode,
sizei count,
enum type,
const void *indices,
sizei primcount,
uint baseinstance);
behaves identically to DrawElements except that <primcount> instances of the
set of elements are executed, the value of instanceID advances between each
set, and the instance advances between each set. Instanced attributes
are advanced as they do during execution of DrawArraysInstancedBaseInstace,
and <baseinstance> has the same effect. It has the same effect as:
if (<mode>, <count>, <type> or <primcount> is invalid)
generate appropriate error
else {
for (int i = 0; i < <primcount>; i++) {
instanceID = i;
DrawElementsOneInstance(<mode>,
<count>,
<type>,
<indices>,
i,
<baseinstance>);
}
instanceID = 0;
}
Add to the list of functions which include DrawElementsBaseVertex,
DrawRangeElementsBaseVertex, and DrawElementsInstancedBaseVertex (p.39):
void DrawElementsInstancedBaseVertexBaseInstance(enum mode,
sizei count,
enum type,
const void *indices,
sizei primcount,
int basevertex,
uint baseinstance);
Append to the paragraph describing DrawElementsBaseVertex,
DrawRangeElementsBaseVertex, and DrawElementsInstancedBaseVertex (p.40):
For DrawElementsInstancedBaseVertexBaseInstance, <baseinstance> is
used to offset the element from which instanced vertex attributes (those
with a non-zero divisor as specified by VertexAttribDivisor) are taken.
Update the definition of DrawElementsIndirect as follows (p.39):
The command
void DrawElementsIndirect(enum mode,
enum type,
const void *indirect );
has the same effect as:
typedef struct {
uint count;
uint primCount;
uint firstIndex;
int baseVertex;
uint baseInstance;
} DrawElementsIndirectCommand;
if (no element array buffer is bound) {
generate appropriate error
} else {
const DrawElementsIndirectCommand *cmd =
(const DrawElementsIndirectCommand *)indirect;
DrawElementsInstancedBaseVertexBaseInstance(
mode,
cmd->count,
type,
cmd->firstIndex * size-of-type,
cmd->primCount,
cmd->baseVertex,
cmd->baseInstance);
}
Remove the sentence "Results are undefined if reservedMustBeZero is non-
zero, but must not lead to GL interruption or termination."
Modifications to Chapter 3 of the the OpenGL 4.1 (Core Profile) Specification
(Rasterization)
None.
Modifications to Chapter 4 of the the OpenGL 4.1 (Core Profile) Specification
(Per-Fragment Operations and the Framebuffer)
None.
Modifications to Chapter 5 of the the OpenGL 4.1 (Core Profile) Specification
(Special Functions)
None.
Modifications to Chapter 6 of the the OpenGL 4.1 (Core Profile) Specification
(State and State Requests)
None.
Additions to the AGL/GLX/WGL Specifications
None.
GLX Protocol
None.
Errors
None.
New State
None.
New Implementation Dependent State
None.
Conformance Testing
TBD.
Issues
1) Does <baseinstance> offset gl_InstanceID?
RESOLVED: No. gl_InstanceID always starts from zero and counts up by one
for each instance rendered. If the shader author requires the actual value
of the instance index, including the base instance, they must pass the
base instance as a uniform. In OpenGL, the vertex attribute divisors are
not passed implicitly to the shader anyway, so the shader writer will need
to take care of this regardless.
2) Is <baseinstance> per-attribute, or global?
RESOLVED: It is global. The same base is used for all instanced attribute
arrays.
3) Do we need any more entry points?
DISCUSSION: Maybe. Technically, we could specify a base vertex to any
drawing command and any instanced vertex attributes would be taken from
that offset within their respective buffers. OpenGL already has enough
entry points. Another possibility is to actually make <baseinstance> OpenGL
state. The application would set it before any draw call (even non-
instanced ones) and this would affect the base used for any instanced vertex
attributes. However, this would introduce performance overhead and would not
work well with Draw{Arrays|Elements}Indirect.
4) DrawElementsInstancedBaseVertexBaseInstance? Really? The length of entry
point names is starting to get silly. Can we clean this up?
RESOLVED: Yes, we can, but not here.
5) What happens if baseInstance is > 2^31-1 (i.e., negative as a signed
integer)?
Need to check with hardware vendors.
Revision History
Rev. Date Author Changes
---- ---------- -------- -----------------------------------------
7 06/13/2014 dkoch fix <baseinstance> typos in overview.
6 01/18/2011 Jon Leech Use floor() in computing element transferred
to the GL to match change in core spec.
5 01/10/2011 gsellers Address bugzilla 7185. Make baseinstance API
parameter unsigned to match structure member.
Add issue 5.
4 01/05/2011 Jon Leech Fix typos from Bug 7202.
3 11/09/2010 gsellers Address bugzilla 7011. Elaborate in overview
and issues. Add placeholder for conformance test
plan.
2 11/08/2010 gsellers Did some TODOs. Check in to SVN.
1 11/04/2010 gsellers Initial revision.