[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