[Mesa-dev] [PATCH] tgsi: Recognize RET in main for tgsi_transform
Jose Fonseca
jfonseca at vmware.com
Tue Feb 13 18:22:00 UTC 2018
On 13/02/18 17:57, sroland at vmware.com wrote:
> From: Roland Scheidegger <sroland at vmware.com>
>
> Shaders coming from dx10 state trackers have a RET before the END.
> And the epilog needs to be placed before the RET (otherwise it will
> get ignored).
> Hence figure out if a RET is in main, in this case we'll place
> the epilog there rather than before the END.
> (At a closer look, there actually seem to be problems with control
> flow in general with output redirection, that would need another
> look. It's enough however to fix draw's aa line emulation in some
> internal bug - lines tend to be drawn with trivial shaders, moving
> either a constant color or a vertex color directly to the output).
>
> v2: add assert so buggy handling of RET in main is detected
> ---
> src/gallium/auxiliary/tgsi/tgsi_transform.c | 62 +++++++++++++++++++++++++----
> 1 file changed, 55 insertions(+), 7 deletions(-)
>
> diff --git a/src/gallium/auxiliary/tgsi/tgsi_transform.c b/src/gallium/auxiliary/tgsi/tgsi_transform.c
> index ffdad13..a13cf90 100644
> --- a/src/gallium/auxiliary/tgsi/tgsi_transform.c
> +++ b/src/gallium/auxiliary/tgsi/tgsi_transform.c
> @@ -110,6 +110,9 @@ tgsi_transform_shader(const struct tgsi_token *tokens_in,
> {
> uint procType;
> boolean first_instruction = TRUE;
> + boolean epilog_emitted = FALSE;
> + int cond_stack = 0;
> + int call_stack = 0;
>
> /* input shader */
> struct tgsi_parse_context parse;
> @@ -166,22 +169,66 @@ tgsi_transform_shader(const struct tgsi_token *tokens_in,
> {
> struct tgsi_full_instruction *fullinst
> = &parse.FullToken.FullInstruction;
> + unsigned opcode = fullinst->Instruction.Opcode;
>
> if (first_instruction && ctx->prolog) {
> ctx->prolog(ctx);
> }
>
> - /* XXX Note: we may also want to look for a main/top-level
> - * TGSI_OPCODE_RET instruction in the future.
> + /*
> + * XXX Note: we handle the case of ret in main.
> + * However, the output redirections done by transform
> + * have their limits with control flow and will generally
> + * not work correctly. e.g.
> + * if (cond) {
> + * oColor = x;
> + * ret;
> + * }
> + * oColor = y;
> + * end;
> + * If the color output is redirected to a temp and modified
> + * by a transform, this will not work (the oColor assignment
> + * in the conditional will never make it to the actual output).
> */
> - if (fullinst->Instruction.Opcode == TGSI_OPCODE_END
> - && ctx->epilog) {
> - /* Emit caller's epilog */
> - ctx->epilog(ctx);
> - /* Emit END */
> + if ((opcode == TGSI_OPCODE_END || opcode == TGSI_OPCODE_RET) &&
> + call_stack == 0 && ctx->epilog && !epilog_emitted) {
> + if (opcode == TGSI_OPCODE_RET && cond_stack != 0) {
> + assert(!"transform ignoring RET in main");
> + } else {
> + assert(cond_stack == 0);
> + /* Emit caller's epilog */
> + ctx->epilog(ctx);
> + epilog_emitted = TRUE;
> + }
> + /* Emit END (or RET) */
> ctx->emit_instruction(ctx, fullinst);
> }
> else {
> + switch (opcode) {
> + case TGSI_OPCODE_IF:
> + case TGSI_OPCODE_UIF:
> + case TGSI_OPCODE_SWITCH:
> + case TGSI_OPCODE_BGNLOOP:
> + cond_stack++;
> + break;
> + case TGSI_OPCODE_CAL:
> + call_stack++;
> + break;
> + case TGSI_OPCODE_ENDIF:
> + case TGSI_OPCODE_ENDSWITCH:
> + case TGSI_OPCODE_ENDLOOP:
> + assert(cond_stack > 0);
> + cond_stack--;
> + break;
> + case TGSI_OPCODE_ENDSUB:
> + assert(call_stack > 0);
> + call_stack--;
> + break;
> + case TGSI_OPCODE_BGNSUB:
> + case TGSI_OPCODE_RET:
> + default:
> + break;
> + }
> if (ctx->transform_instruction)
> ctx->transform_instruction(ctx, fullinst);
> else
> @@ -231,6 +278,7 @@ tgsi_transform_shader(const struct tgsi_token *tokens_in,
> assert( 0 );
> }
> }
> + assert(call_stack == 0);
>
> tgsi_parse_free (&parse);
>
>
LGTM. Thanks.
Reviewed-by: Jose Fonseca <jfonseca at vmware.com>
More information about the mesa-dev
mailing list