nir/lower_int64: respect rounding mode when casting to float
authorIván Briano <ivan.briano@intel.com>
Thu, 14 Sep 2023 19:15:20 +0000 (12:15 -0700)
committerMarge Bot <emma+marge@anholt.net>
Mon, 9 Oct 2023 23:37:52 +0000 (23:37 +0000)
Appendix A: Vulkan environemtn for SPIR-V says:
  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.

Conversion between types are classified as correctly rounded, so let's
do rounding correctly.

v2: check rounding mode for destination bit size (Georg)

Fixes upcoming Vulkan CTS tests:
dEQP-VK.spirv_assembly.instruction.compute.float_controls.fp32.input_args.rounding_rtz_conv_from_uint64_up
dEQP-VK.spirv_assembly.instruction.compute.float_controls.fp32.input_args.rounding_rtz_conv_from_int64_up
dEQP-VK.spirv_assembly.instruction.graphics.float_controls.fp32.input_args.rounding_rtz_conv_from_uint64_up_vert
dEQP-VK.spirv_assembly.instruction.graphics.float_controls.fp32.input_args.rounding_rtz_conv_from_int64_up_vert
dEQP-VK.spirv_assembly.instruction.graphics.float_controls.fp32.input_args.rounding_rtz_conv_from_uint64_up_frag
dEQP-VK.spirv_assembly.instruction.graphics.float_controls.fp32.input_args.rounding_rtz_conv_from_int64_up_frag

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25281>

src/compiler/nir/nir_lower_int64.c

index 02417d4..fdd578b 100644 (file)
@@ -775,11 +775,14 @@ lower_2f(nir_builder *b, nir_def *x, unsigned dest_bit_size,
                                     COND_LOWER_OP(b, iand, x, lsb_mask));
    nir_def *round_up = nir_ior(b, COND_LOWER_CMP(b, ilt, half, rem),
                                nir_iand(b, halfway, is_odd));
-   if (significand_bits >= 32)
-      significand = COND_LOWER_OP(b, iadd, significand,
-                                  COND_LOWER_CAST(b, b2i64, round_up));
-   else
-      significand = nir_iadd(b, significand, nir_b2i32(b, round_up));
+   if (!nir_is_rounding_mode_rtz(b->shader->info.float_controls_execution_mode,
+                                 dest_bit_size)) {
+      if (significand_bits >= 32)
+         significand = COND_LOWER_OP(b, iadd, significand,
+                                     COND_LOWER_CAST(b, b2i64, round_up));
+      else
+         significand = nir_iadd(b, significand, nir_b2i32(b, round_up));
+   }
 
    nir_def *res;