pco: support accessing shareds/coeffs >= 256

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-05-09 12:08:06 +01:00 committed by Marge Bot
parent 22a4fb7f27
commit c002cb91dc
4 changed files with 91 additions and 12 deletions

View file

@ -268,6 +268,7 @@ ForEachMacros: [
'pco_foreach_igrp_in_func',
'pco_foreach_instr_dest',
'pco_foreach_instr_dest_from',
'pco_foreach_instr_dest_hwreg',
'pco_foreach_instr_dest_ssa',
'pco_foreach_instr_dest_ssa_from',
'pco_foreach_instr_dest_vreg',
@ -288,6 +289,7 @@ ForEachMacros: [
'pco_foreach_instr_in_igrp_rev',
'pco_foreach_instr_src',
'pco_foreach_instr_src_from',
'pco_foreach_instr_src_hwreg',
'pco_foreach_instr_src_ssa',
'pco_foreach_instr_src_ssa_from',
'pco_foreach_instr_src_vreg',

View file

@ -699,6 +699,10 @@ PCO_DEFINE_CAST(pco_cf_node_as_func,
pco_foreach_instr_dest (pdest, instr) \
if (pco_ref_is_vreg(*pdest) || pco_ref_is_ssa(*pdest))
#define pco_foreach_instr_dest_hwreg(pdest, instr) \
pco_foreach_instr_dest (pdest, instr) \
if (pco_ref_is_hwreg(*pdest))
#define pco_foreach_instr_src(psrc, instr) \
for (pco_ref *psrc = &instr->src[0]; psrc < &instr->src[instr->num_srcs]; \
++psrc)
@ -723,6 +727,10 @@ PCO_DEFINE_CAST(pco_cf_node_as_func,
pco_foreach_instr_src (psrc, instr) \
if (pco_ref_is_vreg(*psrc) || pco_ref_is_ssa(*psrc))
#define pco_foreach_instr_src_hwreg(psrc, instr) \
pco_foreach_instr_src (psrc, instr) \
if (pco_ref_is_hwreg(*psrc))
#define pco_cf_node_head(list) exec_node_data_head(pco_cf_node, list, node)
#define pco_cf_node_tail(list) exec_node_data_tail(pco_cf_node, list, node)
#define pco_cf_node_next(cf_node) \
@ -1777,6 +1785,17 @@ static inline bool pco_ref_is_reg(pco_ref ref)
return ref.type == PCO_REF_TYPE_REG;
}
/**
* \brief Returns whether a reference is a hardware register.
*
* \param[in] ref PCO reference.
* \return True if the reference is a hardware register.
*/
static inline bool pco_ref_is_hwreg(pco_ref ref)
{
return ref.type == PCO_REF_TYPE_REG && ref.reg_class != PCO_REG_CLASS_VIRT;
}
/**
* \brief Returns whether a reference is an index register.
*
@ -1979,7 +1998,6 @@ static inline unsigned pco_ref_get_reg_index(pco_ref ref)
assert(pco_ref_is_reg(ref) || pco_ref_is_idx_reg(ref));
unsigned index = pco_ref_is_idx_reg(ref) ? ref.idx_reg.offset : ref.val;
assert(index < 256);
return index;
}
@ -2289,7 +2307,6 @@ pco_ref_ssa_vreg(ASSERTED pco_func *func, pco_ref ref, unsigned bits)
static inline pco_ref
pco_ref_hwreg_vec(unsigned index, enum pco_reg_class reg_class, unsigned chans)
{
assert(index < 256);
assert(reg_class != PCO_REG_CLASS_VIRT);
return (pco_ref){
@ -2363,7 +2380,6 @@ static inline pco_ref pco_ref_hwreg_idx_vec(unsigned num,
enum pco_reg_class reg_class,
unsigned chans)
{
assert(offset < 256);
assert(reg_class != PCO_REG_CLASS_VIRT);
return (pco_ref){

View file

@ -333,6 +333,69 @@ static bool legalize_pseudo(pco_instr *instr)
return false;
}
static bool try_legalize_large_hwreg_offsets(pco_instr *instr,
const struct pco_op_info *info)
{
unsigned large_hwreg_count = 0;
pco_ref *large_hwregs[_PCO_OP_MAX_SRCS + _PCO_OP_MAX_DESTS] = { 0 };
enum pco_reg_class hwreg_class = ~0;
unsigned min_large_offset = ~0;
ASSERTED unsigned max_large_offset = 0;
/* Check dests. */
pco_foreach_instr_dest_hwreg (pdest, instr) {
if (pco_ref_get_reg_index(*pdest) < 256)
continue;
large_hwregs[large_hwreg_count++] = pdest;
assert(hwreg_class == ~0 || hwreg_class == pco_ref_get_reg_class(*pdest));
hwreg_class = pco_ref_get_reg_class(*pdest);
min_large_offset = MIN2(min_large_offset, pco_ref_get_reg_index(*pdest));
max_large_offset = MAX2(max_large_offset, pco_ref_get_reg_index(*pdest));
}
/* Check srcs. */
pco_foreach_instr_src_hwreg (psrc, instr) {
if (pco_ref_get_reg_index(*psrc) < 256)
continue;
large_hwregs[large_hwreg_count++] = psrc;
assert(hwreg_class == ~0 || hwreg_class == pco_ref_get_reg_class(*psrc));
hwreg_class = pco_ref_get_reg_class(*psrc);
min_large_offset = MIN2(min_large_offset, pco_ref_get_reg_index(*psrc));
max_large_offset = MAX2(max_large_offset, pco_ref_get_reg_index(*psrc));
}
if (!large_hwreg_count)
return false;
/* We'd need more than one indexed register to support this. */
assert((max_large_offset - min_large_offset) < 256);
pco_builder b =
pco_builder_create(instr->parent_func, pco_cursor_before_instr(instr));
unsigned idx_reg_num = 0;
pco_ref idx_reg =
pco_ref_hwreg_idx(idx_reg_num, idx_reg_num, PCO_REG_CLASS_INDEX);
pco_ref imm = pco_ref_imm32(min_large_offset);
pco_movi32(&b, idx_reg, imm, .exec_cnd = pco_instr_get_exec_cnd(instr));
/* Remap the offset for each large hwreg and replace it with the indexed
* register.
*/
for (unsigned u = 0; u < large_hwreg_count; ++u) {
*large_hwregs[u] = pco_ref_offset(*large_hwregs[u], -min_large_offset);
*large_hwregs[u] = pco_ref_hwreg_idx_from(idx_reg_num, *large_hwregs[u]);
}
return true;
}
/**
* \brief Try to legalizes an instruction.
*
@ -344,11 +407,14 @@ static bool try_legalize(pco_instr *instr)
const struct pco_op_info *info = &pco_op_info[instr->op];
bool progress = false;
/* Skip pseudo instructions. */
if (info->type == PCO_OP_TYPE_PSEUDO)
return legalize_pseudo(instr);
progress |= try_legalize_large_hwreg_offsets(instr, info);
progress |= try_legalize_src_mappings(instr, info);
/* Skip pseudo instructions. */
if (info->type == PCO_OP_TYPE_PSEUDO) {
progress |= legalize_pseudo(instr);
} else {
progress |= try_legalize_src_mappings(instr, info);
}
return progress;
}

View file

@ -2392,8 +2392,6 @@ static void pvr_setup_descriptors(pco_data *data,
data->common.shareds += ROGUE_NUM_TEXSTATE_DWORDS;
}
assert(data->common.shareds < 256);
}
static void
@ -2506,9 +2504,6 @@ static void pvr_postprocess_shader_data(pco_data *data,
pvr_setup_descriptors(data, nir, layout);
/* TODO: common things, like large constants being put into shareds. */
assert(data->common.shareds < 256);
assert(data->common.coeffs < 256);
}
/* Compiles and uploads shaders and PDS programs. */