Module: Mesa Branch: master Commit: 8610af12b6a64011df905b9b0ab2d773dfaae139 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=8610af12b6a64011df905b9b0ab2d773dfaae139
Author: Jason Ekstrand <[email protected]> Date: Wed Sep 30 16:43:31 2020 -0500 spirv: Handle all OpenCL conversion ops with full rounding This is done for kernels via the new convert_alu_types intrinsic. For Vulkan and OpenGL, we maintain the old path so that drivers don't have to add that lowering pass. Reviewed-by: Jesse Natalie <[email protected]> Reviewed-by: Daniel Stone <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6945> --- src/compiler/spirv/spirv_to_nir.c | 2 + src/compiler/spirv/vtn_alu.c | 91 ++++++++++++++++++++++++++++++++------- 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index a670f51adfb..c891e7564d3 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -5135,6 +5135,8 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode, case SpvOpSConvert: case SpvOpFConvert: case SpvOpQuantizeToF16: + case SpvOpSatConvertSToU: + case SpvOpSatConvertUToS: case SpvOpPtrCastToGeneric: case SpvOpGenericCastToPtr: case SpvOpIsNan: diff --git a/src/compiler/spirv/vtn_alu.c b/src/compiler/spirv/vtn_alu.c index 9b4a8e16eef..205eca082c0 100644 --- a/src/compiler/spirv/vtn_alu.c +++ b/src/compiler/spirv/vtn_alu.c @@ -220,9 +220,11 @@ convert_op_src_type(SpvOp opcode) return nir_type_float; case SpvOpSConvert: case SpvOpConvertSToF: + case SpvOpSatConvertSToU: return nir_type_int; case SpvOpUConvert: case SpvOpConvertUToF: + case SpvOpSatConvertUToS: return nir_type_uint; default: unreachable("Unhandled conversion op"); @@ -239,9 +241,11 @@ convert_op_dst_type(SpvOp opcode) return nir_type_float; case SpvOpSConvert: case SpvOpConvertFToS: + case SpvOpSatConvertUToS: return nir_type_int; case SpvOpUConvert: case SpvOpConvertFToU: + case SpvOpSatConvertSToU: return nir_type_uint; default: unreachable("Unhandled conversion op"); @@ -386,6 +390,14 @@ vtn_rounding_mode_to_nir(struct vtn_builder *b, SpvFPRoundingMode mode) return nir_rounding_mode_rtne; case SpvFPRoundingModeRTZ: return nir_rounding_mode_rtz; + case SpvFPRoundingModeRTP: + vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL, + "FPRoundingModeRTP is only supported in kernels"); + return nir_rounding_mode_ru; + case SpvFPRoundingModeRTN: + vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL, + "FPRoundingModeRTN is only supported in kernels"); + return nir_rounding_mode_rd; default: vtn_fail("Unsupported rounding mode: %s", spirv_fproundingmode_to_string(mode)); @@ -393,15 +405,31 @@ vtn_rounding_mode_to_nir(struct vtn_builder *b, SpvFPRoundingMode mode) } } +struct conversion_opts { + nir_rounding_mode rounding_mode; + bool saturate; +}; + static void -handle_rounding_mode(struct vtn_builder *b, struct vtn_value *val, int member, - const struct vtn_decoration *dec, void *_out_rounding_mode) +handle_conversion_opts(struct vtn_builder *b, struct vtn_value *val, int member, + const struct vtn_decoration *dec, void *_opts) { - nir_rounding_mode *out_rounding_mode = _out_rounding_mode; - assert(dec->scope == VTN_DEC_DECORATION); - if (dec->decoration != SpvDecorationFPRoundingMode) - return; - *out_rounding_mode = vtn_rounding_mode_to_nir(b, dec->operands[0]); + struct conversion_opts *opts = _opts; + + switch (dec->decoration) { + case SpvDecorationFPRoundingMode: + opts->rounding_mode = vtn_rounding_mode_to_nir(b, dec->operands[0]); + break; + + case SpvDecorationSaturatedConversion: + vtn_fail_if(b->shader->info.stage != MESA_SHADER_KERNEL, + "Saturated conversions are only allowed in kernels"); + opts->saturate = true; + break; + + default: + break; + } } static void @@ -592,15 +620,48 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp opcode, break; } - case SpvOpFConvert: { - nir_alu_type src_alu_type = nir_get_nir_type_for_glsl_type(vtn_src[0]->type); - nir_alu_type dst_alu_type = nir_get_nir_type_for_glsl_type(dest_type); - nir_rounding_mode rounding_mode = nir_rounding_mode_undef; - - vtn_foreach_decoration(b, dest_val, handle_rounding_mode, &rounding_mode); - nir_op op = nir_type_conversion_op(src_alu_type, dst_alu_type, rounding_mode); + case SpvOpUConvert: + case SpvOpConvertFToU: + case SpvOpConvertFToS: + case SpvOpConvertSToF: + case SpvOpConvertUToF: + case SpvOpSConvert: + case SpvOpFConvert: + case SpvOpSatConvertSToU: + case SpvOpSatConvertUToS: { + unsigned src_bit_size = glsl_get_bit_size(vtn_src[0]->type); + unsigned dst_bit_size = glsl_get_bit_size(dest_type); + nir_alu_type src_type = convert_op_src_type(opcode) | src_bit_size; + nir_alu_type dst_type = convert_op_dst_type(opcode) | dst_bit_size; - dest->def = nir_build_alu(&b->nb, op, src[0], src[1], NULL, NULL); + struct conversion_opts opts = { + .rounding_mode = nir_rounding_mode_undef, + .saturate = false, + }; + vtn_foreach_decoration(b, dest_val, handle_conversion_opts, &opts); + + if (opcode == SpvOpSatConvertSToU || opcode == SpvOpSatConvertUToS) + opts.saturate = true; + + if (b->shader->info.stage == MESA_SHADER_KERNEL) { + if (opts.rounding_mode == nir_rounding_mode_undef && !opts.saturate) { + nir_op op = nir_type_conversion_op(src_type, dst_type, + nir_rounding_mode_undef); + dest->def = nir_build_alu(&b->nb, op, src[0], NULL, NULL, NULL); + } else { + dest->def = nir_convert_alu_types(&b->nb, src[0], src_type, + dst_type, opts.rounding_mode, + opts.saturate); + } + } else { + vtn_fail_if(opts.rounding_mode != nir_rounding_mode_undef && + dst_type != nir_type_float16, + "Rounding modes are only allowed on conversions to " + "16-bit float types"); + nir_op op = nir_type_conversion_op(src_type, dst_type, + opts.rounding_mode); + dest->def = nir_build_alu(&b->nb, op, src[0], NULL, NULL, NULL); + } break; } _______________________________________________ mesa-commit mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-commit
