(forgot to Cc Jason)
On Thu, Jun 8, 2017 at 3:05 PM, Connor Abbott <[email protected]> wrote: > From: Connor Abbott <[email protected]> > > Before, we were just implementing it with a move, which is incorrect > when the source and destination have different bitsizes. To implement > it properly, we need to use the 64-bit pack/unpack opcodes. Since > glslang uses OpBitcast to implement packInt2x32 and unpackInt2x32, this > should fix them on anv (and radv once we enable the int64 capability). > > Fixes: b3135c3c ("anv: Advertise shaderInt64 on Broadwell and above") > Signed-off-by: Connor Abbott <[email protected]> > --- > src/compiler/spirv/vtn_alu.c | 68 > +++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 67 insertions(+), 1 deletion(-) > > diff --git a/src/compiler/spirv/vtn_alu.c b/src/compiler/spirv/vtn_alu.c > index 9e4beed..cd9569b 100644 > --- a/src/compiler/spirv/vtn_alu.c > +++ b/src/compiler/spirv/vtn_alu.c > @@ -210,6 +210,69 @@ vtn_handle_matrix_alu(struct vtn_builder *b, SpvOp > opcode, > } > } > > +static void > +vtn_handle_bitcast(struct vtn_builder *b, struct vtn_ssa_value *dest, > + struct nir_ssa_def *src) > +{ > + if (glsl_get_vector_elements(dest->type) == src->num_components) { > + /* From the definition of OpBitcast in the SPIR-V 1.2 spec: > + * > + * "If Result Type has the same number of components as Operand, they > + * must also have the same component width, and results are computed > per > + * component." > + */ > + dest->def = nir_imov(&b->nb, src); > + return; > + } > + > + /* From the definition of OpBitcast in the SPIR-V 1.2 spec: > + * > + * "If Result Type has a different number of components than Operand, the > + * total number of bits in Result Type must equal the total number of bits > + * in Operand. Let L be the type, either Result Type or Operand’s type, > that > + * has the larger number of components. Let S be the other type, with the > + * smaller number of components. The number of components in L must be an > + * integer multiple of the number of components in S. The first component > + * (that is, the only or lowest-numbered component) of S maps to the first > + * components of L, and so on, up to the last component of S mapping to > the > + * last components of L. Within this mapping, any single component of S > + * (mapping to multiple components of L) maps its lower-ordered bits to > the > + * lower-numbered components of L." > + * > + * Since booleans are a separate type without a width, presumably they > can't > + * be bitcasted. So we only have to deal with 32 vs. 64 bit right now, > which > + * we handle using the pack/unpack opcodes. > + */ > + unsigned src_bit_size = src->bit_size; > + unsigned dest_bit_size = glsl_get_bit_size(dest->type); > + unsigned src_components = src->num_components; > + unsigned dest_components = glsl_get_vector_elements(dest->type); > + if (src_bit_size > dest_bit_size) { > + assert(src_bit_size == 64); > + assert(dest_bit_size == 32); > + assert(dest_components == 2 * src_components); > + nir_ssa_def *dest_chan[4]; > + for (unsigned comp = 0; comp < src_components; comp++) { > + nir_ssa_def *split = > + nir_unpack_64_2x32(&b->nb, nir_channel(&b->nb, src, comp)); > + dest_chan[2 * comp + 0] = nir_channel(&b->nb, split, 0); > + dest_chan[2 * comp + 1] = nir_channel(&b->nb, split, 1); > + } > + dest->def = nir_vec(&b->nb, dest_chan, dest_components); > + } else { > + assert(dest_bit_size == 64); > + assert(src_bit_size == 32); > + assert(src_components == 2 * dest_components); > + nir_ssa_def *dest_chan[4]; > + for (unsigned comp = 0; comp < dest_components; comp++) { > + dest_chan[comp] = > + nir_pack_64_2x32(&b->nb, nir_channels(&b->nb, src, > + 0x3 << (2 * comp))); > + } > + dest->def = nir_vec(&b->nb, dest_chan, dest_components); > + } > +} > + > nir_op > vtn_nir_alu_op_for_spirv_opcode(SpvOp opcode, bool *swap, > nir_alu_type src, nir_alu_type dst) > @@ -285,7 +348,6 @@ vtn_nir_alu_op_for_spirv_opcode(SpvOp opcode, bool *swap, > case SpvOpFUnordGreaterThanEqual: return nir_op_fge; > > /* Conversions: */ > - case SpvOpBitcast: return nir_op_imov; > case SpvOpQuantizeToF16: return nir_op_fquantize2f16; > case SpvOpUConvert: > case SpvOpConvertFToU: > @@ -503,6 +565,10 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp opcode, > break; > } > > + case SpvOpBitcast: > + vtn_handle_bitcast(b, val->ssa, src[0]); > + break; > + > default: { > bool swap; > nir_alu_type src_alu_type = > nir_get_nir_type_for_glsl_type(vtn_src[0]->type); > -- > 2.9.4 > _______________________________________________ mesa-dev mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-dev
