summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlyssa Rosenzweig <alyssa@collabora.com>2022-01-15 15:24:17 -0500
committerEric Engestrom <eric@engestrom.ch>2022-01-26 18:28:29 +0000
commitc7684b11e2bc42e3f78f9ec8717b8bea6ed58751 (patch)
tree3eb278c44c034a7ab8fc8701f4eabda6848a9406
parent448da15129f1854aabf467ac656c3a42f879974a (diff)
pan/bi: Schedule around blend shader register clobbering
By software ABI, a blend shader is permitted to clobber registers R0-R15. The scheduler needs to be aware of this, to avoid moving a write to one of these registers past the BLEND itself. Otherwise the schedule is invalid. This bug affects GLES3.0, but is rare enough in practice that we had missed it. It requires a fragment shader to write to multiple render targets with attached blend shaders, and have temporaries register allocated to R0-R15 that are not read by the blend shader, but are sunk past the BLEND instruction by the scheduler. Prevents a regression when switching boolean representations on: dEQP-GLES31.functional.shaders.builtin_functions.integer.uaddcarry.uvec4_lowp_fragment Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com> Cc: mesa-stable Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14577> (cherry picked from commit b8d37eb1bb99b795d370634a8eadcf83cf5a9d7d)
-rw-r--r--.pick_status.json2
-rw-r--r--src/panfrost/bifrost/bi_schedule.c20
2 files changed, 17 insertions, 5 deletions
diff --git a/.pick_status.json b/.pick_status.json
index 7419fdc0428..4927867ee35 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -3910,7 +3910,7 @@
"description": "pan/bi: Schedule around blend shader register clobbering",
"nominated": true,
"nomination_type": 0,
- "resolution": 0,
+ "resolution": 1,
"main_sha": null,
"because_sha": null
},
diff --git a/src/panfrost/bifrost/bi_schedule.c b/src/panfrost/bifrost/bi_schedule.c
index d974d4a98f1..cc0c128f1ea 100644
--- a/src/panfrost/bifrost/bi_schedule.c
+++ b/src/panfrost/bifrost/bi_schedule.c
@@ -197,7 +197,7 @@ bi_is_sched_barrier(bi_instr *I)
}
static void
-bi_create_dependency_graph(struct bi_worklist st, bool inorder)
+bi_create_dependency_graph(struct bi_worklist st, bool inorder, bool is_blend)
{
struct util_dynarray last_read[64], last_write[64];
@@ -262,6 +262,17 @@ bi_create_dependency_graph(struct bi_worklist st, bool inorder)
}
}
+ /* Blend shaders are allowed to clobber R0-R15. Treat these
+ * registers like extra destinations for scheduling purposes.
+ */
+ if (ins->op == BI_OPCODE_BLEND && !is_blend) {
+ for (unsigned c = 0; c < 16; ++c) {
+ add_dependency(last_read, c, i, st.dependents, st.dep_counts);
+ add_dependency(last_write, c, i, st.dependents, st.dep_counts);
+ mark_access(last_write, c, i);
+ }
+ }
+
bi_foreach_src(ins, s) {
if (ins->src[s].type != BI_INDEX_REGISTER) continue;
@@ -414,7 +425,7 @@ bi_flatten_block(bi_block *block, unsigned *len)
*/
static struct bi_worklist
-bi_initialize_worklist(bi_block *block, bool inorder)
+bi_initialize_worklist(bi_block *block, bool inorder, bool is_blend)
{
struct bi_worklist st = { };
st.instructions = bi_flatten_block(block, &st.count);
@@ -425,7 +436,7 @@ bi_initialize_worklist(bi_block *block, bool inorder)
st.dependents = calloc(st.count, sizeof(st.dependents[0]));
st.dep_counts = calloc(st.count, sizeof(st.dep_counts[0]));
- bi_create_dependency_graph(st, inorder);
+ bi_create_dependency_graph(st, inorder, is_blend);
st.worklist = calloc(BITSET_WORDS(st.count), sizeof(BITSET_WORD));
for (unsigned i = 0; i < st.count; ++i) {
@@ -1796,7 +1807,8 @@ bi_schedule_block(bi_context *ctx, bi_block *block)
/* Copy list to dynamic array */
struct bi_worklist st = bi_initialize_worklist(block,
- bifrost_debug & BIFROST_DBG_INORDER);
+ bifrost_debug & BIFROST_DBG_INORDER,
+ ctx->inputs->is_blend);
if (!st.count) {
bi_free_worklist(st);