The discard condition tells us which channels we want killed. We want to invert that condition to get the channels that should survive (remain live) in f0.1. Emit a CMP to negate it. Nothing generates these today, but that will change shortly. Signed-off-by: Kenneth Graunke <kenneth@whitecape.org> Reviewed-by: Connor Abbott <cwabbott0@gmail.com> Reviewed-by: Matt Turner <mattst88@gmail.com> Reviewed-by: Eric Anholt <eric@anholt.net>tags/10.6-branchpoint
@@ -1258,16 +1258,22 @@ fs_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) | |||
bool has_indirect = false; | |||
switch (instr->intrinsic) { | |||
case nir_intrinsic_discard: { | |||
case nir_intrinsic_discard: | |||
case nir_intrinsic_discard_if: { | |||
/* We track our discarded pixels in f0.1. By predicating on it, we can | |||
* update just the flag bits that aren't yet discarded. By emitting a | |||
* CMP of g0 != g0, all our currently executing channels will get turned | |||
* off. | |||
* update just the flag bits that aren't yet discarded. If there's no | |||
* condition, we emit a CMP of g0 != g0, so all currently executing | |||
* channels will get turned off. | |||
*/ | |||
fs_reg some_reg = fs_reg(retype(brw_vec8_grf(0, 0), | |||
BRW_REGISTER_TYPE_UW)); | |||
fs_inst *cmp = emit(CMP(reg_null_f, some_reg, some_reg, | |||
BRW_CONDITIONAL_NZ)); | |||
fs_inst *cmp; | |||
if (instr->intrinsic == nir_intrinsic_discard_if) { | |||
cmp = emit(CMP(reg_null_f, get_nir_src(instr->src[0]), | |||
fs_reg(0), BRW_CONDITIONAL_Z)); | |||
} else { | |||
fs_reg some_reg = fs_reg(retype(brw_vec8_grf(0, 0), | |||
BRW_REGISTER_TYPE_UW)); | |||
cmp = emit(CMP(reg_null_f, some_reg, some_reg, BRW_CONDITIONAL_NZ)); | |||
} | |||
cmp->predicate = BRW_PREDICATE_NORMAL; | |||
cmp->flag_subreg = 1; | |||
@@ -2415,17 +2415,20 @@ fs_visitor::visit(ir_swizzle *ir) | |||
void | |||
fs_visitor::visit(ir_discard *ir) | |||
{ | |||
assert(ir->condition == NULL); /* FINISHME */ | |||
/* We track our discarded pixels in f0.1. By predicating on it, we can | |||
* update just the flag bits that aren't yet discarded. By emitting a | |||
* CMP of g0 != g0, all our currently executing channels will get turned | |||
* off. | |||
* update just the flag bits that aren't yet discarded. If there's no | |||
* condition, we emit a CMP of g0 != g0, so all currently executing | |||
* channels will get turned off. | |||
*/ | |||
fs_reg some_reg = fs_reg(retype(brw_vec8_grf(0, 0), | |||
BRW_REGISTER_TYPE_UW)); | |||
fs_inst *cmp = emit(CMP(reg_null_f, some_reg, some_reg, | |||
BRW_CONDITIONAL_NZ)); | |||
fs_inst *cmp; | |||
if (ir->condition) { | |||
ir->condition->accept(this); | |||
cmp = emit(CMP(reg_null_f, this->result, fs_reg(0), BRW_CONDITIONAL_Z)); | |||
} else { | |||
fs_reg some_reg = fs_reg(retype(brw_vec8_grf(0, 0), | |||
BRW_REGISTER_TYPE_UW)); | |||
cmp = emit(CMP(reg_null_f, some_reg, some_reg, BRW_CONDITIONAL_NZ)); | |||
} | |||
cmp->predicate = BRW_PREDICATE_NORMAL; | |||
cmp->flag_subreg = 1; | |||