blob: adc26ef7ad4a4c74a11532b06a355ef4af7e444f [file] [log] [blame]
Name
ARB_gl_spirv
Name Strings
GL_ARB_gl_spirv
Contributors
John Kessenich, Google
Daniel Koch, NVIDIA
Christophe Riccio, Unity
Graham Sellers, AMD
Alejandro PiƱeiro, Igalia
Contact Point for Bug Reports
https://github.com/KhronosGroup/OpenGL-Registry/issues/
Notice
Copyright (c) 2015-2019 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.
Ratified by the Khronos Board of Promoters on July 22, 2016.
Version
Last Modified Date: August 19, 2020
Revision: 46
Number
ARB Extension #190
Dependencies
This extension requires version 3.3 or later of The OpenGL Graphics System.
(It is not written for OpenGL ES.)
This extension is written against the following specifications:
- The GL_KHR_vulkan_glsl extension, Version 30, April 12, 2016.
- The OpenGL Graphics System, Version 4.5, Core Profile, May 28, 2015.
- The OpenGL Shading Language, Version 4.50, Revision 6, April 14, 2016.
- SPIR-V Specification, Version 1.00, Revision 5
This extension interacts with ARB_parallel_shader_compile.
This extension interacts with ARB_separate_shader_objects.
This extension interacts with ARB_program_interface_query.
Overview
This is version 100 of the GL_ARB_gl_spirv extension.
This extension does two things:
1. Allows a SPIR-V module to be specified as containing a programmable
shader stage, rather than using GLSL, whatever the source language
was used to create the SPIR-V module.
2. Modifies GLSL to be a source language for creating SPIR-V modules
for OpenGL consumption. Such GLSL can be used to create such SPIR-V
modules, outside of the OpenGL runtime.
Enabling GLSL SPIR-V 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 features 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 OpenGL. Such tool use is outside the
scope of using the OpenGL 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 OpenGL.
When a front-end is used to accept the GLSL features in 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 GLSL SPIR-V support available, using the
predefined
#define GL_SPIRV 100
This allows shader code to say, for example,
#ifdef GL_SPIRV
layout(constant_id = 11) const int count = 4;
#if GL_SPIRV > 100
...
#endif
#else
const int count = 6;
#endif
SPIR-V Modules
--------------
An entire stage is held in a single SPIR-V module. The SPIR-V model is
that multiple (e.g., GLSL) compilation units forming a single stage
in a high-level language are all compiled and linked together to form a
single entry point (and its call tree) in a SPIR-V module. This would be
done prior to using the OpenGL API to create a program object containing the
stage.
The OpenGL API expects the SPIR-V module to have already been validated,
and can return an error if it discovers anything invalid in
the module. An invalid SPIR-V module is allowed to result in undefined
behavior.
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_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 variable (non-block) -> 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. To the extent variables or members are available in a
version and a stage, its location is as follows:
These are mapped to SPIR-V individual variables, with similarly spelled
built-in decorations (except as noted):
General:
in gl_VertexID
in gl_InstanceID
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)
Compute stage only:
in gl_NumWorkGroups
in gl_WorkGroupSize
in gl_WorkGroupID
in gl_LocalInvocationID
in gl_GlobalInvocationID
in gl_LocalInvocationIndex
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 { // some subset of these members will be used
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.
The subset and order of members will match between stages sharing an
interface.
Mapping of precise:
precise -> NoContraction
Mapping of atomic_uint /offset/ layout qualifier
offset -> Offset (decoration)
Mapping of images
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 *Offset*, *ArrayStride*, and *MatrixStride*
Decoration on struct members
shared/packed -> not allowed
<default> -> not shared, but std140 or std430
xfb_offset -> *Offset* Decoration on the object or struct member
xfb_buffer -> *XfbBuffer* Decoration on the object
xfb_stride -> *XfbStride* Decoration on the object
any xfb_* -> the *Xfb* Execution Mode is set
captured XFB -> has both *XfbBuffer* and *Offset*
non-captured -> lacking *XfbBuffer* or *Offset*
max_vertices -> OutputVertices
Mapping of barriers
barrier() (compute) -> OpControlBarrier(/*Execution*/Workgroup,
/*Memory*/Workgroup,
/*Semantics*/AcquireRelease |
WorkgroupMemory)
barrier() (tess control) -> OpControlBarrier(/*Execution*/Workgroup,
/*Memory*/Invocation,
/*Semantics*/None)
memoryBarrier() -> OpMemoryBarrier(/*Memory*/Device,
/*Semantics*/AcquireRelease |
UniformMemory |
WorkgroupMemory |
ImageMemory)
memoryBarrierBuffer() -> OpMemoryBarrier(/*Memory*/Device,
/*Semantics*/AcquireRelease |
UniformMemory)
memoryBarrierShared() -> OpMemoryBarrier(/*Memory*/Device,
/*Semantics*/AcquireRelease |
WorkgroupMemory)
memoryBarrierImage() -> OpMemoryBarrier(/*Memory*/Device,
/*Semantics*/AcquireRelease |
ImageMemory)
groupMemoryBarrier() -> OpMemoryBarrier(/*Memory*/Workgroup,
/*Semantics*/AcquireRelease |
UniformMemory |
WorkgroupMemory |
ImageMemory)
Mapping of atomics
all atomic builtin functions -> Semantics = None(Relaxed)
atomicExchange() -> OpAtomicExchange
imageAtomicExchange() -> OpAtomicExchange
atomicCompSwap() -> OpAtomicCompareExchange
imageAtomicCompSwap() -> OpAtomicCompareExchange
NA -> OpAtomicCompareExchangeWeak
atomicCounterIncrement -> OpAtomicIIncrement
atomicCounterDecrement -> OpAtomicIDecrement (with post decrement)
atomicCounter -> OpAtomicLoad
Mapping of uniform initializers
Using the OpVariable initializer logic, but only from a constant
instruction (not a global one).
Mapping of other instructions
% -> OpUMod/OpSMod
mod() -> OpFMod
NA -> OpSRem/OpFRem
pack/unpack (conversion) -> pack/unpack in GLSL extended instructions
pack/unpack (no conversion) -> OpBitcast
Differences Relative to Other Specifications
--------------------------------------------
The following summarizes the set of differences to existing specifications.
Additional use of existing SPIR-V features, relative to Vulkan:
+ The *UniformConstant* Storage Class can be used on individual
variables at global scope. (That is, uniforms don't have to be in a
block, unless they are built-in members that are in block in GLSL
version 4.5.)
+ *AtomicCounter* Storage Class can use the *Offset* decoration
+ OriginLowerLeft
+ Uniforms support constant initializers.
Corresponding features that GLSL keeps, despite GL_KHR_vulkan_glsl removal:
. default uniforms (those not inside a uniform block)
. atomic-counter bindings have the /offset/ layout qualifier
. special rules for locations for input doubles in the vertex shader
. origin_lower_left
Addition of features to GLSL:
+ specialization constants, as per GL_KHR_vulkan_glsl
+ #define GL_SPIRV 100, when compiled for OpenGL and SPIR-V generation
+ offset can organize members in a different order than declaration order
Non-acceptance of SPIR-V features, relative to Vulkan:
- VertexIndex and InstanceIndex built-in decorations cannot be used
- Push-constant buffers cannot be used
- *DescriptorSet* must always be 0, if present
- input targets and input attachments
- OpTypeSampler
Corresponding features not added to GLSL that GL_KHR_vulkan_glsl added:
. gl_VertexIndex and gl_InstanceIndex
(gl_VertexID and gl_InstanceID have same semantics as in GLSL)
. push_constant buffers
. descriptor sets
. input_attachment_index and accessing input targets
. shader-combining of textures and samplers
Removal of features from GLSL, as removed by GL_KHR_vulkan_glsl:
- subroutines
- the already deprecated texturing functions (e.g., texture2D())
- the already deprecated noise functions (e.g., noise1())
- compatibility profile features
- gl_DepthRangeParameters and gl_NumSamples
- *shared* and *packed* block layouts
Addition of features to The OpenGL Graphics System:
+ a command to associate a SPIR-V module with a program (ShaderBinary)
+ a command to select a SPIR-V entry point and set specialization
constants in a SPIR-V module (SpecializeShaderARB)
+ a new appendix for SPIR-V validation rules, precision, etc.
Changes of system features, relative to Vulkan:
. Vulkan uses only one binding point for a resource array, while OpenGL
still uses multiple binding points, so binding numbers are counted
differently for SPIR-V used in Vulkan and OpenGL
. gl_FragColor can be written to, but it won't broadcast, for versions of
OpenGL that support gl_FragColor
. Vulkan does not allow multi-dimensional arrays of resources like
UBOs and SSBOs in its SPIR-V environment spec. SPIR-V supports
it and OpenGL already allows this for GLSL shaders. SPIR-V
for OpenGL also allows it.
Additions to the SPIR-V specification:
+ *Offset* can also apply to an object, for transform feedback.
+ *Offset* can also apply to a default uniform, for atomic_uint offset.
New Procedures and Functions
void SpecializeShaderARB(uint shader,
const char* pEntryPoint,
uint numSpecializationConstants,
const uint* pConstantIndex,
const uint* pConstantValue);
New Tokens
Accepted by the <binaryformat> parameter of ShaderBinary:
SHADER_BINARY_FORMAT_SPIR_V_ARB 0x9551
Accepted by the <pname> parameter of GetShaderiv:
SPIR_V_BINARY_ARB 0x9552
Modifications to Chapter 7 of the OpenGL 4.5 (Core Profile) Specification
(Programs and Shaders)
Additions to overview of Chapter 7, "Programs and Shaders"
Modify the 4th paragraph beginning with "Alternatively, pre-compiled
shader binary code..." as follows:
"Alternatively, pre-compiled shader binary code can be loaded
into a shader object. A SPIR-V module can also be associated with a
shader and then _specialized_. An implementation must..."
Additions to Section 7.1, "Shader Objects":
Add the following to the end of the description of ShaderSource:
"If <shader> was previously associated with a SPIR-V module (via the
ShaderBinary command), that association is broken. Upon successful
completion of this command the SPIR_V_BINARY_ARB state of <shader>
is set to FALSE."
Add a new error for the CompileShader command:
"An INVALID_OPERATION error is generated if the SPIR_V_BINARY_ARB
state of <shader> is TRUE."
[[ if ARB_parallel_shader_compile is supported: ]]
Modify the preamble to the MaxShaderCompilerThreadsARB command to read:
"Applications may use the following to hint to the driver the maximum
number of background threads it would like to be used in the process
of compiling or specializing shaders, or linking programs, ..."
Additions to Section 7.2, "Shader Binaries":
In the description of ShaderBinary, remove the text stating that GL
defines no specific binary formats and replace it with the following:
"GL defines an execution environment for shaders created from SPIR-V
modules. To load a SPIR-V binary into GL, set <binaryformat> to
SHADER_BINARY_FORMAT_SPIR_V_ARB. <binary> should point to the start
of a valid SPIR-V module binary and <length> should contain the length
of that binary, in bytes. Upon successful consumption of the SPIR-V
module:
* each entry of <shaders> will be associated with that SPIR-V module,
* the SPIR_V_BINARY_ARB state of each shader is set to TRUE,
* the COMPILE_STATUS of each of these shaders is set to FALSE,
* any existing source string (specified by ShaderSource) is removed, and
* any information about a previous compile is lost.
Shaders associated with SPIR-V modules must be finalized by calling
SpecializeShaderARB as described in Section 7.2.1.
GL also provides a mechanism to obtain token values for additional
binary formats provided by extensions. The number of binary formats..."
Replace the error condition for ShaderBinary which states:
"An INVALID_OPERATION error is generated if more than one of the
handles in shaders refers to the same type of shader object."
with the following:
"An INVALID_OPERATION error is generated if <binaryformat> is not
SHADER_BINARY_FORMAT_SPIR_V_ARB and more than one of the
handles in shaders refers to the same type of shader object."
Insert Subsection 7.2.1, "Shader Specialization":
"Shaders associated with SPIR-V modules must be specialized before they
can be linked into a program object. It is not necessary to specialize
the shader before it is attached to a program object. Once specialized,
a shader may not be specialized again without first re-associating the
original SPIR-V module with it, through ShaderBinary.
Specialization does two things:
* Selects the name of the entry point, for that shader's stage, from
the SPIR-V module.
* Sets the values of all, or a subset of, the specialization constants
in the SPIR-V module.
To specialize a shader created from a SPIR-V module, call:
void SpecializeShaderARB(uint shader,
const char* pEntryPoint,
uint numSpecializationConstants,
const uint* pConstantIndex,
const uint* pConstantValue);
<shader> is the name of a shader object containing unspecialized SPIR-V
as created from a successful call to ShaderBinary to which a SPIR-V
module was passed. <pEntryPoint> is a pointer to a NUL-terminated UTF-8
string specifying the name of the entry point in the SPIR-V module to
use for this shader. <numSpecializationConstants> is the number
of specialization constants whose values to set in this call.
<pConstantIndex> is a pointer to an array of
<numSpecializationConstants> unsigned integers, each holding the index
of a specialization constant in the SPIR-V module whose value to set.
The corresponding entry in <pConstantValue> is used to set the value of
the specialization constant indexed by the entry in <pConstantIndex>.
Although this array is of unsigned integer, each entry is bitcast to the
appropriate type for the module, and therefore, floating-point constants
may be set by including their IEEE-754 bit representation in the
<pConstantValue> array. Specialization constants not referenced by
<pConstantIndex> retain their default values as specified in the SPIR-V
module.
On successful shader specialization, the compile status for <shader>
is set to TRUE. On failure, the compile status for <shader> is set to
FALSE and additional information about the cause of the failure may
be available in the shader compilation log. Specialization can fail
if the SPIR-V module fails to meet the requirements listed in Appendix
"The OpenGL SPIR-V Execution Environment".
Errors
An INVALID_VALUE error is generated if <shader> is not the name
of either a program or shader object.
An INVALID_OPERATION error is generated if <shader> is the name
of a program object.
INVALID_OPERATION is generated if the value of SPIR_V_BINARY_ARB
for <shader> is not TRUE, or if the shader has already been
specialized.
INVALID_VALUE is generated if <pEntryPoint> does not match the
<Name> of any OpEntryPoint declaration in the SPIR-V module
associated with <shader>.
INVALID_OPERATION is generated if the <Execution Mode> of the
OpEntryPoint indicated by <pEntryPoint> does not match the type
of <shader>.
INVALID_VALUE is generated if any element of <pConstantIndex>
refers to a specialization constant that does not exist in the
shader module contained in <shader>."
Additions to Section 7.3, "Program Objects":
Modify the first paragraph after the AttachShader command to read:
"Shader objects may be attached to program objects before source code
or shader binary has been loaded into the shader object, or before the
shader object has been compiled or specialized. Multiple shader ..."
Modify the first paragraph after the LinkProgram command to read:
"Linking can fail for a variety of reasons as specified in the OpenGL
Shading language specification for source shaders, or if the requirements
in the Appendix "The OpenGL SPIR-V Execution Environment" are not met
for SPIR-V shaders, as well as any of the following reasons..."
Modify the second bullet point in the list of reasons LinkProgram can
fail:
"One or more of the shader objects attached to <program> are not compiled
or specialized successfully."
Add a new bullet point to this list:
"All the shader objects attached to <program> do not have the same value
for the SPIR_V_BINARY_ARB state."
Modifications to Section 7.3.1, "Program Interfaces"
Add the following paragraph after the list of rules describing how the
name string is generated, before the paragraph that begins "The order
of the active resource list...":
"For shaders constructed from SPIR-V binaries (that is with a state of
SPIR_V_BINARY_ARB equal to TRUE), variables may not have names associated
with them as the OpName and OpMemberName debug instructions are optional
and may not be present in a SPIR-V module. When the Op*Name instructions
are present, it is implementation-dependent if these are reported via
the name reflection APIs. If no _name reflection information_ is
available, the name string associated with each active variable is the
empty string (""). In this case, any queries that operate with a name
as input, will return INVALID_INDEX or -1 as appropriate, and any queries
that return information about the name of a resource will report a
name length of one (for the null character) and return an empty string
with a length of zero."
Add a new subsection "7.4.spv, SPIR-V Shader Interface Matching" after
section 7.4.1 "Shader Interface Matching":
"7.4.spv, SPIR-V Shader Interface Matching
SPIR-V shaders must also follow the rules in this section, whether they
add to or override those given in section 7.4.1 "Shader Interface
Matching." Most importantly, SPIR-V variables and structure members
do not have names and so no interface matching is done by name strings.
All variables forming the input or output interfaces of shader stages
must be listed as operands to the *OpEntryPoint* instruction and are
declared with the *Input* or *Output* Storage Classes, respectively,
in the SPIR-V module.
Shader built-in variables meeting the following requirements define the
built-in interface block. They must:
- be explicitly declared (there are no implicit built-ins),
- be decorated with the *BuiltIn* decoration,
- be declared in a block whose top-level members are the built-ins.
- not have any *Location* or *Component* decorations.
Built-ins only participate in interface matching if they are declared in
such a block. There must be no more than one built-in interface block
per shader per interface.
User-defined interface variables must be decorated with a *Location*
and can also be decorated with a *Component*. These correspond to the
location and component discussed in section 7.4.1 "Shader Interface
Matching". Uniform and shader storage block variables must also be
decorated with a *Binding*.
A user-defined output variable is considered to match an input variable
in the subsequent stage only if the two variables are declared with the
same *Location* and *Component* decoration and match in type and
decoration, except that interpolation decorations are not required to
match.
Variables or block members declared as structures are considered to
match in type if and only if the structure members match in type,
decoration, number, and declaration order. Variables or block members
declared as arrays are considered to match in type only if both
declarations specify the same element type and size.
At an interface between two non-fragment shader stages, the built-in
interface block must match exactly, as described above. At an interface
involving the fragment shader inputs, the presence or absence of any
built-in output does not affect the interface matching.
At an interface between two shader stages, the user-defined variable
interface must match exactly. Additionally, scalar and vector inputs
are well-defined if there is a corresponding output satisfying all of
the following conditions:
- the input and output match exactly in decoration,
- the output is a vector with the same basic type and has at least as
many components as the input, and
- the common component type of the input and output is 32-bit integer
or floating-point (64-bit component types are excluded).
In this case, the components of the input will be taken from the first
components of the output, and any extra components of the output will
be ignored."
Add a new subsection 7.6.2.spv "SPIR-V Uniform Offsets and Strides" after
section 7.6.2.2 "Standard Uniform Block Layout":
"7.6.2.spv SPIR-V Uniform Offsets and Strides
The SPIR-V decorations *GLSLShared* or *GLSLPacked* must not be used. A
variable in the *Uniform* Storage Class decorated as a *Block* or
*BufferBlock* must be explicitly laid out using the *Offset*, *ArrayStride*,
and *MatrixStride* decorations. These must follow the alignment rules listed
above, but not necessarily the packing rules. More specifically, explicit
SPIR-V offsets and strides must obey the following:
Define the /base alignment/ recursively as:
- A scalar of size N has a base alignment of N.
- A two-component vector, with components of size N, has a base alignment
of 2N.
- A three- or four-component vector, with components of size N, has a base
alignment of 4N.
- An array has a base alignment equal to the base alignment of its element
type, rounded up to a multiple of 16.
- A structure has a base alignment equal to the largest base alignment of
any of its members, rounded up to a multiple of 16.
- A row-major matrix of C columns has a base alignment equal to the base
alignment of a vector of C matrix components.
- A column-major matrix has a base alignment equal to the base alignment
of the matrix column type.
Given this definition, blocks must be laid out such that:
- The *Offset* decoration must be a multiple of its base alignment.
- Any *ArrayStride* or *MatrixStride* decoration must be an integer
multiple of the base alignment of the array or matrix.
- The *Offset* decoration of a member must not place it between the end of
a structure or an array and the next multiple of the base alignment of
that structure or array.
- The numeric order of *Offset* decorations need not follow member
declaration order.
With one exception: Variables in the *Uniform* storage class with a
decoration of *BufferBlock* do not need their base alignments rounded up
to a multiple of 16.
Modifications to Section 7.13 "Shader, Program, and Program Pipeline Queries"
Add the following to the list of <pname> that are accepted by GetShaderiv:
"If <pname> is SPIR_V_BINARY_ARB, TRUE is returned if the shader has been
successfully associated with a SPIR-V binary module by the ShaderBinary
command and FALSE is returned otherwise."
Modify the description of COMPILE_STATUS to be as follows:
"If <pname> is COMPILE_STATUS, TRUE is returned if the shader was last
compiled or specialized successfully, and FALSE is returned otherwise."
[[ if ARB_parallel_shader_compile is supported: ]]
Modify the description of COMPLETION_STATUS_ARB to be as follows:
"If <pname> is COMPLETION_STATUS_ARB, FALSE is returned if the shader is
currently being compiled or specialized by a background thread, TRUE
otherwise."
Modify the Errors list for GetShaderiv and add SPIR_V_BINARY_ARB to the
list of <pname> that are accepted.
In the description of the GetProgramiv command, modify the definitions of
the ACTIVE_ATTRIBUTE_MAX_LENGTH, ACTIVE_UNIFORM_MAX_LENGTH,
TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, and
ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH <pname> values to be as follows:
"If pname is ACTIVE_ATTRIBUTE_MAX_LENGTH, the length of the longest
active attribute name, including a null terminator, is returned.
If no active attributes exist, zero is returned. If no name reflection
information is available, one is returned."
"If pname is ACTIVE_UNIFORM_MAX_LENGTH, the length of the longest active
uniform name, including a null terminator, is returned. If no active
uniforms exist, zero is returned. If no name reflection information is
available, one is returned."
"If pname is TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, the length of the
longest output variable name specified to be used for transform feedback,
including a null terminator, is returned. If no outputs are used for
transform feedback, zero is returned. If no name reflection information
is available, one 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. If no active uniform blocks exist, zero is returned. If no
name reflection information is available, one is returned."
Modify the description of GetShaderInfoLog to read as follows:
"If <shader> is a shader object, GetShaderInfoLog will return either
an empty string or information about the last compilation or
specialization attempt for that object."
Modifications to Section 7.14 "Required State":
Add to the list of state per shader object:
"A boolean holding the SPIR-V binary status, initially FALSE."
Modifications to Chapter 11 of the OpenGL 4.5 (Core Profile) Specification
(Programmable Vertex Processing)
Modify Section 11.1.1 "Vertex Attributes"
Replace the last sentence in the first paragraph ("This binding can be..")
with the following:
"This binding can be specified in the shader text using the location
qualifier, in a SPIR-V shader using the *Location* decoration, by the
application before the program is linked, or automatically assigned by
the GL when the program is linked."
In the second paragraph of the definition of BindAttribLocation, replace
occurrences of "shader text" with "shader text or SPIR-V binary".
Add to the end of the third paragraph of the definition of
BindAttribLocation:
"BindAttribLocation has no effect on SPIR-V shaders as the locations
must always be fully specified in the SPIR-V shader as described in
section 11.1.1.1 (SPIR-V Vertex Input Interface)."
Add the following new subsection to the end of section 11.1.1
"Vertex Attributes":
"Section 11.1.1.1 SPIR-V Vertex Input interface
When a SPIR-V vertex stage is present, the vertex shader
variables listed by *OpEntryPoint* with the *Input* Storage Class
form the vertex input attribute interface. These inputs must be
decorated with a *Location* and can also be decorated with a
*Component* decoration. These correspond to the location and
component layout discussed in section 11.1.1 "Vertex Attributes."
The vertex shader input variables are matched only by the
*Location* and *Component* decorations, and must have a corresponding
attribute and binding in the pipeline."
Modify section 11.1.2.1 "Output Variables"
Replace the first sentence of the second paragraph describing transform
feedback mode ("The set of variables to record...") with the following:
"The set of variables to record can be specified in shader text using
xfb_buffer, xfb_offset, or xfb_stride layout qualifiers. For SPIR-V
shaders, these are specified by the *XfbBuffer*, *Offset*, and *XfbStride*
decorations, respectively. When a SPIR-V entry point is using any of these
for transform feedback, it must declare the *Xfb* Execution Mode."
Modify the last paragraph of the definition of TransformFeedbackVaryings
("If the shader is used to record...") as follows:
"If the shader used to record output variables for transform feedback
varyings uses the xfb_buffer, xfb_offset, or xfb_stride layout qualifiers,
or its SPIR-V entry point declares the *Xfb* Execution Mode, the values
specified by TransformFeedbackVaryings are ignored, and the set of
variables captured for transform feedback is instead derived from the
specified layout qualifiers or SPIR-V decorations: outputs specifying both
an *XfbBuffer* and an *Offset* are captured, while outputs not specifying
both of these are not captured. Values are captured each time the shader
writes to such a decorated object."
Modifications to Chapter 15 of the OpenGL 4.5 (Core Profile) Specification
(Programmable Fragment Processing)
Modify section 15.2.3 "Shader Outputs"
Replace the sentence leading up to the definition of the
BindFragDataLocationIndexed command with the following:
"The binding of a user-defined output variable to components of a
fragment color number can be specified explicitly in the shader text,
SPIR-V shader, or using the command ..."
Modify the paragraph following the definition of BindFragDataLocation,
replacing the second and third sentences with the following:
"Output variables declared with location, component, or index layout
qualifiers will use the values specified in the shader text. For SPIR-V
shaders, these are specified by the *Location*, *Component*, and *Index*
decorations. Output variables without such layout or decoration qualifiers
will use the bindings specified by BindFragDataLocationIndexed or
BindFragDataLocation, if any. BindFragDataLocation* has no effect on
SPIR-V shaders as the locations must always be fully specified as
described in section 15.2.3.1 (SPIR-V Fragment Output Interface)."
Add the following new subsection to the end of 15.2.3 "Shader Outputs"
"Section 15.2.3.1 "SPIR-V Fragment Output Interface"
When a SPIR-V fragment stage is present, the variables listed by
*OpEntryPoint* with the *Output* Storage Class form the fragment
output interface. These variables must be decorated with a *Location*
They can also be decorated with a *Component* and/or an *Index*.
User-defined fragment shader output variables are matched only by their
*Location*, *Component*, and *Index* decorations. If two outputs
are placed within the same location, they must have the same underlying
type (floating-point or integer). No component aliasing of output
variables is allowed. That is, there must not be two output variables
which have the same location, component, and index, either explicitly
declared or implied. Output values written by a fragment shader must
be declared with either *OpTypeFloat* or *OpTypeInt*, and a *Width* of
32. Composites of these types are also permitted."
Add Appendix A.spv "The OpenGL SPIR-V Execution Environment" to the OpenGL 4.5
(Core Profile) Specification
"A.spv.1 (Required Versions and Formats)
An implementation of this extension must support the 1.0 version of
SPIR-V and the 1.0 version of the SPIR-V Extended Instructions for GLSL.
A SPIR-V module passed into ShaderBinary is interpreted as a series of
32-bit words in host endianness, with literal strings packed as described
in section 2.2 of the SPIR-V Specification. The first few words of the
SPIR-V module must be a magic number and a SPIR-V version number, as
described in section 2.3 of the SPIR-V Specification.
A.spv.2 (Valid SPIR-V Built-In Variable Decorations)
Implementations supporting GL 4.5 must support the following
built-in variable decorations. When used with earlier versions
of GL, this list may be subset to the functionality in that
version. Each built-in below lists the minimum OpenGL version
(or extension) that is required to use the built-in variable
decoration.
Built-in Variable Decoration Minimum GL version (Extension)
---------------------------- -----------------------------
NumWorkgroups GL 4.3 (ARB_compute_shader)
WorkgroupSize GL 4.3 (ARB_compute_shader)
WorkgroupId GL 4.3 (ARB_compute_shader)
LocalInvocationId GL 4.3 (ARB_compute_shader)
GlobalInvocationId GL 4.3 (ARB_compute_shader)
LocalInvocationIndex GL 4.3 (ARB_compute_shader)
VertexId
InstanceId
Position
PointSize
ClipDistance
CullDistance GL 4.5 (ARB_cull_distance)
PrimitiveId
InvocationId GL 4.0 (ARB_tessellation_shader)
Layer
ViewportIndex GL 4.1 (ARB_viewport_array)
PatchVertices GL 4.0 (ARB_tessellation_shader)
TessLevelOuter GL 4.0 (ARB_tessellation_shader)
TessLevelInner GL 4.0 (ARB_tessellation_shader)
TessCoord GL 4.0 (ARB_tessellation_shader)
FragCoord
FrontFacing
PointCoord
SampleId GL 4.0 (ARB_sample_shading)
SamplePosition GL 4.0 (ARB_sample_shading)
SampleMask GL 4.0 (ARB_sample_shading)
HelperInvocation GL 4.5 (ARB_ES3_1_compatibility)
FragDepth
A.spv.3 (Valid SPIR-V Capabilities)
Implementations supporting OpenGL 4.5 must support the following
capability operands declared by OpCapability.
When used against earlier versions of GL, this list may be subset
to the functionality in that version. Each capability below lists
the OpenGL version (or extension) that is required to use the
OpCapability.
OpCapability Minimum GL version (Extension)
------------------------------ -----------------------------
Matrix
Shader
Geometry
Tessellation GL 4.0 (ARB_tessellation_shader)
Float64 GL 4.0 (ARB_gpu_shader_fp64)
AtomicStorage GL 4.2 (ARB_shader_atomic_counters)
TessellationPointSize GL 4.0 (ARB_tessellation_shader)
GeometryPointSize
ImageGatherExtended GL 4.0 (ARB_gpu_shader5)
StorageImageMultisample GL 4.2 (ARB_shader_image_load_store)
UniformBufferArrayDynamicIndexing GL 4.0 (ARB_gpu_shader5)
SampledImageArrayDynamicIndexing GL 4.0 (ARB_gpu_shader5)
StorageBufferArrayDynamicIndexing GL 4.3 (ARB_shader_storage_buffer_object)
StorageImageArrayDynamicIndexing GL 4.2 (ARB_shader_image_load_store)
ClipDistance
CullDistance GL 4.5 (ARB_cull_distance)
ImageCubeArray GL 4.0 (ARB_texture_cube_map_array)
SampleRateShading GL 4.0 (ARB_sample_shading)
ImageRect
SampledRect
Sampled1D
Image1D
SampledCubeArray GL 4.0 (ARB_texture_cube_map_array)
SampledBuffer
ImageBuffer
ImageMSArray
StorageImageExtendedFormats GL 4.2 (ARB_shader_image_load_store)
ImageQuery
DerivativeControl GL 4.5 (ARB_derivative_control)
InterpolationFunction GL 4.0 (ARB_gpu_shader5)
TransformFeedback
GeometryStreams GL 4.0 (ARB_gpu_shader5)
StorageImageWriteWithoutFormat GL 4.2 (ARB_shader_image_load_store)
MultiViewport GL 4.1 (ARB_viewport_array)
Implementations supporting ARB_gpu_shader_int64 must support the
following operand declared by OpCapability:
Int64
Implementations supporting ARB_sparse_texture2 must support the
following operand declared by OpCapability:
SparseResidency
Implementations supporting ARB_sparse_texture_clamp must support the
following operand declared by OpCapability:
MinLod
Implementations supporting EXT_shader_image_load_formatted must
support the following operand declared by OpCapability:
StorageImageReadWithoutFormat
Implementations supporting NV_shader_atomic_int64 must support the
following operand declared by OpCapability:
Int64Atomics
A.spv.4 (Validation rules)
(in addition to what's allowed/disallowed above)
Every entry point must have no return value and accept no arguments.
The *Logical* addressing model must be selected.
*Scope* for execution must be limited to:
- Workgroup
- Subgroup
*Scope* for memory must be limited to:
- Device
- Workgroup
- Invocation
*Storage Class* must be limited to:
- *UniformConstant*
- *Input*
- *Uniform*
- *Output*
- *Workgroup*
- *Private*
- *Function*
- *AtomicCounter*
- *Image*
Images:
- OpTypeImage must declare a scalar 32-bit float or 32-bit integer
type for the /Sampled Type/.
- OpSampledImage, OpImageQuerySizeLod, and OpImageQueryLevels must
only consume an /Image/ operand whose type has its /Sampled/
operand set to 1.
- The /Depth/ operand of OpTypeImage is ignored.
- The Image Format of OpImageWrite must not be Unknown, unless the
StorageImageWriteWithoutFormat OpCapability was declared.
*AtomicCounter* storage class:
- Unless otherwise specified, variables declared in the AtomicCounter
storage class must be unsigned 32-bit integers.
- When using the Atomic Instructions, the 'Memory Semantics' operand
must be *AtomicCounterMemory*, without inclusion of memory-ordering
bits (implying *Relaxed* semantics).
Decorations:
- The Flat, NoPerspective, Sample, and Centroid decorations must not
be used on variables with Storage Class other than *Input* or on
variables used in the interface of non-fragment shader entry points.
- The Patch decoration must not be used on variables in the interface
of a vertex, geometry, or fragment shader stage's entry point.
- OpTypeRuntimeArray must only be used for the last member of an
OpTypeStruct in the Uniform Storage Class and is decorated as
BufferBlock.
- If the *Xfb* Execution Mode is set, any output variable that is at
least partially captured:
* must be decorated with an *XfbBuffer*, declaring the capturing buffer
* must have at least one captured output variable in the capturing
buffer decorated with an *XfbStride* (and all such *XfbStride* values
for the capturing buffer must be equal)
- If the *Xfb* Execution Mode is set, any captured output:
* must be a non-structure decorated with *Offset* or a member of a
structure whose type member is decorated with *Offset*
(not all members of such a struct need be captured)
* must be a numerical type scalar, vector, matrix, or array of these
* must have an *Offset* that is a multiple of its first component
* must have an *Offset* that is a multiple of 8 if any captured output
in the capturing buffer is a 64-bit type, in which case the
corresponding *XfbStride* must also be a multiple of 8
* must not overlap (i.e., alias in any capturing buffer) any other
captured output
* must not have an *Offset* that causes overflow of the *XfbStride*
Compute Shaders
- For each compute shader entry point, either a LocalSize execution
mode or an object decorated with the WorkgroupSize decoration must
be specified.
Recursion:
- For all entry points, the static function-call graph rooted at that
entry point must not contain cycles.
User declared input and output variables:
- Must not use OpTypeBool, either directly or as part of an aggregate.
Atomic Access Rules:
- Atomic instructions must declare a scalar 32-bit integer type, or a
scalar 64-bit integer type if the *Int64Atomics* capability is enabled,
for the value pointed to by *Pointer*
A.spv.5 (Precision and Operation of SPIR-V Instructions)
The following rules apply to both single and double-precision floating
point instructions:
- Positive and negative infinities and positive and negative zeros are
generated as dictated by [IEEE 754], but subject to the precisions
allowed in the following table.
- Dividing a non-zero by a zero results in the appropriately signed
IEEE 754 infinity.
- Any denormalized value input into a shader or potentially generated
by any instruction in a shader may be flushed to 0.
- The rounding mode cannot be set and is undefined.
- NaNs are not required to be generated. Instructions that operate on
a NaN are not required to return a NaN as the result.
- Support for signaling NaNs is optional and exceptions are never
raised.
The precision of double-precision instructions is at least that of
single precision. For single precision (32 bit) instructions,
precisions are required to be at least as follows:
Instruction Precision
----------- ---------
OpFAdd Correctly rounded
OpFSub Correctly rounded
OpFMul Correctly rounded
OpFOrdEqual, OpFUnordEqual Correct result
OpFOrdLessThan, OpFUnordLessThan Correct result
OpFOrdGreaterThan, OpFUnordGreaterThan Correct result
OpFOrdLessThanEqual, OpFUnordLessThanEqual Correct result
OpFOrdGreaterThanEqual, OpFUnordGreaterThanEqual Correct result
OpFDiv 2.5 ULP for b in the
range [2^(-126), 2^(126)]
conversions between types Correctly rounded
A.spv.6 (Precision of GLSL.std.450 Instructions)
Instruction Precision
----------- ---------
fma() Inherited from OpFMul followed by OpFAdd.
exp(x), exp2(x) (3+2*|x|) ULP
log(), log2() 3 ULP outside the range [0.5, 2.0]
absolute error < 2^(-21) inside the range [0.5, 2.0]
pow(x, y) Inherited from exp2(y * log2(x))
sqrt() Inherited from 1.0 / inversesqrt()
inversesqrt() 2 ULP
GLSL.std.450 extended instructions specifically defined in terms of
the above instructions inherit the above errors. GLSL.std.450
extended instructions not listed above and not defined in terms of the
above have undefined precision. These include, for example, the
trigonometric functions and determinant.
For the OpSRem and OpSMod instructions, if either operand is negative
the result is undefined.
Changes to The OpenGL Shading Language Specification, Version 4.50
Changes to Chapter 1 of the OpenGL Shading Language 4.50 Specification
(Introduction)
Add a paragraph: "The OpenGL API will specify the OpenGL commands used to
manipulate SPIR-V shaders. Independent offline tool chains will compile
GLSL down to the SPIR-V intermediate language. SPIR-V generation is not
enabled with a #extension, #version, or a profile. Instead, use of GLSL
for SPIR-V is determined by offline tool-chain use. See the documentation
of such tools to see how to request generation of SPIR-V for OpenGL."
"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 3 of the OpenGL Shading Language 4.50 Specification
(Basics)
After describing the compatibility profile rules, add:
"Compatibility-profile features are not available when generating SPIR-V."
Add a new paragraph at the end of section "3.3 Preprocessor": "When
shaders are compiled for OpenGL SPIR-V, the following predefined macro is
available:
#define GL_SPIRV 100
Changes to Chapter 4 of the OpenGL Shading Language 4.50 Specification
(Variables and Types)
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 bullet
"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 bullet
"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
------------------------------------------------------------------------
(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."
At the end of the paragraphs describing the *location* rules, add this
paragraph:
"When generating SPIR-V, all *in* and *out* qualified user-declared
(non built-in) variables and blocks (or all their members) must have a
shader-specified *location*. Otherwise, a compile-time error is
generated."
[Note that an earlier existing rule just above this says "If a block has
no block-level *location* layout qualifier, it is required that either all
or none of its members have a *location* layout qualifier, or a compile-
time error results."]
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 workgroup 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
"Types containing arrays sized with a specialization constant cannot be
compared, assigned as aggregates, declared with an initializer, or used
as an initializer. They can, however, be passed as arguments to
functions having formal parameters of the same type.
"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."
Change section 4.4.5 Uniform and Shader Storage Block Layout Qualifiers
Add
"The 'shared' and 'packed' layout qualifiers are not available when
generating SPIR-V."
Change
"The initial state of compilation is as if the following were declared:"
To
"The initial state of compilation when generating SPIR-V is as if the
following were declared:"
layout(std140, column_major) uniform;
layout(std430, column_major) buffer;
"The initial state of compilation when not generating SPIR-V is as if
the following were declared:..."
Change
"It is a compile-time error to specify an offset that is smaller than
the offset of the previous member in the block or that lies within the
previous member of the block."
To
"It is a compile-time error to have any offset, explicit or assigned,
that lies within another member of the block. When not generating
SPIR-V, it is a compile-time error to specify an offset that is smaller
than the offset of the previous member in the block."
Changes to Chapter 5 of the OpenGL Shading Language 4.50 Specification
(Operators and Expressions)
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(), and bool() constructors for type conversions
from any of the following types to any of the following types:
* int
* uint
* bool
- vector versions of the above conversion constructors
- allowed implicit conversions of the above
- swizzles (e.g., foo.yx)
- The following when applied to integer or unsigned integer types:
* unary negative ( - )
* binary operations ( + , - , * , / , % )
* shift ( <<, >> )
* bitwise operations ( & , | , ^ )
- The following when applied to integer or unsigned integer scalar types:
* comparison ( == , != , > , >= , < , <= )
- The following when applied to the Boolean scalar type:
* not ( ! )
* logical operations ( && , || , ^^ )
* comparison ( == , != )
- The ternary operator ( ? : )
Changes to Chapter 6 of the OpenGL Shading Language 4.50 Specification
Add at the beginning of section 6.1.2 Subroutines:
"Subroutine functionality is not available when generating SPIR-V."
Changes to Chapter 7 of the OpenGL Shading Language 4.50 Specification
(Built-In Variables)
Add to the beginning of section 7.4 Built-In Uniform State:
"Built-in uniform state is not available when generating SPIR-V."
Section 8.14 "Noise Functions"
Add: "Noise functions are not present when generating SPIR-V."
Changes to Chapter 9 of the OpenGL Shading Language 4.50 Specification
(Shading Language Grammar for Core Profile)
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
Changes to the SPIR-V specification
Section 3.20. Decoration
*Offset* can also apply to an object, for transform feedback.
*Offset* can also apply to an object in AtomicCounter storage for an
atomic counter.
Dependencies on ARB_parallel_shader_compile
If ARB_parallel_shader_compile is supported, the shader specialization
may occur on a background thread in the same manner that compiling and
linking does.
Dependencies on ARB_separate_shader_objects
If ARB_separate_shader_objects is not supported, ignore all references
to separable program objects.
Dependencies on ARB_program_interface_query
If ARB_prorgram_interface_query is not supported, ignore references
to commands added by this extension, however other commands defined
in terms of these functions still operate as specified before the
addition of the program interface query extension.
New State
Add the following to Table 23.30 "Shader Object State"
Get Value Type Get Command Initial Value Description Sec
----------------- ----- ------------ ------------- --------------------- ---
SPIR_V_BINARY_ARB B GetShaderiv FALSE Shader is associated 7.2
with a SPIR-V module.
Usage Example
const uint* pSpirVModule; // This points to the SPIR-V code in memory
uint spirVLength; // Length of pSpirVModule in bytes.
// Create the shader object.
GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
// Load the SPIR-V module into the shader object
glShaderBinary(1, &shader,
GL_SHADER_BINARY_FORMAT_SPIR_V_ARB,
pSpirVModule, spirVLength);
// This will now return FALSE
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
// Specialize the shader
const GLuint constantIndices[] = { 0, 7, 3 };
const GLuint constantValues[] = { 1, 42, 0x3F800000 };
glSpecializeShaderARB(shader,
"main",
3,
constantIndices,
constantValues);
// This should now return TRUE
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
// Create a program, attach our shader to it, and link
GLuint program = glCreateProgram();
glAttachShader(program, shader);
glLinkProgram(program);
Issues
1. Do we need separate extensions to expose legacy GLSL and ESSL legacy
capabilities in SPIR-V?
DISCUSSION:
When GLSL was created, multiple extensions were simultaneously introduced
to separate the API mechanism (ARB_shader_objects), the shading language
(GL_ARB_shading_language_100) and the shader stages (GL_ARB_vertex_shader,
GL_ARB_fragment_shader).
We can expect that future versions of OpenGL will support SPIR-V
as well but with a different set of capabilities.
Additionally, it's probably enough for the ARB to only define a SPIR-V
capabilities for OpenGL 4.5 but SPIR-V is not only going to be consumed by
OpenGL implementation but also by engine tool chains which can't afford to
only support the last version of OpenGL. As a result Unity would define its
own private extensions at least to clearly define the capability sets our
engine supports at time T, e.g.: GL_UNITY_spirv_webgl,
GL_UNITY_spirv_base_level, GL_UNITY_spirv_base_compute,
GL_UNITY_spirv_max_level, etc to target older versions of OpenGL without
being forced to use a specific GLSL version.
For example, GL_UNITY_spirv_base_compute has a feature subset between
GLSL 420 + GL_ARB_shader_storage_buffer_object + GL_ARB_compute_shader +
GL_ARB_shader_image_load_store and GLES 310 would correspond to what we
call an OpenGL device level in Unity 5.1.
We should except that many engines would have the need of such ISV
specific capability sets. This said it's important for the Khronos Group
to set future convergence point but OpenGL 4.5 is not realistic today, which
is the domain where ISVs must work.
Possible Resolution:
Two extensions:
- GL_ARB_program_binary_spirv to specify the mechanism.
- GL_ARB_spir_v_gl_450 to specify the required SPIR-V capabilities for
OpenGL 4.5.
Key data needed: What will IHVs actually support?
RESOLVED:
Minimum: 3.3 for desktop
3.1 for ES [ however, ES is not covered by this extension ]
Need to add capabilities needed to distinguish between 3.3 and 4.5.
See bug 14520 for data on fine-grained capabilities and other
relevant details.
2. Do we want to look at SPIR-V as a shading language or a binary format?
DISCUSSION:
Practically, this issue is about whether we want to load SPIR-V
through the shader object API, the program binary API or do we need
a new construct. Unfortunately, there is a lot of issues with the
two first options and the third might be a little too complex.
Support through program binary API:
- SPIR-V is the standard binary format
- It makes SPIR-V a post LinkProgram construct
- No location remapping is possible (glBindAttribLocation,
glBindFragDataLocation[Indexed])
- Can't support multiple OpEntryPoint instructions
- Can't provide program arguments (alternative to #pragma)
- Can't retrieve SPIR-V source. GL_NUM_PROGRAM_BINARY_FORMATS can
enumerate multiple format but glGetProgramBinary doesn't allow us to
select the format we want to query back.
- Currently SPIR-V doesn't support multiple shader stages per module
but this would be useful for linked programs.
Support through shader object API:
- OpenGL API allows to attach multiple shader objects but SPIR-V modules
are fully contained: A single module define the entire stage.
- SPIR-V modules don't have to support multiple stage per module but we
lose the represent linked program and perform offline cross shader stage
dead code elimination.
- Need a new glCompileShader variant to support multiple entry-points
(OpEntryPoint) or compilation arguments (OpCompileFlag)
- glShaderSource doesn't allow to specify the shading language. Is looking
at the first bytes to check the magic string okay?
- Reflection may be striped from SPIR-V modules
Support through new API, "modules":
// The difference between a module and a shader:
// - Can contain multiple entry points
// - Could specify the language, support both GLSL and SPIR-V (maybe)
// - Can contain multiple shader stages
// - Cross shader stage dead code elimination could be perform offline. (How to hint the compiler? OpCompileFlag?)
// - Could be faster to compile shader variants?
// - Programs created with glLinkProgramModule don't need GL_PROGRAM_SEPARABLE
// - No need to specify the shader stage at object creation, it's embedded in the SPIR-V module
GLint length = 0;
GLbyte* binary = LoadBinary(Path, &length);
GLuint ModuleName = 0;
glCreateModules(1, &ModuleName);
glCompileModule(ModuleName, GL_SHADING_LANGUAGE_SPIR_V, &binary, &length);
GLboolean HasReflection = GL_FALSE;
glGetModuleiv(ModuleName, GL_MODULE_REFLECTION, &HasReflection);
GLuint ProgramName[2];
glCreatePrograms(2, &ProgramName[0]);
assert(HasReflection == GL_TRUE);
GLchar const * Strings[] = {"gl_Position", "block.Color"};
glTransformFeedbackVaryings(ProgramName[0], 2, Strings, GL_INTERLEAVED_ATTRIBS);
glBindAttribLocation(ProgramName[0], 0, "Position");
glBindAttribLocation(ProgramName[0], 1, "Color");
glBindFragDataLocation(ProgramName[0], 0, "Color");
glLinkProgramModule(ProgramName[0], ModuleName, "mainA", "-pragma optimize(on)");
glLinkProgramModule(ProgramName[1], ModuleName, "mainB", "-pragma optimize(on)");
Other notes:
- API doesn't require GLSL -> SPIR-V followed by getProgramBinary()
* need an ID for specifying you want a SPIR-V binary?
(christophe) GetProgramBinary doesn't do conversion, currently we would retrieve a SPIR-V
is the program binary was a SPIR-V binary. However, that would prevent query a of native
binary cache. I guess we could add a program parameter or specific that if we use
GL_PROGRAM_BINARY_RETRIEVABLE_HINT GetProgramBinary return a native program binary cache,
otherwise we get a SPIR-V binary back.
- LoadProgramBinary() needs a flag to link by SSO or by name?
* or does API spec. just say this comes from using SSO mode or...?
(christophe) GL_PROGRAM_SEPARABLE doesn't change linking by name or by location.
In GLSL 450, when locations are present, we link by location. Otherwise, we link by name.
GL_PROGRAM_SEPARABLE protects the shader code against a backward compatibility change regarding
gl_PerVertex block. With separated shader stages, the block must be declared in the shader will
before it was optional. This behavior was requested by AMD during the separated program
ratification process.
Neither the program binary API or the shader object API
seem to match SPIR-V features. Creating a new module API has potential but maybe
we could build something around the shader object.
RESOLVED: Use the existing ShaderBinary() and a new entry point,
SpecializeShaderARB() to set specialization constants.
3. Allow more than one stage per SPIR-V module?
DISCUSSION:
SPIR-V supports multiple entry points per module, of any stage, or any
number of instances of the same stage. However, the knowledge of which
of those might be used together lies outside the module.
OpenGL supports both linked programs and separated programs. If we
consider strict separated programs with a program per shader stage, we can
rely on a SPIR-V module per program. However, linked programs allows
combining multiple shader stages into a single program. Furthermore,
linked programs are more efficient than separated programs as the
implementation can perform cross shader stages optimizations and packing of
inputs and outputs with linked programs.
Allowing multiple shader stage in a module would profile a semantic for
linked programs and would allow performing dead code elimination and input
and output location packing offline.
RESOLVED: Allow full generality of what SPIR-V supports, and have
the new entry points in the API select the subset of a module that it
cares about.
4. Do we want to expose multiple entry points?
DISCUSSION:
SPIR-V supports multiple entry points through the OpEntryPoint
instruction. Do we want to expose this?
A way to expose it would be to introduce a variant of glLinkProgram
which takes the entry point main as an argument.
Typically, engines such as UE4 and Unity are rebuilding a big shared shader
library over and over again for each shader variation.
While orthogonal to GL_ARB_program_instance, this feature would work
extremely well with program instance for an application.
We could defer but I'll rather have all the SPIR-V interactions
mechanisms defined in one extension from start to provide first class
citizenship to SPIR-V.
RESOLVED: This is mostly a duplicate of Issue 3, and a single resolution
for both is needed there in that one place.
5. Do we want to add support for "constantId" in OpenGL?
RESOLVED: Have the new entry points in the API support specializing
constants, as in Vulkan.
6. Do we want to support multiple modules per program
DISCUSSION:
A use case could be to compile subroutines into different modules
and link a set of subroutines we want to use into a program canvas.
In another use case, using multiple entry points we could build multiple
code paths sharing the same shader library.
SPIR-V for Vulkan currently expects fully linked stages.
This could be part of a much needed rework or the subroutines.
Okay to defer for now.
RESOLVED: Fully linked modules only, no direct "subroutine" support.
7. Do we want to be able to provide compilation arguments?
DISCUSSION:
SPIR-V supports the OpCompileFlag instructions to store
compilation arguments however OpenGL doesn't support compilation
arguments. If we add a new variant of glLinkProgram, it could be an
opportunity to add a compilation arguments parameter to glLinkProgram.
Some use cases:
- Compiling the shaders with different optimizations: It's currently
supported with #pragma but SPIR-V doesn't contain preprocessor
information
- Vendors refused to fix GLSL bugs and there are a lot of them. The
reason is that fixing these bugs could cause to break shader compilation
hence applications. If we want to start a virtue circle, we need to
give developers the opportunity to enforce conformant compilation.
- Display on or off warnings in the compilation log.
- All the cool stuff C++ compilers are using compilation arguments for.
Note that the instruction OpCompileFlag was removed from SPIR-V, and
a Bug 13418 "Need a way to control target-compiler behavior from the API"
was deferred to a future release.
RESOLVED: No flags in first release.
8. Do we want to build a reflection API on SPIR-V modules specifics?
- Retrieve compilation arguments
- Retrieve shader stages included
- Retrieve the list of entry points
- Retrieve the list of required capabilities
Arguably, it's trivial to build a SPIR-V parser and figure this out
ourselves.
DISCUSSION:
If drivers implement SPIR-V support by lowering it to the same
representation that GLSL is lowered to, and that representation is the
source of reflection information, much reflection would naturally be
present.
RESOLVED: First start without reflection, then add later if needed.
In the meantime, we have to document how the existing API operates
with no reflection information. See Issue 22.
9. Separate programs require gl_PerVertex output blocks to be declared.
How do we enforce this requirement in SPIR-V modules?
DISCUSSION: Force compiler to generate a gl_PerVertex block if the
shader code writes vertex-shader output built-ins?
RESOLVED: (In the validation rules): SPIR-V should contain the
same form of input/output block as expected by recent versions of GLSL.
All in/out built-in show up in SPIR-V in blocks, as per Vulkan rules.
GLSL can stay the same, front ends need to block non-blocked built-ins.
10. Do we want to support glBindAttribLocation and glBindFragDataLocation[Indexed]
with SPIR-V? Also, what about glTransformFeedbackVaryings?
DISCUSSION: Locations can be explicitly put into the shader, and
then the application uses the right location.
Note that SPIR-V 1.0 does not allow using specialization constants for
layout(location=X) ... // X must be a literal, not specialized
Alternatively, add a SPIR-V instruction that assigns a string name to an
input which the API can use to link with. This would initially be an
extension to SPIR-V as part of this.
RESOLVED: Don't support any of glBindAttribLocation,
glBindFragDataLocation[Index], or glTransformFeedbackVaryings.
11. What capabilities do we need for GL 4.5?
RESOLVED: There is a Appendix A.spv for this.
12. How is user-linkage done between stages?
DISCUSSION: SPIR-V linkage is by location number and BuiltIn decoration.
Does OpenGL need linkage by name? Is SSO required to work with SPIR-V?
Require OpName can't be stripped out for linkage objects. If we use the
program binary API, yes but this is not desirable. See issue 2.
RESOLVED: Link the Vulkan way: built-in decorations, location numbers,
etc., never by name. No reflection required. This is a lot like SSO.
13. Can we really handle separate textures and samplers?
DISCUSSION: AMD: No, can't do this because OpenGL has features that need
cross validation that can't be done.
RESOLVED: Remove separate textures and samplers.
14. Are there differences in binding counting between Vulkan and OpenGL?
DISCUSSION: Yes, OpenGL uses multiple binding points for a resource array
while Vulkan uses just one.
RESOLVED: This leaves OpenGL as is, but state in the overview what this
difference is.
15. What GL version(s) should be required for the ImageQuery OpCapability?
DISCUSSION: The GL features it corresponds with are:
- textureSize - EXT_gpu_shader4 (GL 3.0)
- textureQueryLod - ARB_texture_query_lod (GL 4.0)
- textureQueryLevels - ARB_texture_query_levels (GL 4.3)
- imageSize - ARB_shader_image_size (GL 4.3)
- textureSamples, imageSamples - ARB_shader_texture_image_samples (GL 4.5)
The belief is that these are largely software features and while some
of them were not added until later API versions, it was not because of
hardware reasons.
RESOLVED: Require ImageQuery to be supported for all versions of GL,
as it is required for all Vulkan implementations.
16. At what point should an error due to an invalid SPIR-V module/capability
be reported? ShaderBinary, SpecializeShaderARB, LinkProgram time?
ShaderBinary says a "valid SPIR-V module binary" is required, but you
can have a valid module that uses capabilities or extensions not
supported by an implementation.
RESOLVED. ShaderBinary is expected to form an association between the
SPIR-V module and likely would not parse the module as would be required
to detect unsupported capabilities or other validation failures. In order
to avoid requiring the implementation to parse the module multiples times,
we allow this analysis to happen at either SpecializeShaderARB or
LinkProgram time, similar to how many errors for source shaders are
detected at either compile or link time.
17. Should we allow program objects to contain both source shaders and
SPIR-V binary shaders, or should this be a link time failure?
RESOLVED. No. This would be needlessly complex to specify. Make this
a link-time error. This can be determined by examining the
SPIR_V_BINARY_ARB state of each shader. They must either: all be TRUE
(SPIR-V shader) or all be FALSE (source shaders). If an application
really wishes to mix source and SPIR-V binary shaders, this can be
done at program object boundaries by using separable program objects
(if supported).
18. Do we need a section for "SPIR-V Transform Feedback Interface"?
This would discuss any requirements for the Xfb related decorations
in SPIR-V.
RESOLVED. Yes.
19. How should the program interface query operations behave for program
objects created from SPIR-V shaders?
DISCUSSION: we previously said we didn't need reflection to work
for SPIR-V shaders (at least for the first version), however we
are left with specifying how it should "not work". The primary issue
is that SPIR-V binaries are not required to have names associated
with variables. They can be associated in debug information, but there
is no requirement for that to be present, and it should not be relied
upon.
Options:
A) Make it work. If debug names are present they are enumerated
correctly with associated variables. If the names aren't present,
the compiler or driver gets to make them up. Alternatively, we could
augment SPIR-V to have a mode where all interface variables need to
have names which must not be stripped.
B) Completely disallow it. All/Most such operations return an error.
This may result in some implementation-dependent behavior which
is impossible to know (although this problem may exist anyhow due
to the offline-compilation step). This would likely include not
being able to tell how many active resources there are and related
problems.
C) Allow as much as possible to work "naturally". You can query for
the number of active resources, and for details about them. Anything
that doesn't query by name will work as expected. Queries for maximum
length of names return one. Queries for anything "by name" return
INVALID_INDEX (or -1). Querying the name property of a resource
returns an empty string. This may allow many queries to work, but it's
not clear how useful it would be if you can't actually know which
specific variable you are retrieving information on. If everything
is specified a-priori by location/binding/offset/index/component
in the shader, this may be sufficient.
RESOLVED. Pick (c), but also allow debug names to be returned if an
implementation wants to.
20. How should we deal with implementation-dependent behavior that
must normally be queried after linking? Examples include:
- set of active resources
- offsets and strides of GLSLShared and GLSLPacked UBO/SSBOs
- MATRIX_STRIDE, UNIFORM_ARRAY_STRIDE for UBOs (only relevant for
packed/shared?)
- UNIFORM_ARRAY_STRIDE for arrays of atomic counter buffers.
DISCUSSION:
- Option (c) from issue 19 allows determination of active resources (by
shader specified layouts, but not name).
- GLSLShared and GLSLPacked should not be allowed in this
extension as there is no way to sensibly support, short of Option (a)
from Issue 19.
- For arrays of atomic counters, Option (c) from Issue 19 may be enough
to figure this out, but I'm not sure that will work for offline
compilation. Do we need to define a standard "layout" (stride) for
arrays of atomic counters?
RESOLVED:
Picked (c) in issue 19, allowing determination of the number and types
of active resources.
Remove the shared and packed layouts and have the same behavior as in
Vulkan.
Atomic counter buffers don't have an associated name string already so
there should be no issue with figuring out the UNIFORM_ARRAY_STRIDE for
them.
21. What do we need to say about various linking rules related to "named
uniform blocks" and "named shader storage blocks"?
RESOLVED. We don't need to say anything, as they won't have
names in SPIR-V shaders, so they aren't really "named". Instead of
being identified by name they are identified (and matched) by
uniform block index and/or binding.
22. How do the program interface query APIs work when no name reflection
information is available?
RESOLVED: The following naturally follows from the specification:
GetProgramInterfaceiv(.., pname=MAX_NAME_LENGTH, ..) -> params = 1
GetProgramResourceIndex(.., name) -> INVALID_INDEX
GetProgramResourceName(.., length, name) -> length=0, name = ""
GetProgramResourceiv(.., props=NAME_LENGTH, ..) -> params = 1
GetProgramResourceLocation(.., name) -> -1
GetProgramResourceLocationIndex(.., name) -> -1
GetUniformLocation(.., name) -> -1
GetActiveUniformName(.., length, uniformName) -> length=0, uniformName = ""
GetUniformIndices(..,uniformNames, uniformIndices) -> uniformIndices=INVALID_INDEX
GetActiveUniform(..,length,.., name) -> length = 0, name = ""
GetActiveUniformsiv(..,pname=UNIFORM_NAME_LENGTH,..) -> params = 1
GetUniformBlockIndex(.., uniformBlockName) -> INVALID_INDEX
GetActiveUniformBlockName(..,length,uniformBlockName) -> length=0, uniformBlockName=""
GetActiveUniformBlockiv(.., pname=UNIFORM_BLOCK_NAME_LENGTH, ..) -> params = 1
GetActiveAttrib(..) -> length = 0, name = ""
GetAttribLocation(.., name) -> -1
GetTransformFeedbackVarying(..) -> length = 0, name = ""
GetFragDatatLocation(.., name) -> -1
GetFragDataIndex(.., name) -> -1
GetProgramiv(.., pname=ACTIVE_ATTRIBUTE_MAX_LENGTH, ..) -> params = 1
GetProgramiv(.., pname=ACTIVE_UNIFORM_MAX_LENGTH, ..) -> params = 1
GetProgramiv(.., pname=TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, ..) -> params = 1
GetProgramiv(.., pname=ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, ..) -> params = 1
23. How does setting uniforms work if we can't query for locations based on
names?
RESOLVED. The shaders need to specify explicit locations for all uniform
variables. The application can use offline reflection (or a reflection
library) to know which variables are at which location, and then
use that to specify the values of uniforms by location, as normal
(e.g. Uniform*, ProgramUniform*).
24. What about UniformBlockBinding and ShaderStorageBlockBinding?
RESOLVED. Because it is not possible to obtain the uniform block index
or storage block index from an unnamed block, the binding value remains
as specified in the shader by the layout qualifier or decoration.
If you are feeling lucky you could just guess and remap used index values
[0, #active blocks), but you won't really know what is going
where, so just treat it as an immutable binding, similar to the atomic
counter buffer binding point. Really.
25. What about subroutine queries based on names?
RESOLVED. SPIR-V does not currently support subroutines, so it is not
possibly to have any active subroutines from a SPIR-V based shader,
and thus there is never anything to report.
26. How do we change the location of samplers and images?
RESOLVED. You don't. Well you can using Uniform1i as usual, but you have
no way of knowing which location corresponds to which sampler or image
variable as GetUniformLocation won't work without a named variable. Best
to just treat them as immutable bindings which are specified in the
shader source or binary.
27. Appendix A.spv.3 gives a list of required capabilities that correspond
to the core GL 4.5 features as well as for *some* of the ARB extensions
that require shading language support. What about the rest of the
ARB and vendor extensions that require shading language support?
RESOLVED: Extensions that can be represented in terms of core
SPIR-V 1.0 functionality don't need any specific consideration.
Other ARB or vendor extensions that require SPIR-V functionality that
can't be expressed in terms of SPIR-V 1.0 functionality will need to
have SPIR-V extensions defined to add the required functionality.
Further GL extensions can be defined to advertise support for
consuming such SPIR-V capabilities once they have been defined.
A (partial) list of extensions that are expected to need some form
of modification to SPIR-V follows.
ARB_shader_viewport_layer_array
- need to allow ViewportIndex and Layer to be output by VS
and TES.
ARB_shader_clock
- need clock() builtin function
ARB_shader_ballot
- use subgroup capability and add other builtins
ARB_shader_atomic_counter_ops
- need atomic counter builtin functions
ARB_post_depth_coverage
- need post_depth_coverage layout
ARB_fragment_shader_interlock
- need new layouts and interlock builtin functions
KHR_blend_equation_advanced
- need new layouts
ARB_shader_group_vote
- need new builtin functions
ARB_shader_draw_parameters
- need new builtin variables
ARB_bindless_texture
- need new layout qualifiers and probably other semantics
ARB_compute_variable_group_size
- need new layout qualifiers and builtin variables
28. Should a SPIR-V binary linked through this extension work with
ARB_get_program_binary? Do we need to define what would happen
with specialization constants?
RESOLVED. Yes it should work seamlessly, and no, it shouldn't be
required to add more details on how to store specialization
constants. It is expected that GetProgramBinary should operate
irrespective of how the program was created.
(from GL 4.6 spec section 7.5, Program Binaries):
GetProgramBinary returns a binary representation of the
program object's compiled and linked executable source,
henceforth referred to as its program binary.
There are two ways you can end up with a linked executable.
GLSL sources:
ShaderSource() -> CompileShader() -> AttachShader() -> LinkProgram()
SPIR-V binaries:
ShaderBinary() -> SpecializeShader() -> AttachShader() -> LinkProgram()
Exactly what is stored in a program binary is not defined by the
GL spec.
If the driver is storing the final compiled machine assembly for
the program in the program binary, it clearly shouldn't matter
which path it takes to get to the LinkProgram step.
If instead the driver is storing some higher level representation
of the shaders (say the original sources, or some IR) then it's up
to the implementation to store whatever it needs to reconstitute
the linked binary. If the given implementation happened to choose
to store the SPIR-V code then it would also need to store any
relevant specialization information with it as well.
Revision History
Rev. Date Author Changes
---- ----------- ------------ ---------------------------------
46 19-Aug-2020 dgkoch Atomic pointers must be 32-bit or
64-bit scalar integers (SPIR-V/254,
internal API issue 132)
45 17-Sep-2019 Jon Leech Add OpTypeBool constraint on user
interface variables, and require the
StorageImageWriteWithoutFormat
capability for OpImageWrite to
Unknown formats in the Validation
Rules section (internal API issues
111 and 112, respectively).
44 15-Feb-2019 apinheiro Added issue 28, about interaction with
ARB_get_program_binary (internal API issue 100)
43 15-Feb-2019 apinheiro Add uniform initializers reference and
mapping (internal API issue 99)
42 9-Jan-2019 JohnK Explicitly give rules for SPIR-V
uniform offsets (internal API issue
92)
41 10-Dec-2018 Jon Leech Use 'workgroup' consistently
throughout (Bug 11723, internal API
issue 87).
40 29-May-2018 dgkoch note post decrement for atomicCounterDecrement
mapping
39 25-Apr-2018 JohnK add mappings of barriers and atomics
38 10-Apr-2018 dgkoch OpImageQuerySizeLod and OpImageQuerylevels
only work with Sampled images
(SPIR-V/issues/280).
37 20-Feb-2018 dgkoch Add whitelist for accepted storage
classes (SPIR-V/issues/166).
Require Binding for uniform and storage
buffer blocks (opengl/api/issues/55).
36 15-Nov-2017 dgkoch clarify error for glSpecializeShader
and add new error if shader types
mismatch (OpenGL-API/issues/16)
35 25-Oct-2017 JohnK remove the already deprecated noise
functions
34 29-May-2017 dgkoch Fix typos. RuntimeArrays are only
supported on SSBOs.
33 26-May-2017 JohnK Require in/out explicit locations
32 25-Apr-2017 JohnK Bring up-to-date:
Out-of-order block offsets
gl_NumSamples not supported
atomic counter restrictions
bug fixes
31 21-Jul-2016 dgkoch Clarify string length on queries
30 13-Jul-2016 JohnK SPIR-V Offset can also apply to an
atomic_uint offset.
29 04-Jul-2015 dgkoch Allow handles of the same shader types
for ShaderBinary when using SPIRV.
28 09-Jun-2016 dgkoch Move future extensions to Issue 27.
27 08-Jun-2016 dgkoch Assign enums, add a couple missing
errors. Editorial fixes.
Specify required version and format
of SPIRV. Add Issue 27.
26 02-Jun-2016 JohnK Completion of draft. Pack/unpack, TBD,
and resolutions.
25 02-Jun-2016 JohnK Include XFB linking/interface rules
24 02-Jun-2016 JohnK Remove use of GLSL shared/packed
and SPIR-V GLSLShared/GLSLPacked,
bringing in KHR_vulkan_glsl rules for
std140 and std430
23 01-Jun-2016 dgkoch Finish API edits. Cleanup editing
pass on formatting and issue resolutions.
Add issues 22-26 and resolve the rest.
22 26-May-2016 dgkoch Add ARB suffix to SpecializeShader
Add SPIR_V_BINARY_ARB shader state
(and some but not all related rules)
Add a bunch of API edits alluding to
SPIR-V shaders. Lots of comments about
outstanding API areas that still need
to be addressed.
Add unresolved issues 16-21.
21 25-May-2016 JohnK Add interface matching rules
20 19-May-2016 dgkoch Remove language about 'default entry point'
Recast features in terms of GL version.
19 19-May-2016 dgkoch Add min GLSL version required for
built-in variable decorations and
OpCapabilities. Fix various dates.
18 13-May-2016 JohnK Bring in the actual correct subset of
GL_KHR_vulkan_glsl, rather than refer
to it with differences
17 12-May-2016 dgkoch Verify capabilities for GLSL 4.50
Add capabilities for non-core ARB
extensions, and extensions that
already have SPIR-V correspondence.
16 12-May-2016 dgkoch grammatical fixes, replace non-ascii
chars, formatting
15 11-May-2016 JohnK Clear up misc. TBDs throughout
14 11-May-2016 JohnK Flesh out GL_KHR_vulkan_glsl changes
13 11-May-2016 JohnK Move to final organization to flesh out
12 10-May-2016 JohnK Add the Vulkan validation rules that
apply and the TBD from the f2f
11 21-Apr-2016 JohnK Editorial update to API description
10 11-Feb-2016 gsellers Add prototype API language.
9 31-Jan-2016 JohnK Issues 13 & 14
8 04-Dec-2015 JohnK Resolve issue 10
7 05-Nov-2015 JohnK Remove gl_FragColor, update issue 10
6 22-Oct-2015 JohnK Resolutions from Houston
5 21-Oct-2015 JohnK Make into a consistent format
4 16-Oct-2015 JohnK Added dependencies with GL_KHR_vulkan_glsl
3 08-Oct-2015 JohnK Added exec. env. detail, updated issues
2 22-Apr-2015 Christophe Added issues
1 26-Mar-2015 JohnK Initial revision