mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 00:58:05 +02:00
pvr, pco: basic depth feedback/discard/terminate support
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:
parent
7a5511d592
commit
486ca8bbc1
9 changed files with 179 additions and 4 deletions
|
|
@ -2724,3 +2724,7 @@ 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])
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ typedef struct _pco_fs_data {
|
|||
bool pntc; /** Whether the shader uses point coord. */
|
||||
bool phase_change; /** Whether the shader does a phase change. */
|
||||
bool fbfetch; /** Whether the shader fetches from the framebuffer. */
|
||||
bool depth_feedback;
|
||||
bool discard;
|
||||
} uses;
|
||||
} pco_fs_data;
|
||||
|
||||
|
|
|
|||
|
|
@ -2921,6 +2921,12 @@ static inline bool pco_should_skip_pass(const char *pass)
|
|||
/** Integer one. */
|
||||
#define pco_one pco_ref_hwreg(1, PCO_REG_CLASS_CONST)
|
||||
|
||||
/** Integer 2. */
|
||||
#define pco_2 pco_ref_hwreg(2, PCO_REG_CLASS_CONST)
|
||||
|
||||
/** Integer 5. */
|
||||
#define pco_5 pco_ref_hwreg(5, PCO_REG_CLASS_CONST)
|
||||
|
||||
/** Integer 31. */
|
||||
#define pco_31 pco_ref_hwreg(31, PCO_REG_CLASS_CONST)
|
||||
|
||||
|
|
|
|||
|
|
@ -1424,6 +1424,21 @@ encode_map(O_ALPHATST,
|
|||
op_ref_maps=[('backend', [['p0', '_']], ['drc', 's0', 's1', 's2'])]
|
||||
)
|
||||
|
||||
encode_map(O_ALPHAF,
|
||||
encodings=[
|
||||
(I_VISTEST_ATST, [
|
||||
('pwen', ('!pco_ref_is_null', DEST(0))),
|
||||
('ifb', False)
|
||||
])
|
||||
],
|
||||
op_ref_maps=[('backend', [['p0', '_']], ['drc', 's0', 's1', 's2'])]
|
||||
)
|
||||
|
||||
encode_map(O_DEPTHF,
|
||||
encodings=[(I_VISTEST_DEPTHF, [])],
|
||||
op_ref_maps=[('backend', [], ['drc', 'w0'])]
|
||||
)
|
||||
|
||||
encode_map(O_BBYP0BM,
|
||||
encodings=[
|
||||
(I_PHASE0_SRC, [
|
||||
|
|
@ -2814,6 +2829,44 @@ group_map(O_ALPHATST,
|
|||
]
|
||||
)
|
||||
|
||||
group_map(O_ALPHAF,
|
||||
hdr=(I_IGRP_HDR_MAIN, [
|
||||
('oporg', 'be'),
|
||||
('olchk', OM_OLCHK),
|
||||
('w1p', False),
|
||||
('w0p', False),
|
||||
('cc', OM_EXEC_CND),
|
||||
('end', OM_END),
|
||||
('atom', OM_ATOM),
|
||||
('rpt', 1)
|
||||
]),
|
||||
enc_ops=[('backend', O_ALPHAF)],
|
||||
srcs=[
|
||||
('s[0]', ('backend', SRC(1)), 's0'),
|
||||
('s[1]', ('backend', SRC(2)), 's1'),
|
||||
('s[2]', ('backend', SRC(3)), 's2'),
|
||||
]
|
||||
)
|
||||
|
||||
group_map(O_DEPTHF,
|
||||
hdr=(I_IGRP_HDR_MAIN, [
|
||||
('oporg', 'be'),
|
||||
('olchk', OM_OLCHK),
|
||||
('w1p', False),
|
||||
('w0p', False),
|
||||
('cc', OM_EXEC_CND),
|
||||
('end', OM_END),
|
||||
('atom', OM_ATOM),
|
||||
('rpt', 1)
|
||||
]),
|
||||
enc_ops=[('backend', O_DEPTHF)],
|
||||
srcs=[('s[0]', ('backend', SRC(1)), 'w0')],
|
||||
iss=[
|
||||
('is[0]', 's0'),
|
||||
('is[4]', 'fte')
|
||||
]
|
||||
)
|
||||
|
||||
group_map(O_MOVI32,
|
||||
hdr=(I_IGRP_HDR_BITWISE, [
|
||||
('opcnt', 'p0'),
|
||||
|
|
|
|||
|
|
@ -720,6 +720,11 @@ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data)
|
|||
NIR_PASS(_, nir, nir_lower_blend, &data->fs.blend_opts);
|
||||
nir->info.fs.uses_sample_shading = backup;
|
||||
|
||||
nir_opt_peephole_select_options peep_opts = {
|
||||
.limit = 0,
|
||||
.discard_ok = true,
|
||||
};
|
||||
NIR_PASS(_, nir, nir_opt_peephole_select, &peep_opts);
|
||||
NIR_PASS(_, nir, pco_nir_pfo, &data->fs);
|
||||
} else if (nir->info.stage == MESA_SHADER_VERTEX) {
|
||||
NIR_PASS(_,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,15 @@
|
|||
struct pfo_state {
|
||||
struct util_dynarray loads; /** List of fragment loads. */
|
||||
struct util_dynarray stores; /** List of fragment stores. */
|
||||
|
||||
/* Src for depth feedback (NULL if unused). */
|
||||
nir_def *depth_feedback_src;
|
||||
|
||||
nir_def *discard_cond_reg;
|
||||
bool has_discards;
|
||||
|
||||
/* nir_instr *terminate; */
|
||||
|
||||
pco_fs_data *fs; /** Fragment-specific data. */
|
||||
};
|
||||
|
||||
|
|
@ -858,6 +867,8 @@ static bool is_pfo(const nir_instr *instr, UNUSED const void *cb_data)
|
|||
switch (intr->intrinsic) {
|
||||
case nir_intrinsic_store_output:
|
||||
case nir_intrinsic_load_output:
|
||||
case nir_intrinsic_terminate:
|
||||
case nir_intrinsic_terminate_if:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
|
@ -881,12 +892,37 @@ static nir_def *lower_pfo(nir_builder *b, nir_instr *instr, void *cb_data)
|
|||
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
||||
|
||||
switch (intr->intrinsic) {
|
||||
case nir_intrinsic_store_output:
|
||||
return lower_pfo_store(b, intr, state);
|
||||
case nir_intrinsic_store_output: {
|
||||
nir_io_semantics sem = nir_intrinsic_io_semantics(intr);
|
||||
if (sem.location >= FRAG_RESULT_DATA0)
|
||||
return lower_pfo_store(b, intr, state);
|
||||
|
||||
if (sem.location == FRAG_RESULT_DEPTH) {
|
||||
assert(!state->depth_feedback_src);
|
||||
state->depth_feedback_src = nir_mov(b, intr->src[0].ssa);
|
||||
|
||||
return NIR_LOWER_INSTR_PROGRESS_REPLACE;
|
||||
}
|
||||
|
||||
UNREACHABLE("");
|
||||
}
|
||||
|
||||
case nir_intrinsic_load_output:
|
||||
return lower_pfo_load(b, intr, state);
|
||||
|
||||
case nir_intrinsic_terminate:
|
||||
state->has_discards = true;
|
||||
nir_store_reg(b, nir_imm_true(b), state->discard_cond_reg);
|
||||
return NIR_LOWER_INSTR_PROGRESS_REPLACE;
|
||||
|
||||
case nir_intrinsic_terminate_if: {
|
||||
state->has_discards = true;
|
||||
nir_def *val = nir_load_reg(b, state->discard_cond_reg);
|
||||
val = nir_ior(b, val, intr->src[0].ssa);
|
||||
nir_store_reg(b, val, state->discard_cond_reg);
|
||||
return NIR_LOWER_INSTR_PROGRESS_REPLACE;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -894,6 +930,34 @@ static nir_def *lower_pfo(nir_builder *b, nir_instr *instr, void *cb_data)
|
|||
return false;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
/* Insert isp feedback instruction before the first store,
|
||||
* or if there are no stores, at the end.
|
||||
*/
|
||||
if (state->stores.size > 0)
|
||||
b->cursor = nir_before_instr(
|
||||
&(*(nir_intrinsic_instr **)util_dynarray_begin(&state->stores))->instr);
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sink_outputs(nir_shader *shader, struct pfo_state *state)
|
||||
{
|
||||
bool progress = false;
|
||||
|
|
@ -922,13 +986,24 @@ bool pco_nir_pfo(nir_shader *shader, pco_fs_data *fs)
|
|||
{
|
||||
assert(shader->info.stage == MESA_SHADER_FRAGMENT);
|
||||
|
||||
struct pfo_state state = { .fs = fs };
|
||||
nir_builder b = nir_builder_create(nir_shader_get_entrypoint(shader));
|
||||
b.cursor =
|
||||
nir_before_block(nir_start_block(nir_shader_get_entrypoint(shader)));
|
||||
|
||||
struct pfo_state state = {
|
||||
.fs = fs,
|
||||
.discard_cond_reg = nir_decl_reg(&b, 1, 1, 0),
|
||||
};
|
||||
nir_store_reg(&b, nir_imm_false(&b), state.discard_cond_reg);
|
||||
|
||||
util_dynarray_init(&state.loads, NULL);
|
||||
util_dynarray_init(&state.stores, NULL);
|
||||
|
||||
bool progress =
|
||||
nir_shader_lower_instructions(shader, is_pfo, lower_pfo, &state);
|
||||
|
||||
progress |= lower_isp_fb(&b, &state);
|
||||
|
||||
progress |= sink_outputs(shader, &state);
|
||||
|
||||
util_dynarray_fini(&state.stores);
|
||||
|
|
|
|||
|
|
@ -390,6 +390,9 @@ O_SMP = hw_op('smp', OM_ALU_RPT1 + [OM_DIM, OM_PROJ, OM_FCNORM, OM_NNCOORDS,
|
|||
|
||||
O_ALPHATST = hw_op('alphatst', OM_ALU_RPT1, 1, 4)
|
||||
|
||||
O_ALPHAF = hw_op('alphaf', OM_ALU_RPT1, 1, 4)
|
||||
O_DEPTHF = hw_op('depthf', OM_ALU_RPT1, 0, 2)
|
||||
|
||||
## Bitwise.
|
||||
O_MOVI32 = hw_op('movi32', OM_ALU, 1, 1)
|
||||
|
||||
|
|
|
|||
|
|
@ -1300,6 +1300,28 @@ 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:
|
||||
instr = pco_depthf(&tctx->b, pco_ref_drc(PCO_DRC_0), src[0]);
|
||||
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;
|
||||
|
||||
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,
|
||||
pco_ref_imm8(nir_intrinsic_mutex_id_pco(intr)),
|
||||
|
|
|
|||
|
|
@ -1223,7 +1223,12 @@ static void pvr_fragment_state_save(struct pvr_graphics_pipeline *gfx_pipeline,
|
|||
memcpy(&gfx_pipeline->fs_data, shader_data, sizeof(*shader_data));
|
||||
|
||||
/* TODO: add selection for other values of pass type and sample rate. */
|
||||
if (shader_data->fs.uses.fbfetch)
|
||||
|
||||
if (shader_data->fs.uses.depth_feedback)
|
||||
fragment_state->pass_type = ROGUE_TA_PASSTYPE_DEPTH_FEEDBACK;
|
||||
else if (shader_data->fs.uses.discard)
|
||||
fragment_state->pass_type = ROGUE_TA_PASSTYPE_PUNCH_THROUGH;
|
||||
else if (shader_data->fs.uses.fbfetch)
|
||||
fragment_state->pass_type = ROGUE_TA_PASSTYPE_TRANSLUCENT;
|
||||
else
|
||||
fragment_state->pass_type = ROGUE_TA_PASSTYPE_OPAQUE;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue