From 67c0f077a2198b8337a74a1027242b406a6bc571 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Nicolai=20H=C3=A4hnle?= Date: Wed, 10 Aug 2016 18:05:13 +0200 Subject: [PATCH] tgsi/scan: add tgsi_scan_arrays MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reviewed-by: Marek Olšák --- src/gallium/auxiliary/tgsi/tgsi_scan.c | 76 ++++++++++++++++++++++++++++++++++ src/gallium/auxiliary/tgsi/tgsi_scan.h | 17 ++++++++ 2 files changed, 93 insertions(+) diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c index 98d86fc..0167e22 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_scan.c +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c @@ -635,6 +635,82 @@ tgsi_scan_shader(const struct tgsi_token *tokens, tgsi_parse_free(&parse); } +/** + * Collect information about the arrays of a given register file. + * + * @param tokens TGSI shader + * @param file the register file to scan through + * @param max_array_id number of entries in @p arrays; should be equal to the + * highest array id, i.e. tgsi_shader_info::array_max[file]. + * @param arrays info for array of each ID will be written to arrays[ID - 1]. + */ +void +tgsi_scan_arrays(const struct tgsi_token *tokens, + unsigned file, + unsigned max_array_id, + struct tgsi_array_info *arrays) +{ + struct tgsi_parse_context parse; + + if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) { + debug_printf("tgsi_parse_init() failed in tgsi_scan_arrays()!\n"); + return; + } + + memset(arrays, 0, sizeof(arrays[0]) * max_array_id); + + while (!tgsi_parse_end_of_tokens(&parse)) { + struct tgsi_full_instruction *inst; + + tgsi_parse_token(&parse); + + if (parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_DECLARATION) { + struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration; + + if (decl->Declaration.Array && decl->Declaration.File == file && + decl->Array.ArrayID > 0 && decl->Array.ArrayID <= max_array_id) { + struct tgsi_array_info *array = &arrays[decl->Array.ArrayID - 1]; + assert(!array->declared); + array->declared = true; + array->range = decl->Range; + } + } + + if (parse.FullToken.Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION) + continue; + + inst = &parse.FullToken.FullInstruction; + for (unsigned i = 0; i < inst->Instruction.NumDstRegs; i++) { + const struct tgsi_full_dst_register *dst = &inst->Dst[i]; + if (dst->Register.File != file) + continue; + + if (dst->Register.Indirect) { + if (dst->Indirect.ArrayID > 0 && + dst->Indirect.ArrayID <= max_array_id) { + arrays[dst->Indirect.ArrayID - 1].writemask |= dst->Register.WriteMask; + } else { + /* Indirect writes without an ArrayID can write anywhere. */ + for (unsigned j = 0; j < max_array_id; ++j) + arrays[j].writemask |= dst->Register.WriteMask; + } + } else { + /* Check whether the write falls into any of the arrays anyway. */ + for (unsigned j = 0; j < max_array_id; ++j) { + struct tgsi_array_info *array = &arrays[j]; + if (array->declared && + dst->Register.Index >= array->range.First && + dst->Register.Index <= array->range.Last) + array->writemask |= dst->Register.WriteMask; + } + } + } + } + + tgsi_parse_free(&parse); + + return; +} /** diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.h b/src/gallium/auxiliary/tgsi/tgsi_scan.h index f7eefa4..30d0146 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_scan.h +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.h @@ -149,10 +149,27 @@ struct tgsi_shader_info unsigned max_depth; }; +struct tgsi_array_info +{ + /** Whether an array with this ID was declared. */ + bool declared; + + /** The OR of all writemasks used to write to this array. */ + ubyte writemask; + + /** The range with which the array was declared. */ + struct tgsi_declaration_range range; +}; + extern void tgsi_scan_shader(const struct tgsi_token *tokens, struct tgsi_shader_info *info); +void +tgsi_scan_arrays(const struct tgsi_token *tokens, + unsigned file, + unsigned max_array_id, + struct tgsi_array_info *arrays); extern boolean tgsi_is_passthrough_shader(const struct tgsi_token *tokens); -- 2.7.4