nir/format_convert: Add code for bitcasting vectors
authorJason Ekstrand <jason.ekstrand@intel.com>
Fri, 26 Jan 2018 19:34:04 +0000 (11:34 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 9 May 2018 18:16:33 +0000 (11:16 -0700)
This is a fairly direct port from blorp.  The only real change is that
the nir_format_convert version doesn't assume that everything is a vec4.

Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
src/compiler/nir/nir_format_convert.h

index 1b34f6086d39e9b02696ab90d4183bbc6467009c..33d90f260cdee0c67071549c996a6c14012081f7 100644 (file)
@@ -107,6 +107,59 @@ nir_format_pack_uint(nir_builder *b, nir_ssa_def *color,
                                         bits, num_components);
 }
 
+static inline nir_ssa_def *
+nir_format_bitcast_uint_vec_unmasked(nir_builder *b, nir_ssa_def *src,
+                                     unsigned src_bits, unsigned dst_bits)
+{
+   assert(src_bits == 8 || src_bits == 16 || src_bits == 32);
+   assert(dst_bits == 8 || dst_bits == 16 || dst_bits == 32);
+
+   if (src_bits == dst_bits)
+      return src;
+
+   const unsigned dst_components =
+      DIV_ROUND_UP(src->num_components * src_bits, dst_bits);
+   assert(dst_components <= 4);
+
+   nir_ssa_def *dst_chan[4] = { };
+   if (dst_bits > src_bits) {
+      unsigned shift = 0;
+      unsigned dst_idx = 0;
+      for (unsigned i = 0; i < src->num_components; i++) {
+         nir_ssa_def *shifted = nir_ishl(b, nir_channel(b, src, i),
+                                            nir_imm_int(b, shift));
+         if (shift == 0) {
+            dst_chan[dst_idx] = shifted;
+         } else {
+            dst_chan[dst_idx] = nir_ior(b, dst_chan[dst_idx], shifted);
+         }
+
+         shift += src_bits;
+         if (shift >= dst_bits) {
+            dst_idx++;
+            shift = 0;
+         }
+      }
+   } else {
+      nir_ssa_def *mask = nir_imm_int(b, ~0u >> (32 - dst_bits));
+
+      unsigned src_idx = 0;
+      unsigned shift = 0;
+      for (unsigned i = 0; i < dst_components; i++) {
+         dst_chan[i] = nir_iand(b, nir_ushr(b, nir_channel(b, src, src_idx),
+                                               nir_imm_int(b, shift)),
+                                   mask);
+         shift += dst_bits;
+         if (shift >= src_bits) {
+            src_idx++;
+            shift = 0;
+         }
+      }
+   }
+
+   return nir_vec(b, dst_chan, dst_components);
+}
+
 static inline nir_ssa_def *
 nir_format_linear_to_srgb(nir_builder *b, nir_ssa_def *c)
 {