nir: Add a new opcode for [un]packing doubles

HLSL doesn't support bitcasting a 64bit integer to a double. DXIL
doesn't have generic pack/unpack instructions, so we lower those to
integer bitwise ops. As a result, NIR generic double pack/unpack would
require our backend to emit a bitcast to get a double, but we want
to match HLSL semantics and emit MakeDouble/SplitDouble.

Adding a dedicated opcode for double pack/unpack allows us to add a
pass to emit that instead, which lets our backend emit the right
instruction to pack and unpack doubles.

Acked-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10063>
This commit is contained in:
Jesse Natalie 2021-04-06 10:42:59 -07:00 committed by Marge Bot
parent bd219321a5
commit 3c8bcdc863
3 changed files with 15 additions and 0 deletions

View File

@ -241,6 +241,7 @@ lower_alu_instr_scalar(nir_builder *b, nir_instr *instr, void *_data)
case nir_op_unpack_64_2x32:
case nir_op_unpack_64_4x16:
case nir_op_unpack_32_2x16:
case nir_op_unpack_double_2x32_dxil:
return NULL;
LOWER_REDUCTION(nir_op_fdot, nir_op_fmul, nir_op_fadd);

View File

@ -1253,3 +1253,15 @@ binop("umul24", tint32, _2src_commutative + associative,
unop_convert("fisnormal", tbool1, tfloat, "isnormal(src0)")
unop_convert("fisfinite", tbool1, tfloat, "isfinite(src0)")
# DXIL specific double [un]pack
# DXIL doesn't support generic [un]pack instructions, so we want those
# lowered to bit ops. HLSL doesn't support 64bit bitcasts to/from
# double, only [un]pack. Technically DXIL does, but considering they
# can't be generated from HLSL, we want to match what would be coming from DXC.
# This is essentially just the standard [un]pack, except that it doesn't get
# lowered so we can handle it in the backend and turn it into MakeDouble/SplitDouble
unop_horiz("pack_double_2x32_dxil", 1, tuint64, 2, tuint32,
"dst.x = src0.x | ((uint64_t)src0.y << 32);")
unop_horiz("unpack_double_2x32_dxil", 2, tuint32, 1, tuint64,
"dst.x = src0.x; dst.y = src0.x >> 32;")

View File

@ -1201,11 +1201,13 @@ optimizations.extend([
(('unpack_64_2x32_split_y', ('pack_64_2x32_split', a, b)), b),
(('unpack_64_2x32', ('pack_64_2x32_split', a, b)), ('vec2', a, b)),
(('unpack_64_2x32', ('pack_64_2x32', a)), a),
(('unpack_double_2x32_dxil', ('pack_double_2x32_dxil', a)), a),
(('pack_64_2x32_split', ('unpack_64_2x32_split_x', a),
('unpack_64_2x32_split_y', a)), a),
(('pack_64_2x32', ('vec2', ('unpack_64_2x32_split_x', a),
('unpack_64_2x32_split_y', a))), a),
(('pack_64_2x32', ('unpack_64_2x32', a)), a),
(('pack_double_2x32_dxil', ('unpack_double_2x32_dxil', a)), a),
# Comparing two halves of an unpack separately. While this optimization
# should be correct for non-constant values, it's less obvious that it's