diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 760bfeac1d9..464dbb071eb 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -3803,6 +3803,18 @@ typedef enum { nir_io_glsl_opt_varyings = BITFIELD_BIT(17), } nir_io_options; +typedef enum { + nir_lower_packing_op_pack_64_2x32, + nir_lower_packing_op_unpack_64_2x32, + nir_lower_packing_op_pack_64_4x16, + nir_lower_packing_op_unpack_64_4x16, + nir_lower_packing_op_pack_32_2x16, + nir_lower_packing_op_unpack_32_2x16, + nir_lower_packing_op_pack_32_4x8, + nir_lower_packing_op_unpack_32_4x8, + nir_lower_packing_num_ops, +} nir_lower_packing_op; + /** An instruction filtering callback * * Returns true if the instruction should be processed and false otherwise. @@ -4330,6 +4342,12 @@ typedef struct nir_shader_compiler_options { /** Options determining lowering and behavior of inputs and outputs. */ nir_io_options io_options; + /** + * Bit mask of nir_lower_packing_op to skip lowering some nir ops in + * nir_lower_packing(). + */ + unsigned skip_lower_packing_ops; + /** Driver callback where drivers can define how to lower mediump. * Used by nir_lower_io_passes. */ diff --git a/src/compiler/nir/nir_lower_packing.c b/src/compiler/nir/nir_lower_packing.c index 051add8bb12..95a01e3bf85 100644 --- a/src/compiler/nir/nir_lower_packing.c +++ b/src/compiler/nir/nir_lower_packing.c @@ -131,49 +131,55 @@ lower_unpack_32_to_8(nir_builder *b, nir_def *src) static bool lower_pack_instr(nir_builder *b, nir_alu_instr *alu_instr, void *data) { - if (alu_instr->op != nir_op_pack_64_2x32 && - alu_instr->op != nir_op_unpack_64_2x32 && - alu_instr->op != nir_op_pack_64_4x16 && - alu_instr->op != nir_op_unpack_64_4x16 && - alu_instr->op != nir_op_pack_32_2x16 && - alu_instr->op != nir_op_unpack_32_2x16 && - alu_instr->op != nir_op_pack_32_4x8 && - alu_instr->op != nir_op_unpack_32_4x8) + nir_lower_packing_op op; + switch (alu_instr->op) { + case nir_op_pack_64_2x32: + op = nir_lower_packing_op_pack_64_2x32; + break; + case nir_op_unpack_64_2x32: + op = nir_lower_packing_op_unpack_64_2x32; + break; + case nir_op_pack_64_4x16: + op = nir_lower_packing_op_pack_64_4x16; + break; + case nir_op_unpack_64_4x16: + op = nir_lower_packing_op_unpack_64_4x16; + break; + case nir_op_pack_32_2x16: + op = nir_lower_packing_op_pack_32_2x16; + break; + case nir_op_unpack_32_2x16: + op = nir_lower_packing_op_unpack_32_2x16; + break; + case nir_op_pack_32_4x8: + op = nir_lower_packing_op_pack_32_4x8; + break; + case nir_op_unpack_32_4x8: + op = nir_lower_packing_op_unpack_32_4x8; + break; + default: + return false; + } + + if (b->shader->options->skip_lower_packing_ops & BITFIELD_BIT(op)) return false; b->cursor = nir_before_instr(&alu_instr->instr); - nir_def *src = nir_ssa_for_alu_src(b, alu_instr, 0); - nir_def *dest; + typedef nir_def *(*lower_func_t)(nir_builder *b, nir_def *src); + static const lower_func_t lower_funcs[nir_lower_packing_num_ops] = { + [nir_lower_packing_op_pack_64_2x32] = lower_pack_64_from_32, + [nir_lower_packing_op_unpack_64_2x32] = lower_unpack_64_to_32, + [nir_lower_packing_op_pack_64_4x16] = lower_pack_64_from_16, + [nir_lower_packing_op_unpack_64_4x16] = lower_unpack_64_to_16, + [nir_lower_packing_op_pack_32_2x16] = lower_pack_32_from_16, + [nir_lower_packing_op_unpack_32_2x16] = lower_unpack_32_to_16, + [nir_lower_packing_op_pack_32_4x8] = lower_pack_32_from_8, + [nir_lower_packing_op_unpack_32_4x8] = lower_unpack_32_to_8, + }; - switch (alu_instr->op) { - case nir_op_pack_64_2x32: - dest = lower_pack_64_from_32(b, src); - break; - case nir_op_unpack_64_2x32: - dest = lower_unpack_64_to_32(b, src); - break; - case nir_op_pack_64_4x16: - dest = lower_pack_64_from_16(b, src); - break; - case nir_op_unpack_64_4x16: - dest = lower_unpack_64_to_16(b, src); - break; - case nir_op_pack_32_2x16: - dest = lower_pack_32_from_16(b, src); - break; - case nir_op_unpack_32_2x16: - dest = lower_unpack_32_to_16(b, src); - break; - case nir_op_pack_32_4x8: - dest = lower_pack_32_from_8(b, src); - break; - case nir_op_unpack_32_4x8: - dest = lower_unpack_32_to_8(b, src); - break; - default: - unreachable("Impossible opcode"); - } + nir_def *src = nir_ssa_for_alu_src(b, alu_instr, 0); + nir_def *dest = lower_funcs[op](b, src); nir_def_replace(&alu_instr->def, dest); return true;