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 














































































































































































shaderDenormPreserveFloat16, shaderDenormPreserveFloat32, shaderDenormPreserveFloat64 

shaderDenormFlushToZeroFloat16, shaderDenormFlushToZeroFloat32, shaderDenormFlushToZeroFloat64 

shaderSignedZeroInfNanPreserveFloat16, shaderSignedZeroInfNanPreserveFloat32, shaderSignedZeroInfNanPreserveFloat64 

shaderRoundingModeRTEFloat16, shaderRoundingModeRTEFloat32, shaderRoundingModeRTEFloat64 

shaderRoundingModeRTZFloat16, shaderRoundingModeRTZFloat32, shaderRoundingModeRTZFloat64 























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_AMD_shader_explicit_vertex_parameter
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_AMD_gcn_shader
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_AMD_gpu_shader_half_float
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_AMD_gpu_shader_int16
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_AMD_shader_ballot
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_AMD_shader_fragment_mask
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_AMD_shader_image_load_store_lod
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_AMD_shader_trinary_minmax
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_AMD_texture_gather_bias_lod
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_8bit_storage
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_float_controls
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the
SPV_KHR_storage_buffer_storage_class
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_KHR_post_depth_coverage
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_EXT_shader_stencil_export
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_KHR_shader_ballot
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_KHR_subgroup_vote
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NV_sample_mask_override_coverage
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NV_geometry_shader_passthrough
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NV_mesh_shader
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NV_viewport_array2
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_EXT_shader_viewport_index_layer
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NVX_multiview_per_view_attributes
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_EXT_descriptor_indexing
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_KHR_vulkan_memory_model
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NV_compute_shader_derivatives
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NV_fragment_shader_barycentric
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NV_shader_image_footprint
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NV_shading_rate
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NV_ray_tracing
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_GOOGLE_hlsl_functionality1
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_GOOGLE_decorate_string
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_EXT_fragment_invocation_density
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_EXT_physical_storage_buffer
SPIRV extension.
The application can pass a SPIRV module to vkCreateShaderModule that
uses the SPV_NV_cooperative_matrix
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

If
vulkanMemoryModel
is enabled andvulkanMemoryModelDeviceScope
is not enabled, Device scope must not be used. 
If
vulkanMemoryModel
is not enabled, Device scope only extends to the queue family, not the whole device.


QueueFamilyKHR

If
vulkanMemoryModel
is not enabled, QueueFamilyKHR must not be used.


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

RayPayloadNV

IncomingRayPayloadNV

HitAttributeNV

CallableDataNV

IncomingCallableDataNV

ShaderRecordBufferNV

PhysicalStorageBufferEXT


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. 
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.) 
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.


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. 
The
ViewportRelativeNV
decoration must only be used on a variable decorated withLayer
in the vertex, tessellation evaluation, or geometry shader stages. 
The
ViewportRelativeNV
decoration must not be used unless a variable decorated with one ofViewportIndex
orViewportMaskNV
is also statically used by the sameOpEntryPoint
. 
The
ViewportMaskNV
andViewportIndex
decorations must not both be statically used by one or moreOpEntryPoint
’s that form the vertex processing stages of a graphics pipeline. 
Only the roundtonearesteven and the roundtozero 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


OpTypeRuntimeArray
must only be used for:
the last member of an
OpTypeStruct
that is in theStorageBuffer
storage class decorated asBlock
, or that is in thePhysicalStorageBufferEXT
storage class decorated asBlock
, or that is in theUniform
storage class decorated asBufferBlock
. 
If the
RuntimeDescriptorArrayEXT
capability is supported, an array of variables with storage classUniform
,StorageBuffer
, orUniformConstant
, or for the outermost dimension of an array of arrays of such variables.


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. 
For compute shaders using the
DerivativeGroupQuadsNV
execution mode, the first two dimensions of the local workgroup size must be a multiple of two. 
For compute shaders using the
DerivativeGroupLinearNV
execution mode, the product of the dimensions of the local workgroup size must be a multiple of four.


“Result Type” for Non Uniform Group Operations must be limited to 32bit float, 32bit integer, boolean, or vectors of these types. If the
Float64
capability is enabled, double and vectors of double types are also permitted. 
If
OpGroupNonUniformBallotBitCount
is used, the group operation must be one of:
Reduce

InclusiveScan

ExclusiveScan


Atomic instructions must declare a scalar 32bit integer type, or a scalar 64bit integer type if the
Int64Atomics
capability is enabled, for the value pointed to by Pointer.
shaderBufferInt64Atomics must be enabled for 64bit integer atomic operations to be supported on a Pointer with a Storage Class of StorageBuffer or Uniform.

shaderSharedInt64Atomics must be enabled for 64bit integer atomic operations to be supported on a Pointer with a Storage Class of Workgroup.


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

Uniform

Workgroup

Image

StorageBuffer


If an instruction loads from or stores to a resource (including atomics and image instructions) and the resource descriptor being accessed is not dynamically uniform, then the operand corresponding to that resource (e.g. the pointer or sampled image operand) must be decorated with
NonUniformEXT
. 
If
separateDenormSettings
isVK_FALSE
, then the entry point must use the same denormals execution mode for both 16bit and 64bit floatingpoint types. 
If
separateRoundingModeSettings
isVK_FALSE
, then the entry point must use the same rounding execution mode for both 16bit and 64bit floatingpoint types. 
If
shaderSignedZeroInfNanPreserveFloat16
isVK_FALSE
, thenSignedZeroInfNanPreserve
for 16bit floatingpoint type must not be used. 
If
shaderSignedZeroInfNanPreserveFloat32
isVK_FALSE
, thenSignedZeroInfNanPreserve
for 32bit floatingpoint type must not be used. 
If
shaderSignedZeroInfNanPreserveFloat64
isVK_FALSE
, thenSignedZeroInfNanPreserve
for 64bit floatingpoint type must not be used. 
If
shaderDenormPreserveFloat16
isVK_FALSE
, thenDenormPreserve
for 16bit floatingpoint type must not be used. 
If
shaderDenormPreserveFloat32
isVK_FALSE
, thenDenormPreserve
for 32bit floatingpoint type must not be used. 
If
shaderDenormPreserveFloat64
isVK_FALSE
, thenDenormPreserve
for 64bit floatingpoint type must not be used. 
If
shaderDenormFlushToZeroFloat16
isVK_FALSE
, thenDenormFlushToZero
for 16bit floatingpoint type must not be used. 
If
shaderDenormFlushToZeroFloat32
isVK_FALSE
, thenDenormFlushToZero
for 32bit floatingpoint type must not be used. 
If
shaderDenormFlushToZeroFloat64
isVK_FALSE
, thenDenormFlushToZero
for 64bit floatingpoint type must not be used. 
If
shaderRoundingModeRTEFloat16
isVK_FALSE
, thenRoundingModeRTE
for 16bit floatingpoint type must not be used. 
If
shaderRoundingModeRTEFloat32
isVK_FALSE
, thenRoundingModeRTE
for 32bit floatingpoint type must not be used. 
If
shaderRoundingModeRTEFloat64
isVK_FALSE
, thenRoundingModeRTE
for 64bit floatingpoint type must not be used. 
If
shaderRoundingModeRTZFloat16
isVK_FALSE
, thenRoundingModeRTZ
for 16bit floatingpoint type must not be used. 
If
shaderRoundingModeRTZFloat32
isVK_FALSE
, thenRoundingModeRTZ
for 32bit floatingpoint type must not be used. 
If
shaderRoundingModeRTZFloat64
isVK_FALSE
, thenRoundingModeRTZ
for 64bit floatingpoint type must not be used. 
The
Offset
plus size of the type of each variable, in the output interface of the entry point being compiled, decorated withXfbBuffer
must not be greater thanVkPhysicalDeviceTransformFeedbackPropertiesEXT
::maxTransformFeedbackBufferDataSize

For any given
XfbBuffer
value, define the buffer data size to be smallest number of bytes such that, for all outputs decorated with the sameXfbBuffer
value, the size of the output interface variable plus theOffset
is less than or equal to the buffer data size. For a givenStream
, the sum of all the buffer data sizes for all buffers writing to that stream the must not exceedVkPhysicalDeviceTransformFeedbackPropertiesEXT
::maxTransformFeedbackStreamDataSize

Output variables or block members decorated with
Offset
that have a 64bit type, or a composite type containing a 64bit type, must specify anOffset
value aligned to a 8 byte boundary 
Any output block or block member decorated with
Offset
containing a 64bit type consumes a multiple of 8 bytes 
The size of any output block, that contains any member decorated with
Offset
that is a 64bit type, must be a multiple of 8 
The first member of an output block that specifies a
Offset
decoration must specify aOffset
value that is aligned to an 8 byte boundary if that block contains any member decorated withOffset
and is a 64bit type 
Output variables or block members decorated with
Offset
that have a 32bit type, or a composite type contains a 32bit type, must specify anOffset
value aligned to a 4 byte boundary 
Output variables, blocks or block members decorated with
Offset
must only contain base types that have components that are either 32bit or 64bit in size 
The Stream value to
OpEmitStreamVertex
andOpEndStreamPrimitive
must be less thanVkPhysicalDeviceTransformFeedbackPropertiesEXT
::maxTransformFeedbackStreams

If the geometry shader emits to more than one vertex stream and
VkPhysicalDeviceTransformFeedbackPropertiesEXT
::transformFeedbackStreamsLinesTriangles
isVK_FALSE
, then execution mode must beOutputPoints

Only variables or block members in the output interface decorated with
Offset
can be captured for transform feedback, and those variables or block memebers must also be decorated withXfbBuffer
andXfbStride
, or inheritXfbBuffer
andXfbStride
decorations from a block that contains them 
All variables or block members in the output interface of the entry point being compiled decorated with a specific
XfbBuffer
value must all be decorated with identicalXfbStride
values 
If any variables or block members in the output interface of the entry point being compiled are decorated with
Stream
, then all variables belonging to the sameXfbBuffer
must specify the sameStream
value 
Output variables, blocks or block members that are not decorated with
Stream
default to vertex stream zero 
For any two variables or block members in the output interface of the entry point being compiled with the same
XfbBuffer
value, the ranges determined by theOffset
decoration and the size of the type must not overlap 
The stream number value to
Stream
must be less thanVkPhysicalDeviceTransformFeedbackPropertiesEXT
::maxTransformFeedbackStreams

The XFB Stride value to
XfbStride
must be less than or equal toVkPhysicalDeviceTransformFeedbackPropertiesEXT
::maxTransformFeedbackBufferDataStride

RayPayloadNV
storage class must only be used in ray generation, anyhit, closest hit or miss shaders. 
IncomingRayPayloadNV
storage class must only be used in closest hit, anyhit, or miss shaders. 
HitAttributeNV
storage class must only be used in intersection, anyhit, or closest hit shaders. 
CallableDataNV
storage class must only be used in ray generation, closest hit, miss, and callable shaders. 
IncomingCallableDataNV
storage class must only be used in callable shaders. 
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.


If the
PhysicalStorageBuffer64EXT
addressing model is enabled:
Any load or store through a physical pointer type must be aligned to a multiple of the size of the largest scalar type in the pointedto type.

All instructions that support memory access operands and that use a physical pointer must include the
Aligned
operand. 
The pointer value of a memory access instruction must be at least as aligned as specified by the
Aligned
memory access operand. 
Any access chain instruction that accesses into a
RowMajor
matrix must only be used as thePointer
operand toOpLoad
orOpStore
. 
OpConvertUToPtr
andOpConvertPtrToU
must use an integer type whoseWidth
is 64.


For
OpCooperativeMatrixLoadNV
andOpCooperativeMatrixStoreNV
instructions, thePointer
andStride
operands must be aligned to at least the lesser of 16 bytes or the natural alignment of a row or column (depending onColumnMajor
) of the matrix (where the natural alignment is the number of columns/rows multiplied by the component size). 
For
OpTypeCooperativeMatrixNV
, the component type, scope, number of rows, and number of columns must match one of the matrices in any of the supported VkCooperativeMatrixPropertiesNV. 
For
OpCooperativeMatrixMulAddNV
, theResult
,A
,B
, andC
matrices must all have types that satisfy the same supported VkCooperativeMatrixPropertiesNV. That is, for one supported supported VkCooperativeMatrixPropertiesNV, all of the following must hold:
The type of
A
must haveMSize
rows andKSize
columns and have a component type that matchesAType
. 
The type of
B
must haveKSize
rows andNSize
columns and have a component type that matchesBType
. 
The type of
C
must haveMSize
rows andNSize
columns and have a component type that matchesCType
. 
The type of
Result
must haveMSize
rows andNSize
columns and have a component type that matchesDType
. 
The type of
A
,B
,C
, andResult
must all have a scope ofscope
.


OpTypeCooperativeMatrixNV
andOpCooperativeMatrix
* instructions must not be used in shader stages not included in VkPhysicalDeviceCooperativeMatrixPropertiesNV::cooperativeMatrixSupportedStages
.
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.

By default, the implementation may perform optimizations on half, single, or doubleprecision floatingpoint instructions respectively that ignore sign of a zero, or assume that arguments and results are not Nans or \(\pm\infty\), this doesn’t apply to
OpIsNan
andOpIsInf
, which must always correctly detect Nans and \(\pm\infty\). If the entry point is declared with theSignedZeroInfNanPreserve
execution mode, then sign of a zero, Nans, and \(\pm\infty\) must not be ignored.
The following core SPIRV instructions must respect the
SignedZeroInfNanPreserve
execution mode:OpPhi
,OpSelect
,OpReturnValue
,OpVectorExtractDynamic
,OpVectorInsertDynamic
,OpVectorShuffle
,OpCompositeConstruct
,OpCompositeExtract
,OpCompositeInsert
,OpCopyObject
,OpTranspose
,OpFConvert
,OpFNegate
,OpFAdd
,OpFSub
,OpFMul
,OpStore
. This execution mode must also be respected byOpLoad
except for loads from theInput
storage class in the fragment shader stage with the floatingpoint result type. Other SPIRV instruction may also respect theSignedZeroInfNanPreserve
execution mode.


Denormalized values are supported.

By default, any half, single, or doubleprecision denormalized value input into a shader or potentially generated by any instruction or any extended instructions for GLSL in a shader may be flushed to zero.

If the entry point is declared with the
DenormFlushToZero
execution mode then for the affected instuctions the denormalized result must be flushed to zero and the denormalized operands may be flushed to zero. Denormalized values obtained via unpacking an integer into a vector of values with smaller bit width and interpreting those values as floatingpoint numbers must be flushed to zero. 
The following core SPIRV instructions must respect the
DenormFlushToZero
execution mode:OpSpecConstantOp
(except when the opcode isOpQuantizeToF16
),OpFConvert
,OpFNegate
,OpFAdd
,OpFSub
,OpFMul
,OpFDiv
,OpFRem
,OpFMod
,OpVectorTimesScalar
,OpMatrixTimesScalar
,OpVectorTimesMatrix
,OpMatrixTimesVector
,OpMatrixTimesMatrix
,OpOuterProduct
,OpDot
; and the following extended instructions for GLSL:Round
,RoundEven
,Trunc
,FAbs
,Floor
,Ceil
,Fract
,Radians
,Degrees
,Sin
,Cos
,Tan
,Asin
,Acos
,Atan
,Sinh
,Cosh
,Tanh
,Asinh
,Acosh
,Atanh
,Atan2
,Pow
,Exp
,Log
,Exp2
,Log2
,Sqrt
,InverseSqrt
,Determinant
,MatrixInverse
,Modf
,ModfStruct
,FMin
,FMax
,FClamp
,FMix
,Step
,SmoothStep
,Fma
,UnpackHalf2x16
,UnpackDouble2x32
,Length
,Distance
,Cross
,Normalize
,FaceForward
,Reflect
,Refract
,NMin
,NMax
,NClamp
. Other SPIRV instruction may also respect theDenormFlushToZero
execution mode. 
The following core SPIRV instructions must respect the
DenormPreserve
execution mode:OpPhi
,OpSelect
,OpReturnValue
,OpVectorExtractDynamic
,OpVectorInsertDynamic
,OpVectorShuffle
,OpCompositeConstruct
,OpCompositeExtract
,OpCompositeInsert
,OpCopyObject
,OpTranspose
,OpStore
,OpSpecConstantOp
,OpFConvert
,OpFNegate
,OpFAdd
,OpFSub
,OpFMul
,OpVectorTimesScalar
,OpMatrixTimesScalar
,OpVectorTimesMatrix
,OpMatrixTimesVector
,OpMatrixTimesMatrix
,OpOuterProduct
,OpDot
,OpFOrdEqual
,OpFUnordEqual
,OpFOrdNotEqual
,OpFUnordNotEqual
,OpFOrdLessThan
,OpFUnordLessThan
,OpFOrdGreaterThan
,OpFUnordGreaterThan
,OpFOrdLessThanEqual
,OpFUnordLessThanEqual
,OpFOrdGreaterThanEqual
,OpFUnordGreaterThanEqual
; and the following extended instructions for GLSL:FAbs
,FSign
,Radians
,Degrees
,FMin
,FMax
,FClamp
,FMix
,Fma
,PackHalf2x16
,PackDouble2x32
,UnpackHalf2x16
,UnpackDouble2x32
,NMin
,NMax
,NClamp
. This execution mode must also be respected byOpLoad
except for loads from theInput
storage class in the fragment shader stage with the floatingpoint result type. Other SPIRV instruction may also respect theDenormPreserve
execution mode.

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 is not specified, unless the entry point is declared with
the RoundingModeRTE
or the RoundingModeRTZ
execution mode.
These execution modes affect only correctly rounded SPIRV instructions.
These execution modes do not affect OpQuantizeToF16
.
If the rounding mode is not specified then this rounding is implementation
specific, subject to 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) \).
If the entry point is declared with the DenormFlushToZero
execution
mode, then any intermediate denormal value(s) while evaluating the formula
may be flushed to zero.
Denormal final results must be flushed to zero.
If the entry point is declared with the DenormPreserve
execution mode,
then denormals must be preserved throughout the formula.
For half (16 bit) and single (32 bit) precision instructions, precisions are required to be at least as follows:
Instruction  Single precision, unless decorated with RelaxedPrecision  Half precision 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Inherited from \(\sum_{i = 0}^{n  1} x_{i} \times y_{i}\). 


Correct result. 


Correct result. 


Correct result. 


Correct result. 


Correct result. 


2.5 ULP for y in the range [2^{126}, 2^{126}]. 
2.5 ULP for y in the range [2^{14}, 2^{14}]. 

Inherited from x  y × trunc(x/y), for y in the range [2^{126}, 2^{126}]. 
Inherited from x  y × trunc(x/y), for y in the range [2^{14}, 2^{14}]. 

Inherited from x  y × floor(x/y), for y in the range [2^{126}, 2^{126}]. 
Inherited from x  y × floor(x/y), for y in the range [2^{14}, 2^{14}]. 
conversions between types 
Correctly rounded. 
Note
The 
Instruction  Single precision, unless decorated with RelaxedPrecision  Half precision 


Inherited from 


3 + 2 × x ULP. 
1 + 2 × x ULP. 

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

Inherited from 


Inherited from 1.0 / 


2 ULP. 


Inherited from \(\frac{x \times \pi}{180}\). 


Inherited from \(\frac{x \times 180}{\pi}\). 


Absolute error \(\leq 2^{11}\) inside the range \([\pi, \pi]\). 
Absolute error \(\leq 2^{7}\) inside the range \([\pi, \pi]\). 

Absolute error \(\leq 2^{11}\) inside the range \([\pi, \pi]\). 
Absolute error \(\leq 2^{7}\) inside the range \([\pi, \pi]\). 

Inherited from \(\frac{sin()}{cos()}\). 


Inherited from \(atan2(x, sqrt(1.0  x^2))\). 


Inherited from \(atan2(sqrt(1.0  x^2), x)\). 


4096 ULP 
5 ULP. 

Inherited from \((exp(x)  exp(x)) \times 0.5\). 


Inherited from \((exp(x) + exp(x)) \times 0.5\). 


Inherited from \(\frac{sinh()}{cosh()}\). 


Inherited from \(log(x + sqrt(x^2 + 1.0))\). 


Inherited from \(log(x + sqrt(x^2  1.0))\). 


Inherited from \(log(\frac{1.0 + x}{1.0  x}) \times 0.5\). 


Correctly rounded. 


Correctly rounded. 


Inherited from \(sqrt(dot(x, x))\). 


Inherited from \(length(x  y)\). 


Inherited from 


Inherited from \(\frac{x}{length(x)}\). 


Correctly rounded. 


Inherited from x  2.0 × 


Inherited from eta × I  (eta × 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 


Inherited from x × (1.0  a) + y × a. 


Correctly rounded. 


Inherited from t × t × (3.0  2.0 × t), where \(t = clamp(\frac{x  edge0}{edge1  edge0}, 0.0, 1.0)\). 


Correctly rounded. 


Correctly rounded. 


Correctly rounded. 
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.
Note
While the 
OpCooperativeMatrixMulAddNV
performs its operations in an
implementationdependent order and internal precision.
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 














































































