nir: Differentiate between signed and unsigned versions of find_msb

We also make the return types match GLSL.  The GLSL spec specifies that
findMSB and findLSB return a signed integer.  Previously, nir had them
return unsigned.  This updates nir's behavior to match what GLSL expects.

We also update the nir-to-fs generator to take the new instructions.  While
we're at it, we fix the case where the input to findMSB is zero.

Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
This commit is contained in:
Jason Ekstrand 2014-11-07 10:59:16 -08:00
parent a76ccbfacf
commit 10adf8fc85
3 changed files with 30 additions and 11 deletions

View file

@ -1123,9 +1123,25 @@ nir_visitor::visit(ir_expression *ir)
case ir_unop_bitfield_reverse:
emit(nir_op_bitfield_reverse, dest_size, srcs);
break;
case ir_unop_bit_count: emit(nir_op_bit_count, dest_size, srcs); break;
case ir_unop_find_msb: emit(nir_op_find_msb, dest_size, srcs); break;
case ir_unop_find_lsb: emit(nir_op_find_lsb, dest_size, srcs); break;
case ir_unop_bit_count:
emit(nir_op_bit_count, dest_size, srcs);
break;
case ir_unop_find_msb:
switch (types[0]) {
case GLSL_TYPE_UINT:
emit(nir_op_ufind_msb, dest_size, srcs);
break;
case GLSL_TYPE_INT:
emit(nir_op_ifind_msb, dest_size, srcs);
break;
default:
unreachable("Invalid type for findMSB()");
}
break;
case ir_unop_find_lsb:
emit(nir_op_find_lsb, dest_size, srcs);
break;
case ir_unop_noise:
switch (ir->type->vector_elements) {
case 1:

View file

@ -147,8 +147,9 @@ UNOP_HORIZ(unpack_half_2x16_split_y, 1, nir_type_float, 1, nir_type_unsigned)
/*@{*/
UNOP(bitfield_reverse, nir_type_unsigned)
UNOP(bit_count, nir_type_unsigned)
UNOP(find_msb, nir_type_unsigned)
UNOP(find_lsb, nir_type_unsigned)
UNOP_CONVERT(ufind_msb, nir_type_unsigned, nir_type_int)
UNOP(ifind_msb, nir_type_int)
UNOP(find_lsb, nir_type_int)
/*@}*/
UNOP_HORIZ(fnoise1_1, 1, nir_type_float, 1, nir_type_float)

View file

@ -876,19 +876,21 @@ fs_visitor::nir_emit_alu(nir_alu_instr *instr)
emit_percomp(CBIT(result, op[0]), instr->dest.write_mask);
break;
case nir_op_find_msb: {
fs_reg temp = fs_reg(this, glsl_type::uvec4_type);
emit_percomp(FBH(temp, op[0]), instr->dest.write_mask);
case nir_op_ufind_msb:
case nir_op_ifind_msb: {
emit_percomp(FBH(retype(result, BRW_REGISTER_TYPE_UD), op[0]),
instr->dest.write_mask);
/* FBH counts from the MSB side, while GLSL's findMSB() wants the count
* from the LSB side. If FBH didn't return an error (0xFFFFFFFF), then
* subtract the result from 31 to convert the MSB count into an LSB count.
*/
emit_percomp(CMP(reg_null_d, temp, fs_reg(~0), BRW_CONDITIONAL_NZ),
emit_percomp(CMP(reg_null_d, result, fs_reg(-1), BRW_CONDITIONAL_NZ),
instr->dest.write_mask);
temp.negate = true;
fs_inst *inst = ADD(result, temp, fs_reg(31));
fs_reg neg_result(result);
neg_result.negate = true;
fs_inst *inst = ADD(result, neg_result, fs_reg(31));
inst->predicate = BRW_PREDICATE_NORMAL;
emit_percomp(inst, instr->dest.write_mask);
break;