From: Samuel Iglesias Gonsálvez <sigles...@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 <sigles...@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) { /* 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; 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@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev