Module: Mesa Branch: main Commit: bdbd69edb81bf044b4467072548011a08734c8b1 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=bdbd69edb81bf044b4467072548011a08734c8b1
Author: Simon Perretta <[email protected]> Date: Sun Feb 12 15:26:06 2023 +0000 pvr: Add support for validating modifier combos Signed-off-by: Simon Perretta <[email protected]> Acked-by: Frank Binns <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21474> --- src/imagination/.clang-format | 1 + src/imagination/rogue/rogue.h | 60 +++++++++++++++-------- src/imagination/rogue/rogue_encode.c | 4 +- src/imagination/rogue/rogue_info.c | 80 ++++++++++++++++++++++++------- src/imagination/rogue/rogue_validate.c | 88 ++++++++++++++++++++++++++++++++-- 5 files changed, 191 insertions(+), 42 deletions(-) diff --git a/src/imagination/.clang-format b/src/imagination/.clang-format index abb446037e2..2021ccfb223 100644 --- a/src/imagination/.clang-format +++ b/src/imagination/.clang-format @@ -251,6 +251,7 @@ ForEachMacros: [ 'rogue_foreach_instr_in_shader_safe', 'rogue_foreach_instr_in_shader_rev', 'rogue_foreach_instr_in_shader_safe_rev', + 'rogue_foreach_mod_in_set', 'rogue_foreach_reg', 'rogue_foreach_reg_safe', 'rogue_foreach_reg_use', diff --git a/src/imagination/rogue/rogue.h b/src/imagination/rogue/rogue.h index 4ff55bfbcc8..36a61805c41 100644 --- a/src/imagination/rogue/rogue.h +++ b/src/imagination/rogue/rogue.h @@ -348,15 +348,16 @@ enum rogue_instr_phase { ROGUE_INSTR_PHASE_INVALID = ~0, }; -#define rogue_foreach_phase_in_set(p, phases) \ - for (uint64_t __phases = (phases), p; \ - ((p) = ffsll(__phases) - 1, __phases); \ - __phases &= ~(1ull << (p))) +/* TODO: put into bitscan.h */ +#define u_foreach_bit64_rev(b, dword) \ + for (uint64_t __dword = (dword), b; \ + ((b) = util_last_bit64(__dword) - 1, __dword); \ + __dword &= ~(1ull << (b))) -#define rogue_foreach_phase_in_set_rev(p, phases) \ - for (uint64_t __phases = (phases), p; \ - ((p) = util_last_bit64(__phases) - 1, __phases); \ - __phases &= ~(1ull << (p))) +#define rogue_foreach_phase_in_set(p, phases) u_foreach_bit64(p, phases) +#define rogue_foreach_phase_in_set_rev(p, phases) u_foreach_bit64_rev(p, phases) + +#define rogue_foreach_mod_in_set(m, mods) u_foreach_bit64(m, mods) /** Rogue basic block. */ typedef struct rogue_block { @@ -1046,6 +1047,8 @@ enum rogue_alu_op_mod { typedef struct rogue_alu_op_mod_info { const char *str; + uint64_t exclude; /* Can't use this op mod with any of these. */ + uint64_t require; /* Required op mods for this to be used (OR). */ } rogue_alu_op_mod_info; extern const rogue_alu_op_mod_info @@ -1113,6 +1116,8 @@ enum rogue_ctrl_op_mod { typedef struct rogue_ctrl_op_mod_info { const char *str; + uint64_t exclude; /* Can't use this op mod with any of these. */ + uint64_t require; /* Required op mods for this to be used (OR). */ } rogue_ctrl_op_mod_info; extern const rogue_ctrl_op_mod_info @@ -1383,7 +1388,6 @@ typedef struct rogue_backend_op_info { extern const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT]; -/* TODO: Some of these may not be used together; express that in op mod info. */ enum rogue_backend_op_mod { /* In order of priority */ ROGUE_BACKEND_OP_MOD_PROJ, /* Projection (send T co-ordinate). */ @@ -1440,6 +1444,8 @@ enum rogue_backend_op_mod { typedef struct rogue_backend_op_mod_info { const char *str; + uint64_t exclude; /* Can't use this op mod with any of these. */ + uint64_t require; /* Required op mods for this to be used (OR). */ } rogue_backend_op_mod_info; extern const rogue_backend_op_mod_info @@ -1531,6 +1537,25 @@ enum rogue_bitwise_op { ROGUE_BITWISE_OP_COUNT, }; +enum rogue_bitwise_op_mod { + /* In order of priority */ + ROGUE_BITWISE_OP_MOD_TWB, /* Top word break. */ + ROGUE_BITWISE_OP_MOD_PWB, /* Partial word break. */ + ROGUE_BITWISE_OP_MOD_MTB, /* Mask top break. */ + ROGUE_BITWISE_OP_MOD_FTB, /* Find top break. */ + + ROGUE_BITWISE_OP_MOD_COUNT, +}; + +typedef struct rogue_bitwise_op_mod_info { + const char *str; + uint64_t exclude; /* Can't use this op mod with any of these. */ + uint64_t require; /* Required op mods for this to be used (OR). */ +} rogue_bitwise_op_mod_info; + +extern const rogue_bitwise_op_mod_info + rogue_bitwise_op_mod_infos[ROGUE_BITWISE_OP_MOD_COUNT]; + #define ROGUE_BITWISE_OP_MAX_SRCS 7 #define ROGUE_BITWISE_OP_MAX_DSTS 2 @@ -1586,21 +1611,18 @@ typedef struct rogue_bitwise_instr { rogue_src_use src_use[ROGUE_BITWISE_OP_MAX_SRCS]; } rogue_bitwise_instr; -#if 0 -static inline -void -rogue_set_bitwise_op_mod(rogue_bitwise_instr *bitwise, enum rogue_bitwise_op_mod mod) +static inline void rogue_set_bitwise_op_mod(rogue_bitwise_instr *bitwise, + enum rogue_bitwise_op_mod mod) { - bitwise->mod |= BITFIELD64_BIT(mod); + bitwise->mod |= BITFIELD64_BIT(mod); } -static inline -bool -rogue_bitwise_op_mod_is_set(const rogue_bitwise_instr *bitwise, enum rogue_bitwise_op_mod mod) +static inline bool +rogue_bitwise_op_mod_is_set(const rogue_bitwise_instr *bitwise, + enum rogue_bitwise_op_mod mod) { - return !!(bitwise->mod & BITFIELD64_BIT(mod)); + return !!(bitwise->mod & BITFIELD64_BIT(mod)); } -#endif /** * \brief Allocates and initializes a new bitwise instruction. diff --git a/src/imagination/rogue/rogue_encode.c b/src/imagination/rogue/rogue_encode.c index 598edac709e..e4a3cbdce95 100644 --- a/src/imagination/rogue/rogue_encode.c +++ b/src/imagination/rogue/rogue_encode.c @@ -289,7 +289,7 @@ static void rogue_encode_alu_instr(const rogue_alu_instr *alu, #undef DM #undef SM -#define OM(op_mod) BITFIELD64_BIT(ROGUE_BACKEND_OP_MOD_##op_mod) +#define OM(op_mod) ROGUE_BACKEND_OP_MOD_##op_mod static void rogue_encode_backend_instr(const rogue_backend_instr *backend, unsigned instr_size, rogue_instr_encoding *instr_encoding) @@ -471,7 +471,7 @@ static void rogue_encode_backend_instr(const rogue_backend_instr *backend, rogue_backend_op_mod_is_set(backend, OM(PPLOD)); } - if (instr_size >= 3) { + if (instr_size > 3) { instr_encoding->backend.dma.smp.extb = 1; instr_encoding->backend.dma.smp.w = diff --git a/src/imagination/rogue/rogue_info.c b/src/imagination/rogue/rogue_info.c index 6d0212fcb2f..80ea1e1d1f6 100644 --- a/src/imagination/rogue/rogue_info.c +++ b/src/imagination/rogue/rogue_info.c @@ -282,8 +282,11 @@ const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT] = { [1] = T(REGARRAY), [2] = T(VAL), }, + .dst_stride = { + [0] = ~0U, + }, .src_stride = { - [1] = 3, + [1] = ~0U, }, }, [ROGUE_BACKEND_OP_FITRP_PIXEL] = { .str = "fitrp.pixel", .num_dsts = 1, .num_srcs = 4, @@ -318,6 +321,15 @@ const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT] = { [4] = T(REG) | T(IO), [5] = T(VAL), }, + /* TODO: This may depend on the other options set. */ + .src_stride = { + [1] = 3, + [2] = ~0U, + [3] = 3, + }, + .dst_stride = { + [0] = ~0U, + }, }, [ROGUE_BACKEND_OP_SMP2D] = { .str = "smp2d", .num_dsts = 1, .num_srcs = 6, .phase_io = { .dst[0] = IO(S4), .src[1] = IO(S0), .src[2] = IO(S1), .src[3] = IO(S2), }, @@ -336,6 +348,15 @@ const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT] = { [4] = T(REG) | T(IO), [5] = T(VAL), }, + /* TODO: This may depend on the other options set. */ + .src_stride = { + [1] = 3, + [2] = ~0U, + [3] = 3, + }, + .dst_stride = { + [0] = ~0U, + }, }, [ROGUE_BACKEND_OP_SMP3D] = { .str = "smp3d", .num_dsts = 1, .num_srcs = 6, .phase_io = { .dst[0] = IO(S4), .src[1] = IO(S0), .src[2] = IO(S1), .src[3] = IO(S2), }, @@ -354,6 +375,15 @@ const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT] = { [4] = T(REG) | T(IO), [5] = T(VAL), }, + /* TODO: This may depend on the other options set. */ + .src_stride = { + [1] = 3, + [2] = ~0U, + [3] = 3, + }, + .dst_stride = { + [0] = ~0U, + }, }, }; #undef B @@ -361,36 +391,37 @@ const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT] = { #undef OM #undef IO +#define OM(op_mod) BITFIELD64_BIT(ROGUE_BACKEND_OP_MOD_##op_mod) const rogue_backend_op_mod_info rogue_backend_op_mod_infos[ROGUE_BACKEND_OP_MOD_COUNT] = { [ROGUE_BACKEND_OP_MOD_PROJ] = { .str = "proj", }, [ROGUE_BACKEND_OP_MOD_FCNORM] = { .str = "fcnorm", }, [ROGUE_BACKEND_OP_MOD_NNCOORDS] = { .str = "nncoords", }, - [ROGUE_BACKEND_OP_MOD_BIAS] = { .str = "bias", }, - [ROGUE_BACKEND_OP_MOD_REPLACE] = { .str = "replace", }, - [ROGUE_BACKEND_OP_MOD_GRADIENT] = { .str = "gradient", }, + [ROGUE_BACKEND_OP_MOD_BIAS] = { .str = "bias", .exclude = OM(REPLACE) | OM(GRADIENT) }, + [ROGUE_BACKEND_OP_MOD_REPLACE] = { .str = "replace", .exclude = OM(BIAS) | OM(GRADIENT) }, + [ROGUE_BACKEND_OP_MOD_GRADIENT] = { .str = "gradient", .exclude = OM(BIAS) | OM(REPLACE) }, - [ROGUE_BACKEND_OP_MOD_PPLOD] = { .str = "pplod", }, + [ROGUE_BACKEND_OP_MOD_PPLOD] = { .str = "pplod", .require = OM(BIAS) | OM(REPLACE) }, [ROGUE_BACKEND_OP_MOD_TAO] = { .str = "tao", }, [ROGUE_BACKEND_OP_MOD_SOO] = { .str = "soo", }, [ROGUE_BACKEND_OP_MOD_SNO] = { .str = "sno", }, [ROGUE_BACKEND_OP_MOD_WRT] = { .str = "wrt", }, - [ROGUE_BACKEND_OP_MOD_DATA] = { .str = "data", }, - [ROGUE_BACKEND_OP_MOD_INFO] = { .str = "info", }, - [ROGUE_BACKEND_OP_MOD_BOTH] = { .str = "both", }, + [ROGUE_BACKEND_OP_MOD_DATA] = { .str = "data", .exclude = OM(INFO) | OM(BOTH) }, + [ROGUE_BACKEND_OP_MOD_INFO] = { .str = "info", .exclude = OM(DATA) | OM(BOTH) }, + [ROGUE_BACKEND_OP_MOD_BOTH] = { .str = "both", .exclude = OM(DATA) | OM(INFO) }, - [ROGUE_BACKEND_OP_MOD_BYPASS] = { .str = "bypass", }, - [ROGUE_BACKEND_OP_MOD_FORCELINEFILL] = { .str = "forcelinefill", }, + [ROGUE_BACKEND_OP_MOD_BYPASS] = { .str = "bypass", .exclude = OM(FORCELINEFILL) | OM(WRITETHROUGH) | OM(WRITEBACK) | OM(LAZYWRITEBACK) }, + [ROGUE_BACKEND_OP_MOD_FORCELINEFILL] = { .str = "forcelinefill", .exclude = OM(BYPASS) | OM(WRITETHROUGH) | OM(WRITEBACK) | OM(LAZYWRITEBACK) }, - [ROGUE_BACKEND_OP_MOD_WRITETHROUGH] = { .str = "writethrough", }, - [ROGUE_BACKEND_OP_MOD_WRITEBACK] = { .str = "writeback", }, - [ROGUE_BACKEND_OP_MOD_LAZYWRITEBACK] = { .str = "lazywriteback", }, + [ROGUE_BACKEND_OP_MOD_WRITETHROUGH] = { .str = "writethrough", .exclude = OM(BYPASS) | OM(FORCELINEFILL) | OM(WRITEBACK) | OM(LAZYWRITEBACK) }, + [ROGUE_BACKEND_OP_MOD_WRITEBACK] = { .str = "writeback", .exclude = OM(BYPASS) | OM(FORCELINEFILL) | OM(WRITETHROUGH) | OM(LAZYWRITEBACK) }, + [ROGUE_BACKEND_OP_MOD_LAZYWRITEBACK] = { .str = "lazywriteback", .exclude = OM(BYPASS) | OM(FORCELINEFILL) | OM(WRITETHROUGH) | OM(WRITEBACK) }, - [ROGUE_BACKEND_OP_MOD_SLCBYPASS] = { .str = "slcbypass", }, - [ROGUE_BACKEND_OP_MOD_SLCWRITEBACK] = { .str = "slcwriteback", }, - [ROGUE_BACKEND_OP_MOD_SLCWRITETHROUGH] = { .str = "slcwritethrough", }, - [ROGUE_BACKEND_OP_MOD_SLCNOALLOC] = { .str = "slcnoalloc", }, + [ROGUE_BACKEND_OP_MOD_SLCBYPASS] = { .str = "slcbypass", .exclude = OM(SLCWRITEBACK) | OM(SLCWRITETHROUGH) | OM(SLCNOALLOC) }, + [ROGUE_BACKEND_OP_MOD_SLCWRITEBACK] = { .str = "slcwriteback", .exclude = OM(SLCBYPASS) | OM(SLCWRITETHROUGH) | OM(SLCNOALLOC) }, + [ROGUE_BACKEND_OP_MOD_SLCWRITETHROUGH] = { .str = "slcwritethrough", .exclude = OM(SLCBYPASS) | OM(SLCWRITEBACK) | OM(SLCNOALLOC) }, + [ROGUE_BACKEND_OP_MOD_SLCNOALLOC] = { .str = "slcnoalloc", .exclude = OM(SLCBYPASS) | OM(SLCWRITEBACK) | OM(SLCWRITETHROUGH) }, [ROGUE_BACKEND_OP_MOD_ARRAY] = { .str = "array", }, [ROGUE_BACKEND_OP_MOD_INTEGER] = { .str = "integer", }, @@ -400,6 +431,21 @@ const rogue_backend_op_mod_info rogue_backend_op_mod_infos[ROGUE_BACKEND_OP_MOD_ [ROGUE_BACKEND_OP_MOD_SAT] = { .str = "sat", }, }; +#undef OM + +#define OM(op_mod) BITFIELD64_BIT(ROGUE_BITWISE_OP_MOD_##op_mod) +const rogue_bitwise_op_mod_info + rogue_bitwise_op_mod_infos[ROGUE_BITWISE_OP_MOD_COUNT] = { + [ROGUE_BITWISE_OP_MOD_TWB] = { .str = "twb", + .exclude = OM(PWB) | OM(MTB) | OM(FTB) }, + [ROGUE_BITWISE_OP_MOD_PWB] = { .str = "pwb", + .exclude = OM(TWB) | OM(MTB) | OM(FTB) }, + [ROGUE_BITWISE_OP_MOD_MTB] = { .str = "mtb", + .exclude = OM(TWB) | OM(PWB) | OM(FTB) }, + [ROGUE_BITWISE_OP_MOD_FTB] = { .str = "ftb", + .exclude = OM(TWB) | OM(PWB) | OM(MTB) }, + }; +#undef OM #define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type) #define PH(type) ROGUE_INSTR_PHASE_##type diff --git a/src/imagination/rogue/rogue_validate.c b/src/imagination/rogue/rogue_validate.c index a0c351b9e60..e8f9d7b4caa 100644 --- a/src/imagination/rogue/rogue_validate.c +++ b/src/imagination/rogue/rogue_validate.c @@ -224,6 +224,23 @@ static void validate_src(rogue_validation_state *state, state->ctx.ref = NULL; } +static bool validate_alu_op_mod_combo(uint64_t mods) +{ + rogue_foreach_mod_in_set (mod, mods) { + const rogue_alu_op_mod_info *info = &rogue_alu_op_mod_infos[mod]; + + /* Check if any excluded op mods have been included. */ + if (info->exclude & mods) + return false; + + /* Check if any required op mods have been missed. */ + if (info->require && !(info->require & mods)) + return false; + } + + return true; +} + static void validate_alu_instr(rogue_validation_state *state, const rogue_alu_instr *alu) { @@ -238,10 +255,13 @@ static void validate_alu_instr(rogue_validation_state *state, if (rogue_alu_comp_is_none(alu) && alu->op == ROGUE_ALU_OP_TST) validate_log(state, "ALU comparison not set for test op."); - /* Initial check if instruction modifiers are valid. */ + /* Check if instruction modifiers are valid. */ if (!rogue_mods_supported(alu->mod, info->supported_op_mods)) validate_log(state, "Unsupported ALU op modifiers."); + if (!validate_alu_op_mod_combo(alu->mod)) + validate_log(state, "Unsupported ALU op modifier combination."); + /* Instruction repeat checks. */ if (alu->instr.repeat > 1 && !info->dst_repeat_mask && !info->src_repeat_mask) { @@ -270,6 +290,23 @@ static void validate_alu_instr(rogue_validation_state *state, } } +static bool validate_backend_op_mod_combo(uint64_t mods) +{ + rogue_foreach_mod_in_set (mod, mods) { + const rogue_backend_op_mod_info *info = &rogue_backend_op_mod_infos[mod]; + + /* Check if any excluded op mods have been included. */ + if (info->exclude & mods) + return false; + + /* Check if any required op mods have been missed. */ + if (info->require && !(info->require & mods)) + return false; + } + + return true; +} + static void validate_backend_instr(rogue_validation_state *state, const rogue_backend_instr *backend) { @@ -279,10 +316,13 @@ static void validate_backend_instr(rogue_validation_state *state, const rogue_backend_op_info *info = &rogue_backend_op_infos[backend->op]; - /* Initial check if instruction modifiers are valid. */ + /* Check if instruction modifiers are valid. */ if (!rogue_mods_supported(backend->mod, info->supported_op_mods)) validate_log(state, "Unsupported backend op modifiers."); + if (!validate_backend_op_mod_combo(backend->mod)) + validate_log(state, "Unsupported backend op modifier combination."); + /* Instruction repeat checks. */ if (backend->instr.repeat > 1 && !info->dst_repeat_mask && !info->src_repeat_mask) { @@ -311,6 +351,23 @@ static void validate_backend_instr(rogue_validation_state *state, } } +static bool validate_ctrl_op_mod_combo(uint64_t mods) +{ + rogue_foreach_mod_in_set (mod, mods) { + const rogue_ctrl_op_mod_info *info = &rogue_ctrl_op_mod_infos[mod]; + + /* Check if any excluded op mods have been included. */ + if (info->exclude & mods) + return false; + + /* Check if any required op mods have been missed. */ + if (info->require && !(info->require & mods)) + return false; + } + + return true; +} + /* Returns true if instruction can end block. */ static bool validate_ctrl_instr(rogue_validation_state *state, const rogue_ctrl_instr *ctrl) @@ -327,10 +384,13 @@ static bool validate_ctrl_instr(rogue_validation_state *state, validate_log(state, "Ctrl op did not expect target block, but one provided."); - /* Initial check if instruction modifiers are valid. */ + /* Check if instruction modifiers are valid. */ if (!rogue_mods_supported(ctrl->mod, info->supported_op_mods)) validate_log(state, "Unsupported CTRL op modifiers."); + if (!validate_ctrl_op_mod_combo(ctrl->mod)) + validate_log(state, "Unsupported CTRL op modifier combination."); + /* Instruction repeat checks. */ if (ctrl->instr.repeat > 1 && !info->dst_repeat_mask && !info->src_repeat_mask) { @@ -369,6 +429,23 @@ static bool validate_ctrl_instr(rogue_validation_state *state, return info->ends_block; } +static bool validate_bitwise_op_mod_combo(uint64_t mods) +{ + rogue_foreach_mod_in_set (mod, mods) { + const rogue_bitwise_op_mod_info *info = &rogue_bitwise_op_mod_infos[mod]; + + /* Check if any excluded op mods have been included. */ + if (info->exclude & mods) + return false; + + /* Check if any required op mods have been missed. */ + if (info->require && !(info->require & mods)) + return false; + } + + return true; +} + static void validate_bitwise_instr(rogue_validation_state *state, const rogue_bitwise_instr *bitwise) { @@ -378,10 +455,13 @@ static void validate_bitwise_instr(rogue_validation_state *state, const rogue_bitwise_op_info *info = &rogue_bitwise_op_infos[bitwise->op]; - /* Initial check if instruction modifiers are valid. */ + /* Check if instruction modifiers are valid. */ if (!rogue_mods_supported(bitwise->mod, info->supported_op_mods)) validate_log(state, "Unsupported bitwise op modifiers."); + if (!validate_bitwise_op_mod_combo(bitwise->mod)) + validate_log(state, "Unsupported bitwise op modifier combination."); + /* Instruction repeat checks. */ if (bitwise->instr.repeat > 1 && !info->dst_repeat_mask && !info->src_repeat_mask) {
