[Mesa-dev] [PATCH 12/22] spirv/nir: implement DF conversions

Samuel Iglesias Gonsálvez siglesias at igalia.com
Fri Dec 2 08:22:36 UTC 2016


On Thu, 2016-12-01 at 18:50 -0800, Jason Ekstrand wrote:
> On Fri, Nov 25, 2016 at 12:52 AM, Juan A. Suarez Romero <jasuarez at iga
> lia.com> wrote:
> > From: Samuel Iglesias Gonsálvez <siglesias at igalia.com>
> > 
> > SPIR-V does not have special opcodes for DF conversions. We need to
> > identify
> > them by checking the bit size of the operand and the result.
> > 
> > Signed-off-by: Samuel Iglesias Gonsálvez <siglesias at igalia.com>
> > ---
> >  src/compiler/spirv/spirv_to_nir.c | 29 ++++++++++++++++++++++-----
> > --
> >  src/compiler/spirv/vtn_alu.c      | 37
> > +++++++++++++++++++++++++++----------
> >  src/compiler/spirv/vtn_private.h  |  3 ++-
> >  3 files changed, 51 insertions(+), 18 deletions(-)
> > 
> > diff --git a/src/compiler/spirv/spirv_to_nir.c
> > b/src/compiler/spirv/spirv_to_nir.c
> > index a13f72a..81c73da 100644
> > --- a/src/compiler/spirv/spirv_to_nir.c
> > +++ b/src/compiler/spirv/spirv_to_nir.c
> > @@ -1211,12 +1211,21 @@ vtn_handle_constant(struct vtn_builder *b,
> > SpvOp opcode,
> > 
> >        default: {
> >           bool swap;
> > -         nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode,
> > &swap);
> > -
> > -         unsigned num_components = glsl_get_vector_elements(val-
> > >const_type);
> >           unsigned bit_size =
> >              glsl_get_bit_size(val->const_type);
> > 
> > +         bool is_double_dst = bit_size == 64;
> > +         bool is_double_src = is_double_dst;
> > +         /* We assume there is no double conversion here */
> > +         assert(bit_size != 64 ||
> > +                (opcode != SpvOpConvertFToU && opcode !=
> > SpvOpConvertFToS &&
> > +                 opcode != SpvOpConvertSToF && opcode !=
> > SpvOpConvertUToF &&
> > +                 opcode != SpvOpFConvert));
> > +         nir_op op =
> > +            vtn_nir_alu_op_for_spirv_opcode(opcode, &swap,
> > +                                            is_double_dst,
> > is_double_src);
> > +
> > +         unsigned num_components = glsl_get_vector_elements(val-
> > >const_type);
> >           nir_const_value src[4];
> >           assert(count <= 7);
> >           for (unsigned i = 0; i < count - 4; i++) {
> > @@ -1224,16 +1233,22 @@ vtn_handle_constant(struct vtn_builder *b,
> > SpvOp opcode,
> >                 vtn_value(b, w[4 + i], vtn_value_type_constant)-
> > >constant;
> > 
> >              unsigned j = swap ? 1 - i : i;
> > -            assert(bit_size == 32);
> >              for (unsigned k = 0; k < num_components; k++)
> > -               src[j].u32[k] = c->value.u[k];
> > +               if (!is_double_src)
> > +                  src[j].u32[k] = c->value.u[k];
> > +               else
> > +                  src[j].f64[k] = c->value.d[k];
> >           }
> > 
> >           nir_const_value res = nir_eval_const_opcode(op,
> > num_components,
> >                                                       bit_size,
> > src);
> > 
> > -         for (unsigned k = 0; k < num_components; k++)
> > -            val->constant->value.u[k] = res.u32[k];
> > +         for (unsigned k = 0; k < num_components; k++) {
> > +            if (!is_double_dst)
> > +               val->constant->value.u[k] = res.u32[k];
> > +            else
> > +               val->constant->value.d[k] = res.f64[k];
> > +         }
> > 
> >           break;
> >        } /* default */
> > diff --git a/src/compiler/spirv/vtn_alu.c
> > b/src/compiler/spirv/vtn_alu.c
> > index 95ff2b1..e444d3f 100644
> > --- a/src/compiler/spirv/vtn_alu.c
> > +++ b/src/compiler/spirv/vtn_alu.c
> > @@ -211,7 +211,8 @@ vtn_handle_matrix_alu(struct vtn_builder *b,
> > SpvOp opcode,
> >  }
> > 
> >  nir_op
> > -vtn_nir_alu_op_for_spirv_opcode(SpvOp opcode, bool *swap)
> > +vtn_nir_alu_op_for_spirv_opcode(SpvOp opcode, bool *swap,
> > +                                bool is_double_dst, bool
> > is_double_src)
> 
> I think it would be better if we did this as dst_bit_size and
> src_bit_size.  That would make this simpler for basically every
> caller.  Also, it makes it more 8/16-bit ready.
>  

OK.

> >  {
> >     /* Indicates that the first two arguments should be swapped. 
> > This is
> >      * used for implementing greater-than and less-than-or-equal.
> > @@ -284,16 +285,21 @@ vtn_nir_alu_op_for_spirv_opcode(SpvOp opcode,
> > bool *swap)
> >     case SpvOpFUnordGreaterThanEqual:               return
> > nir_op_fge;
> > 
> >     /* Conversions: */
> > -   case SpvOpConvertFToU:           return nir_op_f2u;
> > -   case SpvOpConvertFToS:           return nir_op_f2i;
> > -   case SpvOpConvertSToF:           return nir_op_i2f;
> > -   case SpvOpConvertUToF:           return nir_op_u2f;
> > +   case SpvOpConvertFToU:           return is_double_src ?
> > nir_op_d2u : nir_op_f2u;
> > +   case SpvOpConvertFToS:           return is_double_src ?
> > nir_op_d2i : nir_op_f2i;
> > +   case SpvOpConvertSToF:           return is_double_dst ?
> > nir_op_i2d : nir_op_i2f;
> > +   case SpvOpConvertUToF:           return is_double_dst ?
> > nir_op_u2d : nir_op_u2f;
> 
> The time is soon coming (not sure if you want to do this now or not)
> to add a nir helper:
> 
> nir_op nir_type2type_op(nir_alu_type src, nir_alu_type dst);
> 
> I'm OK open-coding it for now, but as soon as we add int64 or any 8
> or 16-bit types, we'll want it.
>  

OK, I am going to do it now.

Thanks,

Sam

> >     case SpvOpBitcast:               return nir_op_imov;
> >     case SpvOpUConvert:
> >     case SpvOpQuantizeToF16:         return nir_op_fquantize2f16;
> > -   /* TODO: NIR is 32-bit only; these are no-ops. */
> > +   /* TODO: int64 is not supported yet. This is a no-op. */
> >     case SpvOpSConvert:              return nir_op_imov;
> > -   case SpvOpFConvert:              return nir_op_fmov;
> > +   case SpvOpFConvert:
> > +      if (is_double_src && !is_double_dst)
> > +         return nir_op_d2f;
> > +      if (!is_double_src && is_double_dst)
> > +         return nir_op_f2d;
> > +      return nir_op_fmov;
> > 
> >     /* Derivatives: */
> >     case SpvOpDPdx:         return nir_op_fddx;
> > @@ -457,7 +463,10 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp
> > opcode,
> >     case SpvOpFUnordLessThanEqual:
> >     case SpvOpFUnordGreaterThanEqual: {
> >        bool swap;
> > -      nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap);
> > +      bool is_double_src = src[0]->bit_size;
> > +      bool is_double_dst = glsl_get_bit_size(val->ssa->type);
> > +      nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap,
> > +                                                  is_double_dst,
> > is_double_src);
> > 
> >        if (swap) {
> >           nir_ssa_def *tmp = src[0];
> > @@ -481,7 +490,10 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp
> > opcode,
> >     case SpvOpFOrdLessThanEqual:
> >     case SpvOpFOrdGreaterThanEqual: {
> >        bool swap;
> > -      nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap);
> > +      bool is_double_src = src[0]->bit_size;
> > +      bool is_double_dst = glsl_get_bit_size(val->ssa->type);
> > +      nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap,
> > +                                                  is_double_dst,
> > is_double_src);
> > 
> >        if (swap) {
> >           nir_ssa_def *tmp = src[0];
> > @@ -500,7 +512,12 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp
> > opcode,
> > 
> >     default: {
> >        bool swap;
> > -      nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap);
> > +      bool is_double_src = src[0]->bit_size == 64;
> > +      bool is_double_dst =
> > +         glsl_get_bit_size(val->ssa->type) == 64;
> > +
> > +      nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap,
> > +                                                  is_double_dst,
> > is_double_src);
> > 
> >        if (swap) {
> >           nir_ssa_def *tmp = src[0];
> > diff --git a/src/compiler/spirv/vtn_private.h
> > b/src/compiler/spirv/vtn_private.h
> > index 47579fe..7159f8b 100644
> > --- a/src/compiler/spirv/vtn_private.h
> > +++ b/src/compiler/spirv/vtn_private.h
> > @@ -480,7 +480,8 @@ typedef void
> > (*vtn_execution_mode_foreach_cb)(struct vtn_builder *,
> >  void vtn_foreach_execution_mode(struct vtn_builder *b, struct
> > vtn_value *value,
> >                                  vtn_execution_mode_foreach_cb cb,
> > void *data);
> > 
> > -nir_op vtn_nir_alu_op_for_spirv_opcode(SpvOp opcode, bool *swap);
> > +nir_op vtn_nir_alu_op_for_spirv_opcode(SpvOp opcode, bool *swap,
> > +                                       bool is_double_dst, bool
> > is_double_src);
> > 
> >  void vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,
> >                      const uint32_t *w, unsigned count);
> > --
> > 2.7.4
> > 
> > _______________________________________________
> > mesa-dev mailing list
> > mesa-dev at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/mesa-dev
> > 
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20161202/3e339650/attachment.sig>


More information about the mesa-dev mailing list