From ac41e9dd18eeb8a1dc8c8dd0d50649ca4739dbce Mon Sep 17 00:00:00 2001 From: Simon Perretta Date: Tue, 4 Feb 2025 17:43:44 +0000 Subject: [PATCH] pco: support combined depth/discard isp feedback Signed-off-by: Simon Perretta Acked-by: Erik Faye-Lund Part-of: --- src/compiler/nir/nir_intrinsics.py | 6 ++-- src/imagination/pco/pco_internal.h | 3 ++ src/imagination/pco/pco_nir_pvfio.c | 24 ++++++++------ src/imagination/pco/pco_trans_nir.c | 50 ++++++++++++++++------------- 4 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 55203d482b6..14d6950d9f6 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -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]) diff --git a/src/imagination/pco/pco_internal.h b/src/imagination/pco/pco_internal.h index 59514fe27cc..0b4b8c231e1 100644 --- a/src/imagination/pco/pco_internal.h +++ b/src/imagination/pco/pco_internal.h @@ -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) diff --git a/src/imagination/pco/pco_nir_pvfio.c b/src/imagination/pco/pco_nir_pvfio.c index 6e45b9aeda5..7012854f21b 100644 --- a/src/imagination/pco/pco_nir_pvfio.c +++ b/src/imagination/pco/pco_nir_pvfio.c @@ -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; } diff --git a/src/imagination/pco/pco_trans_nir.c b/src/imagination/pco/pco_trans_nir.c index 58112e0de24..b9953233ad8 100644 --- a/src/imagination/pco/pco_trans_nir.c +++ b/src/imagination/pco/pco_trans_nir.c @@ -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,