nir: fix denorms in unpack_half_1x16()

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).

v3:
- Adapt to use the new NIR lowering framework (Andres).

v4:
- Updated to renamed shader info member and enum values (Andres).

v5:
- Simplify flags logic operations (Caio).

Signed-off-by: Samuel Iglesias Gonsálvez <siglesias@igalia.com>
Signed-off-by: Andres Gomez <agomez@igalia.com>
Reviewed-by: Connor Abbott <cwabbott0@gmail.com> [v2]
This commit is contained in:
Samuel Iglesias Gonsálvez
2018-07-09 09:46:59 +02:00
committed by Andres Gomez
parent f097247dd8
commit 1e0e3ed15a
4 changed files with 45 additions and 7 deletions

View File

@@ -254,6 +254,17 @@ 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 (0 == (u & 0x7c00))
u &= 0x8000;
return _mesa_half_to_float(u);
}
/**
* Evaluate one component of unpackHalf2x16.
*/

View File

@@ -145,13 +145,23 @@ lower_alu_instr_scalar(nir_builder *b, nir_instr *instr, void *_data)
*/
return NULL;
case nir_op_unpack_half_2x16_flush_to_zero:
case nir_op_unpack_half_2x16: {
if (!b->shader->options->lower_unpack_half_2x16)
return NULL;
nir_ssa_def *packed = nir_ssa_for_alu_src(b, alu, 0);
return nir_vec2(b, nir_unpack_half_2x16_split_x(b, packed),
nir_unpack_half_2x16_split_y(b, packed));
if (alu->op == nir_op_unpack_half_2x16_flush_to_zero) {
return nir_vec2(b,
nir_unpack_half_2x16_split_x_flush_to_zero(b,
packed),
nir_unpack_half_2x16_split_y_flush_to_zero(b,
packed));
} else {
return nir_vec2(b,
nir_unpack_half_2x16_split_x(b, packed),
nir_unpack_half_2x16_split_y(b, packed));
}
}
case nir_op_pack_uvec2_to_uint: {

View File

@@ -362,14 +362,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")

View File

@@ -387,7 +387,8 @@ build_atan2(nir_builder *b, nir_ssa_def *y, nir_ssa_def *x)
static nir_op
vtn_nir_alu_op_for_spirv_glsl_opcode(struct vtn_builder *b,
enum GLSLstd450 opcode)
enum GLSLstd450 opcode,
unsigned execution_mode)
{
switch (opcode) {
case GLSLstd450Round: return nir_op_fround_even;
@@ -433,7 +434,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 & FLOAT_CONTROLS_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:
@@ -678,13 +683,16 @@ handle_glsl450_alu(struct vtn_builder *b, enum GLSLstd450 entrypoint,
return;
}
default:
default: {
unsigned execution_mode =
b->shader->info.float_controls_execution_mode;
val->ssa->def =
nir_build_alu(&b->nb,
vtn_nir_alu_op_for_spirv_glsl_opcode(b, entrypoint),
vtn_nir_alu_op_for_spirv_glsl_opcode(b, entrypoint, execution_mode),
src[0], src[1], src[2], NULL);
return;
}
}
}
static void