Vulkan-Docs/doc/specs/misc/GL_KHR_vulkan_glsl.txt

1172 lines
45 KiB
Plaintext
Raw Normal View History

2016-02-16 09:53:44 +00:00
Name
KHR_vulkan_glsl
Name Strings
GL_KHR_vulkan_glsl
Contact
John Kessenich (johnkessenich 'at' google.com), Google
Contributors
Jeff Bolz, NVIDIA
Kerch Holt, NVIDIA
Kenneth Benzie, Codeplay
Neil Henning, Codeplay
Neil Hickey, ARM
Daniel Koch, NVIDIA
Timothy Lottes, Epic Games
David Neto, Google
Notice
Copyright (c) 2015 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Status
Approved by Vulkan working group 03-Dec-2015.
Ratified by the Khronos Board of Promoters 15-Jan-2016.
Version
Last Modified Date: 10-Feb-2016
Revision: 25
Number
TBD.
Dependencies
This extension can be applied to OpenGL GLSL versions 1.40
(#version 140) and higher.
This extension can be applied to OpenGL ES ESSL versions 3.10
(#version 310) and higher.
All these versions map GLSL/ESSL semantics to the same SPIR-V 1.0
semantics (approximating the most recent versions of GLSL/ESSL).
Overview
This is version 100 of the GL_KHR_vulkan_glsl extension.
This extension modifies GLSL to be used as a high-level language for the
Vulkan API. GLSL is compiled down to SPIR-V, which the Vulkan API
consumes.
The following features are removed:
* default uniforms (uniform variables not inside a uniform block),
except for opaque types
* atomic-counter bindings: atomic counters form a one-dimensional space
* subroutines
* shared and packed block layouts
* the already deprecated texturing functions (e.g., texture2D())
* compatibility-mode-only features
* DepthRangeParameters
* gl_VertexID and gl_InstanceID
The following features are added:
* push-constant buffers
* shader-combining of separate textures and samplers
* descriptor sets
* specialization constants
* gl_VertexIndex and gl_InstanceIndex
* subpass inputs
The following features are changed:
* gl_FragColor will no longer indicate an implicit broadcast
* arrays of opaque uniforms take only one binding number for
the entire object, not one per array element
Each of these is discussed in more detail below.
Enabling These Features
-----------------------
This extension is not enabled with a #extension as other extensions are.
It is also not enabled through use of a profile or #version. The intended
level of GLSL/ESSL features, independent from Vulkan-specific usage, comes
from the traditional use of #version, profile, and #extension.
Instead, use of this extension is an effect of using a GLSL front-end in a
mode that has it generate SPIR-V for Vulkan. Such tool use is outside the
scope of using the Vulkan API and outside the definition of GLSL and this
extension. See the documentation of the compiler to see how to request
generation of SPIR-V for Vulkan.
When a front-end is used to accept this extension, it must error check and
reject shaders not adhering to this specification, and accept those that
do. Implementation-dependent maximums and capabilities are supplied to, or
part of, the front-end, so it can do error checking against them.
A shader can query the level of Vulkan support available, using the
predefined
#define VULKAN 100
This allows shader code to say, for example,
#ifdef VULKAN
layout(set = 1, binding = 0) uniform sampler s;
layout(set = 1, binding = 1) uniform texture2D t;
#if VULKAN > 100
...
#endif
#else
layout(binding = 0) uniform sampler2D ts;
#endif
Push Constants
--------------
Push constants reside in a uniform block declared using the new
layout-qualifier-id "push_constant" applied to a uniform-block declaration.
The API writes a set of constants to a push-constant buffer, and the shader
reads them from a push_constant block:
layout(push_constant) uniform BlockName {
int member1;
float member2;
...
} InstanceName;
... = InstanceName.member2; // read a push constant
The memory accounting used for the push_constant uniform block is different
than for other uniform blocks: There is a separate small pool of memory
it must fit within. By default, a push_constant buffer follows the std430
packing rules.
Combining separate samplers and textures
----------------------------------------
A sampler, declared with the keyword 'sampler', contains just filtering
information, containing neither a texture nor an image:
uniform sampler s; // a handle to filtering information
A texture, declared with keywords like 'texture2D', contains just image
information, not filtering information:
uniform texture2D t; // a handle to a texture (an image in SPIR-V)
Constructors can then be used to combine a sampler and a texture at the
point of making a texture lookup call:
texture2D(sampler2D(t, s), ...);
Note, layout() information is omitted above for clarity of this feature.
Descriptor Sets
---------------
Bound objects can further declare which Vulkan descriptor set they belong
to, using 'set':
layout(set = N, ...) ... // declared object belongs to descriptor set N
For example, two combined texture/sampler objects can be declared in two
different descriptor sets as follows
layout(set = 0, binding = 0) uniform sampler2D ts3;
layout(set = 1, binding = 0) uniform sampler2D ts4;
See the API documentation for more detail on the operation model of
descriptor sets.
Specialization Constants
------------------------
SPIR-V specialization constants, which can be set later by the client API,
can be declared using "layout(constant_id=...)". For example, to make a
specialization constant with a default value of 12:
layout(constant_id = 17) const int arraySize = 12;
Above, "17" is the ID by which the API or other tools can later refer to
this specific specialization constant. The API or an intermediate tool can
then change its value to another constant integer before it is fully
lowered to executable code. If it is never changed before final lowering,
it will retain the value of 12.
Specialization constants have const semantics, except they don't fold.
Hence, an array can be declared with 'arraySize' from above:
vec4 data[arraySize]; // legal, even though arraySize might change
Specialization constants can be in expressions:
vec4 data2[arraySize + 2];
This will make data2 be sized by 2 more than whatever constant value
'arraySize' has when it is time to lower the shader to executable code.
An expression formed with specialization constants also behaves in the
shader like a specialization constant, not a like a constant.
arraySize + 2 // a specialization constant (with no constant_id)
Such expressions can be used in the same places as a constant.
The constant_id can only be applied to a scalar *int*, a scalar *float*
or a scalar *bool*.
Only basic operators and constructors can be applied to a specialization
constant and still result in a specialization constant:
layout(constant_id = 17) const int arraySize = 12;
sin(float(arraySize)); // result is not a specialization constant
While SPIR-V specialization constants are only for scalars, a vector
can be made by operations on scalars:
layout(constant_id = 18) const int scX = 1;
layout(constant_id = 19) const int scZ = 1;
const vec3 scVec = vec3(scX, 1, scZ); // partially specialized vector
A built-in variable can have a 'constant_id' attached to it:
layout(constant_id = 18) gl_MaxImageUnits;
This makes it behave as a specialization constant. It is not a full
redeclaration; all other characteristics are left intact from the
original built-in declaration.
The built-in vector gl_WorkGroupSize can be specialized using special
layout local_size_{xyz}_id's applied to the "in" qualifier. For example:
layout(local_size_x_id = 18, local_size_z_id = 19) in;
This leaves gl_WorkGroupSize.y as a non-specialization constant, with
gl_WorkGroupSize being a partially specialized vector. Its x and z
components can be later specialized using the ID's 18 and 19.
gl_VertexIndex and gl_InstanceIndex
-----------------------------------
Adds two new built-in variables, gl_VertexIndex and gl_InstanceIndex to
replace the existing built-in variables gl_VertexID and gl_InstanceID.
In the situations where the indexing is relative to some base offset,
these built-in variables are defined, for Vulkan, to take on values as
follows:
gl_VertexIndex base, base+1, base+2, ...
gl_InstanceIndex base, base+1, base+2, ...
Where it depends on the situation what the base actually is.
Subpass Inputs
--------------
Within a rendering pass, a subpass can write results to an output target
that can then be read by the next subpass as an input subpass. The
"Subpass Input" feature regards the ability to read an output target.
Subpasses are read through a new set of types, available only
to fragment shaders:
subpassInput
subpassInputMS
isubpassInput
isubpassInputMS
usubpassInput
usubpassInputMS
Unlike sampler and image objects, subpass inputs are implicitly addressed
by the fragment's (x, y, layer) coordinate.
A subpass input is selected by using a new layout qualifier identifier
'input_attachment_index'. For example:
layout(input_attachment_index = i, ...) uniform subpassInput t;
An input_attachment_index of i selects the ith entry in the input pass
list. (See API specification for more information.)
These objects support reading the subpass input through the following
functions:
gvec4 subpassLoad(gsubpassInput subpass);
gvec4 subpassLoad(gsubpassInputMS subpass, int sample);
gl_FragColor
------------
The fragment-stage built-in gl_FragColor, which implies a broadcast to all
outputs, is not present in SPIR-V. Shaders where writing to gl_FragColor
is allowed can still write to it, but it only means to write to an output:
- of the same type as gl_FragColor
- decorated with location 0
- not decorated as a built-in variable.
There is no implicit broadcast.
Mapping to SPIR-V
-----------------
For informational purposes (non-specification), the following is an
expected way for an implementation to map GLSL constructs to SPIR-V
constructs:
Mapping of storage classes:
uniform sampler2D...; -> UniformConstant
uniform blockN { ... } ...; -> Uniform, with Block decoration
in / out variable -> Input/Output, possibly with block (below)
in / out block... -> Input/Output, with Block decoration
buffer blockN { ... } ...; -> Uniform, with BufferBlock decoration
... uniform atomic_uint ... -> AtomicCounter
shared -> Workgroup
<normal global> -> Private
Mapping of input/output blocks or variables is the same for all versions
of GLSL or ESSL. To the extent variables or members are available in a
version, its location is as follows:
These are mapped to SPIR-V individual variables, with similarly spelled
built-in decorations (except as noted):
Any stage:
in gl_NumWorkGroups
in gl_WorkGroupSize
in gl_WorkGroupID
in gl_LocalInvocationID
in gl_GlobalInvocationID
in gl_LocalInvocationIndex
in gl_VertexIndex
in gl_InstanceIndex
in gl_InvocationID
in gl_PatchVerticesIn (PatchVertices)
in gl_PrimitiveIDIn (PrimitiveID)
in/out gl_PrimitiveID (in/out based only on storage qualifier)
in gl_TessCoord
in/out gl_Layer
in/out gl_ViewportIndex
patch in/out gl_TessLevelOuter (uses Patch decoration)
patch in/out gl_TessLevelInner (uses Patch decoration)
Fragment stage only:
in gl_FragCoord
in gl_FrontFacing
in gl_ClipDistance
in gl_CullDistance
in gl_PointCoord
in gl_SampleID
in gl_SamplePosition
in gl_HelperInvocation
out gl_FragDepth
in gl_SampleMaskIn (SampleMask)
out gl_SampleMask (in/out based only on storage qualifier)
These are mapped to SPIR-V blocks, as implied by the pseudo code, with
the members decorated with similarly spelled built-in decorations:
Non-fragment stage:
in/out gl_PerVertex {
gl_Position
gl_PointSize
gl_ClipDistance
gl_CullDistance
} (name of block is for debug only)
There is at most one input and one output block per stage in SPIR-V.
Mapping of precision qualifiers:
lowp -> RelaxedPrecision, on variable and operation
mediump -> RelaxedPrecision, on variable and operation
highp -> 32-bit, same as int or float
portability tool/mode -> OpQuantizeToF16
Mapping of precise:
precise -> NoContraction
Mapping of images
subpassInput -> OpTypeImage with 'Dim' of SubpassData
subpassLoad() -> OpImageRead
imageLoad() -> OpImageRead
imageStore() -> OpImageWrite
texelFetch() -> OpImageFetch
imageAtomicXXX(params, data) -> %ptr = OpImageTexelPointer params
OpAtomicXXX %ptr, data
XXXQueryXXX(combined) -> %image = OpImage combined
OpXXXQueryXXX %image
Mapping of layouts
std140/std430 -> explicit offsets/strides on struct
shared/packed -> not allowed
<default> -> not shared, but std140 or std430
max_vertices -> OutputVertices
Mapping of other instructions
% -> OpUMod/OpSMod
mod() -> OpFMod
NA -> OpSRem/OpFRem
atomicExchange() -> OpAtomicExchange
imageAtomicExchange() -> OpAtomicExchange
atomicCompSwap() -> OpAtomicCompareExchange
imageAtomicCompSwap() -> OpAtomicCompareExchange
NA -> OpAtomicCompareExchangeWeak
Changes to Chapter 1 of the OpenGL Shading Language Specification
Change the last paragraph of "1.3 Overview": "The OpenGL Graphics System
Specification will specify the OpenGL entry points used to manipulate and
communicate with GLSL programs and GLSL shaders."
Add a paragraph: "The Vulkan API will specify the Vulkan entry points used
to manipulate SPIR-V shaders. Independent offline tool chains will compile
GLSL down to the SPIR-V intermediate language. Vulkan use is not enabled
with a #extension, #version, or a profile. Instead, use of GLSL for Vulkan
is determined by offline tool-chain use. See the documentation of such
tools to see how to request generation of SPIR-V for Vulkan."
"GLSL -> SPIR-V compilers must be directed as to what SPIR-V *Capabilities*
are legal at run-time and give errors for GLSL feature use outside those
capabilities. This is also true for implementation-dependent limits that
can be error checked by the front-end against constants present in the
GLSL source: the front-end can be informed of such limits, and report
errors when they are exceeded."
Changes to Chapter 2 of the OpenGL Shading Language Specification
Change the name from
"2 Overview of OpenGL Shading"
to
"2 Overview of OpenGL and Vulkan Shading"
Remove the word "OpenGL" from three introductory paragraphs.
Changes to Chapter 3 of the OpenGL Shading Language Specification
Add a new paragraph at the end of section "3.3 Preprocessor": "When
shaders are compiled for Vulkan, the following predefined macro is
available:
#define VULKAN 100
Add the following keywords to section 3.6 Keywords:
texture1D texture2D texture3D
textureCube texture2DRect texture1DArray
texture2DArray textureBuffer texture2DMS
texture2DMSArray textureCubeArray
itexture1D itexture2D itexture3D
itextureCube itexture2DRect itexture1DArray
itexture2DArray itextureBuffer
itexture2DMS itexture2DMSArray
itextureCubeArray
utexture1D utexture2D utexture3D
utextureCube utexture2DRect utexture1DArray
utexture2DArray utextureBuffer utexture2DMS
utexture2DMSArray utextureCubeArray
sampler samplerShadow
subpassInput isubpassInput usubpassInput
subpassInputMS isubpassInputMS usubpassInputMS
Changes to Chapter 4 of the OpenGL Shading Language Specification
Add into the tables in section 4.1, interleaved with the existing types,
using the existing descriptions (when not supplied below):
Floating-Point Opaque Types
texture1D
texture2D
texture3D
textureCube
texture2DRect
texture1DArray
texture2DArray
textureBuffer
texture2DMS
texture2DMSArray
textureCubeArray
subpassInput | a handle for accessing a floating-point
| subpass input
subpassInputMS | a handle for accessing a multi-sampled
| floating-point subpass input
Signed Integer Opaque Types
itexture1D
itexture2D
itexture3D
itextureCube
itexture2DRect
itexture1DArray
itexture2DArray
itextureBuffer
itexture2DMS
itexture2DMSArray
itextureCubeArray
isubpassInput | a handle for accessing an integer subpass input
isubpassInputMS | a handle for accessing a multi-sampled integer
| subpass input
Unsigned Integer Opaque Types
utexture1D
utexture2D
utexture3D
utextureCube
utexture2DRect
utexture1DArray
utexture2DArray
utextureBuffer
utexture2DMS
utexture2DMSArray
utextureCubeArray
usubpassInput | a handle for accessing an unsigned integer
| subpass input
usubpassInputMS | a handle for accessing a multi-sampled unsigned
| integer subpass input
Add a new category in this section
"Sampler Opaque Types
sampler | a handle for accessing state describing how to
| sample a texture (without comparison)"
---------------------------------------------------------------------
samplerShadow | a handle for accessing state describing how to
| sample a depth texture with comparison"
Remove "structure member selection" from 4.1.7 and instead add a sentence
"Opaque types cannot be declared or nested in a structure (struct)."
Add a subsection to 4.1.7 Opaque Types:
"4.1.7.x Texture, *sampler*, and *samplerShadow* Types
"Texture (e.g., *texture2D*), *sampler*, and *samplerShadow* types are opaque
types, declared and behaving as described above for opaque types. When
aggregated into arrays within a shader, these types can only be indexed
with a dynamically uniform expression, or texture lookup will result in
undefined values. Texture variables are handles to one-, two-, and
three-dimensional textures, cube maps, etc., as enumerated in the basic
types tables. There are distinct
texture types for each texture target, and for each of float, integer,
and unsigned integer data types. Textures can be combined with a
variable of type *sampler* or *samplerShadow* to create a sampler type
(e.g., sampler2D, or sampler2DShadow). This is done with a constructor,
e.g., sampler2D(texture2D, sampler) or
sampler2DShadow(texture2D, samplerShadow),
and is described in more detail in section 5.4 "Constructors"."
"4.1.7.x Subpass Inputs
"Subpass input types (e.g., subpassInput) are opaque types, declared
and behaving as described above for opaque types. When aggregated into
arrays within a shader, they can only be indexed with a dynamically
uniform integral expression, otherwise results are undefined.
"Subpass input types are handles to two-dimensional single sampled or
multi-sampled images, with distinct types for each of float, integer,
and unsigned integer data types.
"Subpass input types are only available in fragment shaders. It is a
compile-time error to use them in any other stage."
Change section 4.3.3 Constant Expressions:
Add a new very first sentence to this section:
"SPIR-V specialization constants are expressed in GLSL as const, with
a layout qualifier identifier of constant_id, as described in section
4.4.x Specialization-Constant Qualifier."
Add to this sentence:
"A constant expression is one of...
* a variable declared with the const qualifier and an initializer,
where the initializer is a constant expression"
To make it say:
"A constant expression is one of...
* a variable declared with the const qualifier and an initializer,
where the initializer is a constant expression; this includes both
const declared with a specialization-constant layout qualifier,
e.g., 'layout(constant_id = ...)' and those declared without a
specialization-constant layout qualifier"
Add to "including getting an element of a constant array," that
"an array access with a specialization constant as an index does
not result in a constant expression"
Add to this sentence:
"A constant expression is one of...
* the value returned by a built-in function..."
To make it say:
"A constant expression is one of...
* for non-specialization-constants only: the value returned by a
built-in function... (when any function is called with an argument
that is a specialization constant, the result is not a constant
expression)"
Rewrite the last half of the last paragraph to be its own paragraph
saying:
"Non-specialization constant expressions may be evaluated by the
compiler's host platform, and are therefore not required ...
[rest of paragraph stays the same]"
Add a paragraph
"Specialization constant expressions are never evaluated by the
front-end, but instead retain the operations needed to evaluate them
later on the host."
Add to the table in section 4.4 Layout Qualifiers:
| Individual Variable | Block | Allowed Interface
------------------------------------------------------------------------
constant_id = | scalar only | | const
------------------------------------------------------------------------
push_constant | | X | uniform
------------------------------------------------------------------------
set = | opaque only | X | uniform
------------------------------------------------------------------------
input_attachment_index | subpass types only | | uniform
(The other columns remain blank.)
Also add to this table:
| Qualifier Only | Allowed Interface
-------------------------------------------------------
local_size_x_id = | X | in
local_size_y_id = | X | in
local_size_z_id = | X | in
(The other columns remain blank.)
Expand this sentence in section 4.4.1 Input Layout Qualifiers:
"Where integral-constant-expression is defined in section 4.3.3 Constant
Expressions as 'integral constant expression'"
To include the following:
", with it being a compile-time error for integer-constant-expression to
be a specialization constant: The constant used to set a layout
identifier X in layout(layout-qualifier-name = X) must evaluate to a
front-end constant containing no specialization constants."
Change the rules about locations and inputs for doubles, by removing
"If a vertex shader input is any scalar or vector type, it will consume
a single location. If a non-vertex shader input is a scalar or vector
type other than dvec3 or dvec4..."
Replacing the above with
"If an input is a scalar or vector type other than dvec3 or dvec4..."
(Making all stages have the same rule that dvec3 takes two locations...)
Add to the end of section 4.4.3 Uniform Variable Layout Qualifiers:
The /push_constant/ identifier is used to declare an entire block, and
represents a set of "push constants", as defined by the API. It is a
compile-time error to apply this to anything other than a uniform block
declaration. The values in the block will be initialized through the
API, as per the Vulkan API specification. A block declared with
layout(push_constant) must have an /instance-name/ supplied, or a
compile-time error results. There can be only one push_constant
block per stage, or a compile-time or link-time error will result. A
push-constant array can only be indexed with dynamically uniform indexes.
Uniform blocks declared with push_constant use different resources
than those without; and are accounted for separately. See the API
specification for more detail.
After the paragraphs about binding ("The binding identifier..."), add
The /set/ identifier specifies the descriptor set this object belongs to.
It is a compile-time error to apply to just a qualifier or a member of a
block. Any uniform or shader storage block declared without a /set/
identifier is assigned to descriptor set 0. Similarly, any sampler,
texture, or subpass input type declared as a uniform, but without a
/set/ identifier is also assigned to descriptor set 0.
If applied to an object declared as an array, all elements of the array
belong to the specified /set/.
It is a compile-time error for either the /set/ or /binding/ value
to exceed a front-end-configuration supplied maximum value.
Change section 4.4.6 Opaque-Uniform Layout Qualifiers:
Change
"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."
To
"If the binding identifier is used with an array, the entire array
takes just the provided binding number. The next consecutive binding
number is available for a different object."
Add a new subsection at the end of section 4.4:
"4.4.x Specialization-Constant Qualifier
"Specialization constants are declared using "layout(constant_id=...)".
For example:
layout(constant_id = 17) const int arraySize = 12;
"The above makes a specialization constant with a default value of 12.
17 is the ID by which the API or other tools can later refer to
this specific specialization constant. If it is never changed before
final lowering, it will retain the value of 12. It is a compile-time
error to use the constant_id qualifier on anything but a scalar bool,
int, uint, float, or double.
"Built-in constants can be declared to be specialization constants.
For example,
layout(constant_id = 31) gl_MaxClipDistances; // add specialization id
"The declaration uses just the name of the previously declared built-in
variable, with a constant_id layout declaration. It is a compile-time
error to do this after the constant has been used: Constants are strictly
either non-specialization constants or specialization constants, not
both.
"The built-in constant vector gl_WorkGroupSize can be specialized using
the local_size_{xyz}_id qualifiers, to individually give the components
an id. For example:
layout(local_size_x_id = 18, local_size_z_id = 19) in;
"This leaves gl_WorkGroupSize.y as a non-specialization constant, with
gl_WorkGroupSize being a partially specialized vector. Its x and z
components can be later specialized using the ids 18 and 19. These ids
are declared independently from declaring the work-group size:
layout(local_size_x = 32, local_size_y = 32) in; // size is (32,32,1)
layout(local_size_x_id = 18) in; // constant_id for x
layout(local_size_z_id = 19) in; // constant_id for z
"Existing rules for declaring local_size_x, local_size_y, and
local_size_z are not changed by this extension. For the local-size ids,
it is a compile-time error to provide different id values for the same
local-size id, or to provide them after any use. Otherwise, order,
placement, number of statements, and replication do not cause errors.
"Two arrays sized with specialization constants are the same type only if
sized with the same symbol, involving no operations.
layout(constant_id = 51) const int aSize = 20;
const int pad = 2;
const int total = aSize + pad; // specialization constant
int a[total], b[total]; // a and b have the same type
int c[22]; // different type than a or b
int d[aSize + pad]; // different type than a, b, or c
int e[aSize + 2]; // different type than a, b, c, or d
"Arrays inside a block may be sized with a specialization constant, but
the block will have a static layout. Changing the specialized size will
not re-layout the block. In the absence of explicit offsets, the layout
will be based on the default size of the array."
Add a new subsection at the end of section 4.4:
"4.4.y Subpass Qualifier
"Subpasses are declared with the basic 'subpassInput' types. However,
they must have the layout qualifier "input_attachment_index" declared
with them, or a compile-time error results. For example:
layout(input_attachment_index = 2, ...) uniform subpassInput t;
This selects which subpass input is being read from. The value assigned
to 'input_attachment_index', say i (input_attachment_index = i), selects
that entry (ith entry) in the input list for the pass. See the API
documentation for more detail about passes and the input list.
"If an array of size N is declared, it consume N consecutive
input_attachment_index values, starting with the one provided.
"It is a compile-time or link-time error to have different variables
declared with the same input_attachment_index. This includes any overlap
in the implicit input_attachment_index consumed by array declarations.
"It is a compile-time error if the value assigned to an
input_attachment_index is greater than or equal to
gl_MaxInputAttachments."
Remove all mention of the 'shared' and 'packed' layout qualifiers.
Change section 4.4.5 Uniform and Shader Storage Block Layout Qualifiers
"The initial state of compilation is as if the following were declared:
layout(std140, column_major) uniform; // without push_constant
layout(std430, column_major) buffer;
"However, when push_constant is declared, the default layout of the
buffer will be std430. There is no method to globally set this default."
Changes to Chapter 5 of the OpenGL Shading Language Specification
Add a new subsection at the end of section 5.4 "Constructors":
"5.4.x Sampler Constructors
"Sampler types, like *sampler2D* can be declared with an initializer
that is a constructor of the same type, and consuming a texture and a
sampler. For example:
layout(...) uniform sampler s; // handle to filtering information
layout(...) uniform texture2D t; // handle to a texture
in vec2 tCoord;
...
texture2D(sampler2D(t, s), tCoord);
The result of a sampler constructor cannot be assigned to a variable:
... sampler2D sConstruct = sampler2D(t, s); // ERROR
Sampler constructors can only be consumed by a function parameter.
Sampler constructors of arrays are illegal:
layout(...) uniform texture2D tArray[6];
...
... sampler2D[](tArray, s) ... // ERROR
Formally:
* every sampler type can be used as a constructor
* the type of the constructor must match the type of the
variable being declared
* the constructor's first argument must be a texture type
* the constructor's second argument must be a scalar of type
*sampler* or *samplerShadow*
* the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array)
of the texture type must match that of the constructed sampler type
(that is, the suffixes of the type of the first argument and the
type of the constructor will be spelled the same way)
* the presence or absence of depth comparison (Shadow) must match
between the constructed sampler type and the type of the second argument
* there is no control flow construct (e.g., "?:") that consumes any
sampler type
Change section 5.9 Expressions
Add under "The sequence (,) operator..."
"Texture and sampler types cannot be used with the sequence (,)
operator."
Change under "The ternary selection operator (?:)..."
"The second and third expressions can be any type, as long their types
match."
To
"The second and third expressions can be any type, as long their types
match, except for texture and sampler types, which result in a
compile-time error."
Add a section at the end of section 5
"5.x Specialization Constant Operations"
Only some operations discussed in this section may be applied to a
specialization constant and still yield a result that is as
specialization constant. The operations allowed are listed below.
When a specialization constant is operated on with one of these
operators and with another constant or specialization constant, the
result is implicitly a specialization constant.
- int(), uint(), float(), and bool() constructors for type conversions
from any of the following types to any of the following types:
* int
* uint
* float
* double
* bool
- vector versions of the above conversion constructors
- allowed implicit conversions of the above
- The operators
* unary negative ( - )
* not ( ! )
* binary operations ( + , - , * , / , % )
* shift ( <<, >> )
* bitwise operations ( & , | , ^ )
* swizzles (e.g., foo.yx)
* logical operations ( && , || , ^^ )
* comparison ( == , != , > , >= , < , <= )
Changes to Chapter 7 of the OpenGL Shading Language Specification
Changes to section 7.1 Built-In Language Variables
Replace gl_VertexID and gl_InstanceID, for non-ES with:
"in int gl_VertexIndex;"
"in int gl_InstanceIndex;"
For ES, add:
"in highp int gl_VertexIndex;"
"in highp int gl_InstanceIndex;"
The following definition for gl_VertexIndex should replace the definition
for gl_VertexID:
"The variable gl_VertexIndex is a vertex language input variable that
holds an integer index for the vertex, [See issue 7 regarding which
name goes with which semantics] relative to a base. While the
variable gl_VertexIndex is always present, its value is not always
defined. See XXX in the API specification."
The following definition for gl_InstanceIndex should replace the definition
for gl_InstanceID:
"The variable gl_InstanceIndex is a vertex language input variable that
holds the instance number of the current primitive in an instanced draw
call, relative to a base. If the current primitive does not come from
an instanced draw call, the value of gl_InstanceIndex is zero."
[See issue 7 regarding which name goes with which semantics]
Changes to section 7.3 Built-In Constants
Add
"const int gl_MaxInputAttachments = 1;"
Changes to Chapter 8 of the OpenGL Shading Language Specification
Add a section
"8.X Subpass Functions
"Subpass functions are only available in a fragment shader.
"Subpass inputs are read through the built-in functions below. The gvec...
and gsubpass... are matched, where they must both be the same floating
point, integer, or unsigned integer variants.
Add a table with these two entries (in the same cell):
"gvec4 subpassLoad(gsubpassInput subpass)
gvec4 subpassLoad(gsubpassInputMS subpass, int sample)"
With the description:
"Read from a subpass input, from the implicit location (x, y, layer)
of the current fragment coordinate."
Changes to the grammar
Arrays can no longer require the size to be a compile-time folded constant
expression. Change
| LEFT_BRACKET constant_expression RIGHT_BRACKET
to
| LEFT_BRACKET conditional_expression RIGHT_BRACKET
and change
| array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET
to
| array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET
Issues
1. Can we have specialization sizes in an array in a block? That prevents
putting known offsets on subsequent members.
RESOLUTION: Yes, but it does not affect offsets.
2. Can a specialization-sized array be passed by value?
RESOLUTION: Yes, if they are sized with the same specialization constant.
3. Can a texture array be variably indexed? Dynamically uniform?
Resolution (bug 14683): Dynamically uniform indexing.
4. Are arrays of a descriptor set all under the same set number, or does, say,
an array of size 4 use up 4 descriptor sets?
RESOLUTION: There is no array of descriptor sets. Arrays of resources
are in a single descriptor set and consume a single binding number.
5. Which descriptor set arrays can be variably or non-uniformly indexed?
RESOLUTION: There is no array of descriptor sets.
6. Do we want an alternate way of doing composite member specialization
constants? For example,
layout(constant_id = 18) gl_WorkGroupSize.y;
Or
layout(constant_id = 18, local_size_y = 16) in;
Or
layout(constant_id = 18) wgy = 16;
const ivec3 gl_WorkGroupSize = ivec3(1, wgy, 1);
RESOLUTION: No. Use local_size_x_id etc. for workgroup size, and
defer any more generalized way of doing this for composites.
7. What names do we really want to use for
gl_VertexIndex base, base+1, base+2, ...
gl_InstanceIndex base, base+1, base+2, ...
RESOLUTION: Use the names above.
Note that gl_VertexIndex is equivalent to OpenGL's gl_VertexID in that
it includes the value of the baseVertex parameter. gl_InstanceIndex is
NOT equivalent to OpenGL's gl_InstanceID because gl_InstanceID does NOT
include the baseInstance parameter.
8. What should "input subpasses" really be called?
RESOLVED: subpassInput.
9. The spec currently does not restrict where sampler constructors can go,
but should it? E.g., can the user write a shader like the following:
uniform texture2D t[MAX_TEXTURES];
uniform sampler s[2];
uniform int textureCount;
uniform int sampleCount;
uniform bool samplerCond;
float ShadowLookup(bool pcf, vec2 tcBase[MAX_TEXTURES])
{
float result = 0;
for (int textureIndex = 0; textureIndex < textureCount; ++textureIndex)
{
for (int sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex)
{
vec2 tc = tcBase[textureIndex] + offsets[sampleIndex];
if (samplerCond)
result += texture(sampler2D(t[textureIndex], s[0]), tc).r;
else
result += texture(sampler2D(t[textureIndex], s[1]), tc).r;
}
Or, like this?
uniform texture2D t[MAX_TEXTURES];
uniform sampler s[2];
uniform int textureCount;
uniform int sampleCount;
uniform bool samplerCond;
sampler2D combined0[MAX_TEXTURES] = sampler2D(t, s[0]);
sampler2D combined1[MAX_TEXTURES] = sampler2D(t, s[1]);
float ShadowLookup(bool pcf, vec2 tcBase[MAX_TEXTURES])
{
for (int textureIndex = 0; textureIndex < textureCount; ++textureIndex) {
for (int sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex) {
vec2 tc = tcBase[textureIndex] + offsets[sampleIndex];
if (samplerCond)
result += texture(combined0[textureIndex], tc).r;
else
result += texture(combined1[textureIndex], tc).r;
}
...
RESOLUTION (bug 14683): Only constructed at the point of use, where passed
as an argument to a function parameter.
Revision History
Rev. Date Author Changes
---- ----------- ------- --------------------------------------------
25 10-Feb-2016 JohnK Incorporate resolutions from the face to face
24 28-Jan-2016 JohnK Update the resolutions from the face to face
23 6-Jan-2016 Piers Remove support for gl_VertexID and
gl_InstanceID since they aren't supported by
Vulkan.
22 29-Dec-2015 JohnK support old versions and add semantic mapping
21 09-Dec-2015 JohnK change spelling *subpass* -> *subpassInput* and
include this and other texture/sample types in
the descriptor-set-0 default scheme
20 01-Dec-2015 JohnK push_constant default to std430, opaque types
can only aggregate as arrays
19 25-Nov-2015 JohnK Move "Shadow" from texture types to samplerShadow
18 23-Nov-2015 JohnK Bug 15206 - Indexing of push constant arrays
17 18-Nov-2015 JohnK Bug 15066: std140/std43 defaults
16 18-Nov-2015 JohnK Bug 15173: subpass inputs as arrays
15 07-Nov-2015 JohnK Bug 14683: new rules for separate texture/sampler
14 07-Nov-2015 JohnK Add specialization operators, local_size_*_id
rules, and input dvec3/dvec4 always use two
locations
13 29-Oct-2015 JohnK Rules for input att. numbers, constant_id,
and no subpassLoadMS()
12 29-Oct-2015 JohnK Explain how gl_FragColor is handled
11 9-Oct-2015 JohnK Add issue: where can sampler constructors be
10 7-Sep-2015 JohnK Add first draft specification language
9 5-Sep-2015 JohnK - make specialization id's scalar only, and
add local_size_x_id... for component-level
workgroup size setting
- address several review comments
8 2-Sep-2015 JohnK switch to using the *target* style of target
types (bug 14304)
7 15-Aug-2015 JohnK add overview for input targets
6 12-Aug-2015 JohnK document gl_VertexIndex and gl_InstanceIndex
5 16-Jul-2015 JohnK push_constant is a layout qualifier
VULKAN is the only versioning macro
constantID -> constant_id
4 12-Jul-2015 JohnK Rewrite for clarity, with proper overview,
and prepare to add full semantics
3 14-May-2015 JohnK Minor changes from meeting discussion
2 26-Apr-2015 JohnK Add controlling features/capabilities
1 26-Mar-2015 JohnK Initial revision