spirv/nir: keep track of SPV_KHR_float_controls execution modes
authorSamuel Iglesias Gonsálvez <siglesias@igalia.com>
Thu, 31 May 2018 10:20:30 +0000 (12:20 +0200)
committerAndres Gomez <agomez@igalia.com>
Tue, 17 Sep 2019 20:39:18 +0000 (23:39 +0300)
v2:
- Add support for rounding modes for each floating point bit size.

v3:
- Commit e68871f6a44 ("spirv: Handle constants and types before
  execution modes") changed when the execution modes are handled,
  which affects the result of the floating point constants when the
  rounding mode is set in the execution mode. Moved the handling of
  the rounding modes before we handle the constants.

v4:
- Rename vtn_decoration "literals" to "operands" (Andres).
- Simplify execution mode parsing util function (Caio).
- Extend the comment about the timing of the handling of the rounding
  modes (Caio).

v5:
- Correct extension name (Caio).
- Rename shader info member (Andres).
- Rename float controls enum (Andres).

Signed-off-by: Samuel Iglesias Gonsálvez <siglesias@igalia.com>
Signed-off-by: Andres Gomez <agomez@igalia.com>
Reviewed-by: Connor Abbott <cwabbott0@gmail.com> [v3]
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
src/compiler/shader_enums.h
src/compiler/shader_info.h
src/compiler/spirv/spirv_to_nir.c

index 0f402f427413e0e50b8dfd53328f3be5bec94b56..7eac07b5c11ac224871779ab78ef3cd98a6c1bc6 100644 (file)
@@ -858,6 +858,26 @@ enum gl_derivative_group {
    DERIVATIVE_GROUP_LINEAR,
 };
 
+enum float_controls
+{
+   FLOAT_CONTROLS_DEFAULT_FLOAT_CONTROL_MODE        = 0x0000,
+   FLOAT_CONTROLS_DENORM_PRESERVE_FP16              = 0x0001,
+   FLOAT_CONTROLS_DENORM_PRESERVE_FP32              = 0x0002,
+   FLOAT_CONTROLS_DENORM_PRESERVE_FP64              = 0x0004,
+   FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP16         = 0x0008,
+   FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP32         = 0x0010,
+   FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP64         = 0x0020,
+   FLOAT_CONTROLS_SIGNED_ZERO_INF_NAN_PRESERVE_FP16 = 0x0040,
+   FLOAT_CONTROLS_SIGNED_ZERO_INF_NAN_PRESERVE_FP32 = 0x0080,
+   FLOAT_CONTROLS_SIGNED_ZERO_INF_NAN_PRESERVE_FP64 = 0x0100,
+   FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP16            = 0x0200,
+   FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP32            = 0x0400,
+   FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP64            = 0x0800,
+   FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP16            = 0x1000,
+   FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP32            = 0x2000,
+   FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP64            = 0x4000,
+};
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index ae894f3082b6913b457d831c0ac577206581d87f..8b0176f0438ca91883e548e10b4bc5a172d3624f 100644 (file)
@@ -154,6 +154,9 @@ typedef struct shader_info {
    /** Was this shader linked with any transform feedback varyings? */
    bool has_transform_feedback_varyings;
 
+   /* SPV_KHR_float_controls: execution mode for floating point ops */
+   unsigned float_controls_execution_mode;
+
    union {
       struct {
          /* Which inputs are doubles */
index acf73ee19529e737e83b89d24948441497ac4e31..f46b0a9bb02654a785e51a131a3007d95046991c 100644 (file)
@@ -3925,6 +3925,14 @@ vtn_handle_execution_mode(struct vtn_builder *b, struct vtn_value *entry_point,
       b->shader->info.fs.sample_interlock_unordered = true;
       break;
 
+   case SpvExecutionModeDenormPreserve:
+   case SpvExecutionModeDenormFlushToZero:
+   case SpvExecutionModeSignedZeroInfNanPreserve:
+   case SpvExecutionModeRoundingModeRTE:
+   case SpvExecutionModeRoundingModeRTZ:
+      /* Already handled in vtn_handle_rounding_mode_in_execution_mode() */
+      break;
+
    default:
       vtn_fail("Unhandled execution mode: %s (%u)",
                spirv_executionmode_to_string(mode->exec_mode),
@@ -3932,6 +3940,63 @@ vtn_handle_execution_mode(struct vtn_builder *b, struct vtn_value *entry_point,
    }
 }
 
+static void
+vtn_handle_rounding_mode_in_execution_mode(struct vtn_builder *b, struct vtn_value *entry_point,
+                                           const struct vtn_decoration *mode, void *data)
+{
+   vtn_assert(b->entry_point == entry_point);
+
+   unsigned execution_mode = 0;
+
+   switch(mode->exec_mode) {
+   case SpvExecutionModeDenormPreserve:
+      switch (mode->operands[0]) {
+      case 16: execution_mode = FLOAT_CONTROLS_DENORM_PRESERVE_FP16; break;
+      case 32: execution_mode = FLOAT_CONTROLS_DENORM_PRESERVE_FP32; break;
+      case 64: execution_mode = FLOAT_CONTROLS_DENORM_PRESERVE_FP64; break;
+      default: vtn_fail("Floating point type not supported");
+      }
+      break;
+   case SpvExecutionModeDenormFlushToZero:
+      switch (mode->operands[0]) {
+      case 16: execution_mode = FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP16; break;
+      case 32: execution_mode = FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP32; break;
+      case 64: execution_mode = FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP64; break;
+      default: vtn_fail("Floating point type not supported");
+      }
+       break;
+   case SpvExecutionModeSignedZeroInfNanPreserve:
+      switch (mode->operands[0]) {
+      case 16: execution_mode = FLOAT_CONTROLS_SIGNED_ZERO_INF_NAN_PRESERVE_FP16; break;
+      case 32: execution_mode = FLOAT_CONTROLS_SIGNED_ZERO_INF_NAN_PRESERVE_FP32; break;
+      case 64: execution_mode = FLOAT_CONTROLS_SIGNED_ZERO_INF_NAN_PRESERVE_FP64; break;
+      default: vtn_fail("Floating point type not supported");
+      }
+      break;
+   case SpvExecutionModeRoundingModeRTE:
+      switch (mode->operands[0]) {
+      case 16: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP16; break;
+      case 32: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP32; break;
+      case 64: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTE_FP64; break;
+      default: vtn_fail("Floating point type not supported");
+      }
+      break;
+   case SpvExecutionModeRoundingModeRTZ:
+      switch (mode->operands[0]) {
+      case 16: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP16; break;
+      case 32: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP32; break;
+      case 64: execution_mode = FLOAT_CONTROLS_ROUNDING_MODE_RTZ_FP64; break;
+      default: vtn_fail("Floating point type not supported");
+      }
+      break;
+
+   default:
+      break;
+   }
+
+   b->shader->info.float_controls_execution_mode |= execution_mode;
+}
+
 static bool
 vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,
                                         const uint32_t *w, unsigned count)
@@ -4658,6 +4723,13 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
    /* Set shader info defaults */
    b->shader->info.gs.invocations = 1;
 
+   /* Parse rounding mode execution modes. This has to happen earlier than
+    * other changes in the execution modes since they can affect, for example,
+    * the result of the floating point constants.
+    */
+   vtn_foreach_execution_mode(b, b->entry_point,
+                              vtn_handle_rounding_mode_in_execution_mode, NULL);
+
    b->specializations = spec;
    b->num_specializations = num_spec;