<div dir="ltr"><div class="gmail_extra"><div>On Thu, Jun 8, 2017 at 3:05 PM, Connor Abbott <span dir="ltr"><<a href="mailto:connora@valvesoftware.com" target="_blank">connora@valvesoftware.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">From: Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>><br>
<br>
Before, we were just implementing it with a move, which is incorrect<br>
when the source and destination have different bitsizes. To implement<br>
it properly, we need to use the 64-bit pack/unpack opcodes. Since<br>
glslang uses OpBitcast to implement packInt2x32 and unpackInt2x32, this<br>
should fix them on anv (and radv once we enable the int64 capability).<br>
<br>
Fixes: b3135c3c ("anv: Advertise shaderInt64 on Broadwell and above")<br>
Signed-off-by: Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>><br>
---<br>
 src/compiler/spirv/vtn_alu.c | 68 ++++++++++++++++++++++++++++++<wbr>+++++++++++++-<br>
 1 file changed, 67 insertions(+), 1 deletion(-)<br>
<br>
diff --git a/src/compiler/spirv/vtn_alu.c b/src/compiler/spirv/vtn_alu.c<br>
index 9e4beed..cd9569b 100644<br>
--- a/src/compiler/spirv/vtn_alu.c<br>
+++ b/src/compiler/spirv/vtn_alu.c<br>
@@ -210,6 +210,69 @@ vtn_handle_matrix_alu(struct vtn_builder *b, SpvOp opcode,<br>
    }<br>
 }<br>
<br>
+static void<br>
+vtn_handle_bitcast(struct vtn_builder *b, struct vtn_ssa_value *dest,<br>
+                   struct nir_ssa_def *src)<br>
+{<br>
+   if (glsl_get_vector_elements(<wbr>dest->type) == src->num_components) {<br>
+      /* From the definition of OpBitcast in the SPIR-V 1.2 spec:<br>
+       *<br>
+       * "If Result Type has the same number of components as Operand, they<br>
+       * must also have the same component width, and results are computed per<br>
+       * component."<br>
+       */<br>
+      dest->def = nir_imov(&b->nb, src);<br>
+      return;<br>
+   }<br>
+<br>
+   /* From the definition of OpBitcast in the SPIR-V 1.2 spec:<br>
+    *<br>
+    * "If Result Type has a different number of components than Operand, the<br>
+    * total number of bits in Result Type must equal the total number of bits<br>
+    * in Operand. Let L be the type, either Result Type or Operand’s type, that<br>
+    * has the larger number of components. Let S be the other type, with the<br>
+    * smaller number of components. The number of components in L must be an<br>
+    * integer multiple of the number of components in S. The first component<br>
+    * (that is, the only or lowest-numbered component) of S maps to the first<br>
+    * components of L, and so on, up to the last component of S mapping to the<br>
+    * last components of L. Within this mapping, any single component of S<br>
+    * (mapping to multiple components of L) maps its lower-ordered bits to the<br>
+    * lower-numbered components of L."<br>
+    *<br>
+    * Since booleans are a separate type without a width, presumably they can't<br>
+    * be bitcasted. So we only have to deal with 32 vs. 64 bit right now, which<br>
+    * we handle using the pack/unpack opcodes.<br></blockquote><div><br></div><div>This won't last long.... The Igalia guys already have patches in the works to add 16-bit support.  Also, I'm guessing 8-bit ints are going to be a thing at some point.  I think we can make this more general and make their lives easier...<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+    */<br>
+   unsigned src_bit_size = src->bit_size;<br>
+   unsigned dest_bit_size = glsl_get_bit_size(dest->type);<br>
+   unsigned src_components = src->num_components;<br>
+   unsigned dest_components = glsl_get_vector_elements(dest-<wbr>>type);<br></blockquote><div><br></div><div>How about something like this:<br><br></div><div>unsigned size = src_components * src_bit_size;<br></div><div>assert(size == dest_components * dest_bit_size);<br></div><div>unsigned min_bit_size = MIN2(src_bit_size, dest_bit_size);<br></div><div>unsigned total_comps = size / min_bit_size;<br></div><div><br></div><div>NIR_VLA(nir_ssa_def *, unpacked);<br></div><div><br></div><div>for (unsigned idx = 0, i = 0; i < src_comps; i++) {<br></div><div>   nir_ssa_def *chan = nir_channel(&b->nb, src, i);<br></div><div>   if (src_bit_size == min_bit_size) {<br></div><div>      total_comps[idx++] = chan;<br></div><div>   } else {<br></div>      assert(min_bit_size == 32 && src_bit_size == 64);<br>      nir_ssa_def *split =<br>
         nir_unpack_64_2x32(&b->nb, nir_channel(&b->nb, src, comp)); <br>      unpacked[idx++] = nir_channel(&b->nb, split, 0);<br>      unpacked[idx++] = nir_channel(&b->nb, split, 1);<br></div><div><div>   }<br></div><div>}<br><br></div><div>nir_ssa_def *vec_src[4];<br></div><div>for (unsigned idx = 0, i = 0; i < dest_comps; i++) {<br>   if (dest_bit_size == min_bit_size) {</div><div>      vec_src[i] = unpacked[idx++];<br></div><div>   } else {<br></div><div>      assert(min_bit_size == 32 && dest_bit_size == 64);<br></div><div>      nir_ssa_def *src0 = unpacked[idx++];<br><div>      nir_ssa_def *src1 = unpacked[idx++];<br></div></div><div>      vec_src[i] = nir_pack_64_2x32(&b->nb, nir_vec2(&b->nb, src0, src1));<br>   }<br>}<br><br></div><div>dest->def = nir_vec(&b->nb, vec_src, dest_components);<br><br></div><div>What do you think?  Another thought: Should this go in nir_builder?<br><br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+   if (src_bit_size > dest_bit_size) {<br>
+      assert(src_bit_size == 64);<br>
+      assert(dest_bit_size == 32);<br>
+      assert(dest_components == 2 * src_components);<br>
+      nir_ssa_def *dest_chan[4];<br>
+      for (unsigned comp = 0; comp < src_components; comp++) {<br>
+         nir_ssa_def *split =<br>
+            nir_unpack_64_2x32(&b->nb, nir_channel(&b->nb, src, comp)); <br></blockquote></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+         dest_chan[2 * comp + 0] = nir_channel(&b->nb, split, 0);<br>
+         dest_chan[2 * comp + 1] = nir_channel(&b->nb, split, 1);<br>
+      }<br>
+      dest->def = nir_vec(&b->nb, dest_chan, dest_components);<br>
+   } else {<br>
+      assert(dest_bit_size == 64);<br>
+      assert(src_bit_size == 32);<br>
+      assert(src_components == 2 * dest_components);<br>
+      nir_ssa_def *dest_chan[4];<br>
+      for (unsigned comp = 0; comp < dest_components; comp++) {<br>
+         dest_chan[comp] =<br>
+            nir_pack_64_2x32(&b->nb, nir_channels(&b->nb, src,<br>
+                                                  0x3 << (2 * comp)));<br>
+      }<br>
+      dest->def = nir_vec(&b->nb, dest_chan, dest_components);<br>
+   }<br>
+}<br>
+<br>
 nir_op<br>
 vtn_nir_alu_op_for_spirv_<wbr>opcode(SpvOp opcode, bool *swap,<br>
                                 nir_alu_type src, nir_alu_type dst)<br>
@@ -285,7 +348,6 @@ vtn_nir_alu_op_for_spirv_<wbr>opcode(SpvOp opcode, bool *swap,<br>
    case SpvOpFUnordGreaterThanEqual:               return nir_op_fge;<br>
<br>
    /* Conversions: */<br>
-   case SpvOpBitcast:               return nir_op_imov;<br>
    case SpvOpQuantizeToF16:         return nir_op_fquantize2f16;<br>
    case SpvOpUConvert:<br>
    case SpvOpConvertFToU:<br>
@@ -503,6 +565,10 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,<br>
       break;<br>
    }<br>
<br>
+   case SpvOpBitcast:<br>
+      vtn_handle_bitcast(b, val->ssa, src[0]);<br>
+      break;<br>
+<br>
    default: {<br>
       bool swap;<br>
       nir_alu_type src_alu_type = nir_get_nir_type_for_glsl_<wbr>type(vtn_src[0]->type);<br>
<span class="gmail-HOEnZb"><font color="#888888">--<br>
2.9.4<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>