nv50/ir/nir: implement vote and ballot

v2: add vote_eq support
    use the new subop intrinsic helper
    add ballot
v3: add read_(first_)invocation
v8: handle vectorized intrinsics
    don't require C++11 features
v9: lower_subgroups to 32 bit (produces less instructions)
    use getSSA and getScratch instead of new_LValue

Signed-off-by: Karol Herbst <kherbst@redhat.com>
This commit is contained in:
Karol Herbst 2017-12-20 17:06:03 +01:00
parent 4dec7f81e0
commit fa361a3c1e
1 changed files with 48 additions and 0 deletions

View File

@ -498,6 +498,12 @@ int
Converter::getSubOp(nir_intrinsic_op op)
{
switch (op) {
case nir_intrinsic_vote_all:
return NV50_IR_SUBOP_VOTE_ALL;
case nir_intrinsic_vote_any:
return NV50_IR_SUBOP_VOTE_ANY;
case nir_intrinsic_vote_ieq:
return NV50_IR_SUBOP_VOTE_UNI;
default:
return 0;
}
@ -1931,6 +1937,42 @@ Converter::visit(nir_intrinsic_instr *insn)
loadImm(newDefs[0], 32u);
break;
}
case nir_intrinsic_vote_all:
case nir_intrinsic_vote_any:
case nir_intrinsic_vote_ieq: {
LValues &newDefs = convert(&insn->dest);
Value *pred = getScratch(1, FILE_PREDICATE);
mkCmp(OP_SET, CC_NE, TYPE_U32, pred, TYPE_U32, getSrc(&insn->src[0], 0), zero);
mkOp1(OP_VOTE, TYPE_U32, pred, pred)->subOp = getSubOp(op);
mkCvt(OP_CVT, TYPE_U32, newDefs[0], TYPE_U8, pred);
break;
}
case nir_intrinsic_ballot: {
LValues &newDefs = convert(&insn->dest);
Value *pred = getSSA(1, FILE_PREDICATE);
mkCmp(OP_SET, CC_NE, TYPE_U32, pred, TYPE_U32, getSrc(&insn->src[0], 0), zero);
mkOp1(OP_VOTE, TYPE_U32, newDefs[0], pred)->subOp = NV50_IR_SUBOP_VOTE_ANY;
break;
}
case nir_intrinsic_read_first_invocation:
case nir_intrinsic_read_invocation: {
LValues &newDefs = convert(&insn->dest);
const DataType dType = getDType(insn);
Value *tmp = getScratch();
if (op == nir_intrinsic_read_first_invocation) {
mkOp1(OP_VOTE, TYPE_U32, tmp, mkImm(1))->subOp = NV50_IR_SUBOP_VOTE_ANY;
mkOp2(OP_EXTBF, TYPE_U32, tmp, tmp, mkImm(0x2000))->subOp = NV50_IR_SUBOP_EXTBF_REV;
mkOp1(OP_BFIND, TYPE_U32, tmp, tmp)->subOp = NV50_IR_SUBOP_BFIND_SAMT;
} else
tmp = getSrc(&insn->src[1], 0);
for (uint8_t i = 0; i < insn->num_components; ++i) {
mkOp3(OP_SHFL, dType, newDefs[i], getSrc(&insn->src[0], i), tmp, mkImm(0x1f))
->subOp = NV50_IR_SUBOP_SHFL_IDX;
}
break;
}
default:
ERROR("unknown nir_intrinsic_op %s\n", nir_intrinsic_infos[op].name);
return false;
@ -2566,7 +2608,13 @@ Converter::run()
if (prog->dbgFlags & NV50_IR_DEBUG_VERBOSE)
nir_print_shader(nir, stderr);
struct nir_lower_subgroups_options subgroup_options = {
.subgroup_size = 32,
.ballot_bit_size = 32,
};
NIR_PASS_V(nir, nir_lower_io, nir_var_all, type_size, (nir_lower_io_options)0);
NIR_PASS_V(nir, nir_lower_subgroups, &subgroup_options);
NIR_PASS_V(nir, nir_lower_regs_to_ssa);
NIR_PASS_V(nir, nir_lower_load_const_to_scalar);
NIR_PASS_V(nir, nir_lower_vars_to_ssa);