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:

committed by
Andres Gomez

parent
f097247dd8
commit
1e0e3ed15a
@@ -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.
|
||||
*/
|
||||
|
@@ -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: {
|
||||
|
@@ -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")
|
||||
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user