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.2 implementation must support the 1.0, 1.1, 1.2, 1.3, 1.4, and 1.5 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 table below lists the set of SPIR-V capabilities that may be supported in Vulkan implementations. The application must not use any of these capabilities in SPIR-V passed to vkCreateShaderModule unless one of the following conditions is met for the VkDevice specified in the device parameter of vkCreateShaderModule:

  • The corresponding field in the table is blank.

  • Any corresponding Vulkan feature is enabled.

  • Any corresponding Vulkan extension is enabled.

  • Any corresponding Vulkan property is supported.

  • The corresponding core version is supported (as returned by VkPhysicalDeviceProperties::apiVersion).

Table 81. List of SPIR-V Capabilities and corresponding Vulkan features, extensions, or core version
SPIR-V OpCapability
                Vulkan feature, extension, or core version

Matrix
                VK_API_VERSION_1_0

Shader
                VK_API_VERSION_1_0

InputAttachment
                VK_API_VERSION_1_0

Sampled1D
                VK_API_VERSION_1_0

Image1D
                VK_API_VERSION_1_0

SampledBuffer
                VK_API_VERSION_1_0

ImageBuffer
                VK_API_VERSION_1_0

ImageQuery
                VK_API_VERSION_1_0

DerivativeControl
                VK_API_VERSION_1_0

Geometry
                VkPhysicalDeviceFeatures::geometryShader

Tessellation
                VkPhysicalDeviceFeatures::tessellationShader

Float64
                VkPhysicalDeviceFeatures::shaderFloat64

Int64
                VkPhysicalDeviceFeatures::shaderInt64

Int64Atomics
                VkPhysicalDeviceVulkan12Features::shaderBufferInt64Atomics
                VkPhysicalDeviceVulkan12Features::shaderSharedInt64Atomics

AtomicFloat32AddEXT
                VkPhysicalDeviceShaderAtomicFloatFeaturesEXT::shaderBufferFloat32AtomicAdd
                VkPhysicalDeviceShaderAtomicFloatFeaturesEXT::shaderSharedFloat32AtomicAdd
                VkPhysicalDeviceShaderAtomicFloatFeaturesEXT::shaderImageFloat32AtomicAdd
                VkPhysicalDeviceShaderAtomicFloatFeaturesEXT::sparseImageFloat32AtomicAdd

AtomicFloat64AddEXT
                VkPhysicalDeviceShaderAtomicFloatFeaturesEXT::shaderBufferFloat64AtomicAdd
                VkPhysicalDeviceShaderAtomicFloatFeaturesEXT::shaderSharedFloat64AtomicAdd

Int64ImageEXT
                VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT::shaderImageInt64Atomics

Int16
                VkPhysicalDeviceFeatures::shaderInt16

TessellationPointSize
                VkPhysicalDeviceFeatures::shaderTessellationAndGeometryPointSize

GeometryPointSize
                VkPhysicalDeviceFeatures::shaderTessellationAndGeometryPointSize

ImageGatherExtended
                VkPhysicalDeviceFeatures::shaderImageGatherExtended

StorageImageMultisample
                VkPhysicalDeviceFeatures::shaderStorageImageMultisample

UniformBufferArrayDynamicIndexing
                VkPhysicalDeviceFeatures::shaderUniformBufferArrayDynamicIndexing

SampledImageArrayDynamicIndexing
                VkPhysicalDeviceFeatures::shaderSampledImageArrayDynamicIndexing

StorageBufferArrayDynamicIndexing
                VkPhysicalDeviceFeatures::shaderStorageBufferArrayDynamicIndexing

StorageImageArrayDynamicIndexing
                VkPhysicalDeviceFeatures::shaderStorageImageArrayDynamicIndexing

ClipDistance
                VkPhysicalDeviceFeatures::shaderClipDistance

CullDistance
                VkPhysicalDeviceFeatures::shaderCullDistance

ImageCubeArray
                VkPhysicalDeviceFeatures::imageCubeArray

SampleRateShading
                VkPhysicalDeviceFeatures::sampleRateShading

SparseResidency
                VkPhysicalDeviceFeatures::shaderResourceResidency

MinLod
                VkPhysicalDeviceFeatures::shaderResourceMinLod

SampledCubeArray
                VkPhysicalDeviceFeatures::imageCubeArray

ImageMSArray
                VkPhysicalDeviceFeatures::shaderStorageImageMultisample

StorageImageExtendedFormats
                VK_API_VERSION_1_0

InterpolationFunction
                VkPhysicalDeviceFeatures::sampleRateShading

StorageImageReadWithoutFormat
                VkPhysicalDeviceFeatures::shaderStorageImageReadWithoutFormat

StorageImageWriteWithoutFormat
                VkPhysicalDeviceFeatures::shaderStorageImageWriteWithoutFormat

MultiViewport
                VkPhysicalDeviceFeatures::multiViewport

DrawParameters
                VkPhysicalDeviceVulkan11Features::shaderDrawParameters
                VK_KHR_shader_draw_parameters

MultiView
                VkPhysicalDeviceVulkan11Features::multiview

DeviceGroup
                VK_API_VERSION_1_1
                VK_KHR_device_group

VariablePointersStorageBuffer
                VkPhysicalDeviceVulkan11Features::variablePointersStorageBuffer

VariablePointers
                VkPhysicalDeviceVulkan11Features::variablePointers

ShaderClockKHR
                VK_KHR_shader_clock

StencilExportEXT
                VK_EXT_shader_stencil_export

SubgroupBallotKHR
                VK_EXT_shader_subgroup_ballot

SubgroupVoteKHR
                VK_EXT_shader_subgroup_vote

ImageReadWriteLodAMD
                VK_AMD_shader_image_load_store_lod

ImageGatherBiasLodAMD
                VK_AMD_texture_gather_bias_lod

FragmentMaskAMD
                VK_AMD_shader_fragment_mask

SampleMaskOverrideCoverageNV
                VK_NV_sample_mask_override_coverage

GeometryShaderPassthroughNV
                VK_NV_geometry_shader_passthrough

ShaderViewportIndex
                VkPhysicalDeviceVulkan12Features::shaderOutputViewportIndex

ShaderLayer
                VkPhysicalDeviceVulkan12Features::shaderOutputLayer

ShaderViewportIndexLayerEXT
                VK_EXT_shader_viewport_index_layer

ShaderViewportIndexLayerNV
                VK_NV_viewport_array2

ShaderViewportMaskNV
                VK_NV_viewport_array2

PerViewAttributesNV
                VK_NVX_multiview_per_view_attributes

StorageBuffer16BitAccess
                VkPhysicalDeviceVulkan11Features::storageBuffer16BitAccess

UniformAndStorageBuffer16BitAccess
                VkPhysicalDeviceVulkan11Features::uniformAndStorageBuffer16BitAccess

StoragePushConstant16
                VkPhysicalDeviceVulkan11Features::storagePushConstant16

StorageInputOutput16
                VkPhysicalDeviceVulkan11Features::storageInputOutput16

GroupNonUniform
                VK_SUBGROUP_FEATURE_BASIC_BIT

GroupNonUniformVote
                VK_SUBGROUP_FEATURE_VOTE_BIT

GroupNonUniformArithmetic
                VK_SUBGROUP_FEATURE_ARITHMETIC_BIT

GroupNonUniformBallot
                VK_SUBGROUP_FEATURE_BALLOT_BIT

GroupNonUniformShuffle
                VK_SUBGROUP_FEATURE_SHUFFLE_BIT

GroupNonUniformShuffleRelative
                VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT

GroupNonUniformClustered
                VK_SUBGROUP_FEATURE_CLUSTERED_BIT

GroupNonUniformQuad
                VK_SUBGROUP_FEATURE_QUAD_BIT

GroupNonUniformPartitionedNV
                VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV

SampleMaskPostDepthCoverage
                VK_EXT_post_depth_coverage

ShaderNonUniform
                VK_API_VERSION_1_2
                VK_EXT_descriptor_indexing

RuntimeDescriptorArray
                VkPhysicalDeviceVulkan12Features::runtimeDescriptorArray

InputAttachmentArrayDynamicIndexing
                VkPhysicalDeviceVulkan12Features::shaderInputAttachmentArrayDynamicIndexing

UniformTexelBufferArrayDynamicIndexing
                VkPhysicalDeviceVulkan12Features::shaderUniformTexelBufferArrayDynamicIndexing

StorageTexelBufferArrayDynamicIndexing
                VkPhysicalDeviceVulkan12Features::shaderStorageTexelBufferArrayDynamicIndexing

UniformBufferArrayNonUniformIndexing
                VkPhysicalDeviceVulkan12Features::shaderUniformBufferArrayNonUniformIndexing

SampledImageArrayNonUniformIndexing
                VkPhysicalDeviceVulkan12Features::shaderSampledImageArrayNonUniformIndexing

StorageBufferArrayNonUniformIndexing
                VkPhysicalDeviceVulkan12Features::shaderStorageBufferArrayNonUniformIndexing

StorageImageArrayNonUniformIndexing
                VkPhysicalDeviceVulkan12Features::shaderStorageImageArrayNonUniformIndexing

InputAttachmentArrayNonUniformIndexing
                VkPhysicalDeviceVulkan12Features::shaderInputAttachmentArrayNonUniformIndexing

UniformTexelBufferArrayNonUniformIndexing
                VkPhysicalDeviceVulkan12Features::shaderUniformTexelBufferArrayNonUniformIndexing

StorageTexelBufferArrayNonUniformIndexing
                VkPhysicalDeviceVulkan12Features::shaderStorageTexelBufferArrayNonUniformIndexing

Float16
                VkPhysicalDeviceVulkan12Features::shaderFloat16
                VK_AMD_gpu_shader_half_float

Int8
                VkPhysicalDeviceVulkan12Features::shaderInt8

StorageBuffer8BitAccess
                VkPhysicalDeviceVulkan12Features::storageBuffer8BitAccess

UniformAndStorageBuffer8BitAccess
                VkPhysicalDeviceVulkan12Features::uniformAndStorageBuffer8BitAccess

StoragePushConstant8
                VkPhysicalDeviceVulkan12Features::storagePushConstant8

VulkanMemoryModel
                VkPhysicalDeviceVulkan12Features::vulkanMemoryModel

VulkanMemoryModelDeviceScope
                VkPhysicalDeviceVulkan12Features::vulkanMemoryModelDeviceScope

DenormPreserve
                VkPhysicalDeviceVulkan12Properties::shaderDenormPreserveFloat16
                VkPhysicalDeviceVulkan12Properties::shaderDenormPreserveFloat32
                VkPhysicalDeviceVulkan12Properties::shaderDenormPreserveFloat64

DenormFlushToZero
                VkPhysicalDeviceVulkan12Properties::shaderDenormFlushToZeroFloat16
                VkPhysicalDeviceVulkan12Properties::shaderDenormFlushToZeroFloat32
                VkPhysicalDeviceVulkan12Properties::shaderDenormFlushToZeroFloat64

SignedZeroInfNanPreserve
                VkPhysicalDeviceVulkan12Properties::shaderSignedZeroInfNanPreserveFloat16
                VkPhysicalDeviceVulkan12Properties::shaderSignedZeroInfNanPreserveFloat32
                VkPhysicalDeviceVulkan12Properties::shaderSignedZeroInfNanPreserveFloat64

RoundingModeRTE
                VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTEFloat16
                VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTEFloat32
                VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTEFloat64

RoundingModeRTZ
                VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTZFloat16
                VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTZFloat32
                VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTZFloat64

ComputeDerivativeGroupQuadsNV
                VkPhysicalDeviceComputeShaderDerivativesFeaturesNV::computeDerivativeGroupQuads

ComputeDerivativeGroupLinearNV
                VkPhysicalDeviceComputeShaderDerivativesFeaturesNV::computeDerivativeGroupLinear

FragmentBarycentricNV
                VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV::fragmentShaderBarycentric

ImageFootprintNV
                VkPhysicalDeviceShaderImageFootprintFeaturesNV::imageFootprint

ShadingRateNV
                VkPhysicalDeviceShadingRateImageFeaturesNV::shadingRateImage

MeshShadingNV
                VK_NV_mesh_shader

RayTracingKHR
                VkPhysicalDeviceRayTracingPipelineFeaturesKHR::rayTracingPipeline

RayQueryKHR
                VkPhysicalDeviceRayQueryFeaturesKHR::rayQuery

RayTraversalPrimitiveCullingKHR
                VkPhysicalDeviceRayTracingPipelineFeaturesKHR::rayTraversalPrimitiveCulling

RayTracingNV
                VK_NV_ray_tracing

TransformFeedback
                VkPhysicalDeviceTransformFeedbackFeaturesEXT::transformFeedback

GeometryStreams
                VkPhysicalDeviceTransformFeedbackFeaturesEXT::geometryStreams

FragmentDensityEXT
                VkPhysicalDeviceFragmentDensityMapFeaturesEXT::fragmentDensityMap

PhysicalStorageBufferAddresses
                VkPhysicalDeviceVulkan12Features::bufferDeviceAddress
                VkPhysicalDeviceBufferDeviceAddressFeaturesEXT::bufferDeviceAddress

CooperativeMatrixNV
                VkPhysicalDeviceCooperativeMatrixFeaturesNV::cooperativeMatrix

IntegerFunctions2INTEL
                VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL::shaderIntegerFunctions2

ShaderSMBuiltinsNV
                VkPhysicalDeviceShaderSMBuiltinsFeaturesNV::shaderSMBuiltins

FragmentShaderSampleInterlockEXT
                VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT::fragmentShaderSampleInterlock

FragmentShaderPixelInterlockEXT
                VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT::fragmentShaderPixelInterlock

FragmentShaderShadingRateInterlockEXT
                VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT::fragmentShaderShadingRateInterlock
                VkPhysicalDeviceShadingRateImageFeaturesNV::shadingRateImage

DemoteToHelperInvocationEXT
                VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT::shaderDemoteToHelperInvocation

FragmentShadingRateKHR
                VkPhysicalDeviceFragmentShadingRateFeaturesKHR::pipelineFragmentShadingRate
                VkPhysicalDeviceFragmentShadingRateFeaturesKHR::primitiveFragmentShadingRate
                VkPhysicalDeviceFragmentShadingRateFeaturesKHR::attachmentFragmentShadingRate

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.

SPIR-V Extensions

The application can pass a SPIR-V module to vkCreateShaderModule that uses the following SPIR-V extensions if one of the following conditions is met for the VkDevice specified in the device parameter of vkCreateShaderModule:

  • Any corresponding Vulkan extension is enabled.

  • The corresponding core version is supported (as returned by VkPhysicalDeviceProperties::apiVersion).

Table 82. List of SPIR-V Extensions and corresponding Vulkan extensions or core version
SPIR-V OpExtension
                Vulkan extension or core version

SPV_KHR_variable_pointers
                VK_API_VERSION_1_1
                VK_KHR_variable_pointers

SPV_AMD_shader_explicit_vertex_parameter
                VK_AMD_shader_explicit_vertex_parameter

SPV_AMD_gcn_shader
                VK_AMD_gcn_shader

SPV_AMD_gpu_shader_half_float
                VK_AMD_gpu_shader_half_float

SPV_AMD_gpu_shader_int16
                VK_AMD_gpu_shader_int16

SPV_AMD_shader_ballot
                VK_AMD_shader_ballot

SPV_AMD_shader_fragment_mask
                VK_AMD_shader_fragment_mask

SPV_AMD_shader_image_load_store_lod
                VK_AMD_shader_image_load_store_lod

SPV_AMD_shader_trinary_minmax
                VK_AMD_shader_trinary_minmax

SPV_AMD_texture_gather_bias_lod
                VK_AMD_texture_gather_bias_lod

SPV_KHR_shader_draw_parameters
                VK_API_VERSION_1_1
                VK_KHR_shader_draw_parameters

SPV_KHR_8bit_storage
                VK_API_VERSION_1_2
                VK_KHR_8bit_storage

SPV_KHR_16bit_storage
                VK_API_VERSION_1_1
                VK_KHR_16bit_storage

SPV_KHR_shader_clock
                VK_KHR_shader_clock

SPV_KHR_float_controls
                VK_API_VERSION_1_2
                VK_KHR_shader_float_controls

SPV_KHR_storage_buffer_storage_class
                VK_API_VERSION_1_1
                VK_KHR_storage_buffer_storage_class

SPV_KHR_post_depth_coverage
                VK_EXT_post_depth_coverage

SPV_EXT_shader_stencil_export
                VK_EXT_shader_stencil_export

SPV_KHR_shader_ballot
                VK_EXT_shader_subgroup_ballot

SPV_KHR_subgroup_vote
                VK_EXT_shader_subgroup_vote

SPV_NV_sample_mask_override_coverage
                VK_NV_sample_mask_override_coverage

SPV_NV_geometry_shader_passthrough
                VK_NV_geometry_shader_passthrough

SPV_NV_mesh_shader
                VK_NV_mesh_shader

SPV_NV_viewport_array2
                VK_NV_viewport_array2

SPV_NV_shader_subgroup_partitioned
                VK_NV_shader_subgroup_partitioned

SPV_EXT_shader_viewport_index_layer
                VK_API_VERSION_1_2
                VK_EXT_shader_viewport_index_layer

SPV_NVX_multiview_per_view_attributes
                VK_NVX_multiview_per_view_attributes

SPV_EXT_descriptor_indexing
                VK_API_VERSION_1_2
                VK_EXT_descriptor_indexing

SPV_KHR_vulkan_memory_model
                VK_API_VERSION_1_2
                VK_KHR_vulkan_memory_model

SPV_NV_compute_shader_derivatives
                VK_NV_compute_shader_derivatives

SPV_NV_fragment_shader_barycentric
                VK_NV_fragment_shader_barycentric

SPV_NV_shader_image_footprint
                VK_NV_shader_image_footprint

SPV_NV_shading_rate
                VK_NV_shading_rate_image

SPV_NV_ray_tracing
                VK_NV_ray_tracing

SPV_KHR_ray_tracing
                VK_KHR_ray_tracing_pipeline

SPV_KHR_ray_query
                VK_KHR_ray_query

SPV_GOOGLE_hlsl_functionality1
                VK_GOOGLE_hlsl_functionality1

SPV_GOOGLE_user_type
                VK_GOOGLE_user_type

SPV_GOOGLE_decorate_string
                VK_GOOGLE_decorate_string

SPV_EXT_fragment_invocation_density
                VK_EXT_fragment_density_map

SPV_KHR_physical_storage_buffer
                VK_API_VERSION_1_2
                VK_KHR_buffer_device_address

SPV_EXT_physical_storage_buffer
                VK_EXT_buffer_device_address

SPV_NV_cooperative_matrix
                VK_NV_cooperative_matrix

SPV_NV_shader_sm_builtins
                VK_NV_shader_sm_builtins

SPV_EXT_fragment_shader_interlock
                VK_EXT_fragment_shader_interlock

SPV_EXT_demote_to_helper_invocation
                VK_EXT_shader_demote_to_helper_invocation

SPV_KHR_fragment_shading_rate
                VK_KHR_fragment_shading_rate

SPV_KHR_non_semantic_info
                VK_KHR_shader_non_semantic_info

SPV_EXT_shader_image_int64
                VK_EXT_shader_image_atomic_int64

SPV_KHR_terminate_invocation
                VK_KHR_shader_terminate_invocation

Validation Rules within a Module

A SPIR-V module passed to vkCreateShaderModule must conform to the following rules:

Standalone SPIR-V Validation

The following rules can be validated with only the SPIR-V module itself. They do not depend on knowledge of the implementation and its capabilities or knowledge of runtime information, such as enabled features.

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

  • The static function-call graph for an entry point must not contain cycles. That is, static recursion is not allowed.

  • The Logical or PhysicalStorageBuffer64 addressing model must be selected.

  • Scope for execution must be limited to Workgroup or Subgroup.

  • If the Scope for execution is Workgroup, then it must only be used in the task, mesh, tessellation control, or compute execution models.

  • Scope for memory must be limited to Device, QueueFamily, Workgroup, ShaderCallKHR, Subgroup, or Invocation.

  • If the Scope for memory is Workgroup, then it must only be used in the task, mesh, or compute execution models.

  • If the Scope for memory is ShaderCallKHR, then it must only be used in ray generation, intersection, closest hit, any-hit, miss, and callable execution models.

  • If the Scope for memory is Invocation, then memory semantics must be None.

  • 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, RayPayloadKHR, IncomingRayPayloadKHR, HitAttributeKHR, CallableDataKHR, IncomingCallableDataKHR, ShaderRecordBufferKHR, or PhysicalStorageBuffer.

  • If the Storage Class is Output, then it must not be used in the RayGenerationKHR, IntersectionKHR, AnyHitKHR, ClosestHitKHR, MissKHR, or CallableKHR execution models.

  • If the Storage Class is Workgroup, then it must only be used in the task, mesh, or compute execution models.

  • Acquire memory semantics must not be used with OpAtomicStore.

  • Release memory semantics must not be used with OpAtomicLoad.

  • AcquireRelease memory semantics must not be used with OpAtomicStore or OpAtomicLoad.

  • OpMemoryBarrier must use one of Acquire, Release, AcquireRelease, or SequentiallyConsistent memory semantics and must include at least one storage class.

  • If the semantics for OpControlBarrier includes one of Acquire, Release, AcquireRelease, or SequentiallyConsistent memory semantics, then it must include at least one storage class.

  • Any OpVariable with an Initializer operand must have Output, Private, or Function as its Storage Class operand.

  • Scope for OpReadClockKHR must be limited to Subgroup or Device

  • The OriginLowerLeft execution mode must not be used; fragment entry points must declare OriginUpperLeft.

  • The PixelCenterInteger execution mode must not be used. Pixels are always centered at half-integer coordinates.

  • Any variable in the UniformConstant storage class must be typed as either OpTypeImage, OpTypeSampler, OpTypeSampledImage, OpTypeAccelerationStructureKHR, or an array of one of these types.

  • OpTypeImage must declare a scalar 32-bit float, 64-bit integer, or 32-bit 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 an OpImageTexelPointer is used in an atomic operation, the image type of the image parameter to OpImageTexelPointer must have an image format of R64i, R64ui, R32f, R32i, or R32ui.

  • OpImageQuerySizeLod, and OpImageQueryLevels 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.

  • 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, and ConstOffsets image operands.

  • Image operand Offset must only be used with OpImage*Gather instructions.

  • The “Component” operand of OpImageGather, and OpImageSparseGather must be the <id> of a constant instruction.

  • Objects of types OpTypeAccelerationStructureKHR and arrays of this type must not be stored to or modified.

  • The value of the “Hit Kind” operand of OpReportIntersectionKHR must be in the range [0,127].

  • Structure types must not contain opaque types.

  • Any BuiltIn decoration not listed in Built-In Variables must not be used.

  • The GLSLShared and GLSLPacked decorations must not be used.

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

  • The ViewportRelativeNV decoration must only be used on a variable decorated with Layer in the vertex, tessellation evaluation, or geometry shader stages.

  • The ViewportRelativeNV decoration must not be used unless a variable decorated with one of ViewportIndex or ViewportMaskNV is also statically used by the same OpEntryPoint.

  • The ViewportMaskNV and ViewportIndex decorations must not both be statically used by one or more OpEntryPoint’s that form the vertex processing stages of a graphics pipeline.

  • Only the round-to-nearest-even and the round-towards-zero rounding modes can be used for the FPRoundingMode decoration.

  • The FPRoundingMode decoration can only be used for the floating-point conversion instructions as described in the SPV_KHR_16bit_storage SPIR-V extension.

  • Variables decorated with Invariant and variables with structure types that have any members decorated with Invariant must be in the Output or Input storage class. Invariant used on an Input storage class variable or structure member has no effect.

  • If the VulkanMemoryModel capability is not declared, the Volatile decoration must be used on any variable declaration that includes one of the SMIDNV, WarpIDNV, SubgroupSize, SubgroupLocalInvocationId, SubgroupEqMask, SubgroupGeMask, SubgroupGtMask, SubgroupLeMask, or SubgroupLtMask BuiltIn decorations when used in the ray generation, closest hit, miss, intersection, or callable shaders, or with the RayTmaxKHR Builtin decoration when used in an intersection shader.

  • If the VulkanMemoryModel capability is declared, the OpLoad instruction must use the Volatile memory semantics when it accesses into any variable that includes one of the SMIDNV, WarpIDNV, SubgroupSize, SubgroupLocalInvocationId, SubgroupEqMask, SubgroupGeMask, SubgroupGtMask, SubgroupLeMask, or SubgroupLtMask BuiltIn decorations when used in the ray generation, closest hit, miss, intersection, or callable shaders, or with the RayTmaxKHR Builtin decoration when used in an intersection shader.

  • OpTypeRuntimeArray must only be used for the last member of an OpTypeStruct that is in the StorageBuffer or PhysicalStorageBuffer storage class decorated as Block, or that is in the Uniform storage class decorated as BufferBlock.

  • A type T that is an array sized with a specialization constant can be, or be contained in, the type of a Variable V only if: T is the (top-level) type of V; V is declared in the Function, Private, or Workgroup storage classes; V is an interface variable with an additional level of arrayness, as described in interface matching, in which case T is allowed to be the element type of the (top-level) type of V.

  • If OpControlBarrier is used in ray generation, intersection, any-hit, closest hit, miss, fragment, vertex, tessellation evaluation, or geometry shaders, the execution Scope must be Subgroup.

  • For each compute shader entry point, either a LocalSize execution mode or an object decorated with the WorkgroupSize 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.

  • If OpGroupNonUniformBallotBitCount is used, the group operation must be limited to Reduce, InclusiveScan, or ExclusiveScan

  • The Pointer operand of all atomic instructions must have a Storage Class limited to Uniform, Workgroup, Image, StorageBuffer

  • Output variables or block members decorated with Offset that have a 64-bit type, or a composite type containing a 64-bit type, must specify an Offset value aligned to a 8 byte boundary

  • Any output block or block member decorated with Offset containing a 64-bit type consumes a multiple of 8 bytes

  • The size of any output block containing any member decorated with Offset that is a 64-bit type must be a multiple of 8

  • The first member of an output block that specifies a Offset decoration must specify a Offset value that is aligned to an 8 byte boundary if that block contains any member decorated with Offset and is a 64-bit type

  • Output variables or block members decorated with Offset that have a 32-bit type, or a composite type contains a 32-bit type, must specify an Offset 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 32-bit or 64-bit in size

  • Only variables or block members in the output interface decorated with Offset can be captured for transform feedback, and those variables or block members must also be decorated with XfbBuffer and XfbStride, or inherit XfbBuffer and XfbStride decorations from a block containing 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 identical XfbStride 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 same XfbBuffer must specify the same Stream 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 the Offset decoration and the size of the type must not overlap

  • All block members in the output interface of the entry point being compiled that are in the same block and have a declared or inherited XfbBuffer decoration must specify the same XfbBuffer value

  • RayPayloadKHR storage class must only be used in ray generation, any-hit, closest hit or miss shaders.

  • IncomingRayPayloadKHR storage class must only be used in closest hit, any-hit, or miss shaders.

  • There must be at most one variable with the IncomingRayPayloadKHR storage class in the input interface of an entry point.

  • HitAttributeKHR storage class must only be used in intersection, any-hit, or closest hit shaders.

  • There must be at most one variable with the HitAttributeKHR storage class in the input interface of an entry point.

  • A variable with HitAttributeKHR storage class must only be written to in an intersection shader.

  • CallableDataKHR storage class must only be used in ray generation, closest hit, miss, and callable shaders.

  • IncomingCallableDataKHR storage class must only be used in callable shaders.

  • There must be at most one variable with the IncomingCallableDataKHR storage class in the input interface of an entry point.

  • The Base operand of OpPtrAccessChain must point to one of the following: Workgroup, if VariablePointers is enabled; StorageBuffer, if VariablePointers or VariablePointersStorageBuffer is enabled. PhysicalStorageBuffer, if the PhysicalStorageBuffer64 addressing model is enabled.

  • If the PhysicalStorageBuffer64 addressing model is enabled, all instructions that support memory access operands and that use a physical pointer must include the Aligned operand.

  • If the PhysicalStorageBuffer64 addressing model is enabled, any access chain instruction that accesses into a RowMajor matrix must only be used as the Pointer operand to OpLoad or OpStore.

  • If the PhysicalStorageBuffer64 addressing model is enabled, OpConvertUToPtr and OpConvertPtrToU must use an integer type whose Width is 64.

  • OpTypeForwardPointer must have a storage class of PhysicalStorageBuffer.

Runtime SPIR-V Validation

The following rules must be validated at runtime. These rules depend on knowledge of the implementation and its capabilities and knowledge of runtime information, such as enabled features.

  • If vulkanMemoryModel is enabled and vulkanMemoryModelDeviceScope is not enabled, Device memory scope must not be used.

  • If vulkanMemoryModel is not enabled, Device memory scope only extends to the queue family, not the whole device.

  • If vulkanMemoryModel is not enabled, QueueFamily memory scope must not be used.

  • if shaderSubgroupClock is not enabled, the Subgroup scope must not be used for OpReadClockKHR.

    • Device

  • if shaderDeviceClock is not enabled, the Device scope must not be used for OpReadClockKHR.

  • The converted bit width, signedness, and numeric type of the Image Format operand of an OpTypeImage must match the Sampled Type, as defined in Image Format and Type Matching.

  • The Result Type operand of OpImageRead must be a vector of four components.

  • If shaderStorageImageWriteWithoutFormat is not enabled and an OpTypeImage has “Image Format” operand of Unknown, any variables created with the given type must be decorated with NonWritable.

  • If shaderStorageImageReadWithoutFormat is not enabled and an OpTypeImage has “Image Format” operand of Unknown, any variables created with the given type must be decorated with NonReadable.

  • Any BuiltIn decoration that corresponds only to Vulkan features or extensions that have not been enabled must not be used.

  • OpTypeRuntimeArray must only be used for an array of variables with storage class Uniform, StorageBuffer, or UniformConstant, or for the outermost dimension of an array of arrays of such variables if the runtimeDescriptorArray feature is enabled,

  • 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 NonUniform.

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

    • If the Float64 capability is enabled, 64-bit floating-point and vector of 64-bit floating-point types are also permitted.

    • If the Int8 capability is enabled and the shaderSubgroupExtendedTypes feature is VK_TRUE, 8-bit integer and vector of 8-bit integer types are also permitted.

    • If the Int16 capability is enabled and the shaderSubgroupExtendedTypes feature is VK_TRUE, 16-bit integer and vector of 16-bit integer types are also permitted.

    • If the Int64 capability is enabled and the shaderSubgroupExtendedTypes feature is VK_TRUE, 64-bit integer and vector of 64-bit integer types are also permitted.

    • If the Float16 capability is enabled and the shaderSubgroupExtendedTypes feature is VK_TRUE, 16-bit floating-point and vector of 16-bit floating-point types are also permitted.

  • If subgroupBroadcastDynamicId is VK_TRUE, and the shader module version is 1.5 or higher, the “Index” for OpGroupNonUniformQuadBroadcast must be dynamically uniform within the derivative group. Otherwise, “Index” must be a constant.

  • If subgroupBroadcastDynamicId is VK_TRUE, and the shader module version is 1.5 or higher, the “Id” for OpGroupNonUniformBroadcast must be dynamically uniform within the subgroup. Otherwise, “Id” must be a constant.

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

  • shaderBufferFloat32Atomics or shaderBufferFloat32AtomicAdd or shaderBufferFloat64Atomics or shaderBufferFloat64AtomicAdd must be enabled for floating-point atomic operations to be supported on a Pointer with a Storage Class of StorageBuffer.

  • shaderSharedFloat32Atomics or shaderSharedFloat32AtomicAdd or shaderSharedFloat64Atomics or shaderSharedFloat64AtomicAdd must be enabled for floating-point atomic operations to be supported on a Pointer with a Storage Class of Workgroup.

  • shaderImageFloat32Atomics or shaderImageFloat32AtomicAdd must be enabled for 32-bit floating-point atomic operations to be supported on a Pointer with a Storage Class of Image.

  • sparseImageFloat32Atomics or sparseImageFloat32AtomicAdd must be enabled for 32-bit floating-point atomics to be supported on sparse images.

    • shaderImageInt64Atomics must be enabled for 64-bit integer atomic operations to be supported on a Pointer with a Storage Class of Image.

  • If denormBehaviorIndependence is VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY, then the entry point must use the same denormals execution mode for both 16-bit and 64-bit floating-point types.

  • If denormBehaviorIndependence is VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE, then the entry point must use the same denormals execution mode for all floating-point types.

  • If roundingModeIndependence is VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY, then the entry point must use the same rounding execution mode for both 16-bit and 64-bit floating-point types.

  • If roundingModeIndependence is VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE, then the entry point must use the same rounding execution mode for all floating-point types.

  • If shaderSignedZeroInfNanPreserveFloat16 is VK_FALSE, then SignedZeroInfNanPreserve for 16-bit floating-point type must not be used.

  • If shaderSignedZeroInfNanPreserveFloat32 is VK_FALSE, then SignedZeroInfNanPreserve for 32-bit floating-point type must not be used.

  • If shaderSignedZeroInfNanPreserveFloat64 is VK_FALSE, then SignedZeroInfNanPreserve for 64-bit floating-point type must not be used.

  • If shaderDenormPreserveFloat16 is VK_FALSE, then DenormPreserve for 16-bit floating-point type must not be used.

  • If shaderDenormPreserveFloat32 is VK_FALSE, then DenormPreserve for 32-bit floating-point type must not be used.

  • If shaderDenormPreserveFloat64 is VK_FALSE, then DenormPreserve for 64-bit floating-point type must not be used.

  • If shaderDenormFlushToZeroFloat16 is VK_FALSE, then DenormFlushToZero for 16-bit floating-point type must not be used.

  • If shaderDenormFlushToZeroFloat32 is VK_FALSE, then DenormFlushToZero for 32-bit floating-point type must not be used.

  • If shaderDenormFlushToZeroFloat64 is VK_FALSE, then DenormFlushToZero for 64-bit floating-point type must not be used.

  • If shaderRoundingModeRTEFloat16 is VK_FALSE, then RoundingModeRTE for 16-bit floating-point type must not be used.

  • If shaderRoundingModeRTEFloat32 is VK_FALSE, then RoundingModeRTE for 32-bit floating-point type must not be used.

  • If shaderRoundingModeRTEFloat64 is VK_FALSE, then RoundingModeRTE for 64-bit floating-point type must not be used.

  • If shaderRoundingModeRTZFloat16 is VK_FALSE, then RoundingModeRTZ for 16-bit floating-point type must not be used.

  • If shaderRoundingModeRTZFloat32 is VK_FALSE, then RoundingModeRTZ for 32-bit floating-point type must not be used.

  • If shaderRoundingModeRTZFloat64 is VK_FALSE, then RoundingModeRTZ for 64-bit floating-point 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 with XfbBuffer must not be greater than VkPhysicalDeviceTransformFeedbackPropertiesEXT::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 same XfbBuffer value, the size of the output interface variable plus the Offset is less than or equal to the buffer data size. For a given Stream, the sum of all the buffer data sizes for all buffers writing to that stream the must not exceed VkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackStreamDataSize

  • The Stream value to OpEmitStreamVertex and OpEndStreamPrimitive must be less than VkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackStreams

  • If the geometry shader emits to more than one vertex stream and VkPhysicalDeviceTransformFeedbackPropertiesEXT::transformFeedbackStreamsLinesTriangles is VK_FALSE, then execution mode must be OutputPoints

  • The stream number value to Stream must be less than VkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackStreams

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

  • If the PhysicalStorageBuffer64 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 pointed-to type.

  • If the PhysicalStorageBuffer64 addressing model is enabled the pointer value of a memory access instruction must be at least as aligned as specified by the Aligned memory access operand.

  • 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, the Result, A, B, and C matrices must all have types that satisfy the same supported VkCooperativeMatrixPropertiesNV. That is, for one supported VkCooperativeMatrixPropertiesNV, all of the following must hold:

    • The type of A must have MSize rows and KSize columns and have a component type that matches AType.

    • The type of B must have KSize rows and NSize columns and have a component type that matches BType.

    • The type of C must have MSize rows and NSize columns and have a component type that matches CType.

    • The type of Result must have MSize rows and NSize columns and have a component type that matches DType.

    • The type of A, B, C, and Result must all have a scope of scope.

  • OpTypeCooperativeMatrixNV and OpCooperativeMatrix* instructions must not be used in shader stages not included in VkPhysicalDeviceCooperativeMatrixPropertiesNV::cooperativeMatrixSupportedStages.

  • DescriptorSet and Binding decorations must obey the constraints on storage class, type, and descriptor type described in DescriptorSet and Binding Assignment

  • For OpCooperativeMatrixLoadNV and OpCooperativeMatrixStoreNV instructions, the Pointer and Stride operands must be aligned to at least the lesser of 16 bytes or the natural alignment of a row or column (depending on ColumnMajor) of the matrix (where the natural alignment is the number of columns/rows multiplied by the component size).

  • For compute shaders using the DerivativeGroupLinearNV execution mode, the product of the dimensions of the local workgroup size must be a multiple of four.

  • If the VK_KHR_portability_subset extension is enabled, and VkPhysicalDevicePortabilitySubsetFeaturesKHR::shaderSampleRateInterpolationFunctions is VK_FALSE, then GLSL.std.450 fragment interpolation functions are not supported by the implementation and OpCapability must not be set to InterpolationFunction.

  • If tessellationShader is enabled, and the VK_KHR_portability_subset extension is enabled, and VkPhysicalDevicePortabilitySubsetFeaturesKHR::tessellationIsolines is VK_FALSE, then OpExecutionMode must not be set to IsoLines.

  • If tessellationShader is enabled, and the VK_KHR_portability_subset extension is enabled, and VkPhysicalDevicePortabilitySubsetFeaturesKHR::tessellationPointMode is VK_FALSE, then OpExecutionMode must not be set to PointMode.

  • If storageBuffer8BitAccess is VK_FALSE, then objects containing an 8-bit integer element must not have storage class of StorageBuffer, ShaderRecordBufferKHR, or PhysicalStorageBuffer.

  • If uniformAndStorageBuffer8BitAccess is VK_FALSE, then objects in the Uniform storage class with the Block decoration and in the StorageBuffer, ShaderRecordBufferKHR, or PhysicalStorageBuffer storage class with the same decoration must not have an 8-bit integer member.

  • If storagePushConstant8 is VK_FALSE, then objects containing an 8-bit integer element must not have storage class of PushConstant.

  • If storageBuffer16BitAccess is VK_FALSE, then objects containing a 16-bit integer element must not have storage class of StorageBuffer, ShaderRecordBufferKHR, or PhysicalStorageBuffer.

  • If uniformAndStorageBuffer16BitAccess is VK_FALSE, then objects in the Uniform storage class with the Block decoration and in the StorageBuffer, ShaderRecordBufferKHR, or PhysicalStorageBuffer storage class with the same decoration must not have a 16-bit integer member.

  • If storagePushConstant16 is VK_FALSE, then objects containing a 16-bit integer element must not have storage class of PushConstant.

  • If storageInputOutput16 is VK_FALSE, then objects containing a 16-bit integer element must not have storage class of Input or Output.

  • Atomic instructions must declare a scalar 32-bit integer type, or a scalar 32-bit floating-point type if the shaderBufferFloat32Atomics or shaderBufferFloat32AtomicAdd or shaderSharedFloat32Atomics or shaderSharedFloat32AtomicAdd or shaderImageFloat32Atomics or shaderImageFloat32AtomicAdd or sparseImageFloat32Atomics or sparseImageFloat32AtomicAdd is enabled, or a scalar 64-bit floating-point type if the shaderBufferFloat64Atomics or shaderBufferFloat64AtomicAdd or shaderSharedFloat64Atomics or shaderSharedFloat64AtomicAdd is enabled, or a scalar 64-bit integer type if the Int64Atomics capability is enabled, for the value pointed to by Pointer.

  • If fragmentStoresAndAtomics is not enabled, then all storage image, storage texel buffer, and storage buffer variables in the fragment stage must be decorated with the NonWritable decoration.

  • If vertexPipelineStoresAndAtomics is not enabled, then all storage image, storage texel buffer, and storage buffer variables in the vertex, tessellation, and geometry stages must be decorated with the NonWritable decoration.

  • If subgroupQuadOperationsInAllStages is VK_FALSE, then quad subgroup operations must not be used except for in fragment and compute stages.

  • Group operations with subgroup scope must not be used if the shader stage is not in subgroupSupportedStages.

  • The first element of the Offset operand of InterpolateAtOffset must be greater than or equal to:

    fragwidth × minInterpolationOffset

    where fragwidth is the width of the current fragment in pixels.

  • The first element of the Offset operand of InterpolateAtOffset must be less than or equal to:

    fragwidth × (maxInterpolationOffset + ULP ) - ULP

    where fragwidth is the width of the current fragment in pixels and ULP = 1 / 2subPixelInterpolationOffsetBits.

  • The second element of the Offset operand of InterpolateAtOffset must be greater than or equal to:

    fragheight × minInterpolationOffset

    where fragheight is the height of the current fragment in pixels.

  • The second element of the Offset operand of InterpolateAtOffset must be less than or equal to:

    fragheight × (maxInterpolationOffset + ULP ) - ULP

    where fragheight is the height of the current fragment in pixels and ULP = 1 / 2subPixelInterpolationOffsetBits.

  • For OpRayQueryInitializeKHR instructions:

    • All components of the Ray Origin and Ray Direction operands must be finite floating-point values.

    • The Ray Tmin and Ray Tmax operands must be non-negative floating-point values.

    • The Ray Tmin operand must be less than or equal to the Ray Tmax operand.

    • The above operands must not contain NaNs.

    • Acceleration Structure must be an acceleration structure built as a top-level acceleration structure.

  • For OpRayQueryGenerateIntersectionKHR instructions:

    • Hit T must satisfy the condition Ray TminHit TRay Tmax, where Ray Tmin is equal to the value returned by OpRayQueryGetRayTMinKHR with the same ray query object, and Ray Tmax is equal to the value of OpRayQueryGetIntersectionTKHR for the current committed intersection with the same ray query object.

  • For OpTraceRayKHR instructions:

    • All components of the Ray Origin and Ray Direction operands must be finite floating-point values.

    • The Ray Tmin and Ray Tmax operands must be non-negative floating-point values.

    • The Ray Tmin operand must be less than or equal to the Ray Tmax operand.

    • The above operands must not contain NaNs.

    • Acceleration Structure must be an acceleration structure built as a top-level acceleration structure.

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.

  • By default, the implementation may perform optimizations on half, single, or double-precision floating-point instructions that ignore sign of a zero, or assume that arguments and results are not NaNs or infinities. If the entry point is declared with the SignedZeroInfNanPreserve execution mode, then NaNs, infinities, and the sign of zero must not be ignored.

    • The following core SPIR-V 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 by OpLoad except for loads from the Input storage class in the fragment shader stage with the floating-point result type. Other SPIR-V instructions may also respect the SignedZeroInfNanPreserve execution mode.

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

  • 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 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 floating-point numbers must be flushed to zero.

    • The following core SPIR-V instructions must respect the DenormFlushToZero execution mode: OpSpecConstantOp (with opcode OpFConvert), 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 DenormPreserve execution 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.

Correctly Rounded

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.

ULP

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

Inherited From …​

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

Table 83. Precision of core SPIR-V Instructions
Instruction Single precision, unless decorated with RelaxedPrecision Half precision

OpFAdd

Correctly rounded.

OpFSub

Correctly rounded.

OpFMul, OpVectorTimesScalar, OpMatrixTimesScalar

Correctly rounded.

OpDot(x, y)

Inherited from .

OpFOrdEqual, OpFUnordEqual

Correct result.

OpFOrdLessThan, OpFUnordLessThan

Correct result.

OpFOrdGreaterThan, OpFUnordGreaterThan

Correct result.

OpFOrdLessThanEqual, OpFUnordLessThanEqual

Correct result.

OpFOrdGreaterThanEqual, OpFUnordGreaterThanEqual

Correct result.

OpFDiv(x,y)

2.5 ULP for |y| in the range [2-126, 2126].

2.5 ULP for |y| in the range [2-14, 214].

OpFRem(x,y)

Inherited from x - y × trunc(x/y).

OpFMod(x,y)

Inherited from x - y × floor(x/y).

conversions between types

Correctly rounded.

Note

The OpFRem and OpFMod instructions use cheap approximations of remainder, and the error can be large due to the discontinuity in trunc() and floor(). This can produce mathematically unexpected results in some cases, such as FMod(x,x) computing x rather than 0, and can also cause the result to have a different sign than the infinitely precise result.

Table 84. Precision of GLSL.std.450 Instructions
Instruction Single precision, unless decorated with RelaxedPrecision Half precision

fma()

Inherited from OpFMul followed by OpFAdd.

exp(x), exp2(x)

ULP.

ULP.

log(), log2()

3 ULP outside the range . Absolute error < inside the range .

3 ULP outside the range . Absolute error < inside the range .

pow(x, y)

Inherited from exp2(y × log2(x)).

sqrt()

Inherited from 1.0 / inversesqrt().

inversesqrt()

2 ULP.

radians(x)

Inherited from .

degrees(x)

Inherited from .

sin()

Absolute error inside the range .

Absolute error inside the range .

cos()

Absolute error inside the range .

Absolute error inside the range .

tan()

Inherited from .

asin(x)

Inherited from .

acos(x)

Inherited from .

atan(), atan2()

4096 ULP

5 ULP.

sinh(x)

Inherited from .

cosh(x)

Inherited from .

tanh()

Inherited from .

asinh(x)

Inherited from .

acosh(x)

Inherited from .

atanh(x)

Inherited from .

frexp()

Correctly rounded.

ldexp()

Correctly rounded.

length(x)

Inherited from .

distance(x, y)

Inherited from .

cross()

Inherited from OpFSub(OpFMul, OpFMul).

normalize(x)

Inherited from .

faceforward(N, I, NRef)

Inherited from dot(NRef, I) < 0.0 ? N : -N.

reflect(x, y)

Inherited from x - 2.0 × dot(y, x) × y.

refract(I, N, eta)

Inherited from k < 0.0 ? 0.0 : eta × I - (eta × dot(N, I) + sqrt(k)) × N, where k = 1 - eta × eta × (1.0 - dot(N, I) × dot(N, I)).

round

Correctly rounded.

roundEven

Correctly rounded.

trunc

Correctly rounded.

fabs

Correctly rounded.

fsign

Correctly rounded.

floor

Correctly rounded.

ceil

Correctly rounded.

fract

Correctly rounded.

modf

Correctly rounded.

fmin

Correctly rounded.

fmax

Correctly rounded.

fclamp

Correctly rounded.

fmix(x, y, a)

Inherited from .

step

Correctly rounded.

smoothStep(edge0, edge1, x)

Inherited from , where .

nmin

Correctly rounded.

nmax

Correctly rounded.

nclamp

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 OpSRem and OpSMod instructions are supported by the Vulkan environment, they require non-negative values and thus do not enable additional functionality beyond what OpUMod provides.

OpCooperativeMatrixMulAddNV performs its operations in an implementation-dependent order and internal precision.

Image Format and Type Matching

When specifying the Image Format as anything other than Unknown, the converted bit width, type, and signedness as shown in the table below, must match the Sampled Type.

Note

Formatted accesses are always converted from a shader readable type to the resource’s format or vice versa via Format Conversion for reads and Texel Output Format Conversion for writes. As such, the bit width and format below do not necessarily match 1:1 with what might be expected for some formats.

For a given Image Format, the Sampled Type must be the type described in the Type column of the below table, with its Literal Width set to that in the Bit Width column, and its Literal Signedness to that in the Signedness column (where applicable).

Image Format Type Bit Width Signedness

Unknown

Any

Any

Any

Rgba32f

OpTypeFloat

32

N/A

Rg32f

R32f

Rgba16f

Rg16f

R16f

Rgba16

Rg16

R16

Rgba16Snorm

Rg16Snorm

R16Snorm

Rgb10A2

R11fG11fB10f

Rgba8

Rg8

R8

Rgba8Snorm

Rg8Snorm

R8Snorm

Rgba32i

OpTypeInt

32

1

Rg32i

R32i

Rgba16i

Rg16i

R16i

Rgba8i

Rg8i

R8i

Rgba32ui

0

Rg32ui

R32ui

Rgba16ui

Rg16ui

R16ui

Rgb10a2ui

Rgba8ui

Rg8ui

R8ui

Compatibility Between SPIR-V Image Formats And Vulkan Formats

SPIR-V Image Format values are compatible with VkFormat values as defined below:

Table 85. SPIR-V and Vulkan Image Format Compatibility
SPIR-V Image Format Compatible Vulkan Format

Unknown

Any

Rgba32f

VK_FORMAT_R32G32B32A32_SFLOAT

Rgba16f

VK_FORMAT_R16G16B16A16_SFLOAT

R32f

VK_FORMAT_R32_SFLOAT

Rgba8

VK_FORMAT_R8G8B8A8_UNORM

Rgba8Snorm

VK_FORMAT_R8G8B8A8_SNORM

Rg32f

VK_FORMAT_R32G32_SFLOAT

Rg16f

VK_FORMAT_R16G16_SFLOAT

R11fG11fB10f

VK_FORMAT_B10G11R11_UFLOAT_PACK32

R16f

VK_FORMAT_R16_SFLOAT

Rgba16

VK_FORMAT_R16G16B16A16_UNORM

Rgb10A2

VK_FORMAT_A2B10G10R10_UNORM_PACK32

Rg16

VK_FORMAT_R16G16_UNORM

Rg8

VK_FORMAT_R8G8_UNORM

R16

VK_FORMAT_R16_UNORM

R8

VK_FORMAT_R8_UNORM

Rgba16Snorm

VK_FORMAT_R16G16B16A16_SNORM

Rg16Snorm

VK_FORMAT_R16G16_SNORM

Rg8Snorm

VK_FORMAT_R8G8_SNORM

R16Snorm

VK_FORMAT_R16_SNORM

R8Snorm

VK_FORMAT_R8_SNORM

Rgba32i

VK_FORMAT_R32G32B32A32_SINT

Rgba16i

VK_FORMAT_R16G16B16A16_SINT

Rgba8i

VK_FORMAT_R8G8B8A8_SINT

R32i

VK_FORMAT_R32_SINT

Rg32i

VK_FORMAT_R32G32_SINT

Rg16i

VK_FORMAT_R16G16_SINT

Rg8i

VK_FORMAT_R8G8_SINT

R16i

VK_FORMAT_R16_SINT

R8i

VK_FORMAT_R8_SINT

Rgba32ui

VK_FORMAT_R32G32B32A32_UINT

Rgba16ui

VK_FORMAT_R16G16B16A16_UINT

Rgba8ui

VK_FORMAT_R8G8B8A8_UINT

R32ui

VK_FORMAT_R32_UINT

Rgb10a2ui

VK_FORMAT_A2B10G10R10_UINT_PACK32

Rg32ui

VK_FORMAT_R32G32_UINT

Rg16ui

VK_FORMAT_R16G16_UINT

Rg8ui

VK_FORMAT_R8G8_UINT

R16ui

VK_FORMAT_R16_UINT

R8ui

VK_FORMAT_R8_UINT