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

Jason Ekstrand jason at jlekstrand.net
Fri Dec 2 02:50:04 UTC 2016


On Fri, Nov 25, 2016 at 12:52 AM, Juan A. Suarez Romero <jasuarez at igalia.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.


>  {
>     /* 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.


>     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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20161201/e8692a39/attachment-0001.html>


More information about the mesa-dev mailing list