blob: df8e5f61017e6a32db6e56d1bda9894e8c3fed6f [file] [log] [blame]
Name
ARB_shading_language_420pack
Name Strings
GL_ARB_shading_language_420pack
Contact
John Kessenich (cepheus 'at' frii.com)
Contributors
Pat Brown, NVIDIA
Jeff Bolz, NVIDIA
Pierre Boudier, AMD
Piers Daniell, NVIDIA
Patrick Doane, Blizzard
John Kessenich
Daniel Koch, Transgaming
Bill Licea-Kane, AMD
Barthold Lichtenbelt, NVIDIA
Ian Romanick, Intel
Bruce Merry, ARM
Graham Sellers, AMD
Robert Simpson, Qualcomm
Notice
Copyright (c) 2011-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 25-Jul-2011.
Approved by the Khronos Promoters on 2011/07/29.
Version
Last Modified Date: 11-Sep-2014
Revision: 4
Number
ARB Extension #108
Dependencies
GLSL 1.3 is required for all features. GLSL 1.4 is required
declaring a binding for a uniform block, as uniform blocks were not
present until version 1.4.
This extension interacts with the ARB_shader_image_load_store
extension, for assigning locations to image variables.
References to *patch* are not valid unless tessellation stages are
present and enabled.
While this document is self-contained, clarifying context for how to
add the following changes can be seen by looking at version 4.20 of
the GLSL specification.
Overview
This is a language feature only extension formed from changes made
to version 4.20 of GLSL. It includes:
* Add line-continuation using '\', as in C++.
* Change from ASCII to UTF-8 for the language character set and also
allow any characters inside comments.
* Allow implicit conversions of return values to the declared type of
the function.
* The *const* keyword can be used to declare variables within a function
body with initializer expressions that are not constant expressions.
* Qualifiers on variable declarations no longer have to follow a strict
order. The layout qualifier can be used multiple times, and multiple
parameter qualifiers can be used. However, this is not as
straightforward as saying declarations have arbitrary lists of
initializers. Typically, one qualifier from each class of qualifiers
is allowed, so care is now taken to classify them and say so. Then,
of these, order restrictions are removed.
* Add layout qualifier identifier "binding" to bind the location of a
uniform block. This requires version 1.4 of GLSL. If this extension
is used with an earlier version than 1.4, this feature is not present.
* Add layout qualifier identifier "binding" to bind units to sampler
and image variable declarations.
* Add C-style curly brace initializer lists syntax for initializers.
Full initialization of aggregates is required when these are used.
* Allow ".length()" to be applied to vectors and matrices, returning
the number of components or columns.
* Allow swizzle operations on scalars.
* Built-in constants for gl_MinProgramTexelOffset and
gl_MaxProgramTexelOffset.
IP Status
No known IP claims.
Additions to Chapter 3 of the OpenGL Shading Language
Change the opening of 3.1 Character Set to
"The source character set used for the OpenGL shading languages, outside of
comments, is a subset of UTF-8. It includes the following characters:
"The backslash ( \ ) as the line-continuation character when used as
the last character of a line, just before a new line."
and after the list, referring to all the characters:
"An error will be given if any other character is used outside a comment.
"There are no trigraphs. There are no escape sequences or other uses of the
backslash beyond use as the line-continuation character."
At the end of section 3.2, add
"Line numbers are one more than the number of new lines that have been
processed, including counting the new lines that will be removed by the
line-continuation character ( \ ).
"Lines separated by the line-continuation character preceding a new line
are concatenated together before either comment processing or preprocessing.
No white space is substituted for the line-continuation character. That is,
a single token could be formed by the concatenation by taking the characters
at the end of one line concatenating them with the characters at the
beginning of the next line."
float f\
oo;
// forms a single line equivalent to "float foo;"
// (assuming '\' is the last character before the new line and "oo" are
// the first two characters of the next line)
Add to the preprocessor:
"Preprocessing takes places after new lines have been removed by the
line-continuation character."
"Including the following line in a shader will enable module import and
related extended language features described in this extension:
#extension GL_ARB_shading_language_420pack : <behavior>
where <behavior> is as specified in section 3.3 for the #extension
directive."
A new preprocessor macro is added to the OpenGL Shading Language:
#define GL_ARB_shading_language_420pack 1
Add to the section on comments
"Inside comments, any byte values may be used, except a byte whose value
is 0. No errors will be given for the content of comments and no validation
on the content of comments need be done.
"Removal of new lines by the line-continuation character ( \ ) logically
occurs before comments are processed. That is, a single-line comment ending
in the line-continuation character ( \ ) includes the next line in the
comment."
// a single-line comment containing the next line \
a = b; // this is still in the first comment
Additions to Chapter 4 of the OpenGL Shading Language
Add to the syntax description of integer literals:
"When tokenizing, the maximal token matching the above will be recognized
before a new token is started."
Add to the syntax description of floating-point literals:
"When tokenizing, the maximal token matching the above will be recognized
before a new token is started."
Add to the description of .length():
"This returns a type int."
Add a new section for initializers
"Initializers
"At declaration, an initial value for an aggregate variable may be provided,
specified as an equals (=) followed by an initializer. The initializer is
either an assignment-expression or a list of initializers enclosed in curly
braces. The grammar for the initializer is:
initializer :
assignment-expression
{ initializer-list }
{ initializer-list , }
initializer-list :
initializer
initializer-list , initializer
"The assignment-expression is a normal expression except that a comma ( , )
outside parentheses is interpreted as the end of the initializer, not as the
sequence operator. As explained in more detail below, this allows creation
of nested initializers: The aggregate and its initializer must exactly match
in terms of nesting, number of components/elements/members present at each
level, and types of components/elements/members.
"An assignment-expression in an initializer must be either the same type as
the object it initializes or be a type that can be converted to the object's
type according to section 4.1.10 "Implicit Conversions". Since these include
constructors, an aggregate can be initialized by either a constructor or an
initializer list; an element in an initializer list can be a constructor.
"If an initializer is a list of initializers enclosed in curly braces, the
variable being declared must be a vector, a matrix, an array, or a
structure.
int i = { 1 }; // illegal, i is not an aggregate
"A list of initializers enclosed in a matching set of curly braces is
applied to one aggregate. This may be the variable being declared or an
aggregate contained in the variable being declared. Individual
initializers from the initializer list are applied to the elements/members
of the aggregate, in order.
"If the aggregate has a vector type, initializers from the list are applied
to the components of the vector, in order, starting with component 0. The
number of initializers must match the number of components.
"If the aggregate has a matrix type, initializers from the list must be
vector initializers and are applied to the columns of the matrix, in order,
starting with column 0. The number of initializers must match the number of
columns.
"If the aggregate has a structure type, initializers from the list are
applied to the members of the structure, in the order declared in the
structure, starting with the first member. The number of initializers must
match the number of members.
"Applying these rules, the following matrix declarations are equivalent:
mat2x2 a = mat2( vec2( 1.0, 0.0 ), vec2( 0.0, 1.0 ) );
mat2x2 b = { vec2( 1.0, 0.0 ), vec2( 0.0, 1.0 ) };
mat2x2 c = { { 1.0, 0.0 }, { 0.0, 1.0 } };
"All of the following declarations are illegal.
float a[2] = { 3.4, 4.2, 5.0 }; // illegal
vec2 b = { 1.0, 2.0, 3.0 }; // illegal
mat3x3 c = { vec3(0.0), vec3(1.0), vec3(2.0), vec3(3.0) }; // illegal
mat2x2 d = { 1.0, 0.0, 0.0, 1.0 }; // illegal, can't flatten nesting
struct {
float a;
int b;
} e = { 1.2, 2, 3 }; // illegal
"In all cases, the innermost initializer (i.e., not a list of initializers
enclosed in curly braces) applied to an object must have the same type as
the object being initialized or be a type that can be converted to the
object's type according to section 4.1.10 "Implicit Conversions". In the
latter case, an implicit conversion will be done on the initializer before
the assignment is done. All of the following declarations are illegal.
int a = true; // illegal
vec4 b[2] = { vec4(0.0), 1.0 }; // illegal
mat4x2 c = { vec3(0.0), vec3(1.0) }; // illegal
struct S1 {
vec4 a;
vec4 b;
};
struct {
float s;
float t;
} d[] = { S1(vec4(0.0), vec4(1.1)) }; // illegal
"If an initializer (of either form) is provided for an unsized array, the
size of the array is determined by the number of top-level (non-nested)
initializers within the initializer. All of the following declarations
create arrays explicitly sized with five elements:
float a[] = float[](3.4, 4.2, 5.0, 5.2, 1.1);
float b[] = { 3.4, 4.2, 5.0, 5.2, 1.1 };
float c[] = a; // c is explicitly size 5
float d[5] = b; // means the same thing
"It is an error to have too few or too many initializers in an initializer
list for the aggregate being initialized. That is, all elements of an array,
all members of a structure, all columns of a matrix, and all components of a
vector must have exactly one initializer expression present, with no
unconsumed initializers.
Change the definition of the storage qualifier *const* in the table:
const | a variable whose value cannot be changed
Change the definition of storage qualifiers to only include the following
rows
const
in
out
attribute
uniform
varying
(Removing "centroid in", "sample in", "centroid out", "sample out",
"centroid varying", "patch in", and "patch out".)
and with this introduction:
"Variable declarations may have at most one storage qualifier specified in
front of the type."
and make a new class "Auxiliary Storage Qualifier" to contain
Auxiliary Storage | Meaning
Qualifier |
----------------- -------
centroid | centroid-based interpolation
sample | per-sample interpolation
patch | per-tessellation-patch attributes
add that
"Some input and output qualified variables can be qualified with at most one
additional auxiliary storage qualifier.
"Not all combinations of qualification are allowed. Which variable types can
have which qualifiers are specifically defined in upcoming sections."
Removing
"These interpolation qualifiers may only precede the qualifiers in,
centroid in, sample in, out, centroid out, or sample out in a
declaration."
Change the last paragraph in this section to say
"Initializers in global declarations may only be used in declarations of
global variables with no storage qualifier, with a *const* qualifier or
with a uniform qualifier...."
Change the Constant Qualifier section to instead say
"Named compile-time constants or read-only variables can be declared using
the const qualifier. The const qualifier can be used with any of the
non-void transparent basic data types, as well as with structures and arrays
of these. It is an error to write to a const variable outside of its
declaration, so they must be initialized when declared. For example,
const vec3 zAxis = vec3 (0.0, 0.0, 1.0);
const float ceiling = a + b; // a and b not necessarily constants
"Structure members may not be qualified with *const*. Structure variables
can be declared as *const*, and initialized with a structure constructor or
initializer.
"Initializers for *const* declarations at global scope must be
constant expressions..."
In the Constant Expressions section, change the *const* bullet to say
* a variable declared with the const qualifier and an initializer,
where the initializer is a constant expression
and add the bullet
* valid use of the length() method on a sized object, whether or not the
object itself is constant
Add to "Inputs" section
"It is an error to use any auxiliary or interpolation qualifiers on a vertex
shader input."
"Applying the *patch* qualifier to inputs can only be done in tessellation
evaluation shaders."
"The auxiliary storage qualifiers *centroid* and *sample* can also be
applied, as well as the interpolation qualifiers *flat*, *noperspective*,
and *smooth*."
Change all occurances of "patch in qualifier" to "patch qualifier" or
"patch in qualifiers". Similarly for any occurances of "patch out",
"centroid in", "sample in", "centroid out", and "sample out", through-out
the specification.
Also change
"Fragment shader inputs get per-fragment values, typically interpolated
from a previous stage's outputs. They are declared in fragment shaders
with the in storage qualifier, the centroid in storage qualifier, ..."
to
"Fragment shader inputs get per-fragment values, typically interpolated
from a previous stage's outputs. They are declared in fragment shaders
with the in storage qualifier. The auxiliary storage qualifiers centroid
and sample can also be applied, as well as the interpolation qualifiers
flat, noperspective, and smooth..."
Change
"They are declared in fragment shaders with the in storage qualifier, the
centroid in storage qualifier, or the deprecated varying and centroid
varying storage qualifiers."
to
"They are declared in fragment shaders with the in storage qualifier or the
deprecated varying storage qualifier."
Add to the "Outputs" section
"A variable also cannot be declared with both the *in* and the *out*
qualifiers."
Change
"Vertex, tessellation evaluation, and geometry output variables output
per-vertex data and are declared using the out, centroid out, or sample out
storage qualifiers"
to
"Vertex, tessellation evaluation, and geometry output variables output
per-vertex data and are declared using the out storage qualifier"
Change
"It is an error to use patch out in a vertex, tessellation evaluation,
or geometry shader."
to
"Applying *patch* to an output can only be done in a tessellation control
shader."
Change
"Per vertex output variables are arrayed (see arrayed under 4.3.4 Inputs)
and declared using out or centroid out storage qualifiers."
to
"Per-vertex output variables are arrayed and declared using the *out*
qualifier without the *patch* qualifier. Per-patch output variables are
declared using the *patch* and *out* storage qualifiers."
Add
"It is an error to use auxiliary storage qualifiers or interpolation
qualifiers on an output in a fragment shader."
Modify Interface Blocks with new relaxed qualifier rules:
"If optional qualifiers are used, they can include interpolation qualifiers,
auxiliary storage qualifiers, and storage qualifiers..."
Add to Layout Qualifiers:
"More than one layout qualifier may appear in a single declaration. If the
same layout-qualifier-name occurs in multiple layout qualifiers for the same
declaration, the last one overrides the former ones."
Add to Uniform Block Layout Qualifiers, if the base language version is 1.4
or above:
layout-qualifier-id
binding = integer-constant
"The binding identifier specifies the uniform buffer binding point
corresponding to the uniform block, which will be used to obtain the
values of the member variables of the block. It is an error to specify the
binding identifier for the global scope or for block member declarations.
Any uniform block declared without a binding identifier is initially
assigned to block binding point zero. After a program is linked, the
binding points used for uniform blocks declared with or without a binding
identifier can be updated by the OpenGL API.
"If the binding identifier is used with a uniform block instanced as an
array then the first element of the array takes the specified block binding
and each subsequent element takes the next consecutive uniform block
binding point.
"If the binding point for any uniform block instance is less than zero, or
greater than or equal to the implementation-dependent maximum number of
uniform buffer bindings, a compilation error will occur. When the binding
identifier is used with a uniform block instanced as an array of size N,
all elements of the array from binding through binding + N - 1 must be
within this range."
Add for sampler and image layout qualifiers:
Note: The "image" variable aspect of this interacts with
ARB_shader_image_load_store and only applies if the extension
ARB_shader_image_load_store is enabled.
"Uniform layout qualifiers can be used to bind opaque uniform variables to
specific buffers or units. Texture image units can be bound to samplers
and image units can be bound to images.
layout-qualifier-id
binding = integer-constant
"The identifier binding specifies which unit will be bound. Any uniform
sampler or image variable declared without a binding qualifier is
initially bound to unit zero. After a program is linked, the unit
referenced by a sampler or image uniform variable declared with or
without a binding identifier can be updated by the OpenGL API.
"If the binding identifier is used with an array, the first element of the
array takes the specified unit and each subsequent element takes the next
consecutive unit.
If the binding is less than zero, or greater than or equal to the
implementation-dependent maximum supported number of units, a compilation
error will occur. When the binding identifier is used with an array of size
N, all elements of the array from binding through binding + N - 1 must be
within this range."
Change the "Interpolation" section to be the "Interplotation Qualifiers"
section and change the first paragraph to now be the following.
"Inputs and outputs that could be interpolated can be further qualified by
at most one of the following interpolation qualifiers:
Qualifier Meaning
--------- -------
smooth perspective correct interpolation
flat no interpolation
noperspective linear interpolation
"The presence of and type of interpolation is controlled by the above
interpolation qualifiers as well as the auxiliary storage qualifiers
*centroid* and *sample*. The auxiliary storage qualifier *patch* is not
used for interpolation; it is an error to use interpolation qualifiers with
*patch*.
Add the following parameter qualifier
Qualifier Meaning
--------- -------
const for function parameters that cannot be written to
and note that precision qualifiers are also allowed on parameters.
Delete the following sentence in the "Invariant Qualifier" section:
"The invariant qualifier must appear before any interpolation qualifiers
or storage qualifiers when combined with a declaration."
Replace the "Order of Qualification" section with the following
4.11 "Order and Repetition of Qualification"
"When multiple qualifiers are present in a variable or parameter
declaration, they may appear in any order, but they must all appear before
the type. The layout qualifier is the only qualifier that can appear more
than once. Further, a declaration can have at most one storage qualifier,
at most one auxiliary storage qualifier, and at most one interpolation
qualifier. If inout is used, neither in nor out may be used. Multiple
memory qualifiers can be used. Any violation of these rules will cause a
compile-time error."
Additions to Chapter 5 of the OpenGL Shading Language
Change the section title "Vector Components" to be "Vector and Scalar
Components and Length". In that section do the following.
Change first sentence to "The names of the components of a vector or
scalar are denoted by a single letter."
Add the following last sentence to its paragraph:
"The component names x, r, and s are, for example, synonyms for the same
(first) component in a vector. They are also the names of the only
component in a scalar."
Add to the example
float height;
height.x // is legal
height.y // is illegal
and to the third example
float f = 1.2;
vec4 dup = f.xxxx; // dup = (1.2, 1.2, 1.2, 1.2)
"This notation is more concise than the constructor syntax. To form an
r-value, it can be applied to any expression that results in a vector or
scalar r-value. Any resulting vector of any operation must be a valid
vector in the language; hence the following is illegal:"
vec4 f;
vec4 g = pos.xyzwxy.xyzw; // illegal; pos.xyzwxy is non-existent "vec6"
Add to the end of this section:
"The *length* method may be applied to vectors (but not scalars). The
result is the number of components in the vector. For example,
vec3 v;
const int L = v.length();
"sets the constant L to 3. The type returned by .length() on a vector is
*int*."
Add to the Matrix Components section:
"The length method may be applied to matrices. The result is the number
of columns of the matrix. For example,
mat3x4 v;
const int L = v.length();
"sets the constant L to 3. The type returned by .length() on a matrix
is *int*."
Additions to Chapter 6 of the OpenGL Shading Language
Add to the "Function Definitions" section the following functionality
regarding function return values:
"If the type of returnValue does not match returnType, there must be an
implicit conversion in section 4.1.10 "Implicit Conversions" that
converts the type of returnValue to returnType, or a compile error will
result."
and the clarifations:
"A void function can only use return without a return argument, even if
the return argument has void type. Return statements only accept values:
void func1() { }
void func2() { return func1(); } // illegal return statement
"Only a precision qualifier is allowed on the return type of a function.
Formal parameters can have parameter, precision, and memory qualifiers,
but no other qualifiers."
Under the section "Function Calling Conventions" change to the *inout*
bullet:
* "The keyword *inout* is used as a qualifier to denote the parameter
is to be both copied in and copied out. It means the same thing as
specifying both in and out."
and the following grammar changes: Delete the const-qualifier parts of
the existing grammar and instead use
parameter-qualifiers :
empty
list of parameter-qualifier
parameter-qualifier :
empty
const
in
out
inout
memory qualifier
precision qualifier
Additions to Chapter 7 of the OpenGL Shading Language
Add to the built-in constants
const int gl_MinProgramTexelOffset = -7;
const int gl_MaxProgramTexelOffset = 8;
Additions to Chapter 9 of the OpenGL Shading Language
TBD.
Conformance Tests
Verify that the following two vectors are identical:
vec4 a = vec4(1.0);
vec4 b = (1.0).xxxx;
Verify that the following generates a compilation error:
vec2 a = 1.xx;
Verify that the following two vectors are identical:
vec2 a = (1).xx;
vec2 b = vec2(1.0);
Verify that the following two arrays are identical:
vec4 a[] = vec4 [] (vec4(1.2), vec4(0.0), vec4(0.0), vec4(0.0),
vec4(0.0), vec4(0.0), vec4(0.0), vec4(2.4),
vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0),
vec4(0.0), vec4(0.0), vec4(0.0), vec4(3.6));
vec4 b[] = { vec4(1.2), vec4(0.0), vec4(0.0), vec4(0.0),
vec4(0.0), vec4(0.0), vec4(0.0), vec4(2.4),
vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0),
vec4(0.0), vec4(0.0), vec4(0.0), vec4(3.6) };
Verify that the following two arrays are identical:
vec4 a[12] = vec4 [] (vec4(1.2), vec4(0.0), vec4(0.0), vec4(0.0),
vec4(0.0), vec4(0.0), vec4(0.0), vec4(2.4),
vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0));
vec4 b[12] = { vec4(1.2), vec4(0.0), vec4(0.0), vec4(0.0),
vec4(0.0), vec4(0.0), vec4(0.0), vec4(2.4) };
Verify that the following three matrices are identical:
mat2x2 a = mat2( vec2( 1.0, 0.0 ), vec2( 0.0, 1.0 ) );
mat2x2 b = { vec2( 1.0, 0.0 ), vec2( 0.0, 1.0 ) };
mat2x2 c = { { 1.0, 0.0 }, { 0.0, 1.0 } };
Verify that the following generates a compliation error:
float a[2] = { 1.0, 2.0, 3.0 };
Verify that the following generates a compliation error:
mat2x2 d = { 1.0, 0.0, 0.0, 1.0 };
Verify that the output of the following fragment shader is (0, 1, 0, 1):
#version 410
#extension GL_ARB_shading_language_420pack: require
out vec4 color;
void main()
{
color = (vec2(0).length() == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
}
Repeat the above test with vec2(0).length() replaced by ivec2(0).length().
Repeat the above test with vec2(0).length() replaced by uvec2(0).length().
Repeat the above test with vec2(0).length() replaced by bvec2(0).length().
Repeat the above test with vec2(0).length() replaced by dvec2(0).length().
Verify that the output of the following fragment shader is (0, 1, 0, 1):
#version 410
#extension GL_ARB_shading_language_420pack: require
out vec4 color;
void main()
{
color = (vec3(0).length() == 3) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
}
Repeat the above test with vec3(0).length() replaced by ivec3(0).length().
Repeat the above test with vec3(0).length() replaced by uvec3(0).length().
Repeat the above test with vec3(0).length() replaced by bvec3(0).length().
Repeat the above test with vec3(0).length() replaced by dvec3(0).length().
Verify that the output of the following fragment shader is (0, 1, 0, 1):
#version 410
#extension GL_ARB_shading_language_420pack: require
out vec4 color;
void main()
{
color = (vec4(0).length() == 4) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
}
Repeat the above test with vec4(0).length() replaced by ivec4(0).length().
Repeat the above test with vec4(0).length() replaced by uvec4(0).length().
Repeat the above test with vec4(0).length() replaced by bvec4(0).length().
Repeat the above test with vec4(0).length() replaced by dvec4(0).length().
Verify that the output of the following fragment shader is (0, 1, 0, 1):
#version 410
#extension GL_ARB_shading_language_420pack: require
out vec4 color;
void main()
{
color = (mat2(0).length() == 2) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
}
Repeat the above test with mat2(0).length() replaced by mat2x2(0).length().
Repeat the above test with mat2(0).length() replaced by dmat2x2(0).length().
Repeat the above test with mat2(0).length() replaced by mat2x3(0).length().
Repeat the above test with mat2(0).length() replaced by dmat2x3(0).length().
Repeat the above test with mat2(0).length() replaced by mat2x4(0).length().
Repeat the above test with mat2(0).length() replaced by dmat2x4(0).length().
Verify that the output of the following fragment shader is (0, 1, 0, 1):
#version 410
#extension GL_ARB_shading_language_420pack: require
out vec4 color;
void main()
{
color = (mat3(0).length() == 3) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
}
Repeat the above test with mat3(0).length() replaced by mat3x2(0).length().
Repeat the above test with mat3(0).length() replaced by dmat3x2(0).length().
Repeat the above test with mat3(0).length() replaced by mat3x3(0).length().
Repeat the above test with mat3(0).length() replaced by dmat3x3(0).length().
Repeat the above test with mat3(0).length() replaced by mat3x4(0).length().
Repeat the above test with mat3(0).length() replaced by dmat3x4(0).length().
Verify that the output of the following fragment shader is (0, 1, 0, 1):
#version 410
#extension GL_ARB_shading_language_420pack: require
out vec4 color;
void main()
{
color = (mat4(0).length() == 4) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
}
Repeat the above test with mat4(0).length() replaced by mat4x2(0).length().
Repeat the above test with mat4(0).length() replaced by dmat4x2(0).length().
Repeat the above test with mat4(0).length() replaced by mat4x3(0).length().
Repeat the above test with mat4(0).length() replaced by dmat4x3(0).length().
Repeat the above test with mat4(0).length() replaced by mat4x4(0).length().
Repeat the above test with mat4(0).length() replaced by dmat4x4(0).length().
Verify that the output of the following fragment shader is (0, 1, 0, 1):
#version 410
#extension GL_ARB_shading_language_420pack: require
out vec4 color;
void main()
{
color = (mat2(0)[0].length() == 2)
? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
}
Repeat the above test with mat2(0)[0].length() replaced by
mat2x2(0)[0].length().
Repeat the above test with mat2(0)[0].length() replaced by
dmat2x2(0)[0].length().
Repeat the above test with mat2(0)[0].length() replaced by
mat3x2(0)[0].length().
Repeat the above test with mat2(0)[0].length() replaced by
dmat3x2(0)[0].length().
Repeat the above test with mat2(0)[0].length() replaced by
mat4x2(0)[0].length().
Repeat the above test with mat2(0)[0].length() replaced by
dmat4x2(0)[0].length().
Verify that the output of the following fragment shader is (0, 1, 0, 1):
#version 410
#extension GL_ARB_shading_language_420pack: require
out vec4 color;
void main()
{
color = (mat3(0)[0].length() == 3)
? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
}
Repeat the above test with mat3(0)[0].length() replaced by
mat2x3(0)[0].length().
Repeat the above test with mat3(0)[0].length() replaced by
dmat2x3(0)[0].length().
Repeat the above test with mat3(0)[0].length() replaced by
mat3x3(0)[0].length().
Repeat the above test with mat3(0)[0].length() replaced by
dmat3x3(0)[0].length().
Repeat the above test with mat3(0)[0].length() replaced by
mat4x3(0)[0].length().
Repeat the above test with mat3(0)[0].length() replaced by
dmat4x3(0)[0].length().
Verify that the output of the following fragment shader is (0, 1, 0, 1):
#version 410
#extension GL_ARB_shading_language_420pack: require
out vec4 color;
void main()
{
color = (mat4(0)[0].length() == 4)
? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
}
Repeat the above test with mat4(0)[0].length() replaced by
mat2x4(0)[0].length().
Repeat the above test with mat4(0)[0].length() replaced by
dmat2x4(0)[0].length().
Repeat the above test with mat4(0)[0].length() replaced by
mat3x4(0)[0].length().
Repeat the above test with mat4(0)[0].length() replaced by
dmat3x4(0)[0].length().
Repeat the above test with mat4(0)[0].length() replaced by
mat4x4(0)[0].length().
Repeat the above test with mat4(0)[0].length() replaced by
dmat4x4(0)[0].length().
Verify that the following shader generates a compilation error:
#version 410
#extension GL_ARB_shading_language_420pack: require
out vec4 color;
void main()
{
float v;
int l = v.length();
color = vec4(1, 0, 0, 1);
}
Repeat the above test with "float v" replaced by "int v".
Repeat the above test with "float v" replaced by "uint v".
Repeat the above test with "float v" replaced by "bool v".
Repeat the above test with "float v" replaced by "double v".
Verify that the following shader compiles without error:
#version 410
#extension GL_ARB_shading_language_420pack: require
void main()
{
float b[vec2(0).length()];
}
Repeat the above test with vec2(0).length() replaced by ivec2(0).length().
Repeat the above test with vec2(0).length() replaced by uvec2(0).length().
Repeat the above test with vec2(0).length() replaced by bvec2(0).length().
Repeat the above test with vec2(0).length() replaced by dvec2(0).length().
Repeat the above test with vec2(0).length() replaced by ivec3(0).length().
Repeat the above test with vec2(0).length() replaced by uvec3(0).length().
Repeat the above test with vec2(0).length() replaced by bvec3(0).length().
Repeat the above test with vec2(0).length() replaced by dvec3(0).length().
Repeat the above test with vec2(0).length() replaced by ivec4(0).length().
Repeat the above test with vec2(0).length() replaced by uvec4(0).length().
Repeat the above test with vec2(0).length() replaced by bvec4(0).length().
Repeat the above test with vec2(0).length() replaced by dvec4(0).length().
Repeat the above test with vec2(0).length() replaced by mat2(0).length().
Repeat the above test with vec2(0).length() replaced by mat2x2(0).length().
Repeat the above test with vec2(0).length() replaced by mat2x3(0).length().
Repeat the above test with vec2(0).length() replaced by mat2x4(0).length().
Repeat the above test with vec2(0).length() replaced by mat3(0).length().
Repeat the above test with vec2(0).length() replaced by mat3x2(0).length().
Repeat the above test with vec2(0).length() replaced by mat3x3(0).length().
Repeat the above test with vec2(0).length() replaced by mat3x4(0).length().
Repeat the above test with vec2(0).length() replaced by mat4(0).length().
Repeat the above test with vec2(0).length() replaced by mat4x2(0).length().
Repeat the above test with vec2(0).length() replaced by mat4x3(0).length().
Repeat the above test with vec2(0).length() replaced by mat4x4(0).length().
Repeat the above test with vec2(0).length() replaced by dmat2(0).length().
Repeat the above test with vec2(0).length() replaced by dmat2x2(0).length().
Repeat the above test with vec2(0).length() replaced by dmat2x3(0).length().
Repeat the above test with vec2(0).length() replaced by dmat2x4(0).length().
Repeat the above test with vec2(0).length() replaced by dmat3(0).length().
Repeat the above test with vec2(0).length() replaced by dmat3x2(0).length().
Repeat the above test with vec2(0).length() replaced by dmat3x3(0).length().
Repeat the above test with vec2(0).length() replaced by dmat3x4(0).length().
Repeat the above test with vec2(0).length() replaced by dmat4(0).length().
Repeat the above test with vec2(0).length() replaced by dmat4x2(0).length().
Repeat the above test with vec2(0).length() replaced by dmat4x3(0).length().
Repeat the above test with vec2(0).length() replaced by dmat4x4(0).length().
More TBD.
Issues
1) How is the ambiguity of swizzling an integer literal resolved?
RESOLVED: Greedy lexing. The sequence "5.x" will be interpreted
as the floating-point literal 5.0 followed by the identifier "x".
2) Should the array subscript operator be applicable to scalars as it is
to vectors?
RESOLVED: NO. In conduction with the rest of the features of this
extension, this would allow writing generic code such as:
#define SUM_COMPONENTS(value, result) \
do {
for (int i = 0; i < (value).length(); i++)
result += (value)[i];
} while (0)
However, using macros in this fashion is a poor approximation
of generic functions. Until a better mechanism is added to
GLSL, there is little utility in array accesses to scalars or
single component vectors.
3) Should vectors and matrices also be able to use initializer lists?
RESOLVED: YES. Many places in the language treat vectors as 2, 3, or
4 element arrays of a scalar type. Matrices are often treated as
arrays of vector types. Continuing that treatment here is logical.
4) What happens when an explicitly sized array is initialized with too few
elements? Is it allowed?
RESOLVED: DISALLOWED. In C/C++ this is allowed. The uninitialized
elements are implicitly initialized to the appropriate reprensentation
of zero. However, the belief is that this enables a variety of
programming errors that are difficult to debug on a GPU.
5) Can scalars be initialized using an initializer list?
RESOLVED: NO. In C/C++ this is allowed. The ISO C99 specification
specifically say, "The initializer for a scalar shall be a single
expression, optionally enclosed in braces." However, this may
pose problems if / when a vec1 type is added.
6) Are initializer lists for vectors flexible in the same way that vector
constructors are? Specifically, is the initialzier list for 'c',
below, legal?
vec2 a = vec2(2, 3);
vec4 b = vec4(1, a, 4); // b = { 1, 2, 3, 4 }
vec4 c = { 1, a, 4 }; // Legal?
RESOLVED: NO. In C++ there is a distinction between a constructor
and an initializer list. If you had vec2 and vec4 classes in C++, a
constructor 'vec4(float, vec2, float)' might exist, but the
initializer list for 'c' would not be legal.
7) Does adding *const* for read-only variables effect array sizing?
RESOLVED. No. Array sizing changes are not part of this proposal. Array
sizing rules stay the same, where sizes must be compile-time constants,
whether or not the keyword 'const' was involved, just like it always has
been. The following was and still is disallowed:
"void foo(const s) { int a[s]; }",
as will be
"void foo() { const s = exp; int a[s]; }".
8) Should we allow non-compile-time constant initializers for const at
global scope as well?
RESOLVED. No. Would make linking more difficult.
9) Do we want to add the new C++ constexpr for declaring constant
functions?
RESOLVED. No, not yet, could be a potential performance benefit in the
future, but treat as a separate extension. Note that most built-in
functions are already understood to be "constexpr". This has been
submitted into bugzilla.
10) What combinations of interpolation qualifiers are allowed? Before,
you could take one of smooth, flat, and noperspective and combine that with
one of centroid, sample, or patch. What do combinations do we actually
want? Do we want multiple intances of a single qualifier allowed?
(E.g. two layout qualifiers, or "in out"?)
RESOLVED. Allow multiple "layout". Not anything else.
11) Should we allow multiple block declarations to use the same
binding point? For example:
layout(binding = 3) uniform Block1 { ... };
layout(binding = 3) uniform Block2 { ... };
RESOLVED: There is no reason to disallow this usage; in particular,
existing UBO shaders effectively declare all blocks with
"layout(block = 0)".
12) Should the qualifier be called "location", "block" or "binding"?
RESOLVED: The qualifier is called "binding" because it makes it more
clear what parameter of UniformBlockBinding that this qualifier
affects. "block" could be confused with either the
<uniformBlockIndex> or <uniformBlockBinding> and "location" might be
confused with the current uses of the qualifier "location" for
attribute locations or it could be confused with uses of "location"
for uniform variable location, which blocks don't have.
13) Should sampler initialization use a layout(binding) qualifier
instead of specifying a uniform initializer?
RESOLVED: Revision #4 of the sampler initialization spec uses a
layout(binding) qualifier for sampler uniforms. This is more
forward looking and makes the spec more consistent with
ARB_uniform_block_binding_initialization and
ARB_shader_atomic_counters.
Revision History
Revision 4, 11-Sep-2014 (pbrown)
- Fix minor typo.
Revision 3, 13-May-2014 (John Kessenich)
- Resolve bug 10593.
Revision 2, 25-Jul-2011 (John Kessenich)
- Mark as complete and approved.
- Tidy up some formating and non-raw-text quote marks.
- Pull in the initializers for images, to completely subsume
GL_ARB_uniform_sampler_initialization.
- Point out image and patch dependencies.
Revision 1, 5-Jul-2011 (John Kessenich)
- Initial version. Formed by combing the content of the
4.20 draft specification and the content of draft
extensions:
* ARB_shading_language_vec1
* ARB_shading_language_relaxed_qualifiers
* ARB_shading_language_length
* ARB_shading_language_initializer_list
* GL_ARB_uniform_block_binding_initialization
* GL_ARB_uniform_sampler_initialization (just sampler binding)
Issues were carried across and renumbered.
Conformance tests were carried over.