From 0ea47d86c7c8a1513ffd98976beeb2e97958fc99 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Thu, 24 Aug 2023 19:19:07 -0400 Subject: [PATCH] agx: Add schedule-specialized get_sr variants Some special registers imply scheduling constraints. We want to have a single scheduling class per instruction in the IR, so fork off various get_sr variants depending on what kind of SR we're reading, and validate that we use the right kind. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/asahi/compiler/agx_compile.c | 8 ++++---- src/asahi/compiler/agx_opcodes.py | 4 +++- src/asahi/compiler/agx_validate.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index ee98ca5..83e7ba2 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -1038,15 +1038,15 @@ agx_emit_intrinsic(agx_builder *b, nir_intrinsic_instr *instr) return agx_get_sr_to(b, dst, AGX_SR_INPUT_SAMPLE_MASK); case nir_intrinsic_load_sample_mask: - return agx_get_sr_to(b, dst, AGX_SR_COVERAGE_MASK); + return agx_get_sr_coverage_to(b, dst, AGX_SR_COVERAGE_MASK); case nir_intrinsic_load_helper_invocation: /* Compare special register to zero. We could lower this in NIR (letting * us fold in an inot) but meh? */ - return agx_icmpsel_to(b, dst, agx_get_sr(b, 32, AGX_SR_IS_ACTIVE_THREAD), - agx_zero(), agx_immediate(1), agx_zero(), - AGX_ICOND_UEQ); + return agx_icmpsel_to( + b, dst, agx_get_sr_coverage(b, 32, AGX_SR_IS_ACTIVE_THREAD), + agx_zero(), agx_immediate(1), agx_zero(), AGX_ICOND_UEQ); case nir_intrinsic_load_vertex_id: assert(b->shader->stage == MESA_SHADER_VERTEX); diff --git a/src/asahi/compiler/agx_opcodes.py b/src/asahi/compiler/agx_opcodes.py index 2585809..6c81d2c 100644 --- a/src/asahi/compiler/agx_opcodes.py +++ b/src/asahi/compiler/agx_opcodes.py @@ -310,7 +310,9 @@ op("local_atomic", op("wait", (0x38, 0xFF, 2, _), dests = 0, can_eliminate = False, imms = [SCOREBOARD], schedule_class = "invalid") -op("get_sr", (0x72, 0x7F | L, 4, _), dests = 1, imms = [SR]) +for (suffix, schedule_class) in [("", "none"), ("_coverage", "coverage")]: + op(f"get_sr{suffix}", (0x72, 0x7F | L, 4, _), dests = 1, imms = [SR], + schedule_class = schedule_class, can_reorder = schedule_class == "none") op("sample_mask", (0x7fc1, 0xffff, 6, _), dests = 0, srcs = 2, can_eliminate = False, schedule_class = "coverage") diff --git a/src/asahi/compiler/agx_validate.c b/src/asahi/compiler/agx_validate.c index 458fdfb..a19a794 100644 --- a/src/asahi/compiler/agx_validate.c +++ b/src/asahi/compiler/agx_validate.c @@ -208,6 +208,34 @@ agx_validate_predecessors(agx_block *block) return true; } +static bool +agx_validate_sr(const agx_instr *I) +{ + bool none = (I->op == AGX_OPCODE_GET_SR); + bool coverage = (I->op == AGX_OPCODE_GET_SR_COVERAGE); + bool barrier = false; /* unused so far, will be GET_SR_BARRIER */ + + /* Filter get_sr instructions */ + if (!(none || coverage || barrier)) + return true; + + switch (I->sr) { + case AGX_SR_ACTIVE_THREAD_INDEX_IN_QUAD: + case AGX_SR_ACTIVE_THREAD_INDEX_IN_SUBGROUP: + case AGX_SR_COVERAGE_MASK: + case AGX_SR_IS_ACTIVE_THREAD: + return coverage; + + case AGX_SR_OPFIFO_CMD: + case AGX_SR_OPFIFO_DATA_L: + case AGX_SR_OPFIFO_DATA_H: + return barrier; + + default: + return none; + } +} + void agx_validate(agx_context *ctx, const char *after) { @@ -261,6 +289,12 @@ agx_validate(agx_context *ctx, const char *after) agx_print_instr(I, stderr); fail = true; } + + if (!agx_validate_sr(I)) { + fprintf(stderr, "Invalid SR after %s\n", after); + agx_print_instr(I, stdout); + fail = true; + } } if (!agx_validate_width(ctx)) { -- 2.7.4