blob: 84e6a5821b93f0246b618762984439f2b02217b2 [file] [log] [blame]
Name
ARB_uniform_buffer_object
Name Strings
GL_ARB_uniform_buffer_object
Contact
Benj Lipchak, APPLE (lipchak 'at' apple.com)
John Rosasco, APPLE (jdr 'at' apple.com)
Jeremy Sandmel, APPLE (jsandmel 'at' apple.com)
Pat Brown, NVIDIA (pbrown 'at' nvidia.com)
Contributors
Rob Barris
Keith Bauer
Bob Beretta
Pat Brown
Nick Burns
Matt Collins
Michael Gold
John Kessenich
Jon Leech
Barthold Lichtenbelt
Benj Lipchak
Bruce Merry
John Rosasco
Jeremy Sandmel
Geoff Stahl
Notice
Copyright (c) 2009-2013 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Specification Update Policy
Khronos-approved extension specifications are updated in response to
issues and bugs prioritized by the Khronos OpenGL Working Group. For
extensions which have been promoted to a core Specification, fixes will
first appear in the latest version of that core Specification, and will
eventually be backported to the extension document. This policy is
described in more detail at
https://www.khronos.org/registry/OpenGL/docs/update_policy.php
Status
Complete. Approved by the ARB on February 17, 2009.
Version
Last Modified Date: 2015/06/23
Author revision: 68
Number
ARB Extension #57
Dependencies
The OpenGL Shading Language (GLSL) is required. OpenGL 2.0 or the
ARB_shader_objects extension is required.
OpenGL 1.5 or ARB_vertex_buffer_object is required.
This extension is written against the OpenGL 2.1 specification and
version 1.20-8 of the OpenGL Shading Language specification.
This extension interacts with OpenGL 3.0, ARB_geometry_shader4,
ARB_texture_rectangle, EXT_gpu_shader4, EXT_texture_array,
EXT_texture_integer, and EXT_texture_buffer_object.
Overview
This extension introduces the concept of a group of GLSL uniforms
known as a "uniform block", and the API mechanisms to store "uniform
blocks" in GL buffer objects.
The extension also defines both a standard cross-platform layout in
memory for uniform block data, as well as mechanisms to allow the GL
to optimize the data layout in an implementation-defined manner.
Prior to this extension, the existing interface for modification of
uniform values allowed modification of large numbers of values using
glUniform* calls, but only for a single uniform name (or a uniform
array) at a time. However, updating uniforms in this manner may not
map well to heterogenous uniform data structures defined for a GL
application and in these cases, the application is forced to either:
A) restructure their uniform data definitions into arrays
or
B) make an excessive number of calls through the GL interface
to one of the Uniform* variants.
These solutions have their disadvantages. Solution A imposes
considerable development overhead on the application developer.
Solution B may impose considerable run-time overhead on the
application if the number of uniforms modified in a given frame of
rendering is sufficiently large.
This extension provides a better alternative to either (A) or (B) by
allowing buffer object backing for the storage associated with all
uniforms of a given GLSL program.
Storing uniform blocks in buffer objects enables several key use
cases:
- sharing of uniform data storage between program objects and
between program stages
- rapid swapping of sets of previously defined uniforms by storing
sets of uniform data on the GL server
- rapid updates of uniform data from both the client and the server
The data storage for a uniform block can be declared to use one of
three layouts in memory: packed, shared, or std140.
- "packed" uniform blocks have an implementation-dependent data
layout for efficiency, and unused uniforms may be eliminated by
the compiler to save space.
- "shared" uniform blocks, the default layout, have an implementation-
dependent data layout for efficiency, but the layout will be uniquely
determined by the structure of the block, allowing data storage to be
shared across programs.
- "std140" uniform blocks have a standard cross-platform cross-vendor
layout (see below). Unused uniforms will not be eliminated.
Any uniforms not declared in a named uniform block are said to
be part of the "default uniform block".
While uniforms in the default uniform block are updated with
glUniform* entry points and can have static initializers, uniforms
in named uniform blocks are not. Instead, uniform block data is updated
using the routines that update buffer objects and can not use static
initializers.
Rules and Concepts Guiding this Specification:
For reference, a uniform has a "uniform index" (subsequently
referred to as "u_index) and also a "uniform location" to
efficiently identify it in the uniform data store of the
implementation. We subsequently refer to this uniform data store of
the implementation as the "uniform database".
A "uniform block" only has a "uniform block index" used for queries
and connecting the "uniform block" to a buffer object. A "uniform
block" has no "location" because "uniform blocks" are not updated
directly. The buffer object APIs are used instead.
Properties of Uniforms and uniform blocks:
a) A uniform is "active" if it exists in the database and has a valid
u_index.
b) A "uniform block" is "active" if it exists in the database and
has a valid ub_index.
c) Uniforms and "uniform blocks" can be inactive because they don't
exist in the source, or because they have been removed by dead
code elimination.
d) An inactive uniform has u_index == INVALID_INDEX.
e) An inactive uniform block has ub_index == INVALID_INDEX.
f) A u_index or ub_index of INVALID_INDEX generates the
INVALID_VALUE error if given as a function argument.
g) The default uniform block, which is not assigned any ub_index, uses a
private, internal data storage, and does not have any buffer object
associated with it.
h) An active uniform that is a member of the default uniform block has
location >= 0 and it has offset == stride == -1.
i) An active uniform that is a member of a named uniform block has
location == -1.
j) A uniform location of -1 is silently ignored if given as a function
argument.
k) Uniform block declarations may not be nested
IP Status
No known IP claims.
New Procedures and Functions
void GetUniformIndices(uint program,
sizei uniformCount,
const char* const * uniformNames,
uint* uniformIndices);
void GetActiveUniformsiv(uint program,
sizei uniformCount,
const uint* uniformIndices,
enum pname,
int* params);
void GetActiveUniformName(uint program,
uint uniformIndex,
sizei bufSize,
sizei* length,
char* uniformName);
uint GetUniformBlockIndex(uint program,
const char* uniformBlockName);
void GetActiveUniformBlockiv(uint program,
uint uniformBlockIndex,
enum pname,
int* params);
void GetActiveUniformBlockName(uint program,
uint uniformBlockIndex,
sizei bufSize,
sizei* length,
char* uniformBlockName);
void BindBufferRange(enum target,
uint index,
uint buffer,
intptr offset,
sizeiptr size);
void BindBufferBase(enum target,
uint index,
uint buffer);
void GetIntegeri_v(enum target, uint index, int* data);
void UniformBlockBinding(uint program,
uint uniformBlockIndex,
uint uniformBlockBinding);
New Types
None.
New Tokens
Accepted by the <target> parameters of BindBuffer, BufferData,
BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData, and
GetBufferPointerv:
UNIFORM_BUFFER 0x8A11
Accepted by the <pname> parameter of GetIntegeri_v, GetBooleanv,
GetIntegerv, GetFloatv, and GetDoublev:
UNIFORM_BUFFER_BINDING 0x8A28
Accepted by the <pname> parameter of GetIntegeri_v:
UNIFORM_BUFFER_START 0x8A29
UNIFORM_BUFFER_SIZE 0x8A2A
Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
GetFloatv, and GetDoublev:
MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
MAX_UNIFORM_BLOCK_SIZE 0x8A30
MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
Accepted by the <pname> parameter of GetProgramiv:
ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
ACTIVE_UNIFORM_BLOCKS 0x8A36
Accepted by the <pname> parameter of GetActiveUniformsiv:
UNIFORM_TYPE 0x8A37
UNIFORM_SIZE 0x8A38
UNIFORM_NAME_LENGTH 0x8A39
UNIFORM_BLOCK_INDEX 0x8A3A
UNIFORM_OFFSET 0x8A3B
UNIFORM_ARRAY_STRIDE 0x8A3C
UNIFORM_MATRIX_STRIDE 0x8A3D
UNIFORM_IS_ROW_MAJOR 0x8A3E
Accepted by the <pname> parameter of GetActiveUniformBlockiv:
UNIFORM_BLOCK_BINDING 0x8A3F
UNIFORM_BLOCK_DATA_SIZE 0x8A40
UNIFORM_BLOCK_NAME_LENGTH 0x8A41
UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
Returned by GetActiveUniformsiv and GetUniformBlockIndex
INVALID_INDEX 0xFFFFFFFFu
2.1 Specification Updates
Additions to Chapter 2 - OpenGL Operation
Section 2.9 - Buffer Objects
Add UNIFORM_BUFFER to list of buffer object targets on:
Pg 35, 2nd pgph
Pg 37, top of page
Pg 38, top of page
Section 2.15 - Vertex Shaders
Pg 79, bump Uniform Variables up to a numbered section since there
will now be hierarchy under it; replace all but first paragraph of
Uniform Variables section on this page, through to the start of the
first full paragraph on p. 80 (beginning "A valid <name>...") under
the description of GetUniformLocation:
Sets of uniforms can be grouped into "uniform blocks". The values of each
uniform in such a set are extracted from the data store of a buffer object
corresponding to the uniform block.
OpenGL Shading Language syntax serves to delimit named blocks of
uniforms that can be backed by a buffer object. These are referred to as
"named uniform blocks," and are assigned a uniform block index. Uniforms
that are declared outside of a named uniform block are said to be part of
the "default uniform block." Default uniform blocks have no name or uniform
block index. Like uniforms, uniform blocks can be active or inactive. Active
uniform blocks are those that contain active uniforms after a program has
been compiled and linked.
The amount of storage available for uniform variables in the default uniform
block accessed by a vertex shader is specified by the value of the
implementation-dependent constant MAX_VERTEX_UNIFORM_COMPONENTS. The total
amount of combined storage available for uniform variables in all uniform
blocks accessed by a vertex shader (including the default uniform block)
is specified by the value of the implementation-dependent
constant MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS. These values
represent the numbers of individual floating-point, integer, or boolean
values that can be held in uniform variable storage for a vertex shader.
A link error is generated if an attempt is made to utilize more than
the space available for vertex shader uniform variables.
When a program is successfully linked, all active uniforms belonging to
the program object's default uniform block are initialized to zero (FALSE
for booleans). A successful link will also generate a location for each
active uniform in the default uniform block. The values of active uniforms
in the default uniform block can be changed using this location and the
appropriate Uniform* command (see below). These locations are invalidated
and new ones assigned after each successful re-link.
Similarly, when a program is successfully linked, all active uniforms
belonging to the program's named uniform blocks are assigned offsets
(and strides for array and matrix type uniforms) within the uniform block
according to layout rules described below. Uniform buffer objects provide
the storage for named uniform blocks, so the values of active uniforms in
named uniform blocks may be changed by modifying the contents of the buffer
object using commands such as BufferData, BufferSubData, MapBuffer, and
UnmapBuffer. Uniforms in a named uniform block are not assigned a location
and may not be modified using the Uniform* commands. The offsets and strides
of all active uniforms belonging to named uniform blocks of a program object
are invalidated and new ones assigned after each successful re-link.
To find the location within a program object of an active uniform
variable associated with the default uniform block, use the command
int GetUniformLocation(uint program, const char *name);
This command will return the location of uniform variable <name> if it
is associated with the default uniform block. <name> must be a
null-terminated string, without white space. The value -1 will be returned
if <name> does not correspond to an active uniform variable name in
<program>, if <name> is associated with a named uniform block, or if
<name> starts with the reserved prefix "gl_".
If <program> has not been successfully linked, the error INVALID_OPERATION
is generated. After a program is linked, the location of a uniform
variable will not change, unless the program is re-linked.
A valid <name>...
Pg 80, insert before the description of GetActiveUniform:
Named uniform blocks, like uniforms, are identified by name strings.
Uniform block indices corresponding to uniform block names can be queried
by calling
uint GetUniformBlockIndex(uint program,
const char* uniformBlockName);
<program> is the name of a program object for which the command
LinkProgram has been issued in the past. It is not
necessary for <program> to have been linked successfully. The link
could have failed because the number of active uniforms exceeded the
limit.
<uniformBlockName> must contain a null-terminated string specifying
the name of a uniform block.
GetUniformBlockIndex returns the uniform block index for the
uniform block named <uniformBlockName> of <program>. If
<uniformBlockName> does not identify an active uniform block of
<program>, or an error occurred, then INVALID_INDEX is returned.
The indices of the active uniform blocks of a program are assigned in
consecutive order, beginning with zero.
An active uniform block's name string can be queried from its
uniform block index by calling
void GetActiveUniformBlockName(uint program,
uint uniformBlockIndex,
sizei bufSize,
sizei* length,
char* uniformBlockName);
<program> is the name of a program object for which the command
LinkProgram has been issued in the past. It is not
necessary for <program> to have been linked successfully. The link
could have failed because the number of active uniforms exceeded the
limit.
<uniformBlockIndex> must be an active uniform block index of
<program>, in the range zero to the value of
ACTIVE_UNIFORM_BLOCKS - 1. The value of
ACTIVE_UNIFORM_BLOCKS can be queried with GetProgramiv (see
section 6.1.14). If <uniformBlockIndex> is greater than or equal to
the value of ACTIVE_UNIFORM_BLOCKS, the error INVALID_VALUE is
generated.
The string name of the uniform block identified by <uniformBlockIndex>
is returned into <uniformBlockName>. The name is
null-terminated. The actual number of characters written into
<uniformBlockName>, excluding the null terminator, is returned in <length>.
If <length> is NULL, no length is returned.
<bufSize> contains the maximum number of characters (including the
null terminator) that will be written back to <uniformBlockName>.
If an error occurs, nothing will be written to <uniformBlockName> or
<length>.
Information about an active uniform block can be queried by calling
void GetActiveUniformBlockiv(uint program,
uint uniformBlockIndex,
enum pname,
int* params);
<program> is the name of a program object for which the command
LinkProgram has been issued in the past. It is not
necessary for <program> to have been linked successfully. The link
could have failed because the number of active uniforms exceeded the
limit.
<uniformBlockIndex> is an active uniform block index of <program>.
If <uniformBlockIndex> is greater than or equal to the value of
ACTIVE_UNIFORM_BLOCKS, or is not the index of an active uniform
block in <program>, the error INVALID_VALUE is generated.
If no error occurs, the uniform block parameter(s) specified by
<pname> are returned in <params>. Otherwise, nothing will be written
to <params>.
If <pname> is UNIFORM_BLOCK_BINDING, then
the index of the uniform buffer binding
point last selected by the uniform block specified by <uniformBlockIndex>
for <program> is returned. If no uniform block has been previously
specified, zero is returned.
If <pname> is UNIFORM_BLOCK_DATA_SIZE, the value returned is the
implementation-dependent minimum total buffer object size, in
basic machine units, required to hold all active uniforms in the
uniform block identified by <uniformBlockIndex>.
It is neither guaranteed nor expected that a given implementation will
arrange uniform values as tightly packed in a buffer object. The exception
to this is the "std140" uniform block layout, which guarantees specific
packing behavior and does not require the application to query for offsets
and strides. In this case, the minimum size may still be queried, even
though it is determined in advance based only on the uniform block
declaration (see "Standard Uniform Block Layout" in section 2.15.3.1.2).
The total amount of buffer object storage available for any given uniform
block is subject to an implementation-dependent limit; the maximum amount
of available space, in basic machine units, can be queried by calling
GetIntegerv with the constant MAX_UNIFORM_BLOCK_SIZE. If the amount
of storage required for a uniform block exceeds this limit, a program may
fail to link.
If <pname> is UNIFORM_BLOCK_NAME_LENGTH, then the total length
(including the null terminator) of the name of the uniform block
identified by <uniformBlockIndex> is returned.
If <pname> is UNIFORM_BLOCK_ACTIVE_UNIFORMS, then the number of
active uniforms in the uniform block identified by
<uniformBlockIndex> is returned.
If <pname> is UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, then a list
of the active uniform indices for the uniform block identified by
<uniformBlockIndex> is returned.
The number of elements that will be written to <params> is the value
of UNIFORM_BLOCK_ACTIVE_UNIFORMS for <uniformBlockIndex>.
If <pname> is UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER, or
UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, then
a boolean value indicating whether the uniform block identified by
<uniformBlockIndex> is referenced by the vertex, geometry, or fragment
programming stage of <program>, respectively, is returned.
Each active uniform, whether in a named uniform block or in the default
block, is assigned an index when a program is linked. These indices are
assigned in consecutive order, beginning with zero. The indices assigned
to a set of uniforms in a program may be queried by calling
void GetUniformIndices(uint program,
sizei uniformCount,
const char* const * uniformNames,
uint* uniformIndices);
<program> is the name of a program object for which the command
LinkProgram has been issued in the past. It is not
necessary for <program> to have been linked successfully. The link
could have failed because the number of active uniforms exceeded the
limit.
<uniformCount> indicates both the number of elements in the array of
names <uniformNames> and the number of indices that may be written to
<uniformIndices>.
<uniformNames> contains a list of <uniformCount> name strings
identifying the uniform names to be queried for indices. For each name
string in <uniformNames>, the index assigned to the active uniform of
that name will be written to the corresponding element of
<uniformIndices>. If a string in <uniformNames> is not the name of an
active uniform, the value INVALID_INDEX will be written to the
corresponding element of <uniformIndices>.
If an error occurs, nothing is written to <uniformIndices>.
The name of an active uniform may be queried from the corresponding uniform
index by calling
void GetActiveUniformName(uint program,
uint uniformIndex,
sizei bufSize,
sizei* length,
char* uniformName);
<program> is the name of a program object for which the command
LinkProgram has been issued in the past. It is not
necessary for <program> to have been linked successfully. The link
could have failed because the number of active uniforms exceeded the
limit.
<uniformIndex> must be an active uniform index of the program
<program>, in the range zero to the value of ACTIVE_UNIFORMS - 1.
The value of ACTIVE_UNIFORMS can be queried with GetProgramiv. If
<uniformIndex> is greater than or equal to the value of
ACTIVE_UNIFORMS, the error INVALID_VALUE is generated.
The name of the uniform identified by <uniformIndex> is
returned as a null-terminated string in <uniformName>.
The actual number of characters written into <uniformName>, excluding the
null terminator, is returned in <length>. If <length> is NULL, no length is
returned. The maximum number of characters that may be written into
<uniformName>, including the null terminator, is specified by <bufSize>.
The returned uniform name can be the name of built-in uniform state as
well. The complete list of built-in uniform state is described in section
7.5 of the OpenGL Shading Language specification. The length of the
longest uniform name in <program> is given by the value of
ACTIVE_UNIFORM_MAX_LENGTH, which can be queried with GetProgramiv.
If GetActiveUniformName is not successful, nothing is written to
<length> or <uniformName>.
Each uniform variable, declared in a shader, is broken down into one or
more strings using the "." (dot) and "[]" operators, if necessary, to the
point that it is legal to pass each string back into GetUniformLocation,
for default uniform block uniform names, or GetUniformIndices, for
named uniform block uniform names.
Pg 80, replace description of GetActiveUniform
Information about active uniforms can be obtained by calling either
void GetActiveUniform(uint program,
uint index,
sizei bufSize,
sizei* length,
int* size,
enum* type,
char* name);
or
void GetActiveUniformsiv(uint program,
sizei uniformCount,
const uint* uniformIndices,
enum pname,
int* params);
<program> is the name of a program object for which the command
LinkProgram has been issued in the past. It is not
necessary for <program> to have been linked successfully. The link
could have failed because the number of active uniforms exceeded the
limit.
These commands provide information about the uniform or uniforms selected
by <index> or <uniformIndices>, respectively. In GetActiveUniform, an
<index> of 0 selects the first active uniform, and an <index> of the value
of ACTIVE_UNIFORMS - 1 selects the last active uniform. In
GetActiveUniformsiv, <uniformIndices> is an array of such active uniform
indices. If any index is greater than or equal to the value of
ACTIVE_UNIFORMS, the error INVALID_VALUE is generated.
For the selected uniform, GetActiveUniform returns the uniform name as a
null-terminated string in <name>. The actual number of
characters written into <name>, excluding the null terminator, is returned
in <length>. If <length> is NULL, no length is returned. The maximum
number of characters that may be written into <name>, including the null
terminator, is specified by <bufSize>. The returned uniform name can be the
name of built-in uniform state as well. The complete list of built-in
uniform state is described in section 7.5 of the OpenGL Shading Language
specification. The length of the longest uniform name in <program> is given
by ACTIVE_UNIFORM_MAX_LENGTH.
Each uniform variable, declared in a shader, is broken down into one or
more strings using the "." (dot) and "[]" operators, if necessary, to the
point that it is legal to pass each string back into GetUniformLocation,
for default uniform block uniform names, or GetUniformIndices, for
named uniform block uniform names.
For the selected uniform, GetActiveUniform returns the type of the uniform
into <type> and the size of the uniform is into <size>. The value in
<size> is in units of the uniform type, which can be any of the
values in Table 2.utype.
If one or more elements of an array are active, GetActiveUniform will
return the name of the array in <name>, subject to the restrictions listed
above. The type of the array is returned in <type>. The <size> parameter
contains the highest array element index used, plus one. The compiler or
linker determines the highest index used. There will be only one active
uniform reported by the GL per uniform array.
GetActiveUniform will return as much information about active uniforms as
possible. If no information is available, <length> will be set to zero and
<name> will be an empty string. This situation could arise if
GetActiveUniform is issued after a failed link.
If an error occurs, nothing is written to <length>, <size>, <type>,
or <name>.
Type Name Token Keyword Type Name Token Keyword
--------------- ------- --------------- -------
FLOAT float SAMPLER_1D sampler1D
FLOAT_VEC2 vec2 SAMPLER_2D sampler2D
FLOAT_VEC3 vec3 SAMPLER_3D sampler3D
FLOAT_VEC4 vec4 SAMPLER_CUBE samplerCube
INT int SAMPLER_1D_SHADOW sampler1DShadow
INT_VEC2 ivec2 SAMPLER_2D_SHADOW sampler2DShadow
INT_VEC3 ivec3 SAMPLER_1D_ARRAY_EXT sampler1DArray
INT_VEC4 ivec4 SAMPLER_2D_ARRAY_EXT sampler2DArray
UNSIGNED_INT unsigned int SAMPLER_1D_ARRAY_SHADOW_EXT sampler1DArrayShadow
UNSIGNED_INT_VEC2_EXT uvec2 SAMPLER_2D_ARRAY_SHADOW_EXT sampler2DArrayShadow
UNSIGNED_INT_VEC3_EXT uvec3 SAMPLER_CUBE_SHADOW_EXT samplerCubeShadow
UNSIGNED_INT_VEC4_EXT uvec4 SAMPLER_2D_RECT_ARB sampler2DRect
BOOL bool SAMPLER_2D_RECT_SHADOW_ARB sampler2DRectShadow
BOOL_VEC2 bvec2 INT_SAMPLER_1D_EXT isampler1D
BOOL_VEC3 bvec3 INT_SAMPLER_2D_EXT isampler2D
BOOL_VEC4 bvec4 INT_SAMPLER_3D_EXT isampler3D
FLOAT_MAT2 mat2 INT_SAMPLER_CUBE_EXT isamplerCube
FLOAT_MAT3 mat3 INT_SAMPLER_1D_ARRAY_EXT isampler1DArray
FLOAT_MAT4 mat4 INT_SAMPLER_2D_ARRAY_EXT isampler2DArray
FLOAT_MAT2x3 mat2x3 UNSIGNED_INT_SAMPLER_1D_EXT usampler1D
FLOAT_MAT2x4 mat2x4 UNSIGNED_INT_SAMPLER_2D_EXT usampler2D
FLOAT_MAT3x2 mat3x2 UNSIGNED_INT_SAMPLER_3D_EXT usampler3D
FLOAT_MAT3x4 mat3x4 UNSIGNED_INT_SAMPLER_CUBE_EXT usamplerCube
FLOAT_MAT4x2 mat4x2 UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT usampler1DArray
FLOAT_MAT4x3 mat4x3 UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT usampler2DArray
SAMPLER_BUFFER_EXT samplerBuffer
INT_SAMPLER_BUFFER_EXT isamplerBuffer
UNSIGNED_INT_SAMPLER_BUFFER_EXT usamplerBuffer
INT_SAMPLER_2D_RECT_EXT isampler2DRect
UNSIGNED_INT_SAMPLER_2D_RECT_EXT usampler2DRect
-----------------------------------------------------------------------
Table 2.utype: OpenGL Shading Language type tokens returned by
GetActiveUniform and GetActiveUniformsiv, and corresponding shading
language keywords declaring each such type.
For GetActiveUniformsiv, <uniformCount> indicates both the number of
elements in the array of indices <uniformIndices> and the number of
parameters written to <params> upon successful return. <pname> identifies
a property of each uniform in <uniformIndices> that should be written into
the corresponding element of <params>. If an error occurs, nothing will
be written to <params>.
If <pname> is UNIFORM_TYPE, then an array identifying the types
of the uniforms specified by the corresponding array of
<uniformIndices> is returned. The returned types can be any of the
values in Table 2.utype.
If <pname> is UNIFORM_SIZE, then an array identifying the size
of the uniforms specified by the corresponding array of
<uniformIndices> is returned. The sizes returned are in units of the type
returned by a query of UNIFORM_TYPE. For active uniforms that are
arrays, the size is the number of active elements in the array; for
all other uniforms, the size is one.
If <pname> is UNIFORM_NAME_LENGTH, then an array identifying the
length, including the terminating null character, of the uniform
name strings specified by the corresponding array of
<uniformIndices> is returned.
If <pname> is UNIFORM_BLOCK_INDEX, then an array identifying the
uniform block index of each of the uniforms specified by the
corresponding array of <uniformIndices> is returned. The index of a
uniform associated with the default uniform block is -1.
If <pname> is UNIFORM_OFFSET, then an array of uniform buffer offsets
is returned. For uniforms in a named uniform block, the returned value
will be its offset, in basic machine units, relative to the beginning of
the uniform block in the buffer object data store. For uniforms in the
default uniform block, -1 will be returned.
If <pname> is UNIFORM_ARRAY_STRIDE, then an array identifying
the stride between elements, in basic machine units, of each of the
uniforms specified by the corresponding array of <uniformIndices> is
returned. The stride of a uniform associated with the default
uniform block is -1. Note that this information only makes sense for
uniforms that are arrays. For uniforms that are not arrays, but are
declared in a named uniform block, an array stride of zero is
returned.
If <pname> is UNIFORM_MATRIX_STRIDE, then an array identifying
the stride between columns of a column-major matrix or rows of a
row-major matrix, in basic machine units, of each of the uniforms
specified by the corresponding array of <uniformIndices> is
returned. The matrix stride of a uniform associated with the default
uniform block is -1. Note that this information only makes sense for
uniforms that are matrices. For uniforms that are not matrices, but
are declared in a named uniform block, a matrix stride of zero is
returned.
If <pname> is UNIFORM_IS_ROW_MAJOR, then
an array identifying whether each of the uniforms
specified by the corresponding array of <uniformIndices> is a row-major
matrix or not is returned. A value of one indicates a row-major
matrix, and a value of zero indicates a column-major matrix, a matrix
in the default uniform block, or a non-matrix.
Pg 81, replace Uniform* description with:
To load values into the uniform variables of the default uniform block of
the program object that is currently in use, use the commands
...
The given values are loaded into the default uniform block uniform
variable location identified by <location>.
Sub-section 2.15.3.1 - Uniform Blocks
The values of uniforms arranged in named uniform blocks are extracted from
buffer object storage. The mechanisms for placing individual uniforms in
a buffer object and connecting a uniform block to an individual buffer
object are described below.
There is a set of implementation-dependent maximums for the number of
active uniform blocks used by each shader (vertex, fragment, geometry).
If the number of uniform blocks used by any shader in the program exceeds
its corresponding limit, the program will fail to link. The limits for
vertex, fragment, and geometry shaders can be obtained by calling
GetIntegerv with <pname> values of MAX_VERTEX_UNIFORM_BLOCKS,
MAX_FRAGMENT_UNIFORM_BLOCKS, and MAX_GEOMETRY_UNIFORM_BLOCKS,
respectively.
Additionally, there is an implementation-dependent limit on the sum of the
number of active uniform blocks used by each shader of a program. If a
uniform block is used by multiple shaders, each such use counts separately
against this combined limit. The combined uniform block use limit can be
obtained by calling GetIntegerv with a <pname> of
MAX_COMBINED_UNIFORM_BLOCKS.
When a named uniform block is declared by multiple shaders in a program,
it must be declared identically in each shader. The uniforms within the
block must be declared with the same names and types, and in the same
order. If a program contains multiple shaders with different declarations
for the same named uniform block differs between shader, the program will
fail to link.
Sub-section 2.15.3.1.1 - Uniform Buffer Object Storage
When stored in buffer objects associated with uniform blocks, uniforms are
represented in memory as follows:
- Members of type "bool" are extracted from a buffer object by reading a
single uint-typed value at the specified offset. All non-zero
values correspond to true, and zero corresponds to false.
- Members of type "int" are extracted from a buffer object by reading a
single int-typed value at the specified offset.
- Members of type "uint" are extracted from a buffer object by reading a
single uint-typed value at the specified offset.
- Members of type "float" are extracted from a buffer object by reading a
single float-typed value at the specified offset.
- Vectors with <N> elements with basic data types of "bool", "int",
"uint", or "float" are extracted as <N> values in consecutive memory
locations beginning at the specified offset, with components stored in
order with the first (X) component at the lowest offset. The GL data
type used for component extraction is derived according to the rules for
scalar members above.
- Column-major matrices with <C> columns and <R> rows (using the type
"mat<C>x<R>", or simply "mat<C>" if <C>==<R>) are treated as an array of
<C> floating-point column vectors, each consisting of <R> components.
The column vectors will be stored in order, with column zero at the
lowest offset. The difference in offsets between consecutive columns of
the matrix will be referred to as the column stride, and is constant
across the matrix. The column stride, UNIFORM_MATRIX_STRIDE, is an
implementation-dependent value and may be queried after a program is
linked.
- Row-major matrices with <C> columns and <R> rows (using the type
"mat<C>x<R>", or simply "mat<C>" if <C>==<R>) are treated as an array of
<R> floating-point row vectors, each consisting of <C> components. The
row vectors will be stored in order, with row zero at the lowest offset.
The difference in offsets between consecutive rows of the matrix will be
referred to as the row stride, and is constant across the matrix. The
row stride, UNIFORM_MATRIX_STRIDE, is an implementation-dependent
value and may be queried after a program is linked.
- Arrays of scalars, vectors, and matrices are stored in memory by element
order, with array member zero at the lowest offset. The difference in
offsets between each pair of elements in the array in basic machine
units is referred to as the array stride, and is constant across the
entire array. The array stride, UNIFORM_ARRAY_STRIDE, is an
implementation-dependent value and may be queried after a program is
linked.
Sub-section 2.15.3.1.2 - Standard Uniform Block Layout
By default, uniforms contained within a uniform block are extracted from
buffer storage in an implementation-dependent manner. Applications may
query the offsets assigned to uniforms inside uniform blocks with query
functions provided by the GL.
The "layout" qualifier provides shaders with control of the layout of
uniforms within a uniform block. When the "std140" layout is specified,
the offset of each uniform in a uniform block can be derived from the
definition of the uniform block by applying the set of rules described
below.
If a uniform block is declared in multiple shaders linked together into a
single program, the link will fail unless the uniform block declaration,
including layout qualifier, are identical in all such shaders.
When using the "std140" storage layout, structures will be laid out in
buffer storage with its members stored in monotonically increasing order
based on their location in the declaration. A structure and each
structure member have a base offset and a base alignment, from which an
aligned offset is computed by rounding the base offset up to a multiple of
the base alignment. The base offset of the first member of a structure is
taken from the aligned offset of the structure itself. The base offset of
all other structure members is derived by taking the offset of the last
basic machine unit consumed by the previous member and adding one. Each
structure member is stored in memory at its aligned offset. The members
of a top-level uniform block are laid out in buffer storage by treating
the uniform block as a structure with a base offset of zero.
(1) If the member is a scalar consuming <N> basic machine units, the
base alignment is <N>.
(2) If the member is a two- or four-component vector with components
consuming <N> basic machine units, the base alignment is 2<N> or
4<N>, respectively.
(3) If the member is a three-component vector with components consuming
<N> basic machine units, the base alignment is 4<N>.
(4) If the member is an array of scalars or vectors, the base alignment
and array stride are set to match the base alignment of a single
array element, according to rules (1), (2), and (3), and rounded up
to the base alignment of a vec4. The array may have padding at the
end; the base offset of the member following the array is rounded up
to the next multiple of the base alignment.
(5) If the member is a column-major matrix with <C> columns and <R>
rows, the matrix is stored identically to an array of <C> column
vectors with <R> components each, according to rule (4).
(6) If the member is an array of <S> column-major matrices with <C>
columns and <R> rows, the matrix is stored identically to a row of
<S>*<C> column vectors with <R> components each, according to rule
(4).
(7) If the member is a row-major matrix with <C> columns and <R> rows,
the matrix is stored identically to an array of <R> row vectors
with <C> components each, according to rule (4).
(8) If the member is an array of <S> row-major matrices with <C> columns
and <R> rows, the matrix is stored identically to a row of <S>*<R>
row vectors with <C> components each, according to rule (4).
(9) If the member is a structure, the base alignment of the structure is
<N>, where <N> is the largest base alignment value of any of its
members, and rounded up to the base alignment of a vec4. The
individual members of this sub-structure are then assigned offsets
by applying this set of rules recursively, where the base offset of
the first member of the sub-structure is equal to the aligned offset
of the structure. The structure may have padding at the end; the
base offset of the member following the sub-structure is rounded up
to the next multiple of the base alignment of the structure.
(10) If the member is an array of <S> structures, the <S> elements of
the array are laid out in order, according to rule (9).
For uniform blocks laid out according to these rules, the minimum buffer
object size returned by the UNIFORM_BLOCK_DATA_SIZE query is derived by
taking the offset of the last basic machine unit consumed by the last
uniform of the uniform block (including any end-of-array or
end-of-structure padding), adding one, and rounding up to the next
multiple of the base alignment required for a vec4.
Sub-section 2.15.3.2 - Uniform Buffer Object Bindings
The value an active uniform inside a named uniform block is extracted from
the data store of a buffer object bound to one of an array of uniform
buffer binding points. The number of binding points can be queried using
GetIntegerv with the constant MAX_UNIFORM_BUFFER_BINDINGS.
Buffer objects are bound to uniform block binding points by calling one of
the commands
void BindBufferRange(enum target,
uint index,
uint buffer,
intptr offset,
sizeiptr size);
void BindBufferBase(enum target,
uint index,
uint buffer);
with <target> set to UNIFORM_BUFFER. There is an array of buffer
object binding points with which uniform blocks can be associated via
UniformBlockBinding, plus a single general binding point that can be
used by other buffer object manipulation functions (e.g. BindBuffer,
MapBuffer). Both commands bind the buffer object named by <buffer> to the
general binding point, and additionally bind the buffer object to the
binding point in the array given by <index>. The error INVALID_VALUE is
generated if <index> is greater than or equal to the value of
MAX_UNIFORM_BUFFER_BINDINGS.
For BindBufferRange, <offset> specifies a starting offset into the
buffer object <buffer>, and <size> specifies the amount of data that can
be read from the buffer object while used as the storage for a uniform
block. Both <offset> and <size> are in basic machine units. An
INVALID_VALUE error is generated if <size> is less than or equal to zero
or if <offset> is not a multiple of the implementation-dependent
required alignment (the value of UNIFORM_BUFFER_OFFSET_ALIGNMENT).
BindBufferBase binds the entire buffer, even when the size of the buffer
is changed after the binding is established. It is equivalent to calling
BindBufferRange with <offset> zero, while <size> is determined by the
size of the bound buffer at the time the binding is used.
Regardless of the size specified with BindBufferRange, or indirectly
with BindBufferBase, the GL will never read or write beyond the end of a
bound buffer. This may result in visibly different behavior when a
buffer overflow would otherwise result.
Each of a program's active uniform blocks has a corresponding uniform buffer
object binding point. This binding point can be assigned by calling:
void UniformBlockBinding(uint program,
uint uniformBlockIndex,
uint uniformBlockBinding);
<program> is a name of a program object for which the command LinkProgram
has been issued in the past.
<uniformBlockIndex> must be an active uniform block index of the program
<program>. Otherwise, INVALID_VALUE is generated.
<uniformBlockBinding> must be less than MAX_UNIFORM_BUFFER_BINDINGS.
Otherwise, INVALID_VALUE is generated.
If successful, UniformBlockBinding specifies that
<program> will use the data store of the buffer object bound to the
binding point <uniformBlockBinding> to extract the values of the uniforms
in the uniform block identified by <uniformBlockIndex>.
The results of Begin or commands that perform an implicit Begin are
undefined when an active uniform block of the active program is assigned a
uniform buffer binding point where the <size> parameter to BindBufferRange
is less than the value of UNIFORM_BLOCK_DATA_SIZE for that uniform
block, or when no buffer object is bound to that binding point, and may
result in GL interruption or termination.
When executing shaders that access uniform blocks, the binding point
corresponding to each active uniform block must be populated with a buffer
object with a size no smaller than the minimum required size of the
uniform block (UNIFORM_BLOCK_DATA_SIZE). For binding points populated
by BindBufferRange, the size in question is the value of the <size>
parameter. If any active uniform block is not backed by a sufficiently
large buffer object, the results of shader execution are undefined, and
may result in GL interruption or termination. Shaders may be executed to
process the primitives and vertices specified between Begin and End commands
or by Draw* or MultiDraw* commands (see section 2.8). Shaders may also
be executed as a result of DrawPixels, Bitmap, or RasterPos* commands.
When a program object is linked or re-linked, the uniform buffer object
binding point assigned to each of its active uniform blocks is reset to
zero.
Additions to Chapter 3 - Rasterization
3.11.1 Shader Variables, p. 196
Replace the second two sentences with:
The amount of storage available for fragment shader uniform variables in
the default uniform block is specified by the value of the implementation-
dependent constant MAX_FRAGMENT_UNIFORM_COMPONENTS. The total amount of
combined storage available for fragment shader uniform variables in all
uniform blocks (including the default uniform block) is specified by the
value of the implementation-dependent constant
MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS. These values represent the
numbers of individual floating-point, integer, or boolean values that can be
held in uniform variable storage for a fragment shader.
Additions to Chapter 4 - Per-Fragment Operations and the Framebuffer
None
Additions to Chapter 5 - State and State Requests
5.4 Display Lists, p. 244
Add the following language to the list of commands excluded from
display list compilation:
"Buffer objects: BindBufferRange, BindBufferBase"
Additions to Chapter 6 - State and State Requests
6.1.1 Simple Queries, p. 247
Add the following paragraph:
Indexed simple state variables are queried with the command
void GetIntegeri_v(enum target, uint index, int* data);
<target> is the name of the indexed state and <index> is the
index of the particular element being queried. <data> is a
pointer to a scalar or array of the indicated type in which
to place the returned data. An INVALID_VALUE error is generated
if <index> is outside the valid range for the indexed state
<target>.
6.1.13 Buffer Object Queries, p. 260
Add after description of GetBufferPointerv:
To query which buffer objects are bound to the array of uniform
buffer binding points and will be used as the storage for
active uniform blocks, call GetIntegeri_v with <param> set to
UNIFORM_BUFFER_BINDING. <index> must be in the range
zero to the value of MAX_UNIFORM_BUFFER_BINDINGS - 1.
The name of the buffer object bound to <index> is returned in
<values>. If no buffer object is bound for <index>, zero is
returned in <values>.
To query the starting offset or size of the range of each buffer object
binding used for uniform buffers, call GetIntegeri_v with <param> set to
UNIFORM_BUFFER_START or UNIFORM_BUFFER_SIZE respectively. <index> must
be in the range zero to the value of MAX_UNIFORM_BUFFER_BINDINGS - 1. If
the parameter (starting offset or size) was not specified when the
buffer object was bound (e.g. if bound with BindBufferBase), or if no
buffer object is bound to <index>, zero is returned.
6.1.14 Shader and Program Queries
Pg 261, continuation of paragraph defining "GetProgramiv"
If <pname> is ACTIVE_UNIFORM_BLOCKS the number of uniform
blocks for <program> containing active uniforms is returned.
If <pname> is ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, the
length of the longest active uniform block name, including
the null terminator, is returned.
Pg 263, replace GetUniform{f|i}v description with:
... return the value or values of the uniform at location <location>
of the default uniform block for program object <program>...
GLX Protocol
GLX protocol for BindBufferRange, BindBufferBase and GetIntegeri_v
was added through NV_transform_feedback and EXT_draw_buffers2
protocol specs.
The following rendering commands are sent to the server as part of
a glXRender request:
UniformBlockBinding
2 16 rendering command length
2 366 rendering command opcode
4 CARD32 program
4 CARD32 uniformBlockIndex
4 CARD32 uniformBlockBinding
The following non-rendering commands are added:
GetUniformIndices
1 CARD8 opcode(X assigned)
1 215 GLX opcode
2 4+n+(s+p)/4 request length
4 GLX_CONTEXT_TAG context tag
4 CARD32 program
4 CARD32 uniformCount
n LISTofINT32 lengths[n], n = uniformCount, lengths[i] = strlen(uniformNames[i]) + 1, 0 <= i < n.
s LISTofCHAR uniformNames, s = length[0]+...+length[n-1].
array
p unused, p = pad(s)
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 n reply length
4 unused
4 CARD32 n (number of uniform Indices)
if (n == 1) this follows:
4 CARD32 uniformIndices
12 unused
otherwise this follows:
16 unused
4*n LISTofCARD32 uniformIndices
GetActiveUniformsiv
1 CARD8 opcode(X assigned)
1 216 GLX opcode
2 5+n request length
4 GLX_CONTEXT_TAG context tag
4 CARD32 program
4 INT32 uniformCount(n)
4 ENUM pname
n LISTofCARD32 uniformIndices
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 n reply length
4 unused
if (n == 1) this follows:
4 INT32 params
12 unused
otherwise this follows:
16 unused
4*n LISTofINT32 params
GetActiveUniformName
1 CARD8 opcode(X assigned)
1 217 GLX opcode
2 5 request length
4 GLX_CONTEXT_TAG context tag
4 CARD32 program
4 CARD32 uniformIndex
4 INT32 bufsize
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length, m = (n+p)/4
4 unused
4 INT32 n
16 unused
n LISTofCHAR uniformName, n = strlen(uniformName)+1
p unused, p=pad(n)
GetUniformBlockIndex
1 CARD8 opcode(X assigned)
1 218 GLX opcode
2 3+(n+p)/4 request length
4 GLX_CONTEXT_TAG context tag
4 CARD32 program
n LISTofCHAR uniformBlockName, n = strlen(uniformBlockName)+1
p unused, p=pad(n)
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 0 reply length
4 CARD32 return value
20 unused
GetActiveUniformBlockiv
1 CARD8 opcode(X assigned)
1 219 GLX opcode
2 5 request length
4 GLX_CONTEXT_TAG context tag
4 CARD32 program
4 CARD32 uniformBlockIndex
4 ENUM pname
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 n reply length
4 unused
if (n == 1) this follows:
4 INT32 params
12 unused
otherwise this follows:
16 unused
4*n LISTofINT32 params
GetActiveUniformBlockName
1 CARD8 opcode(X assigned)
1 220 GLX opcode
2 5 request length
4 GLX_CONTEXT_TAG context tag
4 CARD32 program
4 CARD32 uniformBlockIndex
4 INT32 bufsize
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length, m = (n+p)/4
4 unused
4 INT32 n
16 unused
n LISTofCHAR uniformBlockName, n = strlen(uniformBlockName)+1
p unused, p=pad(n)
OpenGL Shading Language Spec v1.20.8 Updates
Including the following line in a shader can be used to control the
language features described in this extension:
#extension GL_ARB_uniform_buffer_object : <behavior>
where <behavior> is as specified in section 3.3.
A new preprocessor #define is added to the OpenGL Shading
Language:
#define GL_ARB_uniform_buffer_object 1
Add two new sections:
4.3.5.1 Uniform Blocks
Variable declarations at global scope can be grouped into a named block to
provide coarser granularity for manipulation, sharing, or backing than is
achievable with individual declarations. This is currently only allowed for
uniform variables grouped into uniform blocks. All other uses are reserved.
The application backs a uniform block with a buffer. This allows application
access to a set of uniform variables through a single buffer. The
application will need to query the offsets of the variables within the
block or follow standard rules for block layout in order to know how to
layout the contents of a buffer used to back the block.
A uniform block (rather than a uniform variable) is created by the uniform
keyword, followed by a block name, followed by an open curly brace ( { ) as
follows:
uniform-block :
layout-qualifieropt uniform block-name { member-list } ;
layout-qualifier :
layout ( layout-qualifier-id-list )
member-list :
member-declaration
member-declaration member-list
member-declaration :
layout-qualifieropt uniformopt basic-type declarators ;
Where declarators are the same as for other uniform variable declarations,
except initializers are not allowed. Layout qualifiers are defined in the
next section.
For example,
uniform Transform {
mat4 ModelViewMatrix;
mat4 ModelViewProjectionMatrix;
uniform mat3 NormalMatrix; // reuse of uniform is optional
float Deformation;
};
The above establishes a uniform block named "Transform" with four uniforms
grouped inside it.
The names declared inside the block are accessed as if they were declared
outside the block. In no way does the shader ever access block members
through any use of block-name.
Uniform block names and variable names declared within uniform blocks are
scoped at the program level. Matching block names from multiple compilation
units in the same program must match in terms of having the same number of
declarations with the same sequence of types and the same sequence of member
names, as well as having the same member-wise layout qualification (see next
section). Any mismatch will generate a link error.
Sampler types are not allowed inside of uniform blocks. All other types,
arrays, and structures allowed for uniforms are allowed within a uniform
block.
There is an implementation-dependent limit on the number of uniform blocks
that can be used per stage. If this limit is exceeded, it will cause a link
error.
4.3.5.2 Uniform Block Layout Qualifiers
The layout-qualifier-id-list for uniform blocks is a comma separated list of
the following qualifiers:
shared (default)
packed
std140
row_major
column_major (default)
These qualifiers are identifiers, not keywords. None of these have any
semantic affect at all on the usage of the variables being declared; they
only describe how data is laid out in memory. For example, matrix semantics
are always column-based, as described in the rest of this specification, no
matter what layout qualifiers are being used.
Uniform block layout qualifiers can be declared at global scope, on a single
uniform block, or on a single block member.
At global scope, it is an error to use layout qualifiers to declare a
variable. Instead, at global scope, layout qualifiers apply just to the
keyword uniform and establish default qualification for subsequent blocks:
layout-defaults :
layout-qualifier uniform ;
When this is done, the previous default qualification is first inherited and
then overridden as per the override rules listed below for each qualifier
listed in the declaration. The result becomes the new default qualification
scoped to subsequent uniform block definitions. Layout defaults can only be
specified at global scope.
The initial state of compilation is as if the following were declared:
layout(shared, column_major) uniform;
Explicitly declaring this in a shader will return defaults back to their
initial state.
Uniform blocks can be declared with optional layout qualifiers, and so can
their individual member declarations. Such block layout qualification is
scoped only to the content of the block. As with global layout declarations,
block layout qualification first inherits from the current default
qualification and then overrides it. Similarly, individual member layout
qualification is scoped just to the member declaration, and inherits from
and overrides the block's qualification.
The shared qualifier overrides only the std140 and packed qualifiers; other
qualifiers are inherited. The compiler/linker will ensure that multiple
programs and programmable stages containing this definition will share the
same memory layout for this block, as long as they also matched in their
row_major and/or column_major qualifications. This allows use of the same
buffer to back the same block definition across different programs.
The packed qualifier overrides only std140 and shared; other qualifiers are
inherited. When packed is used, no shareable layout is guaranteed. The
compiler and linker can optimize memory use based on what variables actively
get used and on other criteria. Offsets must be queried, as there is no
other way of guaranteeing where (and which) variables reside within the
block. Attempts to share a packed uniform block across programs or stages
will generally fail. However, implementations may aid application management
of packed blocks by using canonical layouts for packed blocks.
The std140 qualifier overrides only the packed and shared qualifiers; other
qualifiers are inherited. The layout is explicitly determined by this, as
described in the API specification section 2.15.3.1.2. Hence, as in shared
above, the resulting layout is shareable across programs.
Layout qualifiers on member declarations cannot use the shared, packed, or
std140 qualifiers. These can only be used at global scope or on a block
declaration.
The row_major qualifier overrides only the column_major qualifier; other
qualifiers are inherited. It only affects the layout of matrices. Elements
within a matrix row will be contiguous in memory.
The column_major qualifier overrides only the row_major qualifier; other
qualifiers are inherited. It only affects the layout of matrices. Elements
within a matrix column will be contiguous in memory.
When multiple arguments are listed in a layout declaration, the affect will
be the same as if they were declared one at a time, in order from left to
right, each in turn inheriting from and overriding the result from the
previous qualification.
For example
layout(row_major, column_major)
results in the qualification being column_major. Other examples:
layout(shared, row_major) uniform; // default is now shared & row_major
layout(std140) uniform Transform { // layout of this block is std140
mat4 M1; // row_major
layout(column_major) mat4 M2; // column major
mat3 N1; // row_major
};
uniform T2 { // layout of this block is shared
...
};
layout(column_major) uniform T3 { // shared and column_major
mat4 M3; // column_major
layout(row_major) mat4 m4; // row major
mat3 N2; // column_major
};
Interactions with OpenGL 3.0
If OpenGL 3.0 is supported, the introduction of BindBufferBase and
BindBufferRange can be ignored, though the uniform buffer object
language herein will need to be merged with the transform feedback
language in GL 3.0.
If OpenGL 3.0 is supported, the introduction of GetIntegeri_v
can be ignored.
If OpenGL 3.0 is supported, change:
"When a program is successfully linked, all active uniforms belonging to
the program object's default uniform block are initialized to zero (FALSE
for booleans). A successful link will also generate a location for each
active uniform in the default uniform block. The values of active uniforms
in the default uniform block can be changed using this location and the
appropriate Uniform* command (see below)."
to
"When a program is successfully linked, all active uniforms belonging to
the program object's default uniform block are initialized as defined by
the version of the OpenGL Shading Language used to compile the program. A
successful link will also generate a location for each active uniform in
the default uniform block. The values of active uniforms in the default
uniform block can be changed using this location and the appropriate
Uniform* command (see below)."
If OpenGL 3.0 is supported, replace "Begin or commands that perform
an implicit Begin" with "Draw* commands."
If OpenGL 3.0 is supported, UNIFORM_BUFFER is a valid target for
new buffer-related API, e.g. MapBufferRange.
Interactions with EXT_gpu_shader4
If EXT_gpu_shader4 is not supported, then all of the types in table
2.utype with extension suffixes should be omitted.
Interactions with ARB_texture_rectangle
If ARB_texture_rectangle is not available, then all of the types in
table 2.utype with RECT in their names should be omitted.
Interactions with EXT_texture_array
If EXT_texture_array is not available, then all of the types in
table 2.utype with ARRAY in their names should be omitted.
Interactions with EXT_texture_buffer_object
If EXT_texture_buffer_object is not available, then all of the types
in table 2.utype with BUFFER in their names should be omitted.
Interactions with EXT_texture_integer
If EXT_texture_integer is not available, then all of the types in
table 2.utype with UNSIGNED_INT or INT_SAMPLER in their names should
be omitted.
Interactions with ARB_geometry_shader4
If ARB_geometry_shader4 is not supported, omit all mentions of the
geometry shader stage, including MAX_GEOMETRY_UNIFORM_BUFFERS
and UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER. The minimum
value of MAX_COMBINED_UNIFORM_BLOCKS and
MAX_UNIFORM_BUFFER_BINDINGS changes from 36 to 24.
Language describing MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS can be found
in the ARB_geometry_shader4 specification.
Errors
The error INVALID_OPERATION is generated by BindBufferRange and
BindBufferBase if <buffer> is not the name of a valid buffer object.
The error INVALID_VALUE is generated by GetUniformIndices,
GetActiveUniformsiv, GetActiveUniformName, GetUniformBlockIndex,
GetActiveUniformBlockiv, GetActiveUniformBlockName, and
UniformBlockBinding if <program> is not a value generated by GL.
The error INVALID_VALUE is generated by GetUniformIndices and
GetActiveUniformsiv if <uniformCount> is less than zero.
The error INVALID_VALUE is generated by GetActiveUniformName and
GetActiveUniformBlockName if <bufSize> is less than zero.
The error INVALID_VALUE is generated by BindBufferRange if <size> is less
than zero.
The error INVALID_VALUE is generated by GetActiveUniformName if
<uniformIndex> is greater than or equal to ACTIVE_UNIFORMS.
The error INVALID_VALUE is generated by GetActiveUniformsiv if any of
the indices in <uniformIndices> is greater than or equal to ACTIVE_UNIFORMS.
The error INVALID_VALUE is generated by GetActiveUniformBlockiv,
GetActiveUniformBlockName, and UniformBlockBinding if
<uniformBlockIndex> is greater than or equal to ACTIVE_UNIFORM_BLOCKS.
The error INVALID_VALUE is generated by UniformBlockBinding if
<uniformBlockBinding> is greater than or equal to
MAX_UNIFORM_BUFFER_BINDINGS.
The error INVALID_VALUE is generated by BindBufferRange and BindBufferBase
if <index> is greater than or equal to MAX_UNIFORM_BUFFER_BINDINGS.
The error INVALID_VALUE is generated by BindBufferRange if <offset> is not
a multiple of UNIFORM_BUFFER_OFFSET_ALIGNMENT basic machine units.
The error INVALID_ENUM is generated by GetActiveUniformsiv and
GetActiveUniformBlockiv if <pname> is not one of the accepted values.
The error INVALID_ENUM is generated by BindBufferRange and BindBufferBase
if <target> is not an accepted indexable buffer object target.
New State
Initial
Get Value Type Get Command Value Description Sec Attribute
-------------------------- ---- ----------- ----- ------------------------- ----- ---------
UNIFORM_BUFFER_BINDING Z+ GetIntegerv 0 Uniform buffer object 2.15.3 -
bound to the context for
buffer object manipulation.
UNIFORM_BUFFER_BINDING nxZ+ GetIntegeri_v 0 Uniform buffer object 2.15.3 -
bound to the specified
context binding point
ACTIVE_UNIFORM_BLOCKS Z+ GetProgramiv 0 Number of active 2.15.3 -
uniform blocks in a
program
ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
Z+ GetProgramiv 0 Length of longest active 2.15.3 -
uniform block name
UNIFORM_TYPE 0*xZ_27 GetActiveUniformsiv - Type of active uniform 2.15.3 -
UNIFORM_SIZE 0*xZ+ GetActiveUniformsiv - Size of active uniform 2.15.3 -
UNIFORM_NAME_LENGTH 0*xZ+ GetActiveUniformsiv - Uniform name length 2.15.3 -
UNIFORM_BLOCK_INDEX 0*xZ GetActiveUniformsiv - Uniform block index 2.15.3 -
UNIFORM_OFFSET 0*xZ GetActiveUniformsiv - Uniform buffer offset 2.15.3 -
UNIFORM_ARRAY_STRIDE 0*xZ GetActiveUniformsiv - Uniform buffer array 2.15.3 -
stride
UNIFORM_MATRIX_STRIDE 0*xZ GetActiveUniformsiv - Uniform buffer intra- 2.15.3 -
matrix stride
UNIFORM_IS_ROW_MAJOR 0*xZ+ GetActiveUniformsiv - Whether uniform is a 2.15.3 -
row-major matrix
UNIFORM_BLOCK_BINDING 0*xZ+ GetActiveUniformBlockiv 0 Uniform buffer binding 2.15.3 -
points associated with the
specified uniform block
UNIFORM_BLOCK_DATA_SIZE 0*xZ+ GetActiveUniformBlockiv - Size of the storage 2.15.3 -
needed to hold this
uniform block's data
UNIFORM_BLOCK_ACTIVE_UNIFORMS 0*xZ+ GetActiveUniformBlockiv - Count of active 2.15.3 -
uniforms in
the specified
uniform block
UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
0*xnxZ+ GetActiveUniformBlockiv - Array of active 2.15.3 -
uniform indices of
the specified
uniform block
UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER
0*xB GetActiveUniformBlockiv 0 TRUE if uniform block 2.15.3 -
is actively
referenced by the
vertex shader
UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER
0*xB GetActiveUniformBlockiv 0 TRUE if uniform block 2.15.3 -
is actively
referenced by the
geometry shader
UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
0*xB GetActiveUniformBlockiv 0 TRUE if uniform block 2.15.3 -
is actively
referenced by the
fragment shader
New Implementation Dependent State
Minimum
Get Value Type Get Command Value Description Sec Attribute
-------------------------------- -- ----------- ----- ------------------------- ----- ----------
MAX_VERTEX_UNIFORM_BLOCKS Z+ GetIntegerv 12 Maximum number of vertex 2.15.3 -
uniform buffers per
program
MAX_FRAGMENT_UNIFORM_BLOCKS Z+ GetIntegerv 12 Maximum number of fragment 2.15.3 -
uniform buffers per
program
MAX_GEOMETRY_UNIFORM_BLOCKS Z+ GetIntegerv 12 Maximum number of geometry 2.15.3 -
uniform buffers per
program
MAX_COMBINED_UNIFORM_BLOCKS Z+ GetIntegerv 36 Maximum number of uniform 2.15.3 -
buffers per program
MAX_UNIFORM_BUFFER_BINDINGS Z+ GetIntegerv 36 Maximum number of uniform 2.15.3 -
buffer binding points
on the context
MAX_UNIFORM_BLOCK_SIZE Z+ GetIntegerv 16384 Max size in basic machine 2.15.3 -
units of a uniform block
MAX_VERTEX_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for vertex 2.15.3 -
shader uniform variables
in default uniform block
MAX_FRAGMENT_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for fragment 2.15.3 -
shader uniform variables
in default uniform block
MAX_GEOMETRY_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for geometry 2.15.3 -
shader uniform variables
in default uniform block
MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for vertex 2.15.3 -
shader uniform variables
in all uniform blocks
(including default)
MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for fragment 2.15.3 -
shader uniform variables
in all uniform blocks
(including default)
MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for geometry 2.15.3 -
shader uniform variables
in all uniform blocks
(including default)
UNIFORM_BUFFER_OFFSET_ALIGNMENT Z+ GetIntegerv 1 Minimum required alignment 2.15.3 -
for uniform buffer sizes
and offsets
* Minimum value for OpenGL 3.1 is (MAX_<stage>_UNIFORM_BLOCKS *
MAX_UNIFORM_BLOCK_SIZE) + MAX_<stage>_UNIFORM_COMPONENTS. Minimum
value prior to OpenGL 3.1 is MAX_<stage>_UNIFORM_COMPONENTS.
Sample Code
////////////////////////////////////////////////////////////////////////////
Example: Full code of a simple use case: updating a group of variables
in a real shader.
////////////////////////////////////////////////////////////////////////////
//Platform-specific includes go here
#define glError() { \
GLenum err = glGetError(); \
while (err != GL_NO_ERROR) { \
printf("glError: %s caught at %s:%u", \
(char*)gluErrorString(err), __FILE__, __LINE__); \
err = glGetError(); \
exit(-1); \
} \
}
// globals
int initialized = 0;
int width=640;
int height=480;
GLfloat wf,hf;
//uniform names
GLchar* names[] =
{
"SurfaceColor",
"WarmColor",
"CoolColor",
"DiffuseWarm",
"DiffuseCool"
};
GLuint buffer_id, uniformBlockIndex, index, vshad_id, fshad_id, prog_id;
GLsizei uniformBlockSize;
GLint singleSize, offset;
GLfloat colors[] =
{
0.45,0.45,1,1,
0.45,0.45,1,1,
0.75,0.75,0.75,1,
0.0,0.0,1.0,1,
0.0,1.0,0.0,1,
};
void reshape(int w, int h) {
width = w; height = h;
wf = (GLfloat) width;
hf = (GLfloat) height;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, wf/hf, 0.1, 100.0);
}
void init_opengl()
{
reshape(width, height);
//load_shader and link_program are utility functions omitted here
vshad_id = load_shader(GL_VERTEX_SHADER, "gooch.vs");
fshad_id = load_shader(GL_FRAGMENT_SHADER, "gooch.fs");
prog_id = glCreateProgram();
glAttachShader(prog_id, vshad_id);
glAttachShader(prog_id, fshad_id);
link_program(prog_id);
//Update the uniforms using ARB_uniform_buffer_object
glGenBuffers(1, &buffer_id);
//There's only one uniform block here, the 'colors0' uniform block.
//It contains the color info for the gooch shader.
uniformBlockIndex = glGetUniformBlockIndex(prog_id, "colors0");
//We need to get the uniform block's size in order to back it with the
//appropriate buffer
glGetActiveUniformBlockiv(prog_id, uniformBlockIndex,
GL_UNIFORM_BLOCK_DATA_SIZE,
&uniformBlockSize);
glError();
//Create UBO.
glBindBuffer(GL_UNIFORM_BUFFER, buffer_id);
glBufferData(GL_UNIFORM_BUFFER, uniformBlockSize,
NULL, GL_DYNAMIC_DRAW);
//Now we attach the buffer to UBO binding point 0...
glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer_id);
//And associate the uniform block to this binding point.
glUniformBlockBinding(prog_id, uniformBlockIndex, 0);
glError();
//To update a single uniform in a uniform block, we need to get its
//offset into the buffer.
glGetUniformIndices(prog_id, 1, &names[2], &index);
glGetActiveUniformsiv(prog_id, 1, &index,
GL_UNIFORM_OFFSET, &offset);
glGetActiveUniformsiv(prog_id, 1, &index,
GL_UNIFORM_SIZE, &singleSize);
glError();
glViewport(0, 0, width, height);
}
void render()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
glUseProgram(prog_id);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -4);
glColor3f(1.0, 1.0, 1.0);
glBindBuffer(GL_UNIFORM_BUFFER, buffer_id);
//We can use BufferData to upload our data to the shader,
//since we know it's in the std140 layout
glBufferData(GL_UNIFORM_BUFFER, 80, colors, GL_DYNAMIC_DRAW);
//With a non-standard layout, we'd use BufferSubData for each uniform.
glBufferSubData(GL_UNIFORM_BUFFER, offset, singleSize, &colors[8]);
//the teapot winds backwards
glFrontFace(GL_CW);
glutSolidTeapot(1.33);
glFrontFace(GL_CCW);
glutSwapBuffers();
}
void display()
{
if(!initialized)
{
init_opengl();
initialized = 1;
}
render();
}
int main (int argc, const char** argv) {
//GLUT initialization goes here
}
// Vertex shader for Gooch shading
// Author: Randi Rost
// Copyright (c) 2002-2006 3Dlabs Inc. Ltd.
// See 3Dlabs-License.txt for license information
vec3 LightPosition = vec3(0.0, 10.0, 4.0);
varying float NdotL;
varying vec3 ReflectVec;
varying vec3 ViewVec;
void main(void)
{
vec3 ecPos = vec3 (gl_ModelViewMatrix * gl_Vertex);
vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);
vec3 lightVec = normalize(LightPosition - ecPos);
ReflectVec = normalize(reflect(-lightVec, tnorm));
ViewVec = normalize(-ecPos);
NdotL = (dot(lightVec, tnorm) + 1.0) * 0.5;
gl_Position = ftransform();
}
// Fragment shader for Gooch shading, adapted for ARB_uniform_buffer_object
#extension GL_ARB_uniform_buffer_object : enable
layout(std140) uniform colors0
{
float DiffuseCool;
float DiffuseWarm;
vec3 SurfaceColor;
vec3 WarmColor;
vec3 CoolColor;
};
varying float NdotL;
varying vec3 ReflectVec;
varying vec3 ViewVec;
void main (void)
{
vec3 kcool = min(CoolColor + DiffuseCool * SurfaceColor, 1.0);
vec3 kwarm = min(WarmColor + DiffuseWarm * SurfaceColor, 1.0);
vec3 kfinal = mix(kcool, kwarm, NdotL);
vec3 nreflect = normalize(ReflectVec);
vec3 nview = normalize(ViewVec);
float spec = max(dot(nreflect, nview), 0.0);
spec = pow(spec, 32.0);
gl_FragColor = vec4 (min(kfinal + spec, 1.0), 1.0);
}
Examples
The following example illustrates the rules specified by the "std140"
layout.
layout(std140) uniform Example {
// Base types below consume 4 basic machine units
//
// base base align
// rule align off. off. bytes used
// ---- ------ ---- ---- -----------------------
float a; // 1 4 0 0 0..3
vec2 b; // 2 8 4 8 8..15
vec3 c; // 3 16 16 16 16..27
struct { // 9 16 28 32 (align begin)
int d; // 1 4 32 32 32..35
bvec2 e; // 2 8 36 40 40..47
} f; // 9 16 48 48 (pad end)
float g; // 1 4 48 48 48..51
float h[2]; // 4 16 52 64 64..67 (h[0])
// 80 80..83 (h[1])
// 4 16 84 96 (pad end of h)
mat2x3 i; // 5/4 16 96 96 96..107 (i, column 0)
// 112 112..123 (i, column 1)
// 5/4 16 124 128 (pad end of i)
struct { // 10 16 128 128 (align begin)
uvec3 j; // 3 16 128 128 128..139 (o[0].j)
vec2 k; // 2 8 140 144 144..151 (o[0].k)
float l[2]; // 4 16 152 160 160..163 (o[0].l[0])
// 176 176..179 (o[0].l[1])
// 4 16 180 192 (pad end of o[0].l)
vec2 m; // 2 8 192 192 192..199 (o[0].m)
mat3 n[2]; // 6/4 16 200 208 208..219 (o[0].n[0], column 0)
// 224 224..235 (o[0].n[0], column 1)
// 240 240..251 (o[0].n[0], column 2)
// 256 256..267 (o[0].n[1], column 0)
// 272 272..283 (o[0].n[1], column 1)
// 288 288..299 (o[0].n[1], column 2)
// 6/4 16 300 304 (pad end of o[0].n)
// 9 16 304 304 (pad end of o[0])
// 3 16 304 304 304..315 (o[1].j)
// 2 8 316 320 320..327 (o[1].k)
// 4 16 328 336 336..347 (o[1].l[0])
// 352 352..355 (o[1].l[1])
// 4 16 356 368 (pad end of o[1].l)
// 2 8 368 368 368..375 (o[1].m)
// 6/4 16 376 384 384..395 (o[1].n[0], column 0)
// 400 400..411 (o[1].n[0], column 1)
// 416 416..427 (o[1].n[0], column 2)
// 432 432..443 (o[1].n[1], column 0)
// 448 448..459 (o[1].n[1], column 1)
// 464 464..475 (o[1].n[1], column 2)
// 6/4 16 476 480 (pad end of o[1].n)
// 9 16 480 480 (pad end of o[1])
} o[2];
};
Issues
(1) How are offsets to elements in a uniform buffer correlated to
uniform locations?
Resolved: Traditional uniform locations were used in the glUniform
API to access the private uniform storage. This API does not allow
the use of glUniform to update uniforms stored in uniform blocks.
Instead it uses the various means to update buffer objects, and
exposes the byte offsets of the uniforms in the buffer object. So,
in short, uniform locations and uniform offsets are similar concepts
but unrelated.
(2) Should uniforms declared bindable be excluded from a uniform
buffer?
Resolved: No, however, if a bindable uniform is declared inside
a named uniform uniform block, the bindable declaration and all
associated behavior of the bindable uniform extension will be
superceded by the mechanisms defined in this extension to obtain
information about the location of uniforms and to update the values
of those uniforms.
In other words, if the bindable modifier is used on a uniform declared
within a named uniform block, it will be ignored.
(3) Are there restrictions on the data types or the order in which uniforms
are declared that are to be included as part of the uniform buffer?
Resolved: The only restriction is that sampler uniforms can not be
stored in a uniform buffer object. All other uniform types can be
stored in a uniform block.
(4) Should a uniform buffer be split into multiple uniform buffers
on a per data type basis to simplify the buffer offset interface ?
Resolved: No. This violates the intended "generic data store"
convention of buffer objects. Users of this extension are free
to group their uniform definitions on a per data-type basis in
this manner and, indeed, it may, on some implementations, result
in a more efficient uniform update model.
(5) Should uniform buffers be scoped per shader (program
stage) rather than per program (as in GLSL) ?
Resolved: No, this extension does not change the per-program
scope of uniforms. Uniforms in a uniform block, like traditional
GLSL uniforms, are global to a program object.
It's tricky because allowing uniforms to have per-stage scope
exposes both a feature and the possibility for an application
programming error.
feature: an application that wants to use a uniform "foo" in two
stages and wants uniform "foo" has different layouts
and/or values in each stage (or possibly simply does not
care if they do)
vs.
error: an application that wants to use a uniform "foo" in two
stages and does not want them to have different values, but
*accidentally* defines "foo" in each stage differently or
binds different uniform buffers to each stage.
Rather than enable this feature (and simultaneously add possibility
for error) in this extension, we defer the choice to a future
extension.
Note however, some of the motivation for a per-stage scope for
uniform names comes from a broader desire to augment the GLSL API
with a set of per-stage program objects that do not need to be
linked at all. This is possibly a valuable addition to the GL API,
but is left to be defined by an additional extension. Such a future
extension could, if desired, add syntax to the GLSL to allow any
uniform (uniform block or default) to be defined with "per-stage" scope
in a more comprehensive way.
(6) Should AttachUniformBuffer take a <program> argument?
This issue is moot. Earlier versions of this extension included
the additional ability to attach a uniform buffer object directly
to a progam's uniform blocks instead of going through the per-context
uniform buffer binding points.
This feature has been deferred, possibly to be added in a future
extension.
If this routine were to be added and does not take a program
argument, then it should work on the currently bound program
object, and its name should be changed to
ProgramUniformBuffer, to conform to precedent set by
FramebufferTexture, et. all.
Alternately, if AttachUniformBuffer requires a program
argument, it would be for consistency with existing C API to
GLSL (i.e., those that attach shaders to program objects and
query program objects for information).
RESOLUTION: RESOLVED, moot.
(7) Should uniforms in a uniform block be identified by location or
string?
Resolved: By string and also by index (but not location). Name
strings will be used to identify uniforms much as they are
today. Uniform indices were available before for referring to
uniforms because they provide a more efficient update mechanism
to specify uniforms. Uniform block indices have been used in
this extension for the same reason.
The location API not used by this extension and is only relevant for
the glUniform* API.
RESOLUTION: RESOLVED, moot.
(8) What is the order of operations under which a uniform buffer
association is made with a program (or shader)?
It is known that at very least, that the uniform buffer
offsets and strides will be known at link time. Does the
uniform buffer need to be attached to the program prior to linking in
order to keep these offsets constant or can a uniform buffer be
bound to a program at any time post-link effectively acting as
substitute storage for the uniform data?
RESOLVED: Uniform buffer objects are bound to the context's
uniform buffer binding points, and this can happen at any time.
However, the association of a program's uniform block to the context's
uniform buffer binding points can only happen after linking because only
then are uniform block indices known.
(9) Can the existing Uniform API be used to update values in a
uniform buffer?
Resolved: No. The Uniform* API won't update values in a uniform buffer,
which is reinforced by the fact that uniform block uniforms do not have
a location.
(10) When is the size of a uniform block's storage known?
Resolved: Only after linking.
Once a program is linked, the storage needed for a given uniform
block can be determined by querying for
UNIFORM_BLOCK_DATA_SIZE.
If a uniform block needs more storage than the buffer object
bound to the associated uniform buffer binding point can provide,
results are undefined. This is no different than fetching off the end
of an array.
(11) Is it an error to call AttachUniformBuffer prior to
linking the program designated by <program>?
Resolved. This issue is moot because the
AttachUniformBuffer was removed/deferred to a future
extension.
But if this API were added, then yes. INVALID_VALUE is generated
if AttachUniformBuffer is used to attach a buffer to an
invalid uniform block index. Prior to linking, there are no
uniform block indices.
(12) Some hardware does not support some of the GLSL data types
natively (bools or ints perhaps). What limitations do we have in
exposing the raw uniform data storage via the buffer object API ?
Resolved: None, but note that some implementations without
native support for these data types may have to copy the data
in these data types into some more native data types.
Also, queries are provided to expose the layout of the buffer
objects to allow the buffers to be packed properly.
(13) Are there expected limitations for dead uniform elimination
using this extension?
Resolved: yes.
For starters, when using the "std140" layout, an implementation
may not alter the storage layout in any way. This limitation
includes dead uniform elimination. The standard layout must
remain unchanged because an application will depend on it
rather than querying for uniform offsets/strides.
When using the "shared" layout, dead uniform elimination is again
excluded because different uniforms could be eliminated based on
different shaders' uniform usage. In order to preserve shareability
of the uniform blocks, the full contingent of uniforms must remain.
For the "packed" layout, an implementation may take the liberty of
eliminating uniforms and uniform blocks that are not used by the paired
shaders. Here, limitations exist only for arrays. Dead elements may be
stripped from the end of an array that is never dynamically
dereferenced. An application must query UNIFORM_SIZE before
loading array data into the uniform buffer to ensure that trailing
elements exist.
Issue (24) deals with stripping leading elements from an array, and
issue (25) deals with stripping arbitrary elements from an array,
both of which are currently disallowed.
Note that the default uniform block always exists even if it is empty.
(14) Is it necessary to provide array uniform element offsets into
a uniform buffer object? If so, this suggests string parsing
of things such as "myuniform[12]". If not, this assumes array
strides be guaranteed based on array data type for all hw platforms?
Resolved: No. The stride is provided explictly by querying
UNIFORM_ARRAY_STRIDE with GetActiveUniformsiv.
(15) How are the values from static initializer values propagated
to a buffer object once it is attached?
Resolved: Static initialization values declared in a shader mapped
to a uniform buffer are disallowed by the grammar and must be
established through writes to the uniform buffer.
(16) Is GetUniformBlockIndex needed? This information can be
obtained (in reverse mapping) from GetActiveUniformBlock.
Resolved: Yes. GetUniformBlockIndex allows the uniform
block database to be queried in the most natural manner: step 1)
do the expensive conversion from a uniform block name to a
uniform block index, step 2) use the uniform block index to
obtain all other uniform block data, which is a simple array
dereference, not a search.
(17) is GetUniformIndex needed? This information can be obtained (in
reverse mapping) from GetActiveUniform.
Resolved: Yes. See issue (16).
(18) Should we add a separate function GetActiveUniformBlockBufferSize
instead of using GetActiveUniformBlock to return everything.
Resolved: No. This issue became moot when the more general function
GetActiveUniformBlockiv was added.
(19) Should we provide a mechanism for iterating over the uniforms in a
particular uniform block?
Resolved: Yes. This is provided by querying
UNIFORM_BLOCK_ACTIVE_UNIFORMS with GetActiveUniformBlockiv.
(20) Should we provide a means for the application to query the desired
storage format for integers, booleans, and matrices, or should we specify
a format and force non-conforming implementations to do a conversion?
RESOLUTION: No queries will be introduced. Implementations that cannot
handle the prescribed storage formats must convert as necessary.
See also issue (48)
(21) Should we delete the integer and boolean storage types in favor of
implementation repacking of the data when the hardware doesn't support it?
RESOLUTION: RESOLVED, no.
Hardware that doesn't support the types must repack the uniform data
if needed. This is true for all layout options.
(22) How does the program notice new changes to the uniform buffer object?
Should we add a new "UpdateUniforms()" call or use
AttachUniformBuffer(), or UseProgram() to realize changes.
RESOLUTION: Following the "standard" way in which object changes are
noticed, the buffer object in question must be re-bound or
re-attached if the changes to the buffer object come from another
context.
If the changes come from this context, then the intent is to
follow the general object model decision here that governs how
child/container object state changes are made.
[Currently, this means that changes by this context will be
noticed at next draw time, at the latest].
(23) The naming convention choosen for GetActiveUniformsiv and
GetActivePartitionsiv is not a simple matter.
First, considering that the list of uniforms passed into these
routines must be active uniform indices, and is an error if not,
suggests that the name "Active" in these function calls is
redundant. GLSL established a precedent of using "Active" in
the names of functions that require their uniform parameters to
consist solely of active uniforms. For these routines, it is an
error to include an inactive uniform as one of their input
parameters. Consistency with this GLSL precedent is the reason
we've choosen to include "Active" in these routine names.
Second, note that GetActiveUniformsiv does not "get active
uniforms" and GetActiveUniformBlocksiv does not "get active
uniform blocks". There is a compelling argument therefore that
these names are counterintuitive. In reality, these routines
return parameters of active uniforms and active uniform blocks
rather than the uniforms or uniform blocks themselves. Again,
looking back at GLSL precedent note the conventions used for
both GetProgramiv and GetShaderiv. Both of these routines have
a <pname> argument and both of these routines are in fact
returning parameters of programs and shaders respectively
however "Parameters" was not included in the name.
Further challenging this second point are two other
considerations. First, the GL spec prior to GLSL does in fact
use "Parameters" in the name of functions that match this
pattern. Second, this spec itself includes the name of the
output parameter in the name (specifically calls to get Indices
and Names).
In the end, because this specification has to work within the
GLSL framework, it was decided that this precendent should
prevail over all others. Therefore, these routines will not
include "Parameters" in their names.
Resolved: See above.
(24) Do we need to be able to query UNIFORM_START to get the index of
the first active element of an array?
An application must query UNIFORM_SIZE to find the extent of an
array at runtime because the GLSL compiler may have eliminated elements
from the end of a static array during dead code elimination. If the
application is not required to similarly query UNIFORM_START, the
compiler must be prevented from eliminating elements from the start of
an array.
For example, if an application declares "uniform float myFloat[10];" and
accesses only the single element myFloat[7] in the shader text, the
compiler may eliminate elements 8-9 only. Querying UNIFORM_SIZE
will give 8, and UNIFORM_OFFSET will give the offset of element 0.
If we add UNIFORM_START, in this example, querying
UNIFORM_SIZE will give 1, UNIFORM_START will give 7, and
UNIFORM_OFFSET will give the offset of element 7 in the uniform
buffer.
Purely for symmetry, it seems that the compiler should be as free to
strip leading elements as it is to strip trailing elements.
After additional discussions, however, the working group decided
not to introduce this complexity. This feature could be layered
as an additional extension if desired.
RESOLUTION: RESOLVED
(25) Following issue (24), should we provide a mechanism to allow the
compiler to strip *any* dead elements from a uniform array without
restriction, not just leading and trailing elements?
Resolved: No. Too cumbersome for the application to use.
(26) Should we make any guarantees about the ordering of uniforms in the
active uniform array, relative to their uniform block number?
It might be useful to guarantee that the ordering of the
uniforms in the active uniform array is such that all uniforms
in a single uniform block form a contiguous subrange of the
active uniform array.
On the other hand, just knowing the order is probably not enough
since you need to know offsets/strides, packing, etc.
This extension provides uniform block-based uniform updates.
This level of organization is efficient and requires no further
augmentation as this issue suggests.
RESOLUTION: RESOLVED, no
(27) What is the difference between
MAX_LOGICAL_UNIFORM_BUFFERS and
MAX_COMBINED_UNIFORM_BUFFERS?
MAX_LOGICAL_UNIFORM_BUFFERS is the maximum number of
uniform buffer binding points on the context.
MAX_COMBINED_UNIFORM_BUFFERS is the maximum number of
uniform buffers that any one program can use at one time.
Note, see issue (46) for a related issue with textures.
RESOLUTION: RESOLVED
(28) Should we have versions of GetActiveUniforms and GetActiveUniformBlocks
that return intptr types so a cast is not required.
No. Another extension can add them, and they have no real
utility at this time except causing the app to allocate twice as much
storage to store values that can't exceed 32 bits.
RESOLUTION: RESOLVED, No.
(29) Transform feedback writes primitive information to a buffer object
tightly arranged and in accordance with the size of the attributes
designated for transform feedback (or varyings thereof). If uniform
buffers are to leverage data supplied from the transform feedback
operation, yet uniforms are not guaranteed to be tightly packed, how
can one reasonably use transform feedback to populate uniform
buffers?
DISCUSSION: As it stands, existing implementations pack uniform
definitions on 16 byte boundaries, 4 byte boundaries or are tightly
packed. If this is known for a given implementation, uniform
declarations could of course be made such that they lined up on these
boundaries. However, without a dedicated queryable interface in the GL
C API, there is no way to guarantee the portability of this logic.
RESOLUTION: resolved, compatibility with XFB output is only guaranteed
for vec4 types in a "std140" layout uniform block:
In order to facilitate the read-only nature of uniform and
transform feedback data formatting, we've added to this
specification a uniform buffer "std140" layout qualifier guarantee of
vec4 types being tightly packed. This layout guarantee will provide
portability of applications that wish to use transform feedback in
conjunction with uniform buffers as they can simply rely on this
data arrangement, declaring their uniforms accordingly, to allow
ARB_uniform_buffer_object and EXT_transform_feedback to
interoperate.
(30) Should the "active" keyword in shader text be declared per uniform or
per uniform block ?
Note, this issue is mostly moot, as we've decided to use a
different syntax in the GLSL. Earlier versions of this spec
leveraged the concept of 'active' uniforms from GLSL that were
defined with the initial GLSL API.
The discussion that follows pertains to a feature where the user can
declare uniforms and uniform blocks as active explicitly.
DISCUSSION: Declaring a uniform active has the advantages of simplicity
and little additional spec language to describe behavior. When a
uniform is declared active, all of its members are considered active
(for structs and arrays) and therefore the arrangement of the data in
that uniform can be guaranteed to be consistent. Consistency of this
uniform data arrangement can be used to share the uniform across muliple
programs without worrying about dead code elimination changing the
offsets and strides of uniform data.
Declaring uniform blocks active has some of the advantages that were
primary motivating factors for this specficiation being written.
Namely, that uniforms did not have to be aggregated into structures in
order to update them efficiently. In this case, uniforms don't have to
be aggregated into structs in order to share them easily. Another
advantage is the logical distinction of a group of shared uniforms that
is analogous to how the uniform buffer object, also a shared entity,
that backs them.
If a uniform uniform block is declared active, all uniforms therein are
considered active. It is presumed under this model, that an advisable
usage pattern would be to gather the declaration of shared uniforms of
multiple shaders into an atomic shader source call. Then each
individual shader would carry declarations of uniforms unique to
themselves.
GLSL allows piecewise declaration of uniforms in multiple modules in a
program. Piecewise declaration of shared uniform blocks carries with it
some difficulties because missing pieces can change the layout of the
uniform block.
A) Should we disallow piecewise construction of uniform blocks
declared active by setting a compile time error if this is
attempted ?
RESOLVED: Yes, piecewise construction of uniform blocks will be
allowed.
Proposal for active uniform block demarcation:
Active uniform blocks are declared as followed:
active uniform block foo;
uniform <type> a;
uniform <type> b;
uniform <type> c;
uniform block;
The first uniform block delimiter names the uniform block. The second
uniform block, with no name argument, terminates the "foo" uniform block
and indicates that any subsequent uniform definition will be part of the
default uniform block.
Subsequent declarations referring to uniform block "foo" augment the
contents of the uniform block. These subsequent declarations, of
course, can appear within the same shader or within other shader sources
in the same program.
This aggregation mechanism, and the use of piece-wise definitions of
uniform blocks, has sharing implications.
Considering the following example:
*****************************
PROGRAM A Text:
active uniform block foo;
uniform <type> a;
uniform <type> b;
uniform block;
*****************************
PROGRAM B Text:
active uniform block foo;
uniform <type> b;
uniform <type> a;
uniform block;
... some place later in the program text
active uniform block foo;
uniform <type> e;
uniform <type> d;
uniform block;
*****************************
Both the order and the number of uniforms in the aggregate definition of
'foo' in program B must be considered for sharing the uniform buffer
backing A & B corresponding to uniform block 'foo'.
First, order. To avoid potential confusion with order of declarations
of uniforms, all uniforms declared in a uniform block will be sorted in
an implementation defined manner. By doing so, the implementation will
allow sharing of uniform buffers with identical uniform declarations by
name, type and number, but arranged in different orders.
Second, mismatches in declarations of uniforms within 'foo' between two
different programs. Because uniforms are sorted, partial matches of
uniform declarations within uniform blocks are not guaranteed to have
the same offsets when the buffer is bound to different programs. In our
example, there are no guarantees that the offset of uniform 'a' and the
offset of uniform 'b' would be the same in uniform block foo of program
'A' when compared to program 'B'. Applications must therefore use care
when attempting to share uniform buffers between multiple programs
because any mismatch in uniform name or type or the number of uniforms
themselves between uniform block declarations will result in offsets
without correlation and application errors should be expected if any
assumptions about these offsets is made otherwise.
This sharing behavior if of particular significance when defining
shaders as it suggests that the shaders themselves, if they choose to
define uniform blocks piecewise across given program text. This sharing
model suggests defining all uniform uniform blocks that are expected to
be shared as standalone shader text definitions to logically segragate
them from uniform block declarations that can be changed in a piecewise
fashion. In this manner, the logically separated shared uniform uniform
block can be handled as a distinct ShaderSource call and effectively act
as a header file where the uniform block definition is guaranteed to be
the same when used in multiple programs thus allowing sharing and
consistent offsets.
RESOLUTION: RESOLVED
Partitions, uniforms, and varyings can all have the "active" keyword
applied to them. See rules q - t in the rules and concepts list
following the opening summary to this spec.
The resolution of issue (34) to use struct-like syntax for uniform block
definition closes the issue on piecewise definition of uniform blocks
discussed above.
(31) ActiveVaryingNV() uses the GL C API to declare a varying active in
contrast to declaring uniforms/uniform uniform blocks active as suggested in
this specification. Is this inconsistency a concern ?
RESOLUTION: RESOLVED, moot.
Earlier versions of this spec declared uniforms and uniform blocks
as active, and optionally extended this to varyings as well.
Later versions of this spec deferred this concept out of the extension.
The declaring a varying as active via function call requires
that this call is made prior to link time and that it identifies
the varying using a name string. It is more efficient to manage
program resources using indices and is better in terms of
locality of reference to make 'active' declarations in program
text. We should consider whether we might want to add this back
in in a future extension.
(32) GetVaryingLocationNV() returns -1 if the designated name doesn't
exist. Should we return -1 rather than a special purposed token if a
uniform name doesn't exist to follow this precedent ?
RESOLUTION: RESOLVED
This specification uses indices which are unsigned integers and
therefore our unsigned value of 0xFFFFFFFF is not called "-1"
but acts effectively the same on platforms where GLint is
32-bit twos-complement.
Also note, uniform (and varying locations) are signed which
allows them to use -1 as a signifier, but uniform (and uniform
block) indices are unsigned because they are used to iterate
through uniforms (and uniform blocks).
(33) Which uniform buffer object commands must be excluded from display
lists?
RESOLUTION: Resolved
When used with 3.1 (where display lists have been removed
altogether) obviously, this question is moot.
For GL 2.0/3.0, this should be resolved with the following
precedents:
BindUniformBlock should follow the precedent of BindBufferRange,
which does not get included in display lists.
UniformBlockBinding should follow the precedent of glUniform (for
setting samplers) which *does* get included in display lists.
Note, the GL 2.1 spec says (p.244, section 5.4) that "GL
commands that source data from buffer objects dereference the
buffer object data in question at display list compile time,
rather than encoding the buffer ID and buffer offset into the
display list. Only GL commands that are executed immediately,
rather than being compiled into a display list, are permitted to
use a buffer object as a data sink."
The same rules would affect uniform blocks sourcing data from
buffer objects.
So this basically means that only BindUniformBlock is excluded,
(since all queries are already excluded), however see issue (55).
Since we use the BindBufferRange API introduced by OpenGL 3.0, and
those routines are already excluded, there's no additions to the
display list exclusion list needed.
(34) What should the syntax of uniform block demarcation be ?
DISCUSSION: The two following syntaxes were considered:
uniform block foo;
uniform <type> a;
uniform <type> b;
uniform block;
In this example, the "uniform block" keyword both opens and closes the
uniform block.
Second, a struct-like syntax:
uniform myUniformBlock
{
int a;
vec4 b;
};
and
packed uniform myUniformBlock
{
int a;
vec4 b;
};
where "packed" means that the uniform block might be optimized by the
compiler to eliminate/re-order uniforms.
This is functionally equivalent to the current uniform block
syntax in this spec.
RESOLUTION: RESOLVED, using the "struct-like" syntax above.
(35) Should UBOs be bound to context binding points rather than to
programs themselves ?
DISCUSSION:
Attaching UBOs to programs versus the context has the following
advantages:
UBOs and programs have natural encapsulation boundaries that
fit with the conventions of object-oriented design
programming.
Alternately, binding UBOs to the context has the following advantages:
Migration to the possible program environment object design
expected in future versions of OpenGL will be handled more
easily and won't require a semantics change because these
context bindings will all be moved collectively to the PEO
and UBO attachments will not have to be handled as a
"special case" item.
If we support per-context per-stage bindings, then we'll need the
following additions to this extension:
- a set number of binding points on the context for each stage
(vertex/fragment/geometry)
VERTEX_SHADER_BINDING_0..n
GEOMETRY_SHADER_BINDING_0..n
FRAGMENT_SHADER_BINDING_0..n
or alternately, a unified set of per context bindings
SHADER_BINDING_0..n
- a new routine to bind a UBO to a per-stage context binding point
BindUniformBuffer(enum target, uint uniformBlockIndex,
uint buffer);
- a new routine that defines the mapping of a uniform block name
string to a per-stage binding point index
void UniformBlockBinding(uint program, uint unit,
const char* name);
RESOLUTION: RESOLVED,
Note per-context and per-program bindings serve two distinct use cases.
Per-context: assumes that there is generally many to one mapping
between programs and given set of uniform buffers.
Per-program: assumes that there is a one to one mapping between
programs and a given set of uniform buffers.
The original ARB "assembly-language" programming extensions serviced
both use cases (with "program locals" and "program environment"
parameters).
The GLSL programming API dropped the "program environment" /
per-context storage of uniforms in favor of per-program only storage
for uniforms.
This API currently supports only the context binding model, but
a future extension could add the per-program-object bindings if
desired.
(36) How is the query for MAX_{FRAGMENT|VERTEX}_UNIFORM_COMPONENTS
affected by UBOs?
DISCUSSION: MAX_{FRAGMENT|VERTEX}_UNIFORM_COMPONENTS traditionally
referred to the limited amount of dedicated (often register based,
sometimes per-stage) uniform storage. For implementations that
support directly reading uniforms from arbitrary memory, the limit
on uniform storage is generally not quantified by a single number of
uniforms. Instead it is quantified by two numbers: the number of
separate buffers that can be read at one time (per stage), and the
sizes of one of those buffers.
On the other hand for implementations that wish to support this
extension but that still have this limited amount of dedicated
uniform storage this single MAX_{FRAGMENT|VERTEX}_UNIFORM_COMPONENTS
value is still valid.
RESOLUTION: Resolved, as follows:
We added a new set of integer implementation-dependent queries, named
MAX_COMBINED_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_COMPONENTS. These
would indicate the maximum total number of uniforms available between
the default uniform block and all uniform blocks. For this ARB version
of the extension, the minimum maximum would be
MAX_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_COMPONENTS. For the 3.1 core
version, the minimum maximum would be larger:
MAX_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_BLOCKS * MAX_UNIFORM_BLOCK_SIZE +
MAX_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_COMPONENTS.
(37) Do we need MAX_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_BUFFERS
or can we merge these into a single value MAX_UNIFORM_BUFFERS that
is the same for the 3 stages?
DISCUSSION:
3 separate queries is needed only if we think implementations would have
different values for each stage.
RESOLUTION: currently 3 queries, plus a "combined" query.
(38) What's the deal with UniformBlockBinding()? How does it
work? What is it for?
DISCUSSION:
UniformBlockBinding can be defined in two different ways, depending on
the precedent we'd like to use.
It can either be similar to a uniform sampler (i.e., an indirection
table that can choose a particular buffer to use after linking), or
an attribute location (i.e., an indirection table that can choose a
particular buffer to use PRIOR to linking).
The current API chooses the former precedent (i.e., uniform
samplers), and as a result, UniformBlockBinding can be called (in
fact, must be called) after linking the program.
If we desired to change this behavior, we'd need to modify
UniformBlockBinding to take a uniform block *name* intead of *index*,
because a uniform block index is only defined post-link.
This is workable, but slightly less flexible for the developer, at
the cost of an indirection.
RESOLUTION: Use the "sampler" precedent, UniformBlockBinding is
called post link.
(39) Does the matrix packing need to be "per program" state or "per
implementation" state?
DISCUSSION:
Is the choice of matrix packing really "per program"? If not,
should we just use the per-context queries for this information? The
former might be useful if we intend to expose some kind of
per-program packing control in the shading language or API. If we
don't, then the latter might be simpler.
Or do we think we might go further and make this per-uniform state
in the future? if so, then the current per-program query is also
insufficient.
After discussion with the working group, queries for
matrix (and all other uniform layout) will be per-uniform, not
per program, so these routines have been removed.
RESOLUTION: Resolved, this issue is moot.
(40) Are uniform block indices assumed to be "tightly packed"?
Yes, an implementation will assign consecutive indices to
active uniform blocks, starting with zero.
Note that there is no prescribed ordering in which indices must be
assigned. In other words, which uniform block indices are assigned to
which uniform blocks is an implementation choice. An application must
call GetUniformBlockIndex to find the mapping.
RESOLUTION: Resolved, yes.
(41) Is "uniform block" the right name?
The GLSL group considered many names here: "uniform blocks",
"commons", "uniform groups", etc. Regardless of what the GLSL
calls these groupings, we need *some name* that we can describe
in the API spec and in the API names. Currently we use "uniform
block" for this, and the API seems to make sense, but could
change if someone has a better name.
RESOLUTION: RESOLVED, yes.
(42) Should there be an "offset" for the base of the ubo so that an
application can use collections uniforms within a buffer object?
DISCUSSION:
If we do this, we'd need an additional/augmented version of
BindUniformBuffer that takes an offset, and a queriable required
alignment for the offset. See also issue 55.
Currently, we do now support this offset (via BindBufferRange) and an
alignment query (UNIFORM_BUFFER_OFFSET_ALIGNMENT). The offset
is per-context binding point state. We probably want to pick up
UNIFORM_BUFFER_START and UNIFORM_BUFFER_SIZE queries, too. See issue
(65) to track whether we add these.
RESOLUTION: Resolved, there should be an offset for the base of a
uniform block within a UBO. If an implementation can not support
non-zero offsets, they can set UNIFORM_BUFFER_OFFSET_ALIGNMENT
to a sufficiently large value.
(43) Do we need the versions of the uniform queries that query the
GL for the properties/names of multiple uniforms at one time? Or
can we simplify those apis to only query for the property/name of
one uniform at a time?
DISCUSSION: The multiquery apis are useful for getting lists of
uniform data at once, but are more complicated (require arrays of
pointers to output values).
Do we need these?
RESOLUTION: Resolved, we'll replace GetActiveUniformNames with
GetActiveUniformName, but keep the rest which have solid use
cases.
(44) What is the default value for UNIFORM_BLOCK_BINDING?
Having the default values be set equal to the uniform block index at
link time would be convenient. This would make it unnecessary
for apps to call glUniformBlockBinding unless they wanted a
non-default mapping.
After some discussion, using texture samplers as precedent, then
the default value should be zero.
RESOLUTION. Resolved, default value is zero.
(45) What is the default value of UNIFORM_BLOCK_BUFFER_BINDING?
This is moot without the AttachUniformBuffer API. This was the
query for the uniform buffer object bound directly to a uniform
block in the program object.
If we add this API in a future extension, it seems it should be
zero. We would need for the spec to state the precedence of
program attachments over context attachments. I.e., if the
value of UNIFORM_BLOCK_BUFFER_BINDING is non-zero, then
the backing for that uniform block comes from the specified
uniform block uniform buffer binding, otherwise it comes from
the unit binding, and hence from the context that is currently
using the program.
RESOLUTION. RESOLVED, moot.
(46) How do the logical/combined maximums for UBOs and textures
relate to each other?
Textures have these queries:
MAX_TEXTURE_IMAGE_UNITS
maximum textures that can be used by the fragment stage.
MAX_COMBINED_TEXTURE_IMAGE_UNITS
maximum textures that can be used by all program stages
at once.
Ideally, MAX_TEXTURE_IMAGE_UNITS would be called
"MAX_FRAGMENT_TEXTURE_IMAGE_UNITS"
Also, most implementations use MAX_TEXTURE_IMAGE_UNITS to define
the number of per-context binding points for textures, though
technically, there's no requirement that the number of context
binding points is equal to the number of fragment textures.
For instance, if an implementation had the ability to use more
vertex or geometry textures than fragment textures, then this
scheme would break down because there would not be enough
context binding points for these other stages.
This spec tries to avoid this problem with the following queries:
MAX_VERTEX_UNIFORM_BLOCKS
MAX_GEOMETRY_UNIFORM_BLOCKS
MAX_FRAGMENT_UNIFORM_BLOCKS
MAX_COMBINED_UNIFORM_BLOCKS (much like "combined" for textures)
MAX_UNIFORM_BUFFER_BINDINGS (# UBO binding points on context)
For symmetry, we'd recommend that we make a similar update to textures
in the 3.1 spec:
MAX_FRAGMENT_SAMPLERS (= old MAX_TEXTURE_IMAGE_UNITS)
MAX_GEOMETRY_SAMPLERS (= old MAX_GEOMETRY_TEXTURE_IMAGE_UNITS)
MAX_VERTEX_SAMPLERS (= old MAX_VERTEX_TEXTURE_IMAGE_UNITS)
MAX_COMBINED_SAMPLERS (= old MAX_COMBINED_TEXTURE_IMAGE_UNITS)
MAX_TEXTURE_IMAGE_BINDINGS (# texture binding points on context)
RESOLUTION: Resolved. The texture token name changes should be made
in the 3.1 API spec, deprecating the old names.
(47) Is using a keyword to specify packed/shared/std140 the best way
to manage uniform block packing? What do they mean anyway?
DISCUSSION:
There are 3 use cases of interest:
"packed"
- implementation may optimize the layout to remove inactive
uniforms and otherwise restructure the layout for
efficiency.
- application must query the GL for the uniform block layout
"shared"
- implementation may optimize the layout but must use the same
layout across shaders so that the resulting layout can be shared
by multiple shaders
- application must query the GL for the uniform block layout
"std140":
- implementation must use a pre-determined layout, defined
in this specification.
- application need not query the implementation for layout
information as it can be determined by reading the shader
and the specification
Other options considered included:
- an API in the GL
- a #pragma in the GLSL
- gcc style __attribute__ tokens
- others?
RESOLUTION: resolved, we use a layout qualifier construct which
includes identifiers for "packed", "std140", and "shared" which is the
intial default. These qualifiers can be used either within a uniform
block declaration, or at global scope causing subsequent uniform blocks
with unspecified layouts to adopt a new default layout.
(48) What is the "std140" packing layout?
This extension is supposed to define a standard packing layout
that applications can choose to use and know the uniform block
data layout within the uniform buffer without querying the
implementation.
The user would need to opt-in to this layout.
We need to define what this layout looks like.
See also issue (20).
RESOLUTION: resolved, standard layout is now in 2.15.3.1.2.
(49) Will storage of int/ivec*/uint/uvec*/float/vec* be guaranteed
to match the GLint, GLuint, and GLfloat types of the CPU's
implementation? What if the CPU and GPU differ? What about indirect
renderers?
See also issues (20) and (48)
RESOLVED: We've never figured out how to properly handle other buffer
object extensions (e.g., VBO) in conjunction with indirect rendering
with data type differences. This feature should continue that fine (?)
tradition.
Ignoring indirect rendering, if the native data types of the GLSL
executable's processor differs from the client's representation, data
should still be extracted from buffer objects using the client's
representation. Mechanisms that could be used to accomplish this
include:
* having the driver making a copy of the buffer object for internal use,
doing conversion during the copy;
* having the GLSL executable's processor automatically convert data
types as they are fetched; or
* generating code to be executed by the GLSL executable's processor to
manually perform data type conversions.
If dealing with data type mismatches turns out to be a problem on some
implementations, it might be possible to provide an extension where
applications to avoid conversion overhead by storing data using the
native data type of the GPU, instead of the CPU.
(50) This extension needs to be sanitized to be written against
the 2.1 and 3.0 core specs. What are the differences?
Aside from the sanity checking for using the right
section numbers and such, there are two other changes:
1) GetIntegeri_v doesn't exist in 2.0 so needs to be
added by this extension for the 2.0 version
2) The "max components" query needs different behavior
for a 2.1 vs. a 3.0/3.1 implementation. See issue (36)
RESOLUTION: Resolved, interactions section added which
details the differences when OpenGL 3.0 is supported.
Spec is written against OpenGL 2.1, so that's where the
section numbers come from.
(51) Do we need to name the default uniform block with index 0 and
name ""?
This is done for symmetry and to allow iterating through
all uniform blocks, including the default, and treat them
similarly.
On the other hand, it's a little weird since the default
partition can not be used with a buffer object. On the third hand,
maybe some day we will allow that.
As a side note, if we go with a name, should it be "", or
perhaps "gl_DefaultUniformBlock" or something like that.
RESOLUTION: Resolved, do not reserve block number 0 for the default
uniform block. The default uniform block no longer needs a name.
If the uniform block index is queried for a uniform that is associated
with the default uniform block, -1 is returned.
(52) The current extension spec seems to specify "uint" indices, but
the values in the queries such as GetActiveUniformBlockiv are
returned as "int" values. Should we fix this?
Need to double check the APIs to see if we'd have to duplicate
some or all of the queries to make them type safe for signed vs.
unsigned ints.
RESOLUTION: resolved, No. There are a few other places in the GL
query APIs that already suffer from this problem.
(53) What are the UNIFORM_BLOCK_REFERENCED_BY_*_SHADER queries used
for?
The total number of uniform blocks in each stage may be subject
to a per-stage limit on some implementations. These queries
allow the user to query the program's uniform blocks to see
which are used for each stage.
RESOLUTION: resolved
(54) How do the APIs that use uniform locations relate to the
uniforms in named uniform blocks? And how do the APIs
introduced by this extension relate to uniforms in the default
uniform block?
Basically, locations can't be used with uniforms in a uniform
block, so that rules out any queries that require locations.
However, the query APIs introduced by this extension can be used
with all uniforms, including those in a default uniform block.
RESOLUTION: resolved
(55) Should we use the BindBufferBase/BindBufferRange APIs that were
introduced in GL 3.0 instead of BindUniformBuffer?
As defined, they'd work fine.
One side issue: should the "offset" be part of the context binding?
or should the uniform blocks get to each select their own
offset within a single context binding?
If implementations can support the latter, it may allow
applications to get by with fewer context bindings.
If not, then we should replace BindUniformBuffer with
these routines, but for the 2.0 extension version we'd still
need to add those routines and duplicate their spec language
in this spec.
See issue 42 for the resolution of this side issue.
RESOLUTION: resolved, yes we should use BindBufferBase/Range.
(56) Can a mapping from uniform block to uniform buffer object be
queried?
On one hand, it seems like GetActiveUniformBlock could handle
it.
On the other hand, this linking is indirect: a uniform block
selects a binding point, and a binding point binds a UBO. The GL
*could* do the indirect lookup for you, but the data would only be
valid until you changed the unit binding, so it's a little fragile
for the implementation to provide this query.
RESOLUTION: Resolved, not needed, the user can do this.
(57) Should we have MAX_UNIFORM_BUFFER_SIZE or a max size on
uniform block data instead?
The uniform buffer could be larger than the amount of uniform
block(s) data inside it.
Also see issue (36).
RESOLUTION: Resolved, name is MAX_UNIFORM_BLOCK_SIZE.
(58) Is there any expectation that uniforms stay in the order
declared for the packed/shared layouts?
This might make sharing easier, but is not clear if it's
worth it / overly constraining.
RESOLUTION: resolved, yes, names/types must retain declaration order
(59) Do we need the glsl syntax for declaring arrays of uniform
blocks?
Deferred this feature to a future extension.
RESOLUTION, resolved
(60) When using this extension with OpenGL 2.1/3.0, do we require
that uniform buffer object names must be generated with glGenBuffers
to be used with these new entry points?
For OpenGL 3.1 core, there is a blanket requirement to call glGen
for object names.
For OpenGL 2.x, there is not a requirement to call glGen but in
3.0, user-generated names have been deprecated.
For 3.0, we added two new object types (FBO/VAO) that
required the user to call glGen, but existing object types
(textures/renderbuffers/buffer objects) could be used
without calling glGen.
We need to decide what to do with this when exporting
this extension on 2.1 and 3.0.
RESOLUTION: Resolved, this extension does not govern the creation of
buffer objects. That's done by BindBuffer, which is not altered
by this spec, so on 2.1 and 3.0 you'd be able to use any name,
whereas on 3.1 you'd be required to call GenBuffers.
(61) Do we need "instance name" syntax?
RESOLUTION: resolved, deferred for now
(62) Why don't the new tokens and entry points in this extension have
"ARB" suffixes like other ARB extensions?
RESOLVED: Unlike a normal ARB extension, this is a strict subset
of functionality already approved in OpenGL 3.1. This extension
exists only to support that functionality on older hardware that
cannot implement a full OpenGL 3.1 driver. Since there are no
possible behavior changes between the ARB extension and core
features, source code compatibility is improved by not using
suffixes on the extension.
(63) Should we introduce a query of a program's longest uniform name length,
similar to the ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH query of a
program's longest uniform block name?
RESOLUTION: Resolved, no. ACTIVE_UNIFORM_MAX_LENGTH serves this purpose
well enough. No great need for a per uniform block query of the same.
(64) What should the UNIFORM_OFFSET query return for uniforms that
are associated with the default uniform block? Same for strides?
RESOLUTION: Resolved, spec'd to return -1 in these cases.
(65) Should we add queries for the base offset and size of the uniform
buffer bound to a binding point? What should the names be?
DISCUSSION: This would be analogous to the similar transform feedback
queries. Names could be UNIFORM_BUFFER_START and UNIFORM_BUFFER_SIZE.
RESOLUTION: Resolved, yes.
(66) Should we provide some mechanism allow applications to annotate their
uniform declarations to specify an offset by hand? Direct3D 10 does. An
example of the D3D syntax:
cbuffer D3DExample {
float4 a : packoffset(c0); // bytes 0-15
float3 b : packoffset(c16); // bytes 256-267 (c0-c15 are all vec4s)
float1 c : packoffset(c1.y); // bytes 20-23
}
If so, how would we handle a mixed declaration that includes some
uniforms with annotations and others without?
RESOLVED: An annotation mechanism would be useful for fine-grained
application control, but we will defer this.
(67) Should we provide a mechanism to expose both row-major and column-major
storage of matrices?
If no controls are provided in GLSL 1.40, the default resolution for the
UBO layout documentation would be to treat all matrices as column-major.
We will also need to pick a default orientation for matrices with that
use no GLSL language mechanism to declare orientation.
Either way, the UBO GL API should provide a GetActiveUniform query to
determine if an active matrix is stored in row- or column-major order.
RECOMMENDATION: Provide a should have a type modifier for matrix
declarations, for example:
row_major mat4 matrix1;
column_major mat4 matrix2;
It may be desirable to have a global control (e.g., a #pragma) to
specify that all matrices are row- or column-major.
RESOLVED: Yes, we should provide this control. It is now available
in the form of uniform block layout qualifiers. The identifiers
"row_major" and "column_major" are allowed, with the latter serving as
the initial default. These qualifiers can be specified on a per-
matrix basis, a per-uniform block basis (affecting all matrices within
the uniform block that have unspecified orders), or globally. In the
latter case, all subsequent matrices with unspecified order will adopt
a new default order.
(68) Should the buffer layout be expressed in terms of standard GL types?
For example, should the storage for a "vec3" be equivalent to "GLfloat [3]"?
RESOLVED: Yes. One other alternative would be to specify exact type
(e.g., "32-bit floats using IEEE 754 encoding", "32-bit two's complement
integers", etc...). These choices will be roughly equivalent in
practice, and it's probably better to use standard GL types.
(69) Do we need to pad the end of structures and/or arrays using the
standard packing rules? Or should we be able to squeeze data types with
small alignment requirements in the "holes" left at the end of structures or
arrays with larger alignment requirements?
uniform ExamplePad {
// with without
// padding padding comments
// ------- ------- ------------------------
struct { //
vec3 a; // 0..11 0..11
} b; // add 4B of padding?
float c; // 16..19 12..15
vec3 d[2]; // 32..43 16..27 align to 16B due to vec3
// 48..59 32..43 add 4B of padding?
float e; // 64..67 44..47
struct { // align to 16B due to <f>
vec4 f; // 80..95 48..63
ivec2 g; // 96..103 64..71
} h; // add 8B of padding?
uint i; // 112..115 72..75
}
The strongest argument against padding is compactness.
The strongest argument in favor of padding is to have a structure
definition that can be matched with a similar structure definition in
application code. For example, consider the following GLSL code:
uniform Example {
vec3 a[10];
float b;
};
The standard layout rules suggest that the vec3 members of "a" are
effectively padded out to vec4's in the array; so the natural C structure
would look like:
typedef struct { float x, y, z, pad; } vec3InArray;
struct Example {
vec3InArray a[10];
float b;
}
The problem is that without padding the end of arrays, the uniform "b"
will be stored immediately after the last float in a[9], but with the C
structure, that word will be consumed by a[9].pad, and "b" will be stored
one word following.
A similar issue arises with structures; common C compilers seem to pad the
end of structures to the largest alignment of the atomic types used in the
structure. For example, if you have:
struct {
double a;
char b;
} c;
common compilers will generate code where sizeof(c)==16. We are
effectively treating vectors and matrices as atomic types, so it seems to
make sense that for GLSL code like:
struct {
vec4 a;
float b;
} c;
it would follow that sizeof(c)==32.
RESOLVED: Yes, we need to pad in support of the reasons above.
(70) Should "bool" data types be represented as 8-bit quantities (a la
GLboolean in most gl.h versions) or 32-bit?
RESOLVED: Use 32-bit integers.
Using GLboolean (8-bit) would be the closest match to the API types, but
some implementations of this standard may prefer 32-bit integers at this
point. We don't expect uniform blocks to contain enough bool-typed data
where the wasted storage matters significantly.
One other option considered was to have an implementation-dependent
representation, which could be queried, but requiring applications to
query and handle multiple basic data types seemed cumbersome. Even if
we did this, we would still want to have a single representation for a
fully-defined "std140" packing, at least.
(71) What happens we are using indirect rendering where the data types used
by the client and server differ, due to endianness or some other issues
related to basic data type? What happens if the processor running the GLSL
executable uses different data type representations than the application?
DUPLICATE of issue (49)
(72) What parameters should we provide for querying the layout of matrices
(and arrays of matrices) in memory?
RESOLVED: We expect that matrices will be stored as an array of column
vectors or row vectors. There are two possibly independent strides:
- bytes between columns/rows within a single matrix
- bytes between matrices within an array of matrices
The GetActiveUniform*() API for UBO will provide queries for both
strides.
For single matrices, the stride between columns/rows is the only
parameter. Some implementations may provide tightly packed matrices,
where a 3x3 column-major matrix might be represented with 9 consecutive
floats with a 12-byte (3-float) stride between columns. Others, such as
the "std140" packing above represents such a matrix as an array of 3
column or row vectors, but pads each row/column for a 16-byte (4-float)
stride.
For arrays of matrices, two queries would be needed for maximum
flexibility. For example, a hypothetical implementation might pack 3x3
arrays tightly as 9 floats, but require that each array in the matrix be
aligned on a 16-byte boundary. This would have a column stride of 12B,
but would require a matrix stride of 48B, not 3*12=36B. If we didn't
care about such implementations, an alternate approach would be to
treat an array of N column-major matrices with C columns as though it
were an array of N*C column vectors, as in the std140 layout. The
stride between matrices would be derived from the stride between
columns.
Providing multiple queries seems like the safest choice, and doesn't
have any significant down-side. The first stride query, between major
vectors of a matrix, is UNIFORM_MATRIX_STRIDE. The latter query is
actually the same UNIFORM_ARRAY_STRIDE query used for any type of
array element.
(73) Should GetActiveUniform allow you to query if a matrix is column- or
row-major, so an app can determine the layout without knowing how the
matrix is declared in the shader?
RESOLVED: Yes, UNIFORM_IS_ROW_MAJOR.
(74) What's language mechanism should be used for opting into standard
layout?
At the January 2009 F2F, it was recommended to specify a per-uniform
block layout via a language mechanism such as:
layout(<identifier>) uniform {
...
};
where <identifier> must be "std140" in the current standard. Future
extensions and core versions could define additional identifiers (such
as "std140novec4"). The mechanism could be further extended to
include an identifier list if there is ever a need for very fine-grained
control.
There appears to be a strong desire for a global mechanism that doesn't
require individually annotating each and every uniform block. Options
considered include the #pragma described above and a GL API call that
might set a "compiler flag" such as:
glProgramParameteri(program, GL_UNIFORM_BLOCK_LAYOUT, GL_LAYOUT_STD140);
It was noted that the GL API call, since implementations are permitted
to do some or most code generation during glCompileShader(), where a
program parameter would not be available. A similar shader parameter
call could conceivably be provided.
RESOLVED: We've adopted a layout qualifier construct which can be used
to specify the "std140" standard layout either within a uniform block
declaration or at global scope, affecting all subsequently declared
uniform blocks with unspecified layout.
(75) What is the story behind the "std140" packing, and the possible
"std140vec4" alternative?
RESOLVED: The "std140" packing is intended to provide a common
device-independent layout for uniform blocks that can be supported by
all OpenGL 3.1-capable GPUs. Applications using this packing do not
need to query the offsets and strides of all its uniforms and can rely
on the same packing being used on all OpenGL 3.1 implementations.
While some implementations may be able to support a more space-efficient
packing, "std140" does not attempt to provide any features not available
on all platforms. Some of the limitations baked into this packing
include:
* scalars need to be size-aligned;
* vectors are treated as atomic units, and need to be vector-size-
aligned;
* array elements and structures are aligned/padded to 16-byte
boundaries
The array/structure restriction is because some implementations treat
uniform buffers as arrays of four-component vectors and may not be able
to efficiently perform indexed array access with strides less than 16
bytes.
The "std140novec4" alternate packing illustrates an alternate approach
without required 16-byte alignment that might be exposed as a future
vendor extension.
Future versions of OpenGL/GLSL may choose to provide additional sets of
canonical packing rules that may end up being more compact.
(76) When using the standard layout, how is UNIFORM_BLOCK_DATA_SIZE
determined?
RESOLVED: The data size returned by the query is derived by taking the
next free byte after all uniform block members (including any specified
end-of-array or end-of-structure padding) and rounding up to the next
vec4 boundary. It would be equivalent to the offset of a hypothetical
vec4 member added to the end of the uniform block.
There is no implementation-dependent padding of the uniform block data
size when using the standard layout.
Revision History
(v68, 2015-06-23, srahman)
- Add GLX protocol specification.
(v67, 2013-08-17, jon)
- Add extra 'const' qualifier for GetUniformIndices <uniformNames>
argument (Bug 10703).
(v66, 2012-09-17, jon)
- Remove _EXT suffix from GL_UNIFORM_BUFFER_EXT in sample code (Bug
7948).
(v65, 2012-06-28, jon)
- Remove INVALID_VALUE error for BindBufferRange when specifying a
range beyond the current end of buffer. Define BindBufferBase as
specifying a range as large as the actual buffer size at time of
use, and return zero when querying the buffer size as a sentinel
value for the buffer size indicating this behavior. Specify that
the GL will never read from or write to beyond the end of a bound
buffer (Bugs 7318 and 7329, matching OpenGL 4.2 core spec
behavior). Remove dangling references to nonexistent
BindBufferOffset.
(v64, 2011-01-27, jon)