[Mesa-dev] [PATCH] spirv: fix OpSConvert when the source is unsigned

Samuel Iglesias Gonsálvez siglesias at igalia.com
Mon Mar 5 10:18:47 UTC 2018


OpSConvert interprets the MSB of the unsigned value as the sign bit and
extends it to the new type. If we want to preserve the value, we need
to use OpUConvert opcode.

Signed-off-by: Samuel Iglesias Gonsálvez <siglesias at igalia.com>
---
 src/compiler/spirv/vtn_alu.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/compiler/spirv/vtn_alu.c b/src/compiler/spirv/vtn_alu.c
index d0c9e316935..32b4f70d229 100644
--- a/src/compiler/spirv/vtn_alu.c
+++ b/src/compiler/spirv/vtn_alu.c
@@ -354,10 +354,27 @@ vtn_nir_alu_op_for_spirv_opcode(struct vtn_builder *b,
    case SpvOpConvertFToS:
    case SpvOpConvertSToF:
    case SpvOpConvertUToF:
-   case SpvOpSConvert:
    case SpvOpFConvert:
       return nir_type_conversion_op(src, dst, nir_rounding_mode_undef);
 
+   case SpvOpSConvert: {
+      nir_alu_type src_base = (nir_alu_type) nir_alu_type_get_base_type(src);
+      nir_alu_type dst_base = (nir_alu_type) nir_alu_type_get_base_type(dst);
+      if (src_base == nir_type_uint && dst_base == nir_type_int) {
+         /* SPIR-V expects to interpret the unsigned value as signed and
+          * to sign extend. Return the opcode accordingly.
+          */
+         unsigned dst_bit_size = nir_alu_type_get_type_size(dst);
+         switch (dst_bit_size) {
+         case 16:   return nir_op_i2i16;
+         case 32:   return nir_op_i2i32;
+         case 64:   return nir_op_i2i64;
+         default:
+            vtn_fail("Invalid nir alu bit size");
+         }
+      }
+      return nir_type_conversion_op(src, dst, nir_rounding_mode_undef);
+   }
    /* Derivatives: */
    case SpvOpDPdx:         return nir_op_fddx;
    case SpvOpDPdy:         return nir_op_fddy;
-- 
2.14.1



More information about the mesa-dev mailing list