According to VK_KHR_shader_float_controls: "Denormalized values obtained via unpacking an integer into a vector of values with smaller bit width and interpreting those values as floating-point numbers must: be flushed to zero, unless the entry point is declared with the code:DenormPreserve execution mode."
v2: - Add nir_op_unpack_half_2x16_flush_to_zero opcode (Connor) Signed-off-by: Samuel Iglesias Gonsálvez <sigles...@igalia.com> --- src/compiler/nir/nir_constant_expressions.py | 13 +++++++++++++ src/compiler/nir/nir_lower_alu_to_scalar.c | 11 +++++++++-- src/compiler/nir/nir_opcodes.py | 11 ++++++++++- src/compiler/spirv/vtn_glsl450.c | 6 +++++- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/compiler/nir/nir_constant_expressions.py b/src/compiler/nir/nir_constant_expressions.py index 0b3da1b21ac..f8d1c2d3bdc 100644 --- a/src/compiler/nir/nir_constant_expressions.py +++ b/src/compiler/nir/nir_constant_expressions.py @@ -261,6 +261,19 @@ pack_half_1x16(float x) return _mesa_float_to_half(x); } +/** + * Evaluate one component of unpackHalf2x16. + */ +static float +unpack_half_1x16_flush_to_zero(uint16_t u) +{ + if (u < 0x0400) + u = 0; + if (u & 0x8000 && !(u & 0x7c00)) + u = 0x8000; + return _mesa_half_to_float(u); +} + /** * Evaluate one component of unpackHalf2x16. */ diff --git a/src/compiler/nir/nir_lower_alu_to_scalar.c b/src/compiler/nir/nir_lower_alu_to_scalar.c index 2ed4098d59b..6a5a0d2f991 100644 --- a/src/compiler/nir/nir_lower_alu_to_scalar.c +++ b/src/compiler/nir/nir_lower_alu_to_scalar.c @@ -132,6 +132,7 @@ lower_alu_instr_scalar(nir_alu_instr *instr, nir_builder *b) */ return false; + case nir_op_unpack_half_2x16_flush_to_zero: case nir_op_unpack_half_2x16: { if (!b->shader->options->lower_unpack_half_2x16) return false; @@ -139,8 +140,14 @@ lower_alu_instr_scalar(nir_alu_instr *instr, nir_builder *b) nir_ssa_def *packed = nir_ssa_for_alu_src(b, instr, 0); nir_ssa_def *comps[2]; - comps[0] = nir_unpack_half_2x16_split_x(b, packed); - comps[1] = nir_unpack_half_2x16_split_y(b, packed); + + if (instr->op == nir_op_unpack_half_2x16_flush_to_zero) { + comps[0] = nir_unpack_half_2x16_split_x_flush_to_zero(b, packed); + comps[1] = nir_unpack_half_2x16_split_y_flush_to_zero(b, packed); + } else { + comps[0] = nir_unpack_half_2x16_split_x(b, packed); + comps[1] = nir_unpack_half_2x16_split_y(b, packed); + } nir_ssa_def *vec = nir_vec(b, comps, 2); nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, nir_src_for_ssa(vec)); diff --git a/src/compiler/nir/nir_opcodes.py b/src/compiler/nir/nir_opcodes.py index a8ccb237a65..230057c1f30 100644 --- a/src/compiler/nir/nir_opcodes.py +++ b/src/compiler/nir/nir_opcodes.py @@ -357,14 +357,23 @@ unop_horiz("unpack_64_4x16", 4, tuint16, 1, tuint64, unop_horiz("unpack_32_2x16", 2, tuint16, 1, tuint32, "dst.x = src0.x; dst.y = src0.x >> 16;") -# Lowered floating point unpacking operations. +unop_horiz("unpack_half_2x16_flush_to_zero", 2, tfloat32, 1, tuint32, """ +dst.x = unpack_half_1x16_flush_to_zero((uint16_t)(src0.x & 0xffff)); +dst.y = unpack_half_1x16_flush_to_zero((uint16_t)(src0.x << 16)); +""") +# Lowered floating point unpacking operations. unop_convert("unpack_half_2x16_split_x", tfloat32, tuint32, "unpack_half_1x16((uint16_t)(src0 & 0xffff))", "") unop_convert("unpack_half_2x16_split_y", tfloat32, tuint32, "unpack_half_1x16((uint16_t)(src0 >> 16))", "") +unop_convert("unpack_half_2x16_split_x_flush_to_zero", tfloat32, tuint32, + "unpack_half_1x16_flush_to_zero((uint16_t)(src0 & 0xffff))", "") +unop_convert("unpack_half_2x16_split_y_flush_to_zero", tfloat32, tuint32, + "unpack_half_1x16_flush_to_zero((uint16_t)(src0 >> 16))", "") + unop_convert("unpack_32_2x16_split_x", tuint16, tuint32, "src0", "") unop_convert("unpack_32_2x16_split_y", tuint16, tuint32, "src0 >> 16", "") diff --git a/src/compiler/spirv/vtn_glsl450.c b/src/compiler/spirv/vtn_glsl450.c index b6036cf876e..e75efbc695c 100644 --- a/src/compiler/spirv/vtn_glsl450.c +++ b/src/compiler/spirv/vtn_glsl450.c @@ -573,7 +573,11 @@ vtn_nir_alu_op_for_spirv_glsl_opcode(struct vtn_builder *b, case GLSLstd450UnpackUnorm4x8: return nir_op_unpack_unorm_4x8; case GLSLstd450UnpackSnorm2x16: return nir_op_unpack_snorm_2x16; case GLSLstd450UnpackUnorm2x16: return nir_op_unpack_unorm_2x16; - case GLSLstd450UnpackHalf2x16: return nir_op_unpack_half_2x16; + case GLSLstd450UnpackHalf2x16: + if (execution_mode & SHADER_DENORM_FLUSH_TO_ZERO_FP16) + return nir_op_unpack_half_2x16_flush_to_zero; + else + return nir_op_unpack_half_2x16; case GLSLstd450UnpackDouble2x32: return nir_op_unpack_64_2x32; default: -- 2.19.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev