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.4 implementation must support the 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, and 1.6 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).
SPIR-VOpCapabilityVulkan feature, extension, or core version{generated}/spirvcap/captable.adoc

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 following table lists SPIR-V extensions that implementations may support. The application must not pass a SPIR-V module to vkCreateShaderModule that uses the following SPIR-V extensions unless 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).
SPIR-VOpExtensionVulkan extension or core version{generated}/spirvcap/exttable.adoc

Validation Rules Within a Module

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

Standalone SPIR-V Validation

StandaloneSpirvStandalone SPIR-V Validation

Runtime SPIR-V Validation

RuntimeSpirvRuntime SPIR-V Validation

Precision and Operation of SPIR-V Instructions

The following rules apply to operations on all floating-point values:

  • Positive and negative infinities and positive and negative zeros are generated as dictated by IEEE 754 for the specified encoding, but subject to the precisions allowed by each operation for a given encoding, as specified in Precision of Individual Operations.
  • 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 set of operations OpPhi, OpSelect, OpFunctionCall, OpReturnValue, OpVectorExtractDynamic, OpVectorInsertDynamic, OpVectorShuffle, OpCompositeConstruct, OpCompositeExtract, OpCompositeInsert, OpTranspose, OpCopyObject, OpCopyLogical, OpCopyMemory, OpGroupNonUniformBroadcast, OpGroupNonUniformBroadcastFirst, OpGroupNonUniformShuffle, OpGroupNonUniformShuffleXor, OpGroupNonUniformShuffleUp, OpGroupNonUniformShuffleDown, OpGroupNonUniformQuadBroadcast, OpGroupNonUniformQuadSwap, OpSubgroupReadInvocationKHR, OpSubgroupFirstInvocationKHR, OpGroupNonUniformRotateKHR, OpCooperativeMatrixLoadKHR, OpCooperativeMatrixStoreKHR, OpCooperativeMatrixLoadNV, OpCooperativeMatrixStoreNV, OpCooperativeMatrixLoadTensorNV, OpCooperativeMatrixStoreTensorNV, OpAtomicLoad, OpAtomicStore, OpAtomicExchange, OpStore, and OpLoad are referred to as bit-preserving operations.
  • The floating-point environment used for an instruction can be determined as follows:
    • If the SPIR-V specifies it explicitly using the FPFastMath decoration or FPFastMathDefault Execution Mode then that is used.
    • If the environment is not specified in the SPIR-V then it is determined as follows:
      • If the operation is not decorated NoContraction then the flags AllowContract, AllowReassoc, AllowRecip, and AllowTransform are assumed.
      • If any of the following conditions are true then the flags NSZ, NotInf, and NotNaN are assumed:
        • The entry point does not use the Execution Mode
          SignedZeroInfNanPreserve with a bit-width corresponding to one of the operands or to the result type.
        • The operation is not a bit-preserving operation and is not one of OpFConvert, OpFNegate, OpFAdd, OpFSub, OpFMul, OpFDiv, OpIsNan, OpIsInf, OpVectorTimesScalar, OpMatrixTimesScalar, OpVectorTimesMatrix, OpMatrixTimesVector, OpMatrixTimesMatrix, OpOuterProduct, OpDot, OpFOrdEqual, OpFUnordEqual, OpFOrdNotEqual, OpFUnordNotEqual, OpFOrdLessThan, OpFUnordLessThan, OpFOrdGreaterThan, OpFUnordGreaterThan, OpFOrdLessThanEqual, OpFUnordLessThanEqual, OpFOrdGreaterThanEqual, OpFUnordGreaterThanEqual, OpGroupNonUniformAllEqual, OpSubgroupAllEqualKHR, OpGroupNonUniformFMin, OpGroupNonUniformFMax, OpAtomicCompareExchange, OpAtomicCompareExchangeWeak, OpDPdx, OpDPdy, OpFwidth, OpDPdxFine, OpDPdyFine, OpFwidthFine, OpDPdxCoarse, OpDPdyCoarse, or OpFwidthCoarse.
        • The operation is an OpLoad from the Input Storage Class in the fragment shader stage.
  • All bit-preserving operations and the following instructions must not flush denormalized values: OpConstant, OpConstantComposite, OpSpecConstant, OpSpecConstantComposite, and OpBitcast.
  • Denormalized values are supported.
    • By default any denormalized floating-point 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.
    • Denormalized floating-point values whose type use the Float8E4M3EXT or Float8E5M2EXT FP Encoding must be preserved during conversions to IEEE 754 binary 16 floating-point values.
    • If the entry point is declared with the DenormFlushToZero
      Execution Mode then for the affected instructions 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.
    • When denormal values are being flushed, the result of an operation may be considered denormal whenever the infinitely precise result is non-zero and of smaller magnitude than the smallest normal value, even if rounding would otherwise give a normal result.
    • The following core SPIR-V instructions must respect the DenormFlushToZero Execution Mode: OpSpecConstantOp (with opcode OpFConvert), OpFConvert, OpFNegate, OpFAdd, OpFSub, OpFMul, OpFmaKHR, OpFDiv, OpFRem, OpFMod, OpVectorTimesScalar, OpMatrixTimesScalar, OpVectorTimesMatrix, OpMatrixTimesVector, OpMatrixTimesMatrix, OpOuterProduct, OpDot, OpGroupNonUniformFMin, OpGroupNonUniformFMax, OpAtomicFAddEXT, OpAtomicFMinEXT, OpAtomicFMaxEXT, OpDPdx, OpDPdy, OpFwidth, OpDPdxFine, OpDPdyFine OpFwidthFine, OpDPdxCoarse, OpDPdyCoarse, OpFwidthCoarse; 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, Length, Distance, Cross, Normalize, FaceForward, Reflect, Refract, NMin, NMax, and NClamp.
    • The following core SPIR-V instructions must respect the DenormPreserve Execution Mode for floating-point values with an IEEE 754 encoding: OpSpecConstantOp, OpFConvert, OpFNegate, OpFAdd, OpFSub, OpFMul, OpFmaKHR, OpVectorTimesScalar, OpMatrixTimesScalar, OpVectorTimesMatrix, OpMatrixTimesVector, OpMatrixTimesMatrix, OpOuterProduct, OpDot, OpFOrdEqual, OpFUnordEqual, OpFOrdNotEqual, OpFUnordNotEqual, OpFOrdLessThan, OpFUnordLessThan, OpFOrdGreaterThan, OpFUnordGreaterThan, OpFOrdLessThanEqual, OpFUnordLessThanEqual, OpFOrdGreaterThanEqual, OpFUnordGreaterThanEqual, OpSubgroupAllEqualKHR, OpGroupNonUniformAllEqual, OpGroupNonUniformFMin, OpGroupNonUniformFMax, OpAtomicCompareExchange, OpAtomicCompareExchangeWeak, OpAtomicFAddEXT, OpAtomicFMinEXT, OpAtomicFMaxEXT, OpDPdx, OpDPdy, OpFwidth, OpDPdxFine, OpDPdyFine OpFwidthFine, OpDPdxCoarse, OpDPdyCoarse, OpFwidthCoarse; and the following extended instructions for GLSL: FAbs, FSign, Radians, Degrees, FMin, FMax, FClamp, FMix, Fma, PackHalf2x16, PackDouble2x32, UnpackHalf2x16, UnpackDouble2x32, NMin, NMax, and NClamp.

The precision of double-precision instructions is at least that of single precision.

The precision of individual operations is defined in Precision of Individual Operations. Subject to the constraints below, however, implementations may reorder or combine operations, resulting in expressions exhibiting different precisions than might be expected from the constituent operations.

Evaluation of Expressions

Implementations may rearrange floating-point operations using any of the mathematical properties governing the expressions in precise arithmetic, even where the floating- point operations do not share these properties. This includes, but is not limited to associativity and distributivity, and may involve a different number of rounding steps than would occur if the operations were not rearranged. In shaders that use the SignedZeroInfNanPreserve Execution Mode the values must be preserved if they are generated after any rearrangement but the Execution Mode does not change which rearrangements are valid. This rearrangement can be prevented for particular operations by using the NoContraction decoration.

For example, in the absence of the NoContraction decoration implementations are allowed to implement a + b - a and a×ba{a \times b}\over{a} as b. The SignedZeroInfNanPreserve does not prevent these transformations, even though they may overflow to infinity or NaN when evaluated in floating-point.If the NoContraction decoration is applied then operations may not be rearranged, so, for example, a + a - a must account for possible overflow to infinity. If infinities are not preserved then the expression may be replaced with a despite the NoContraction decoration, since the replacement is exact when overflow does not occur. If both NoContraction and SignedZeroInfNanPreserve are used then the result must be infinity for sufficiently large a.

Precision of Individual Operations

The precision of individual operations is defined either in terms of rounding (correctly rounded), as an error bound in ULP, or as inherited from a formula as follows:

Correct Result

Operations that are described as returning the correct result will return the infinitely precise result which, due to the nature of the operation, will not need rounding.

Correctly Rounded

Operations described as correctly rounded will return the infinitely precise result, x, rounded so as to be representable in floating-point. If the entry point is declared with the RoundingModeRTE or the RoundingModeRTZ Execution Mode then this is done according to IEEE 754 roundTiesToEven or roundTowardZero rounding directions, respectively. These execution modes do not affect operations on floating-point values with the following encodings:

  • BFloat16KHR
  • Float8E4M3EXT
  • Float8E5M2EXT

Otherwise, they are rounded with implementation-defined rounding mode.

Correctly Rounded with Implementation-Defined Rounding Mode

Operations described as correctly rounded with implementation-defined rounding mode will return the infinitely precise result, x, rounded so as to be representable in floating-point. 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. Which value is chosen is implementation-defined.

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, finite floating-point numbers a and b such that a ≤ x ≤ b then ulp(x) is the minimum possible distance between such numbers, ulp(x)=min_a,bbaulp(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 non-equal, 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 poison.

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 E=max(xF_min,xF_max)E = \mathrm{max} \left( | x - F\_{\mathrm{min}} |, | x - F\_{\mathrm{max}} | \right) . If the entry point is declared with the DenormPreserve Execution Mode, then denormals must be preserved throughout the formula. Otherwise, any intermediate denormal value(s) while evaluating the formula may be flushed to zero. If the entry point is declared with the DenormFlushToZero execution mode, then denormal final results must be flushed to zero.

The precision of all instructions on float values with the BFloat16KHR encoding is required to be correctly rounded with implementation defined rounding mode.

For IEEE754 half- (16 bit) and single- (32 bit) precision instructions, precisions are required to be at least as follows:

InstructionSingle precision, unless decorated with RelaxedPrecisionHalf precision

OpFNegate

Correct result.

OpFAdd

Correctly rounded.

OpFSub

Correctly rounded.

OpFMul, OpVectorTimesScalar, OpMatrixTimesScalar

Correctly rounded.

OpMatrixTimesVector

Inherited from .

OpVectorTimesMatrix

Inherited from .

OpMatrixTimesMatrix

Inherited from .

OpOuterProduct

Correctly rounded.

OpFmaKHR

Correctly rounded.

OpDot(x, y)

Inherited from .

OpIsNan, OpIsInf

Correct result.

OpFOrdEqual, OpFUnordEqual

Correct result.

OpFOrdNotEqual, OpFUnordNotEqual

Correct result.

OpFOrdLessThan, OpFUnordLessThan

Correct result.

OpFOrdGreaterThan, OpFUnordGreaterThan

Correct result.

OpFOrdLessThanEqual, OpFUnordLessThanEqual

Correct result.

OpFOrdGreaterThanEqual, OpFUnordGreaterThanEqual

Correct result.

OpSubgroupAllEqualKHR

Correct result.

OpGroupNonUniformAllEqual

Correct result.

OpGroupNonUniformFMin, OpGroupNonUniformFMax

Correct result.

OpFDiv(x,y)

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

2.5 ULP for |y| = 0 or |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).

OpQuantizeToF16

Correctly rounded with implementation defined rounding mode.

conversions between types

Correctly rounded.

OpAtomicCompareExchange, OpAtomicCompareExchangeWeak

Correct result.

OpAtomicFAddEXT

Return value correct result, value in memory correctly rounded.

OpAtomicFMinEXT, OpAtomicFMaxEXT

Correct result.

OpDPdx, OpDPdy, OpFwidth

Correctly rounded.

OpDPdxCoarse, OpDPdyCoarse, OpFwidthCoarse

Correctly rounded.

OpDPdxFine, OpDPdyFine, OpFwidthFine

Correctly rounded.

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.
InstructionSingle precision, unless decorated with RelaxedPrecisionHalf 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 , where is a correctly rounded approximation to .

degrees(x)

Inherited from , where is a correctly rounded approximation to .

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

Correct result.

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

Correct result.

fsign

Correct result.

floor

Correctly rounded.

ceil

Correctly rounded.

fract

Correctly rounded.

modf

Correctly rounded.

fmin

Correct result.

fmax

Correct result.

fclamp

Correct result.

fmix(x, y, a)

Inherited from .

step

Correctly rounded.

smoothStep(edge0, edge1, x)

Inherited from , where .

nmin

Correct result.

nmax

Correct result.

nclamp

Correct result.

packHalf2x16

Correctly rounded with implementation defined rounding mode.

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 implementation-defined precision.

If the maintenance8 feature is not enabled and if either operand to OpSRem and OpSMod instructions is negative the result is poison.

While the OpSRem and OpSMod instructions are supported by the Vulkan environment, If the maintenance8 feature is not enabled, 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.

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

OpCooperativeVectorMatrixMulNV and OpCooperativeVectorMatrixMulAddNV perform their operations in an implementation-dependent order and internal precision.

When inputType is VK_COMPONENT_TYPE_FLOAT16_KHR and inputInterpretation is a lower-precision floating-point type (e.g. VK_COMPONENT_TYPE_FLOAT_E4M3_NV or VK_COMPONENT_TYPE_FLOAT_E5M2_NV), the input vector should be converted to the lower-precision type before performing the matrix-vector multiply, but may keep the full 16 bits of precision.

Buffer Indexing Calculations

Pipelines and shaders may be compiled to use 32-bit integer arithmetic to compute byte offsets (e.g. based on OpAccessChain instructions) within a physical storage buffer or buffer, limiting the accessible range to 4GB. For physical storage buffers, the base address is a 64-bit value and the implicit base plus offset calculation uses 64-bit addition.

Note that OpAccessChain indices are always treated as signed, so a 32-bit index can only address 2GB if the ArrayStride is 1.

The offset calculations that have the 4GB limit include:

  • OpAccessChain and OpPtrAccessChain - the total offset summed over all indices multiplied by strides, including spanning multiple access chain instructions that lead to a given memory access.
  • OpCooperativeMatrixLoadNV and OpCooperativeMatrixStoreNV instructions computing an offset based on element, row, and stride parameters.
  • OpCooperativeMatrixLoadKHR and OpCooperativeMatrixStoreKHR instructions computing an offset based on element, row, and stride parameters.
  • OpCooperativeMatrixLoadTensorNV and OpCooperativeMatrixStoreTensorNV instructions computing an offset based on tensor layout state.
  • OpCooperativeVectorMatrixMulAddNV, OpCooperativeVectorMatrixMulNV and OpCooperativeVectorOuterProductAccumulateNV instructions computing an offset based on offset, row, and stride parameters.

64-Bit Indexing

The application can enable 64-bit indexing either by setting the flags VK_PIPELINE_CREATE_2_64_BIT_INDEXING_BIT_EXT or VK_SHADER_CREATE_64_BIT_INDEXING_BIT_EXT or by setting the Execution Mode Shader64BitIndexingEXT on the entry point, which will cause the implementation to use 64 bits of range for those addressing calculations.

If 64-bit indexing is enabled, the calculation of index multiplied by ArrayStride for a runtime-sized array when evaluating an access chain in StorageBuffer or PhysicalStorageBuffer will have 64 bits of range. Similarly, the Element times ArrayStride calculation for OpPtrAccessChain and OpUntypedPtrAccessChainKHR will have 64 bits of range.

The size of a structure type or sized array type in a storage buffer is still limited to 32 bits for various practical reasons, such as that Offset and ArrayStride decorations use 32-bit literals. Only runtime-sized arrays can access beyond the 32-bit limit.
Enabling 64-bit indexing may incur a runtime cost.

If 64-bit indexing is enabled, OpArrayLength and OpUntypedArrayLengthKHRcan have a 64-bit result type.

If 64-bit indexing is enabled, the row/col times stride calculations in OpCooperativeMatrixLoadNV, OpCooperativeMatrixStoreNV, OpCooperativeMatrixLoadKHR, and OpCooperativeMatrixStoreKHR are changed to have 64 bits of range. i.e. Pointer[row*(uint64_t)Stride] and Pointer[col*(uint64_t)Stride]. The stride itself is still limited to 32 bits.

If 64-bit indexing is enabled, the coordinate times stride calculations in tensorCoordToLinear used by OpCooperativeMatrixLoadTensorNV and OpCooperativeMatrixStoreTensorNV in the SPV_NV_cooperative_matrix2 extension are changed to have 64 bits of range for the result:

uint64_t tensorCoordToLinear(tensorLayoutNV t, Coord blockCoord)
{
    uint64_t index = 0;

    for (uint32_t dim = 0; dim <= t.LDim-1; ++dim) {
        // multiply has 64b result
        index += blockCoord[dim] * uint64_t{t.stride[dim]};
    }
    return index;
}

The matrixCoordToTensorElement and matrixCoordToTensorElementWithView functions are also changed to return that 64-bit result.

If 64-bit indexing is enabled, the offset parameters to OpCooperativeVectorLoadNV, OpCooperativeVectorStoreNV, OpCooperativeVectorMatrixMulNV, OpCooperativeVectorMatrixMulAddNV, OpCooperativeVectorOuterProductAccumulateNV, and OpCooperativeVectorReduceSumAccumulateNV can be 64-bit integers.

Signedness of SPIR-V Image Accesses

SPIR-V associates a signedness with all integer image accesses. This is required in certain parts of the SPIR-V and the Vulkan image access pipeline to ensure defined results. The signedness is determined from a combination of the access instruction’s Image Operands and the underlying image’s Sampled Type as follows:

  1. If the instruction’s Image Operands contains the SignExtend operand then the access is signed.
  2. If the instruction’s Image Operands contains the ZeroExtend operand then the access is unsigned.
  3. Otherwise, the image accesses signedness matches that of the Sampled Type of the OpTypeImage being accessed.

Image Format and Type Matching

When specifying the Image Format of an OpTypeImage, the converted bit width and type, as shown in the table below, must match the Sampled Type. The signedness must match the signedness of any access to the image.

Formatted accesses are always converted from a shader readable type to the resource’s format or vice versa via Texel Decode for reads and Texel Encode 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. Every access that is made to the image must have a signedness equal to that in the Signedness column (where applicable).

Image FormatType-Declaration instructionsBit WidthSignedness

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

R64i

OpTypeInt

64

1

R64ui

0

The SPIR-V Type is defined by an instruction in SPIR-V, declared with the Type-Declaration Instruction, Bit Width, and Signedness from above.

Compatibility Between SPIR-V Image Dimensions and Vulkan ImageView Types

SPIR-V Image Dim values are compatible with VkImageView

viewType values as defined below:

SPIR-V Image DimCompatible Vulkan ImageView viewTypes
1DVK_IMAGE_VIEW_TYPE_1D,VK_IMAGE_VIEW_TYPE_1D_ARRAY
2DVK_IMAGE_VIEW_TYPE_2D,VK_IMAGE_VIEW_TYPE_2D_ARRAY
3DVK_IMAGE_VIEW_TYPE_3D
CubeVK_IMAGE_VIEW_TYPE_CUBE,VK_IMAGE_VIEW_TYPE_CUBE_ARRAY

Compatibility Between SPIR-V Image Formats and Vulkan Formats

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

SPIR-V Image FormatCompatible Vulkan Format
UnknownAny
R8VK_FORMAT_R8_UNORM
R8SnormVK_FORMAT_R8_SNORM
R8uiVK_FORMAT_R8_UINT
R8iVK_FORMAT_R8_SINT
Rg8VK_FORMAT_R8G8_UNORM
Rg8SnormVK_FORMAT_R8G8_SNORM
Rg8uiVK_FORMAT_R8G8_UINT
Rg8iVK_FORMAT_R8G8_SINT
Rgba8VK_FORMAT_R8G8B8A8_UNORM
Rgba8SnormVK_FORMAT_R8G8B8A8_SNORM
Rgba8uiVK_FORMAT_R8G8B8A8_UINT
Rgba8iVK_FORMAT_R8G8B8A8_SINT
Rgb10A2VK_FORMAT_A2B10G10R10_UNORM_PACK32
Rgb10a2uiVK_FORMAT_A2B10G10R10_UINT_PACK32
R16VK_FORMAT_R16_UNORM
R16SnormVK_FORMAT_R16_SNORM
R16uiVK_FORMAT_R16_UINT
R16iVK_FORMAT_R16_SINT
R16fVK_FORMAT_R16_SFLOAT
Rg16VK_FORMAT_R16G16_UNORM
Rg16SnormVK_FORMAT_R16G16_SNORM
Rg16uiVK_FORMAT_R16G16_UINT
Rg16iVK_FORMAT_R16G16_SINT
Rg16fVK_FORMAT_R16G16_SFLOAT
Rgba16VK_FORMAT_R16G16B16A16_UNORM
Rgba16SnormVK_FORMAT_R16G16B16A16_SNORM
Rgba16uiVK_FORMAT_R16G16B16A16_UINT
Rgba16iVK_FORMAT_R16G16B16A16_SINT
Rgba16fVK_FORMAT_R16G16B16A16_SFLOAT
R32uiVK_FORMAT_R32_UINT
R32iVK_FORMAT_R32_SINT
R32fVK_FORMAT_R32_SFLOAT
Rg32uiVK_FORMAT_R32G32_UINT
Rg32iVK_FORMAT_R32G32_SINT
Rg32fVK_FORMAT_R32G32_SFLOAT
Rgba32uiVK_FORMAT_R32G32B32A32_UINT
Rgba32iVK_FORMAT_R32G32B32A32_SINT
Rgba32fVK_FORMAT_R32G32B32A32_SFLOAT
R64uiVK_FORMAT_R64_UINT
R64iVK_FORMAT_R64_SINT
R11fG11fB10fVK_FORMAT_B10G11R11_UFLOAT_PACK32

Ray Query Precision and Operation

The values returned by OpRayQueryGetIntersectionTriangleVertexPositionsKHR are transformed by the geometry transform, which is performed at standard floating-point precision, but without a specifically defined order of floating-point operations to perform the matrix multiplication.

Compatibility Between SPIR-V Tensor Element Types And Vulkan Formats

SPIR-V Tensor Element Type values are compatible with VkFormat values as defined below:

SPIR-V Tensor Element TypeCompatible Vulkan Formats
OpTypeBoolVK_FORMAT_R8_BOOL_ARM
OpTypeFloat 8 Float8E4M3EXTVK_FORMAT_R8_SFLOAT_FPENCODING_FLOAT8E4M3_ARM
OpTypeFloat 8 Float8E5M2EXTVK_FORMAT_R8_SFLOAT_FPENCODING_FLOAT8E5M2_ARM
OpTypeFloat 16VK_FORMAT_R16_SFLOAT
OpTypeFloat 16 BFloat16KHRVK_FORMAT_R16_SFLOAT_FPENCODING_BFLOAT16_ARM
OpTypeFloat 32VK_FORMAT_R32_SFLOAT
OpTypeFloat 64VK_FORMAT_R64_SFLOAT
OpTypeInt 8 0VK_FORMAT_R8_UINT
OpTypeInt 8 1VK_FORMAT_R8_SINT
OpTypeInt 16 0VK_FORMAT_R16_UINT
OpTypeInt 16 1VK_FORMAT_R16_SINT
OpTypeInt 32 0VK_FORMAT_R32_UINT
OpTypeInt 32 1VK_FORMAT_R32_SINT
OpTypeInt 64 0VK_FORMAT_R64_UINT
OpTypeInt 64 1VK_FORMAT_R64_SINT