From c002cb91dc462c2b425274fe17c8cb6089421a27 Mon Sep 17 00:00:00 2001 From: Simon Perretta Date: Fri, 9 May 2025 12:08:06 +0100 Subject: [PATCH] pco: support accessing shareds/coeffs >= 256 Signed-off-by: Simon Perretta Acked-by: Erik Faye-Lund Part-of: --- src/imagination/.clang-format | 2 + src/imagination/pco/pco_internal.h | 22 ++++++-- src/imagination/pco/pco_legalize.c | 74 +++++++++++++++++++++++++-- src/imagination/vulkan/pvr_pipeline.c | 5 -- 4 files changed, 91 insertions(+), 12 deletions(-) diff --git a/src/imagination/.clang-format b/src/imagination/.clang-format index 6ce6482ad05..dac7568150f 100644 --- a/src/imagination/.clang-format +++ b/src/imagination/.clang-format @@ -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', diff --git a/src/imagination/pco/pco_internal.h b/src/imagination/pco/pco_internal.h index a336541d64a..4e048720d5a 100644 --- a/src/imagination/pco/pco_internal.h +++ b/src/imagination/pco/pco_internal.h @@ -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){ diff --git a/src/imagination/pco/pco_legalize.c b/src/imagination/pco/pco_legalize.c index 3654e2db099..430aafeae34 100644 --- a/src/imagination/pco/pco_legalize.c +++ b/src/imagination/pco/pco_legalize.c @@ -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; } diff --git a/src/imagination/vulkan/pvr_pipeline.c b/src/imagination/vulkan/pvr_pipeline.c index 3516eaa24f2..691a490cf0e 100644 --- a/src/imagination/vulkan/pvr_pipeline.c +++ b/src/imagination/vulkan/pvr_pipeline.c @@ -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. */