From: Alyssa Rosenzweig Date: Fri, 2 Oct 2020 19:03:58 +0000 (-0400) Subject: pan/bi: Use canonical flow control enum X-Git-Tag: upstream/21.0.0~4405 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0f181f4eaebb6a54a498bea26ecaa00818d71b24;p=platform%2Fupstream%2Fmesa.git pan/bi: Use canonical flow control enum Merges multiple bits and adds some new combinations. The semantics are the compiler are evidently wrong, we'll fix that next. Signed-off-by: Alyssa Rosenzweig Reviewed-by: Boris Brezillon Part-of: --- diff --git a/src/panfrost/bifrost/bi_pack.c b/src/panfrost/bifrost/bi_pack.c index 01c4a79..500566d 100644 --- a/src/panfrost/bifrost/bi_pack.c +++ b/src/panfrost/bifrost/bi_pack.c @@ -45,8 +45,9 @@ bi_pack_header(bi_clause *clause, bi_clause *next_1, bi_clause *next_2, bool is_ dependency_wait |= next_2 ? next_2->dependencies : 0; struct bifrost_header header = { - .back_to_back = clause->back_to_back, - .no_end_of_shader = (next_1 != NULL), + .flow_control = + (next_1 == NULL) ? BIFROST_FLOW_END : + (clause->back_to_back ? BIFROST_FLOW_NBTB : BIFROST_FLOW_NBTB_UNCONDITIONAL), .terminate_discarded_threads = is_fragment, .next_clause_prefetch = clause->next_clause_prefetch, .staging_barrier = clause->staging_barrier, diff --git a/src/panfrost/bifrost/bi_print_common.c b/src/panfrost/bifrost/bi_print_common.c index 5c645eb..e0f8b3f 100644 --- a/src/panfrost/bifrost/bi_print_common.c +++ b/src/panfrost/bifrost/bi_print_common.c @@ -98,3 +98,19 @@ bi_interp_mode_name(enum bifrost_interp_mode mode) default: return ".unknown"; } } + +const char * +bi_flow_control_name(enum bifrost_flow mode) +{ + switch (mode) { + case BIFROST_FLOW_END: return "eos"; + case BIFROST_FLOW_NBTB_PC: return "nbb br_pc"; + case BIFROST_FLOW_NBTB_UNCONDITIONAL: return "nbb r_uncond"; + case BIFROST_FLOW_NBTB: return "nbb"; + case BIFROST_FLOW_BTB_UNCONDITIONAL: return "bb r_uncond"; + case BIFROST_FLOW_BTB_NONE: return "bb"; + case BIFROST_FLOW_WE_UNCONDITIONAL: return "we r_uncond"; + case BIFROST_FLOW_WE: return "we"; + default: return "XXX"; + } +} diff --git a/src/panfrost/bifrost/bi_print_common.h b/src/panfrost/bifrost/bi_print_common.h index 55c0318..2c27ab3 100644 --- a/src/panfrost/bifrost/bi_print_common.h +++ b/src/panfrost/bifrost/bi_print_common.h @@ -35,5 +35,6 @@ const char * bi_output_mod_name(enum bifrost_outmod mod); const char * bi_minmax_mode_name(enum bifrost_minmax_mode mod); const char * bi_round_mode_name(enum bifrost_roundmode mod); const char * bi_interp_mode_name(enum bifrost_interp_mode mode); +const char * bi_flow_control_name(enum bifrost_flow mode); #endif diff --git a/src/panfrost/bifrost/bifrost.h b/src/panfrost/bifrost/bifrost.h index 497dc3b..7638c5b 100644 --- a/src/panfrost/bifrost/bifrost.h +++ b/src/panfrost/bifrost/bifrost.h @@ -67,6 +67,48 @@ enum bifrost_exceptions { BIFROST_EXCEPTIONS_PRECISE_SQRT = 3, }; +/* Describes clause flow control, with respect to control flow and branch + * reconvergence. + * + * Control flow may be considered back-to-back (execute clauses back-to-back), + * non-back-to-back (switch warps after clause before the next clause), write + * elision (back-to-back and elide register slot #3 write from the clause), or + * end of shader. + * + * Branch reconvergence may be disabled, enabled unconditionally, or enabled + * based on the program counter. A clause requires reconvergence if it has a + * successor that can be executed without first executing the clause itself. + * Separate iterations of a loop are treated separately here, so it is also the + * case for a loop exit where the iteration count is not warp-invariant. + * + */ + +enum bifrost_flow { + /* End-of-shader */ + BIFROST_FLOW_END = 0, + + /* Non back-to-back, PC-encoded reconvergence */ + BIFROST_FLOW_NBTB_PC = 1, + + /* Non back-to-back, unconditional reconvergence */ + BIFROST_FLOW_NBTB_UNCONDITIONAL = 2, + + /* Non back-to-back, no reconvergence */ + BIFROST_FLOW_NBTB = 3, + + /* Back-to-back, unconditional reconvergence */ + BIFROST_FLOW_BTB_UNCONDITIONAL = 4, + + /* Back-to-back, no reconvergence */ + BIFROST_FLOW_BTB_NONE = 5, + + /* Write elision, unconditional reconvergence */ + BIFROST_FLOW_WE_UNCONDITIONAL = 6, + + /* Write elision, no reconvergence */ + BIFROST_FLOW_WE = 7, +}; + struct bifrost_header { /* Reserved */ unsigned zero1 : 5; @@ -84,11 +126,12 @@ struct bifrost_header { /* Floating-point excception handling mode */ enum bifrost_exceptions float_exceptions : 2; - // true if the execution mask of the next clause is the same as the mask of - // the current clause. - unsigned back_to_back : 1; - unsigned no_end_of_shader: 1; - unsigned unk2 : 2; + /* Enum describing the flow control, which matters for handling + * divergence and reconvergence efficiently */ + enum bifrost_flow flow_control : 3; + + /* Reserved */ + unsigned zero2 : 1; /* Terminate discarded threads, rather than continuing execution. Set * for fragment shaders for standard GL behaviour of DISCARD. */ diff --git a/src/panfrost/bifrost/disassemble.c b/src/panfrost/bifrost/disassemble.c index 3183d3a..5702e07 100644 --- a/src/panfrost/bifrost/disassemble.c +++ b/src/panfrost/bifrost/disassemble.c @@ -89,12 +89,7 @@ static void dump_header(FILE *fp, struct bifrost_header header, bool verbose) if (header.staging_barrier) fprintf(fp, "osrb "); - if (!header.no_end_of_shader) - fprintf(fp, "eos "); - - if (!header.back_to_back) { - fprintf(fp, "nbb "); - } + fprintf(fp, "%s ", bi_flow_control_name(header.flow_control)); if (header.suppress_inf) fprintf(fp, "inf_suppress "); @@ -109,6 +104,7 @@ static void dump_header(FILE *fp, struct bifrost_header header, bool verbose) fprintf(fp, "ftz_au "); assert(!header.zero1); + assert(!header.zero2); if (header.float_exceptions == BIFROST_EXCEPTIONS_DISABLED) fprintf(fp, "fpe_ts "); @@ -120,9 +116,6 @@ static void dump_header(FILE *fp, struct bifrost_header header, bool verbose) if (header.message_type) fprintf(fp, "%s ", bi_message_type_name(header.next_message_type)); - if (header.unk2) - fprintf(fp, "unk2 "); - if (header.terminate_discarded_threads) fprintf(fp, "td "); @@ -663,7 +656,7 @@ static bool dump_clause(FILE *fp, uint32_t *words, unsigned *size, unsigned offs struct bifrost_header header; memcpy((char *) &header, (char *) &header_bits, sizeof(struct bifrost_header)); dump_header(fp, header, verbose); - if (!header.no_end_of_shader) + if (header.flow_control == BIFROST_FLOW_END) stopbit = true; fprintf(fp, "{\n");