## A.4. Precision and Operation of SPIR-V Instructions

The following rules apply to both 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.
- Any denormalized value input into a shader or potentially generated by any instruction in a shader may be flushed to 0.
- The rounding mode cannot be set and is undefined.
- NaNs may not be generated. Instructions that operate on a NaN may not result in a NaN.
- Support for signaling NaNs is optional and exceptions are never raised.

The precision of double-precision instructions is at least that of single precision. For single precision (32 bit) instructions, precisions are required to be at least as follows, unless decorated with RelaxedPrecision:

Table A.2. Precision of core SPIR-V Instructions

Instruction | Precision
--- | ---
`OpFAdd` | Correctly rounded.
`OpFSub` | Correctly rounded.
`OpFMul` | Correctly rounded.
`OpFOrdEqual`, `OpFUnordEqual` | Correct result.
`OpFOrdLessThan`, `OpFUnordLessThan` | Correct result.
`OpFOrdGreaterThan`, `OpFUnordGreaterThan` | Correct result.
`OpFOrdLessThanEqual`, `OpFUnordLessThanEqual` | Correct result.
`OpFOrdGreaterThanEqual`, `OpFUnordGreaterThanEqual` | Correct result.
`OpFDiv` | 2.5 ULP for b in the range [2-126, 2126].
conversions between types | Correctly rounded.

Table A.3. Precision of GLSL.std.450 Instructions

Instruction | Precision
--- | ---
`fma`() | Inherited from `OpFMul` followed by `OpFAdd`.
`exp`(x), `exp2`(x) | $(3 + 2 \times |x|)$ ULP.
`log`(), `log2`() | 3 ULP outside the range [0.5, 2.0]. Absolute error < 2-21 inside the range [0.5, 2.0].
`pow`(x, y) | Inherited from `exp2`(y × `log2`(x)).
`sqrt`() | Inherited from 1.0 / `inversesqrt`().
`inversesqrt`() | 2 ULP.

GLSL.std.450 extended instructions specifically defined in terms of the above instructions inherit the above errors. GLSL.std.450 extended instructions not listed above and not defined in terms of the above have undefined precision. These include, for example, the trigonometric functions and determinant.

For the `OpSRem` and `OpSMod` instructions, if either operand is negative the result is undefined.

| Note
While the `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.

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:

Table A.4. SPIR-V and Vulkan Image Format Compatibility

SPIR-V Image Format | Compatible Vulkan Format
--- | ---
`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`