Appendix A: Vulkan Environment for SPIRV
Shaders for Vulkan are defined by the Khronos SPIRV Specification as well as the Khronos SPIRV Extended Instructions for GLSL Specification. This appendix defines additional SPIRV requirements applying to Vulkan shaders.
Versions and Formats
A Vulkan 1.1 implementation must support the 1.0, 1.1, 1.2, and 1.3 versions of SPIRV and the 1.0 version of the SPIRV Extended Instructions for GLSL.
A SPIRV module passed into vkCreateShaderModule is interpreted as a series of 32bit words in host endianness, with literal strings packed as described in section 2.2 of the SPIRV Specification. The first few words of the SPIRV module must be a magic number and a SPIRV version number, as described in section 2.3 of the SPIRV Specification.
Capabilities
The SPIRV capabilities listed below must be supported if the corresponding feature or extension is enabled, or if no features or extensions are listed for that capability. Extensions are only listed when there is not also a feature bit associated with that capability.
SPIRV OpCapability 
Vulkan feature or extension name 








































































































The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_KHR_variable_pointers
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_KHR_shader_draw_parameters
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_KHR_16bit_storage
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_KHR_storage_buffer_storage_class
SPIRV extension.
The application must not pass a SPIRV module containing any of the following to vkCreateShaderModule:

any OpCapability not listed above,

an unsupported capability, or

a capability which corresponds to a Vulkan feature or extension which has not been enabled.
Validation Rules within a Module
A SPIRV module passed to vkCreateShaderModule must conform to the following rules:

Every entry point must have no return value and accept no arguments.

Recursion: The static functioncall graph for an entry point must not contain cycles.

The Logical addressing model must be selected.

Scope for execution must be limited to:

Workgroup

Subgroup


Scope for memory must be limited to:

Device

Device scope only extends to the queue family, not the whole device.


Workgroup

Subgroup

Invocation


Scope for Non Uniform Group Operations must be limited to:

Subgroup


Storage Class must be limited to:

UniformConstant

Input

Uniform

Output

Workgroup

Private

Function

PushConstant

Image

StorageBuffer


Memory semantics must obey the following rules:

Acquire must not be used with
OpAtomicStore
. 
Release must not be used with
OpAtomicLoad
. 
AcquireRelease must not be used with
OpAtomicStore
orOpAtomicLoad
. 
Sequentially consistent atomics and barriers are not supported and SequentiallyConsistent is treated as AcquireRelease. SequentiallyConsistent should not be used.

OpMemoryBarrier
must use one of Acquire, Release, AcquireRelease, or SequentiallyConsistent and must include at least one storage class. 
If the semantics for
OpControlBarrier
includes one of Acquire, Release, AcquireRelease, or SequentiallyConsistent, then it must include at least one storage class. 
SubgroupMemory, CrossWorkgroupMemory, and AtomicCounterMemory are ignored.


Any
OpVariable
with anInitializer
operand must have one of the following as its Storage Class operand:
Output

Private

Function


The
OriginLowerLeft
execution mode must not be used; fragment entry points must declareOriginUpperLeft
. 
The
PixelCenterInteger
execution mode must not be used. Pixels are always centered at halfinteger coordinates. 
Any variable in the
UniformConstant
storage class must be typed as either:
OpTypeImage

OpTypeSampler

OpTypeSampledImage

An array of one of these types.


Images and Samplers

OpTypeImage
must declare a scalar 32bit float or 32bit integer type for the “Sampled Type”. (RelaxedPrecision
can be applied to a sampling instruction and to the variable holding the result of a sampling instruction.) 
If the
Sampled
Type
of anOpTypeImage
declaration does not match the numeric format of the corresponding resource in type, as shown in the SPIRV Sampled Type column of the Interpretation of Numeric Format table, the values obtained by reading or sampling from the image are undefined. 
If the signedness of any read or sample operation does not match the signedness of the corresponding resource then the values obtained are undefined.

OpTypeImage
must have a “Sampled” operand of 1 (sampled image) or 2 (storage image). 
If shaderStorageImageReadWithoutFormat is not enabled and an
OpTypeImage
has “Image Format” operand ofUnknown
, any variables created with the given type must be decorated withNonReadable
. 
If shaderStorageImageWriteWithoutFormat is not enabled and an
OpTypeImage
has “Image Format” operand ofUnknown
, any variables created with the given type must be decorated withNonWritable
. 
OpImageQuerySizeLod
, andOpImageQueryLevels
must only consume an “Image” operand whose type has its “Sampled” operand set to 1. 
The (u,v) coordinates used for a
SubpassData
must be the <id> of a constant vector (0,0), or if a layer coordinate is used, must be a vector that was formed with constant 0 for the u and v components. 
The “Depth” operand of
OpTypeImage
is ignored. 
Objects of types
OpTypeImage
,OpTypeSampler
,OpTypeSampledImage
, and arrays of these types must not be stored to or modified.


Any image operation must use at most one of the
Offset
,ConstOffset
, andConstOffsets
image operands. 
Image operand
Offset
must only be used withOpImage
*Gather
instructions. 
The “Component” operand of
OpImageGather
, andOpImageSparseGather
must be the <id> of a constant instruction. 
Structure types must not contain opaque types.

Decorations

Any
BuiltIn
decoration not listed in BuiltIn Variables must not be used. 
Any
BuiltIn
decoration that corresponds only to Vulkan features or extensions that have not been enabled must not be used. 
The
GLSLShared
andGLSLPacked
decorations must not be used. 
The
Flat
,NoPerspective
,Sample
, andCentroid
decorations must not be used on variables with storage class other thanInput
or on variables used in the interface of nonfragment 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. 
Only the roundtonearesteven and the roundtowardszero rounding modes can be used for the
FPRoundingMode
decoration. 
The
FPRoundingMode
decoration can only be used for the floatingpoint conversion instructions as described in theSPV_KHR_16bit_storage
SPIRV extension. 
DescriptorSet
andBinding
decorations must obey the constraints on storage class, type, and descriptor type described in DescriptorSet and Binding Assignment 
Variables decorated with
Invariant
and variables with structure types that have any members decorated withInvariant
must be in theOutput
orInput
storage class.Invariant
used on anInput
storage class variable or structure member has no effect.


OpTypeRuntimeArray
must only be used for:
the last member of an
OpTypeStruct
that is in theStorageBuffer
storage class decorated asBlock
, or that is in theUniform
storage class decorated asBufferBlock
.


Linkage: See Shader Interfaces for additional linking and validation rules.

If
OpControlBarrier
is used in fragment, vertex, tessellation evaluation, or geometry stages, the execution Scope must beSubgroup
. 
Compute Shaders

For each compute shader entry point, either a
LocalSize
execution mode or an object decorated with theWorkgroupSize
decoration must be specified.


“Result Type” for Non Uniform Group Operations must be limited to 32bit floatingpoint, 32bit integer, boolean, or vectors of these types.

If the
Float64
capability is enabled, 64bit floatingpoint and vector of 64bit floatingpoint types are also permitted.


The “Id” operand of
OpGroupNonUniformBroadcast
must be the <id> of a constant instruction. 
If
OpGroupNonUniformBallotBitCount
is used, the group operation must be one of:
Reduce

InclusiveScan

ExclusiveScan


Atomic instructions must declare a scalar 32bit integer type, for the value pointed to by Pointer.

The Pointer operand of all atomic instructions must have a Storage Class limited to:

Uniform

Workgroup

Image

StorageBuffer


The
Base
operand ofOpPtrAccessChain
must point to one of the following storage classes:
Workgroup, if
VariablePointers
is enabled. 
StorageBuffer, if
VariablePointers
orVariablePointersStorageBuffer
is enabled. 
PhysicalStorageBufferEXT, if the
PhysicalStorageBuffer64EXT
addressing model is enabled.

Precision and Operation of SPIRV Instructions
The following rules apply to half, single, and doubleprecision 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 nonzero by a zero results in the appropriately signed IEEE 754 infinity.

Signaling NaNs are not required to be generated and exceptions are never raised. Signaling NaN may be converted to quiet NaNs values by any floating point instruction.

The following instructions must not flush denormalized values:
OpConstant
,OpConstantComposite
,OpSpecConstant
,OpSpecConstantComposite
,OpLoad
,OpStore
,OpBitcast
,OpPhi
,OpSelect
,OpFunctionCall
,OpReturnValue
,OpVectorExtractDynamic
,OpVectorInsertDynamic
,OpVectorShuffle
,OpCompositeConstruct
,OpCompositeExtract
,OpCompositeInsert
,OpCopyMemory
,OpCopyObject
. 
Any denormalized value input into a shader or potentially generated by any instruction in a shader (except those listed above) may be flushed to 0.

The rounding mode cannot be set, and results will be correctly rounded, as described below.

NaNs may not be generated. Instructions that operate on a NaN may not result in a NaN.
The precision of doubleprecision instructions is at least that of single precision.
The precision of operations is defined either in terms of rounding, as an error bound in ULP, or as inherited from a formula as follows.
Operations described as “correctly rounded” will return the infinitely precise result, x, rounded so as to be representable in floatingpoint. The rounding mode used is not defined but must obey the following rules. If x is exactly representable then x will be returned. Otherwise, either the floatingpoint value closest to and no less than x or the value closest to and no greater than x will be returned.
Where an error bound of n ULP (units in the last place) is given, for an operation with infinitely precise result x the value returned must be in the range [x  n * ulp(x), x + n * ulp(x)]. The function ulp(x) is defined as follows:

If there exist nonequal floatingpoint numbers a and b such that a ≤ x ≤ b then ulp(x) is the minimum possible distance between such numbers, \(ulp(x) = \mathrm{min}_{a,b}  b  a \). If such numbers do not exist then ulp(x) is defined to be the difference between the two finite floatingpoint numbers nearest to x.
Where the range of allowed return values includes any value of magnitude larger than that of the largest representable finite floatingpoint number, operations may, additionally, return either an infinity of the appropriate sign or the finite number with the largest magnitude of the appropriate sign. If the infinitely precise result of the operation is not mathematically defined then the value returned is undefined.
Where an operation’s precision is described as being inherited from a formula, the result returned must be at least as accurate as the result of computing an approximation to x using a formula equivalent to the given formula applied to the supplied inputs. Specifically, the formula given may be transformed using the mathematical associativity, commutativity and distributivity of the operators involved to yield an equivalent formula. The SPIRV precision rules, when applied to each such formula and the given input values, define a range of permitted values. If NaN is one of the permitted values then the operation may return any result, otherwise let the largest permitted value in any of the ranges be F_{max} and the smallest be F_{min}. The operation must return a value in the range [x  E, x + E] where \(E = \mathrm{max} \left(  x  F_{\mathrm{min}} ,  x  F_{\mathrm{max}}  \right) \).
For single precision (32 bit) instructions, precisions are required to be at least as follows, unless decorated with RelaxedPrecision:
Instruction  Precision 


Correctly rounded. 

Correctly rounded. 

Correctly rounded. 

Correct result. 

Correct result. 

Correct result. 

Correct result. 

Correct result. 

2.5 ULP for y in the range [2^{126}, 2^{126}]. 
conversions between types 
Correctly rounded. 
Instruction  Precision 


Inherited from 

3 + 2 × x ULP. 

3 ULP outside the range [0.5, 2.0]. Absolute error < 2^{21} inside the range [0.5, 2.0]. 

Inherited from 

Inherited from 1.0 / 

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.
For the OpSRem
and OpSMod
instructions, if either operand is
negative the result is undefined.
Note
While the 
Compatibility Between SPIRV Image Formats And Vulkan Formats
Images which are read from or written to by shaders must have SPIRV image formats compatible with the Vulkan image formats backing the image under the circumstances described for texture image validation. The compatibile formats are:
SPIRV Image Format  Compatible Vulkan Format 














































































