pco: support combined depth/discard isp feedback

Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36412>
This commit is contained in:
Simon Perretta 2025-02-04 17:43:44 +00:00 committed by Marge Bot
parent 0367dc1e42
commit ac41e9dd18
4 changed files with 49 additions and 34 deletions

View file

@ -2725,9 +2725,9 @@ index("unsigned", "mutex_op_pco")
# Perform a mutex operation (slot granularity).
intrinsic("mutex_pco", indices=[MUTEX_ID_PCO, MUTEX_OP_PCO])
# depthf_pco(depth value)
# Perform an ISP depth feedback operation.
intrinsic("depthf_pco", src_comp=[1], bit_sizes=[32])
# isp_feedback_pco(discard condition/undef, depth value/undef)
# Perform an ISP feedback operation.
intrinsic("isp_feedback_pco", src_comp=[1, 1])
# Loads the valid mask.
intrinsic("load_savmsk_vm_pco", src_comp=[], dest_comp=1, indices=[], flags=[CAN_ELIMINATE, CAN_REORDER], bit_sizes=[32])

View file

@ -2927,6 +2927,9 @@ static inline bool pco_should_skip_pass(const char *pass)
/** Integer 5. */
#define pco_5 pco_ref_hwreg(5, PCO_REG_CLASS_CONST)
/** Integer 7. */
#define pco_7 pco_ref_hwreg(7, PCO_REG_CLASS_CONST)
/** Integer 31. */
#define pco_31 pco_ref_hwreg(31, PCO_REG_CLASS_CONST)

View file

@ -36,6 +36,8 @@ struct pfo_state {
nir_def *discard_cond_reg;
bool has_discards;
bool has_sample_check;
/* nir_instr *terminate; */
pco_fs_data *fs; /** Fragment-specific data. */
@ -922,6 +924,7 @@ static nir_def *lower_pfo(nir_builder *b, nir_instr *instr, void *cb_data)
nir_def *cond = nir_ieq_imm(b, smp_msk, 0);
state->has_discards = true;
state->has_sample_check = true;
nir_def *val = nir_load_reg(b, state->discard_cond_reg);
val = nir_ior(b, val, cond);
nir_store_reg(b, val, state->discard_cond_reg);
@ -958,7 +961,8 @@ static bool lower_isp_fb(nir_builder *b, struct pfo_state *state)
{
bool has_depth_feedback = !!state->depth_feedback_src;
assert(!(has_depth_feedback && state->has_discards));
if (!has_depth_feedback && !state->has_discards)
return false;
/* Insert isp feedback instruction before the first store,
* or if there are no stores, at the end.
@ -970,14 +974,16 @@ static bool lower_isp_fb(nir_builder *b, struct pfo_state *state)
b->cursor = nir_after_block(
nir_impl_last_block(nir_shader_get_entrypoint(b->shader)));
if (has_depth_feedback) {
nir_depthf_pco(b, state->depth_feedback_src);
state->fs->uses.depth_feedback = true;
} else if (state->has_discards) {
nir_def *val = nir_load_reg(b, state->discard_cond_reg);
nir_terminate_if(b, val);
state->fs->uses.discard = true;
}
nir_def *undef = nir_undef(b, 1, 32);
nir_isp_feedback_pco(
b,
state->has_discards ? nir_i2b(b, nir_load_reg(b, state->discard_cond_reg))
: undef,
state->depth_feedback_src ? state->depth_feedback_src : undef);
state->fs->uses.discard = state->has_discards;
state->fs->uses.depth_feedback = has_depth_feedback;
return true;
}

View file

@ -1316,33 +1316,39 @@ static pco_instr *trans_intr(trans_ctx *tctx, nir_intrinsic_instr *intr)
instr = lower_alphatst(tctx, dest, src[0], src[1], src[2]);
break;
case nir_intrinsic_depthf_pco:
case nir_intrinsic_isp_feedback_pco: {
assert(tctx->stage == MESA_SHADER_FRAGMENT);
if (tctx->shader->data.fs.uses.depth_feedback &&
!tctx->shader->data.fs.uses.early_frag) {
instr = pco_depthf(&tctx->b, pco_ref_drc(PCO_DRC_0), src[0]);
} else {
return NULL;
bool does_discard = !nir_src_is_undef(intr->src[0]);
bool does_depthf = !nir_src_is_undef(intr->src[1]);
assert(does_depthf == (tctx->shader->data.fs.uses.depth_feedback &&
!tctx->shader->data.fs.uses.early_frag));
if (does_discard) {
pco_tstz(&tctx->b,
pco_ref_null(),
pco_ref_pred(PCO_PRED_P0),
src[0],
.tst_type_main = PCO_TST_TYPE_MAIN_U32);
}
break;
case nir_intrinsic_terminate:
instr = pco_alphaf(&tctx->b,
pco_ref_null(),
pco_ref_drc(PCO_DRC_0),
pco_zero,
pco_zero,
pco_zero);
break;
instr = does_depthf ? pco_depthf(&tctx->b,
pco_ref_drc(PCO_DRC_0),
src[1],
.olchk = true)
: pco_alphaf(&tctx->b,
pco_ref_null(),
pco_ref_drc(PCO_DRC_0),
pco_zero,
pco_zero,
pco_7,
.olchk = true);
if (does_discard)
pco_instr_set_exec_cnd(instr, PCO_EXEC_CND_E1_Z1);
case nir_intrinsic_terminate_if:
instr = pco_alphaf(&tctx->b,
pco_ref_null(),
pco_ref_drc(PCO_DRC_0),
pco_zero,
src[0],
pco_2);
break;
}
case nir_intrinsic_mutex_pco:
instr = pco_mutex(&tctx->b,