nir,intel: lower if (cond) demote() to new intrinsic demote_if(cond)
This will effectively enable the optimization in anv. Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com> Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
This commit is contained in:
committed by
Jason Ekstrand
parent
517005b4cf
commit
e272fdd508
@@ -199,6 +199,7 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader,
|
||||
{
|
||||
switch (instr->intrinsic) {
|
||||
case nir_intrinsic_demote:
|
||||
case nir_intrinsic_demote_if:
|
||||
case nir_intrinsic_discard:
|
||||
case nir_intrinsic_discard_if:
|
||||
assert(shader->info.stage == MESA_SHADER_FRAGMENT);
|
||||
|
||||
@@ -241,8 +241,9 @@ barrier("memory_barrier_shared")
|
||||
barrier("begin_invocation_interlock")
|
||||
barrier("end_invocation_interlock")
|
||||
|
||||
# A conditional discard, with a single boolean source.
|
||||
# A conditional discard/demote, with a single boolean source.
|
||||
intrinsic("discard_if", src_comp=[1])
|
||||
intrinsic("demote_if", src_comp=[1])
|
||||
|
||||
# ARB_shader_group_vote intrinsics
|
||||
intrinsic("vote_any", src_comp=[1], dest_comp=1, flags=[CAN_ELIMINATE])
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
|
||||
/** @file nir_opt_conditional_discard.c
|
||||
*
|
||||
* Handles optimization of lowering if (cond) discard to discard_if(cond).
|
||||
* Handles optimization of lowering of
|
||||
* - if (cond) discard to discard_if(cond) and
|
||||
* - if (cond) demote to demote_if(cond)
|
||||
*/
|
||||
|
||||
static bool
|
||||
@@ -73,30 +75,37 @@ nir_opt_conditional_discard_block(nir_builder *b, nir_block *block)
|
||||
}
|
||||
|
||||
/* Get the first instruction in the then block and confirm it is
|
||||
* a discard or a discard_if
|
||||
* a discard or a demote instruction.
|
||||
*/
|
||||
nir_instr *instr = nir_block_first_instr(then_block);
|
||||
if (instr->type != nir_instr_type_intrinsic)
|
||||
return false;
|
||||
|
||||
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
||||
if (intrin->intrinsic != nir_intrinsic_discard &&
|
||||
intrin->intrinsic != nir_intrinsic_discard_if)
|
||||
return false;
|
||||
|
||||
nir_src cond;
|
||||
|
||||
nir_intrinsic_op op = intrin->intrinsic;
|
||||
assert(if_stmt->condition.is_ssa);
|
||||
nir_ssa_def *cond = if_stmt->condition.ssa;
|
||||
b->cursor = nir_before_cf_node(prev_node);
|
||||
if (intrin->intrinsic == nir_intrinsic_discard)
|
||||
cond = if_stmt->condition;
|
||||
else
|
||||
cond = nir_src_for_ssa(nir_iand(b,
|
||||
nir_ssa_for_src(b, if_stmt->condition, 1),
|
||||
nir_ssa_for_src(b, intrin->src[0], 1)));
|
||||
|
||||
switch (intrin->intrinsic) {
|
||||
case nir_intrinsic_discard:
|
||||
op = nir_intrinsic_discard_if;
|
||||
break;
|
||||
case nir_intrinsic_demote:
|
||||
op = nir_intrinsic_demote_if;
|
||||
break;
|
||||
case nir_intrinsic_discard_if:
|
||||
case nir_intrinsic_demote_if:
|
||||
assert(intrin->src[0].is_ssa);
|
||||
cond = nir_iand(b, cond, intrin->src[0].ssa);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
nir_intrinsic_instr *discard_if =
|
||||
nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if);
|
||||
nir_src_copy(&discard_if->src[0], &cond, discard_if);
|
||||
nir_intrinsic_instr_create(b->shader, op);
|
||||
discard_if->src[0] = nir_src_for_ssa(cond);
|
||||
|
||||
nir_instr_insert_before_cf(prev_node, &discard_if->instr);
|
||||
nir_instr_remove(&intrin->instr);
|
||||
|
||||
@@ -119,7 +119,8 @@ constant_fold_intrinsic_instr(nir_intrinsic_instr *instr)
|
||||
{
|
||||
bool progress = false;
|
||||
|
||||
if (instr->intrinsic == nir_intrinsic_discard_if &&
|
||||
if ((instr->intrinsic == nir_intrinsic_demote_if ||
|
||||
instr->intrinsic == nir_intrinsic_discard_if) &&
|
||||
nir_src_is_const(instr->src[0])) {
|
||||
if (nir_src_as_bool(instr->src[0])) {
|
||||
/* This method of getting a nir_shader * from a nir_instr is
|
||||
@@ -131,9 +132,11 @@ constant_fold_intrinsic_instr(nir_intrinsic_instr *instr)
|
||||
nir_function_impl *impl = nir_cf_node_get_function(cf_node);
|
||||
nir_shader *shader = impl->function->shader;
|
||||
|
||||
nir_intrinsic_instr *discard =
|
||||
nir_intrinsic_instr_create(shader, nir_intrinsic_discard);
|
||||
nir_instr_insert_before(&instr->instr, &discard->instr);
|
||||
nir_intrinsic_op op = instr->intrinsic == nir_intrinsic_discard_if ?
|
||||
nir_intrinsic_discard :
|
||||
nir_intrinsic_demote;
|
||||
nir_intrinsic_instr *new_instr = nir_intrinsic_instr_create(shader, op);
|
||||
nir_instr_insert_before(&instr->instr, &new_instr->instr);
|
||||
nir_instr_remove(&instr->instr);
|
||||
progress = true;
|
||||
} else {
|
||||
|
||||
@@ -3568,6 +3568,7 @@ fs_visitor::nir_emit_fs_intrinsic(const fs_builder &bld,
|
||||
|
||||
case nir_intrinsic_demote:
|
||||
case nir_intrinsic_discard:
|
||||
case nir_intrinsic_demote_if:
|
||||
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. If there's no
|
||||
@@ -3575,7 +3576,8 @@ fs_visitor::nir_emit_fs_intrinsic(const fs_builder &bld,
|
||||
* channels will get turned off.
|
||||
*/
|
||||
fs_inst *cmp = NULL;
|
||||
if (instr->intrinsic == nir_intrinsic_discard_if) {
|
||||
if (instr->intrinsic == nir_intrinsic_demote_if ||
|
||||
instr->intrinsic == nir_intrinsic_discard_if) {
|
||||
nir_alu_instr *alu = nir_src_as_alu_instr(instr->src[0]);
|
||||
|
||||
if (alu != NULL &&
|
||||
|
||||
Reference in New Issue
Block a user