[Mesa-dev] [PATCH] tgsi: Recognize RET in main for tgsi_transform
Brian Paul
brianp at vmware.com
Tue Feb 13 04:19:02 UTC 2018
LGTM.
Reviewed-by: Brian Paul <brianp at vmware.com>
On 02/12/2018 09:10 PM, 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).
> ---
> src/gallium/auxiliary/tgsi/tgsi_transform.c | 50 ++++++++++++++++++++++++++---
> 1 file changed, 45 insertions(+), 5 deletions(-)
>
> diff --git a/src/gallium/auxiliary/tgsi/tgsi_transform.c b/src/gallium/auxiliary/tgsi/tgsi_transform.c
> index ffdad13..94d872c 100644
> --- a/src/gallium/auxiliary/tgsi/tgsi_transform.c
> +++ b/src/gallium/auxiliary/tgsi/tgsi_transform.c
> @@ -110,6 +110,8 @@ tgsi_transform_shader(const struct tgsi_token *tokens_in,
> {
> uint procType;
> boolean first_instruction = TRUE;
> + boolean epilog_emitted = FALSE;
> + int stack_size = 0;
>
> /* input shader */
> struct tgsi_parse_context parse;
> @@ -166,22 +168,60 @@ 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) {
> + if ((opcode == TGSI_OPCODE_END ||
> + (opcode == TGSI_OPCODE_RET && stack_size == 0))
> + && ctx->epilog && !epilog_emitted) {
> /* Emit caller's epilog */
> ctx->epilog(ctx);
> - /* Emit END */
> + epilog_emitted = TRUE;
> + /* Emit END (or RET) */
> + if (opcode == TGSI_OPCODE_END) {
> + assert(stack_size == 0);
> + }
> ctx->emit_instruction(ctx, fullinst);
> }
> else {
> + switch (opcode) {
> + case TGSI_OPCODE_IF:
> + case TGSI_OPCODE_UIF:
> + case TGSI_OPCODE_SWITCH:
> + case TGSI_OPCODE_BGNLOOP:
> + case TGSI_OPCODE_CAL:
> + stack_size++;
> + break;
> + case TGSI_OPCODE_ENDIF:
> + case TGSI_OPCODE_ENDSWITCH:
> + case TGSI_OPCODE_ENDLOOP:
> + case TGSI_OPCODE_ENDSUB:
> + assert(stack_size > 0);
> + stack_size--;
> + break;
> + case TGSI_OPCODE_BGNSUB:
> + case TGSI_OPCODE_RET:
> + default:
> + break;
> + }
> if (ctx->transform_instruction)
> ctx->transform_instruction(ctx, fullinst);
> else
>
More information about the mesa-dev
mailing list