[Mesa-dev] [PATCH v3 27/44] nir: fix denorms in unpack_half_1x16()
Samuel Iglesias Gonsálvez
siglesias at igalia.com
Wed Feb 6 10:44:56 UTC 2019
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 <siglesias at 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
More information about the mesa-dev
mailing list