Appendix A: Vulkan Environment for SPIR-V
Shaders for Vulkan are defined by the Khronos SPIR-V Specification as well as the Khronos SPIR-V Extended Instructions for GLSL Specification. This appendix defines additional SPIR-V 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 SPIR-V and the 1.0 version of the SPIR-V Extended Instructions for GLSL.
A SPIR-V module passed into vkCreateShaderModule 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.
Capabilities
The SPIR-V 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.
SPIR-V 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 SPIR-V module to vkCreateShaderModule that
uses the SPV_KHR_variable_pointers SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_AMD_shader_explicit_vertex_parameter SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_AMD_gcn_shader SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_AMD_gpu_shader_half_float SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_AMD_gpu_shader_int16 SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_AMD_shader_ballot SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_AMD_shader_fragment_mask SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_AMD_shader_image_load_store_lod SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_AMD_shader_trinary_minmax SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_AMD_texture_gather_bias_lod SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_KHR_shader_draw_parameters SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_KHR_8bit_storage SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the
SPV_KHR_16bit_storage
SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the
SPV_KHR_float_controls
SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the
SPV_KHR_storage_buffer_storage_class
SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_KHR_post_depth_coverage SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_EXT_shader_stencil_export SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_KHR_shader_ballot SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_KHR_subgroup_vote SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_sample_mask_override_coverage SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_geometry_shader_passthrough SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_mesh_shader SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_viewport_array2 SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_shader_subgroup_partitioned SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_EXT_shader_viewport_index_layer SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NVX_multiview_per_view_attributes SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_EXT_descriptor_indexing SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_KHR_vulkan_memory_model SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_compute_shader_derivatives SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_fragment_shader_barycentric SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_shader_image_footprint SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_shading_rate SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_ray_tracing SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_GOOGLE_hlsl_functionality1 SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_GOOGLE_decorate_string SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_EXT_fragment_invocation_density SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_EXT_physical_storage_buffer SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_cooperative_matrix SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_NV_shader_sm_builtins SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_EXT_fragment_shader_interlock SPIR-V extension.
The application can pass a SPIR-V module to vkCreateShaderModule that
uses the SPV_EXT_demote_to_helper_invocation SPIR-V extension.
The application must not pass a SPIR-V 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 SPIR-V 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 function-call 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
vulkanMemoryModelis enabled andvulkanMemoryModelDeviceScopeis not enabled, Device scope must not be used. -
If
vulkanMemoryModelis not enabled, Device scope only extends to the queue family, not the whole device.
-
-
QueueFamilyKHR
-
If
vulkanMemoryModelis 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
OpAtomicStoreorOpAtomicLoad. -
Sequentially consistent atomics and barriers are not supported and SequentiallyConsistent is treated as AcquireRelease. SequentiallyConsistent should not be used.
-
OpMemoryBarriermust use one of Acquire, Release, AcquireRelease, or SequentiallyConsistent and must include at least one storage class. -
If the semantics for
OpControlBarrierincludes one of Acquire, Release, AcquireRelease, or SequentiallyConsistent, then it must include at least one storage class. -
SubgroupMemory, CrossWorkgroupMemory, and AtomicCounterMemory are ignored.
-
-
Any
OpVariablewith anInitializeroperand must have one of the following as its Storage Class operand:-
Output
-
Private
-
Function
-
-
The
OriginLowerLeftexecution mode must not be used; fragment entry points must declareOriginUpperLeft. -
The
PixelCenterIntegerexecution mode must not be used. Pixels are always centered at half-integer coordinates. -
Images and Samplers
-
OpTypeImagemust declare a scalar 32-bit float or 32-bit integer type for the “Sampled Type”. (RelaxedPrecisioncan be applied to a sampling instruction and to the variable holding the result of a sampling instruction.) -
OpTypeImagemust have a “Sampled” operand of 1 (sampled image) or 2 (storage image). -
If shaderStorageImageReadWithoutFormat is not enabled and an
OpTypeImagehas “Image Format” operand ofUnknown, any variables created with the given type must be decorated withNonReadable. -
If shaderStorageImageWriteWithoutFormat is not enabled and an
OpTypeImagehas “Image Format” operand ofUnknown, any variables created with the given type must be decorated withNonWritable. -
OpImageQuerySizeLod, andOpImageQueryLevelsmust only consume an “Image” operand whose type has its “Sampled” operand set to 1. -
The (u,v) coordinates used for a
SubpassDatamust 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
OpTypeImageis ignored. -
Objects of types
OpTypeImage,OpTypeSampler,OpTypeSampledImage, and arrays of these types must not be stored to or modified.
-
-
The “Component” operand of
OpImageGather, andOpImageSparseGathermust be the <id> of a constant instruction. -
Structure types must not contain opaque types.
-
Decorations
-
Any
BuiltIndecoration not listed in Built-In Variables must not be used. -
Any
BuiltIndecoration that corresponds only to Vulkan features or extensions that have not been enabled must not be used. -
The
GLSLSharedandGLSLPackeddecorations must not be used. -
The
Flat,NoPerspective,Sample, andCentroiddecorations must not be used on variables with storage class other thanInputor on variables used in the interface of non-fragment shader entry points. -
The
Patchdecoration must not be used on variables in the interface of a vertex, geometry, or fragment shader stage’s entry point. -
The
ViewportRelativeNVdecoration must only be used on a variable decorated withLayerin the vertex, tessellation evaluation, or geometry shader stages. -
The
ViewportRelativeNVdecoration must not be used unless a variable decorated with one ofViewportIndexorViewportMaskNVis also statically used by the sameOpEntryPoint. -
The
ViewportMaskNVandViewportIndexdecorations must not both be statically used by one or moreOpEntryPoint’s that form the vertex processing stages of a graphics pipeline. -
Only the round-to-nearest-even and the round-to-zero rounding modes can be used for the
FPRoundingModedecoration. -
The
FPRoundingModedecoration can only be used for the floating-point conversion instructions as described in theSPV_KHR_16bit_storageSPIR-V extension. -
DescriptorSetandBindingdecorations must obey the constraints on storage class, type, and descriptor type described in DescriptorSet and Binding Assignment
-
-
OpTypeRuntimeArraymust only be used for:-
the last member of an
OpTypeStructthat is in theStorageBufferstorage class decorated asBlock, or that is in thePhysicalStorageBufferEXTstorage class decorated asBlock, or that is in theUniformstorage class decorated asBufferBlock. -
If the
RuntimeDescriptorArrayEXTcapability 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
OpControlBarrieris used in fragment, vertex, tessellation evaluation, or geometry stages, the execution Scope must beSubgroup. -
Compute Shaders
-
For each compute shader entry point, either a
LocalSizeexecution mode or an object decorated with theWorkgroupSizedecoration must be specified. -
For compute shaders using the
DerivativeGroupQuadsNVexecution mode, the first two dimensions of the local workgroup size must be a multiple of two. -
For compute shaders using the
DerivativeGroupLinearNVexecution 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 32-bit float, 32-bit integer, boolean, or vectors of these types. If the
Float64capability is enabled, double and vectors of double types are also permitted. -
If
OpGroupNonUniformBallotBitCountis used, the group operation must be one of:-
Reduce
-
InclusiveScan
-
ExclusiveScan
-
-
Atomic instructions must declare a scalar 32-bit integer type, or a scalar 64-bit integer type if the
Int64Atomicscapability is enabled, for the value pointed to by Pointer.-
shaderBufferInt64Atomics must be enabled for 64-bit integer atomic operations to be supported on a Pointer with a Storage Class of StorageBuffer or Uniform.
-
shaderSharedInt64Atomics must be enabled for 64-bit 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
separateDenormSettingsisVK_FALSE, then the entry point must use the same denormals execution mode for both 16-bit and 64-bit floating-point types. -
If
separateRoundingModeSettingsisVK_FALSE, then the entry point must use the same rounding execution mode for both 16-bit and 64-bit floating-point types. -
If
shaderSignedZeroInfNanPreserveFloat16isVK_FALSE, thenSignedZeroInfNanPreservefor 16-bit floating-point type must not be used. -
If
shaderSignedZeroInfNanPreserveFloat32isVK_FALSE, thenSignedZeroInfNanPreservefor 32-bit floating-point type must not be used. -
If
shaderSignedZeroInfNanPreserveFloat64isVK_FALSE, thenSignedZeroInfNanPreservefor 64-bit floating-point type must not be used. -
If
shaderDenormPreserveFloat16isVK_FALSE, thenDenormPreservefor 16-bit floating-point type must not be used. -
If
shaderDenormPreserveFloat32isVK_FALSE, thenDenormPreservefor 32-bit floating-point type must not be used. -
If
shaderDenormPreserveFloat64isVK_FALSE, thenDenormPreservefor 64-bit floating-point type must not be used. -
If
shaderDenormFlushToZeroFloat16isVK_FALSE, thenDenormFlushToZerofor 16-bit floating-point type must not be used. -
If
shaderDenormFlushToZeroFloat32isVK_FALSE, thenDenormFlushToZerofor 32-bit floating-point type must not be used. -
If
shaderDenormFlushToZeroFloat64isVK_FALSE, thenDenormFlushToZerofor 64-bit floating-point type must not be used. -
If
shaderRoundingModeRTEFloat16isVK_FALSE, thenRoundingModeRTEfor 16-bit floating-point type must not be used. -
If
shaderRoundingModeRTEFloat32isVK_FALSE, thenRoundingModeRTEfor 32-bit floating-point type must not be used. -
If
shaderRoundingModeRTEFloat64isVK_FALSE, thenRoundingModeRTEfor 64-bit floating-point type must not be used. -
If
shaderRoundingModeRTZFloat16isVK_FALSE, thenRoundingModeRTZfor 16-bit floating-point type must not be used. -
If
shaderRoundingModeRTZFloat32isVK_FALSE, thenRoundingModeRTZfor 32-bit floating-point type must not be used. -
If
shaderRoundingModeRTZFloat64isVK_FALSE, thenRoundingModeRTZfor 64-bit floating-point type must not be used. -
The
Offsetplus size of the type of each variable, in the output interface of the entry point being compiled, decorated withXfbBuffermust not be greater thanVkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackBufferDataSize -
For any given
XfbBuffervalue, define the buffer data size to be smallest number of bytes such that, for all outputs decorated with the sameXfbBuffervalue, the size of the output interface variable plus theOffsetis 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
Offsetthat have a 64-bit type, or a composite type containing a 64-bit type, must specify anOffsetvalue aligned to a 8 byte boundary -
Any output block or block member decorated with
Offsetcontaining a 64-bit type consumes a multiple of 8 bytes -
The size of any output block, that contains any member decorated with
Offsetthat is a 64-bit type, must be a multiple of 8 -
The first member of an output block that specifies a
Offsetdecoration must specify aOffsetvalue that is aligned to an 8 byte boundary if that block contains any member decorated withOffsetand is a 64-bit type -
Output variables or block members decorated with
Offsetthat have a 32-bit type, or a composite type contains a 32-bit type, must specify anOffsetvalue aligned to a 4 byte boundary -
Output variables, blocks or block members decorated with
Offsetmust only contain base types that have components that are either 32-bit or 64-bit in size -
The Stream value to
OpEmitStreamVertexandOpEndStreamPrimitivemust be less thanVkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackStreams -
If the geometry shader emits to more than one vertex stream and
VkPhysicalDeviceTransformFeedbackPropertiesEXT::transformFeedbackStreamsLinesTrianglesisVK_FALSE, then execution mode must beOutputPoints -
Only variables or block members in the output interface decorated with
Offsetcan be captured for transform feedback, and those variables or block memebers must also be decorated withXfbBufferandXfbStride, or inheritXfbBufferandXfbStridedecorations 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
XfbBuffervalue must all be decorated with identicalXfbStridevalues -
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 sameXfbBuffermust specify the sameStreamvalue -
Output variables, blocks or block members that are not decorated with
Streamdefault to vertex stream zero -
For any two variables or block members in the output interface of the entry point being compiled with the same
XfbBuffervalue, the ranges determined by theOffsetdecoration and the size of the type must not overlap -
The stream number value to
Streammust be less thanVkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackStreams -
The XFB Stride value to
XfbStridemust be less than or equal toVkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackBufferDataStride -
RayPayloadNVstorage class must only be used in ray generation, any-hit, closest hit or miss shaders. -
IncomingRayPayloadNVstorage class must only be used in closest hit, any-hit, or miss shaders. -
HitAttributeNVstorage class must only be used in intersection, any-hit, or closest hit shaders. -
CallableDataNVstorage class must only be used in ray generation, closest hit, miss, and callable shaders. -
IncomingCallableDataNVstorage class must only be used in callable shaders. -
The
Baseoperand ofOpPtrAccessChainmust point to one of the following storage classes:-
Workgroup, if
VariablePointersis enabled. -
StorageBuffer, if
VariablePointersorVariablePointersStorageBufferis enabled. -
PhysicalStorageBufferEXT, if the
PhysicalStorageBuffer64EXTaddressing model is enabled.
-
-
If the
PhysicalStorageBuffer64EXTaddressing 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 pointed-to type.
-
All instructions that support memory access operands and that use a physical pointer must include the
Alignedoperand. -
The pointer value of a memory access instruction must be at least as aligned as specified by the
Alignedmemory access operand. -
Any access chain instruction that accesses into a
RowMajormatrix must only be used as thePointeroperand toOpLoadorOpStore. -
OpConvertUToPtrandOpConvertPtrToUmust use an integer type whoseWidthis 64.
-
-
For
OpCooperativeMatrixLoadNVandOpCooperativeMatrixStoreNVinstructions, thePointerandStrideoperands 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, andCmatrices 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
Amust haveMSizerows andKSizecolumns and have a component type that matchesAType. -
The type of
Bmust haveKSizerows andNSizecolumns and have a component type that matchesBType. -
The type of
Cmust haveMSizerows andNSizecolumns and have a component type that matchesCType. -
The type of
Resultmust haveMSizerows andNSizecolumns and have a component type that matchesDType. -
The type of
A,B,C, andResultmust all have a scope ofscope.
-
-
OpTypeCooperativeMatrixNVandOpCooperativeMatrix* instructions must not be used in shader stages not included in VkPhysicalDeviceCooperativeMatrixPropertiesNV::cooperativeMatrixSupportedStages.
Precision and Operation of SPIR-V Instructions
The following rules apply to half, 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.
-
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. -
By default, the implementation may perform optimizations on half, single, or double-precision floating-point instructions respectively that ignore sign of a zero, or assume that arguments and results are not Nans or \(\pm\infty\), this does not apply to
OpIsNanandOpIsInf, which must always correctly detect Nans and \(\pm\infty\). If the entry point is declared with theSignedZeroInfNanPreserveexecution mode, then sign of a zero, Nans, and \(\pm\infty\) must not be ignored.-
The following core SPIR-V instructions must respect the
SignedZeroInfNanPreserveexecution 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 byOpLoadexcept for loads from theInputstorage class in the fragment shader stage with the floating-point result type. Other SPIR-V instructions may also respect theSignedZeroInfNanPreserveexecution mode.
-
-
Denormalized values are supported.
-
By default, any half, single, or double-precision denormalized value input into a shader or potentially generated by any instruction (except those listed above) or any extended instructions for GLSL in a shader may be flushed to zero.
-
If the entry point is declared with the
DenormFlushToZeroexecution 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 floating-point numbers must be flushed to zero. -
The following core SPIR-V instructions must respect the
DenormFlushToZeroexecution mode:OpSpecConstantOp(with opcodeOpFConvert),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 SPIR-V instructions (except those excluded above) may also flush denormalized values. -
The following core SPIR-V instructions must respect the
DenormPreserveexecution mode:OpTranspose,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. Other SPIR-V instructions may also preserve denorm values.
-
The precision of double-precision 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
floating-point.
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 SPIR-V 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 floating-point 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 non-equal floating-point 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 floating-point numbers nearest to x.
Where the range of allowed return values includes any value of magnitude larger than that of the largest representable finite floating-point 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 SPIR-V 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 Fmax and the smallest be Fmin.
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, 2126]. |
2.5 ULP for |y| in the range [2-14, 214]. |
|
Inherited from x - y × trunc(x/y). |
|
|
Inherited from x - y × floor(x/y). |
|
conversions between types |
Correctly rounded. |
|
|
Note
The |
| Instruction | Single precision, unless decorated with RelaxedPrecision | Half precision |
|---|---|---|
|
Inherited from |
|
|
\(3 + 2 \times \vert x \vert\) ULP. |
\(1 + 2 \times \vert x \vert\) 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 \(\mathrm{atan2}(x, sqrt(1.0 - x^2))\). |
|
|
Inherited from \(\mathrm{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 \times (1.0 - a) + y \times a\). |
|
|
Correctly rounded. |
|
|
Inherited from \(t^{2} \times (3.0 - 2.0 \times 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.
For the OpSRem and OpSMod instructions, if either operand is
negative the result is undefined.
|
Note
While the |
OpCooperativeMatrixMulAddNV performs its operations in an
implementation-dependent order and internal precision.
Compatibility Between SPIR-V Image Formats And Vulkan Formats
Images which are read from or written to by shaders must have SPIR-V image formats compatible with the Vulkan image formats backing the image under the circumstances described for texture image validation. The compatibile formats are:
| SPIR-V Image Format | Compatible Vulkan Format |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|