zink/spirv: do not use bitwise operations on booleans

According to the SPIR-V specification, these operations require
integer-types. When bit_size is 1, we use booleans, which makes us emit
illegal code.

So let's fix the emitting to check if the first source is one bit wide.

For inot we can take a short-cut, and check the destination instead.
This doesn't work for ieq and ine, so let's not bother to do this
BINOP_LOG.

Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4036>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4036>
This commit is contained in:
Erik Faye-Lund 2020-03-03 19:37:37 +01:00
parent 130c0ba1cc
commit d4b0e28f62

View file

@ -961,9 +961,15 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu)
UNOP(nir_op_f2u32, SpvOpConvertFToU)
UNOP(nir_op_i2f32, SpvOpConvertSToF)
UNOP(nir_op_u2f32, SpvOpConvertUToF)
UNOP(nir_op_inot, SpvOpNot)
#undef UNOP
case nir_op_inot:
if (bit_size == 1)
result = emit_unop(ctx, SpvOpLogicalNot, dest_type, src[0]);
else
result = emit_unop(ctx, SpvOpNot, dest_type, src[0]);
break;
case nir_op_b2i32:
assert(nir_op_infos[alu->op].num_inputs == 1);
result = emit_select(ctx, dest_type, src[0],
@ -1035,8 +1041,6 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu)
BINOP(nir_op_fmod, SpvOpFMod)
BINOP(nir_op_ilt, SpvOpSLessThan)
BINOP(nir_op_ige, SpvOpSGreaterThanEqual)
BINOP(nir_op_ieq, SpvOpIEqual)
BINOP(nir_op_ine, SpvOpINotEqual)
BINOP(nir_op_uge, SpvOpUGreaterThanEqual)
BINOP(nir_op_flt, SpvOpFOrdLessThan)
BINOP(nir_op_fge, SpvOpFOrdGreaterThanEqual)
@ -1045,10 +1049,23 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu)
BINOP(nir_op_ishl, SpvOpShiftLeftLogical)
BINOP(nir_op_ishr, SpvOpShiftRightArithmetic)
BINOP(nir_op_ushr, SpvOpShiftRightLogical)
BINOP(nir_op_iand, SpvOpBitwiseAnd)
BINOP(nir_op_ior, SpvOpBitwiseOr)
#undef BINOP
#define BINOP_LOG(nir_op, spv_op, spv_log_op) \
case nir_op: \
assert(nir_op_infos[alu->op].num_inputs == 2); \
if (nir_src_bit_size(alu->src[0].src) == 1) \
result = emit_binop(ctx, spv_log_op, dest_type, src[0], src[1]); \
else \
result = emit_binop(ctx, spv_op, dest_type, src[0], src[1]); \
break;
BINOP_LOG(nir_op_iand, SpvOpBitwiseAnd, SpvOpLogicalAnd)
BINOP_LOG(nir_op_ior, SpvOpBitwiseOr, SpvOpLogicalOr)
BINOP_LOG(nir_op_ieq, SpvOpIEqual, SpvOpLogicalEqual)
BINOP_LOG(nir_op_ine, SpvOpINotEqual, SpvOpLogicalNotEqual)
#undef BINOP_LOG
#define BUILTIN_BINOP(nir_op, spirv_op) \
case nir_op: \
assert(nir_op_infos[alu->op].num_inputs == 2); \