diff --git a/.pick_status.json b/.pick_status.json index 71d84951a98..bf694156601 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -904,7 +904,7 @@ "description": "pan/va: fix FAU validation", "nominated": true, "nomination_type": 2, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "fd1906afea59073780939810e0e46094264677d3", "notes": null diff --git a/src/panfrost/compiler/valhall/va_validate.c b/src/panfrost/compiler/valhall/va_validate.c index 0afa3dfccac..ffaecd2c069 100644 --- a/src/panfrost/compiler/valhall/va_validate.c +++ b/src/panfrost/compiler/valhall/va_validate.c @@ -60,18 +60,16 @@ fau_state_buffer(struct fau_state *fau, bi_index idx) return false; } +/* Instructions executed in the execution engine may only encode one FAU index. + * Instructions executed by the message unit may encode two FAU indices, + * except for ATEST and BLEND which may sometimes run in the execution engine. + */ static bool -fau_state_uniform(struct fau_state *fau, bi_index idx) +can_use_two_fau_indices(enum bi_opcode op) { - /* Each slot is 64-bits. The low/high half is encoded as the offset of the - * bi_index, which we want to ignore. - */ - unsigned slot = (idx.value & 63); - - if (fau->uniform_slot < 0) - fau->uniform_slot = slot; - - return fau->uniform_slot == slot; + return bi_opcode_props[op].message != BIFROST_MESSAGE_NONE && + op != BI_OPCODE_ATEST && + op != BI_OPCODE_BLEND; } static bool @@ -81,7 +79,32 @@ fau_is_special(enum bir_fau fau) } static bool -fau_state_special(struct fau_state *fau, bi_index idx) +fau_state_uniform(struct fau_state *fau, bi_index idx, enum bi_opcode op) +{ + /* Each slot is 64-bits. The low/high half is encoded as the offset of the + * bi_index, which we want to ignore. + */ + unsigned slot = (idx.value & 63); + + if (fau->uniform_slot < 0) + fau->uniform_slot = slot; + + if (fau->uniform_slot != slot) + return false; + + if (!can_use_two_fau_indices(op)) { + for (unsigned i = 0; i < ARRAY_SIZE(fau->buffer); ++i) { + bi_index buf = fau->buffer[i]; + if (!bi_is_null(buf) && fau_is_special(buf.value)) + return false; + } + } + + return true; +} + +static bool +fau_state_special(struct fau_state *fau, bi_index idx, enum bi_opcode op) { for (unsigned i = 0; i < ARRAY_SIZE(fau->buffer); ++i) { bi_index buf = fau->buffer[i]; @@ -91,11 +114,12 @@ fau_state_special(struct fau_state *fau, bi_index idx) return false; } - return true; + return fau->uniform_slot == -1 || can_use_two_fau_indices(op); } static bool -valid_src(struct fau_state *fau, unsigned fau_page, bi_index src) +valid_src(struct fau_state *fau, unsigned fau_page, bi_index src, + enum bi_opcode op) { if (src.type != BI_INDEX_FAU) return true; @@ -104,9 +128,9 @@ valid_src(struct fau_state *fau, unsigned fau_page, bi_index src) valid &= fau_state_buffer(fau, src); if (src.value & BIR_FAU_UNIFORM) - valid &= fau_state_uniform(fau, src); + valid &= fau_state_uniform(fau, src, op); else if (fau_is_special(src.value)) - valid &= fau_state_special(fau, src); + valid &= fau_state_special(fau, src, op); return valid; } @@ -119,7 +143,7 @@ va_validate_fau(bi_instr *I) unsigned fau_page = va_select_fau_page(I); bi_foreach_src(I, s) { - valid &= valid_src(&fau, fau_page, I->src[s]); + valid &= valid_src(&fau, fau_page, I->src[s], I->op); } return valid; @@ -135,7 +159,7 @@ va_repair_fau(bi_builder *b, bi_instr *I) struct fau_state push = fau; bi_index src = I->src[s]; - if (!valid_src(&fau, fau_page, src)) { + if (!valid_src(&fau, fau_page, src, I->op)) { bi_replace_src(I, s, bi_mov_i32(b, bi_strip_index(src))); /* Rollback update. Since the replacement move doesn't affect FAU