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.

v2:
- No need to check dst type.
- Fix typo in comment.

v3:
- Use src/dst bitsize to get the proper conversion opcode. (Jason)

Signed-off-by: Samuel Iglesias Gonsálvez <sigles...@igalia.com>
---
 src/compiler/spirv/vtn_alu.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/compiler/spirv/vtn_alu.c b/src/compiler/spirv/vtn_alu.c
index d0c9e316935..9dcd183a48d 100644
--- a/src/compiler/spirv/vtn_alu.c
+++ b/src/compiler/spirv/vtn_alu.c
@@ -354,10 +354,19 @@ 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: {
+      /* SPIR-V expects to interpret the unsigned value as signed and
+       * sign extend. Return the opcode accordingly.
+       */
+      unsigned src_bit_size = nir_alu_type_get_type_size(src);
+      nir_alu_type src_type = nir_type_int | src_bit_size;
+      unsigned dst_bit_size = nir_alu_type_get_type_size(dst);
+      nir_alu_type dst_type = nir_type_int | dst_bit_size;
+      return nir_type_conversion_op(src_type, dst_type, 
nir_rounding_mode_undef);
+   }
    /* Derivatives: */
    case SpvOpDPdx:         return nir_op_fddx;
    case SpvOpDPdy:         return nir_op_fddy;
-- 
2.14.1

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to