Module: Mesa
Branch: master
Commit: 8610af12b6a64011df905b9b0ab2d773dfaae139
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=8610af12b6a64011df905b9b0ab2d773dfaae139

Author: Jason Ekstrand <[email protected]>
Date:   Wed Sep 30 16:43:31 2020 -0500

spirv: Handle all OpenCL conversion ops with full rounding

This is done for kernels via the new convert_alu_types intrinsic.  For
Vulkan and OpenGL, we maintain the old path so that drivers don't have
to add that lowering pass.

Reviewed-by: Jesse Natalie <[email protected]>
Reviewed-by: Daniel Stone <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6945>

---

 src/compiler/spirv/spirv_to_nir.c |  2 +
 src/compiler/spirv/vtn_alu.c      | 91 ++++++++++++++++++++++++++++++++-------
 2 files changed, 78 insertions(+), 15 deletions(-)

diff --git a/src/compiler/spirv/spirv_to_nir.c 
b/src/compiler/spirv/spirv_to_nir.c
index a670f51adfb..c891e7564d3 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -5135,6 +5135,8 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp 
opcode,
    case SpvOpSConvert:
    case SpvOpFConvert:
    case SpvOpQuantizeToF16:
+   case SpvOpSatConvertSToU:
+   case SpvOpSatConvertUToS:
    case SpvOpPtrCastToGeneric:
    case SpvOpGenericCastToPtr:
    case SpvOpIsNan:
diff --git a/src/compiler/spirv/vtn_alu.c b/src/compiler/spirv/vtn_alu.c
index 9b4a8e16eef..205eca082c0 100644
--- a/src/compiler/spirv/vtn_alu.c
+++ b/src/compiler/spirv/vtn_alu.c
@@ -220,9 +220,11 @@ convert_op_src_type(SpvOp opcode)
       return nir_type_float;
    case SpvOpSConvert:
    case SpvOpConvertSToF:
+   case SpvOpSatConvertSToU:
       return nir_type_int;
    case SpvOpUConvert:
    case SpvOpConvertUToF:
+   case SpvOpSatConvertUToS:
       return nir_type_uint;
    default:
       unreachable("Unhandled conversion op");
@@ -239,9 +241,11 @@ convert_op_dst_type(SpvOp opcode)
       return nir_type_float;
    case SpvOpSConvert:
    case SpvOpConvertFToS:
+   case SpvOpSatConvertUToS:
       return nir_type_int;
    case SpvOpUConvert:
    case SpvOpConvertFToU:
+   case SpvOpSatConvertSToU:
       return nir_type_uint;
    default:
       unreachable("Unhandled conversion op");
@@ -386,6 +390,14 @@ vtn_rounding_mode_to_nir(struct vtn_builder *b, 
SpvFPRoundingMode mode)
       return nir_rounding_mode_rtne;
    case SpvFPRoundingModeRTZ:
       return nir_rounding_mode_rtz;
+   case SpvFPRoundingModeRTP:
+      vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL,
+                  "FPRoundingModeRTP is only supported in kernels");
+      return nir_rounding_mode_ru;
+   case SpvFPRoundingModeRTN:
+      vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL,
+                  "FPRoundingModeRTN is only supported in kernels");
+      return nir_rounding_mode_rd;
    default:
       vtn_fail("Unsupported rounding mode: %s",
                spirv_fproundingmode_to_string(mode));
@@ -393,15 +405,31 @@ vtn_rounding_mode_to_nir(struct vtn_builder *b, 
SpvFPRoundingMode mode)
    }
 }
 
+struct conversion_opts {
+   nir_rounding_mode rounding_mode;
+   bool saturate;
+};
+
 static void
-handle_rounding_mode(struct vtn_builder *b, struct vtn_value *val, int member,
-                     const struct vtn_decoration *dec, void 
*_out_rounding_mode)
+handle_conversion_opts(struct vtn_builder *b, struct vtn_value *val, int 
member,
+                       const struct vtn_decoration *dec, void *_opts)
 {
-   nir_rounding_mode *out_rounding_mode = _out_rounding_mode;
-   assert(dec->scope == VTN_DEC_DECORATION);
-   if (dec->decoration != SpvDecorationFPRoundingMode)
-      return;
-   *out_rounding_mode = vtn_rounding_mode_to_nir(b, dec->operands[0]);
+   struct conversion_opts *opts = _opts;
+
+   switch (dec->decoration) {
+   case SpvDecorationFPRoundingMode:
+      opts->rounding_mode = vtn_rounding_mode_to_nir(b, dec->operands[0]);
+      break;
+
+   case SpvDecorationSaturatedConversion:
+      vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL,
+                  "Saturated conversions are only allowed in kernels");
+      opts->saturate = true;
+      break;
+
+   default:
+      break;
+   }
 }
 
 static void
@@ -592,15 +620,48 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,
       break;
    }
 
-   case SpvOpFConvert: {
-      nir_alu_type src_alu_type = 
nir_get_nir_type_for_glsl_type(vtn_src[0]->type);
-      nir_alu_type dst_alu_type = nir_get_nir_type_for_glsl_type(dest_type);
-      nir_rounding_mode rounding_mode = nir_rounding_mode_undef;
-
-      vtn_foreach_decoration(b, dest_val, handle_rounding_mode, 
&rounding_mode);
-      nir_op op = nir_type_conversion_op(src_alu_type, dst_alu_type, 
rounding_mode);
+   case SpvOpUConvert:
+   case SpvOpConvertFToU:
+   case SpvOpConvertFToS:
+   case SpvOpConvertSToF:
+   case SpvOpConvertUToF:
+   case SpvOpSConvert:
+   case SpvOpFConvert:
+   case SpvOpSatConvertSToU:
+   case SpvOpSatConvertUToS: {
+      unsigned src_bit_size = glsl_get_bit_size(vtn_src[0]->type);
+      unsigned dst_bit_size = glsl_get_bit_size(dest_type);
+      nir_alu_type src_type = convert_op_src_type(opcode) | src_bit_size;
+      nir_alu_type dst_type = convert_op_dst_type(opcode) | dst_bit_size;
 
-      dest->def = nir_build_alu(&b->nb, op, src[0], src[1], NULL, NULL);
+      struct conversion_opts opts = {
+         .rounding_mode = nir_rounding_mode_undef,
+         .saturate = false,
+      };
+      vtn_foreach_decoration(b, dest_val, handle_conversion_opts, &opts);
+
+      if (opcode == SpvOpSatConvertSToU || opcode == SpvOpSatConvertUToS)
+         opts.saturate = true;
+
+      if (b->shader->info.stage == MESA_SHADER_KERNEL) {
+         if (opts.rounding_mode == nir_rounding_mode_undef && !opts.saturate) {
+            nir_op op = nir_type_conversion_op(src_type, dst_type,
+                                               nir_rounding_mode_undef);
+            dest->def = nir_build_alu(&b->nb, op, src[0], NULL, NULL, NULL);
+         } else {
+            dest->def = nir_convert_alu_types(&b->nb, src[0], src_type,
+                                              dst_type, opts.rounding_mode,
+                                              opts.saturate);
+         }
+      } else {
+         vtn_fail_if(opts.rounding_mode != nir_rounding_mode_undef &&
+                     dst_type != nir_type_float16,
+                     "Rounding modes are only allowed on conversions to "
+                     "16-bit float types");
+         nir_op op = nir_type_conversion_op(src_type, dst_type,
+                                            opts.rounding_mode);
+         dest->def = nir_build_alu(&b->nb, op, src[0], NULL, NULL, NULL);
+      }
       break;
    }
 

_______________________________________________
mesa-commit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to