Mesa (main): virgl: Propagate precice flag through moves
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Apr 12 10:54:12 UTC 2022
Module: Mesa
Branch: main
Commit: a4a34cd3234858dbfe990ede81d3a61edf95c9da
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=a4a34cd3234858dbfe990ede81d3a61edf95c9da
Author: Gert Wollny <gert.wollny at collabora.com>
Date: Sat Apr 9 09:49:25 2022 +0200
virgl: Propagate precice flag through moves
NIR doesn't propagate precise through moves, and with NTT the
last output is usually preceded by a move, so that we no longer
see that the evaluation of some value is supposed to be exact,
and, hence we can't decorate the outputs accordingly.
Fixes with NTT:
dEQP-GLES31.functional.tessellation.common_edge.
triangles_equal_spacing_precise
triangles_fractional_odd_spacing_precise
triangles_fractional_even_spacing_precise
quads_equal_spacing_precise
quads_fractional_odd_spacing_precise
quads_fractional_even_spacing_precise
v2: Don't clear the precise flag when we hit a mov, because we may
hit a if/else construct like below and we don't track branches
IF X
TEMP[0] = OP_PRECICE ...
ELSE
TEMP[0] = MOV CONST[]
ENDIF
Thanks Emma for pointing out the problem.
v2: allocate precise handling flags to transform_prolog (Emma)
Signed-off-by: Gert Wollny <gert.wollny at collabora.com>
Acked-by: Emma Anholt <emma at anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15836>
---
src/gallium/drivers/virgl/virgl_tgsi.c | 48 +++++++++++++++++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)
diff --git a/src/gallium/drivers/virgl/virgl_tgsi.c b/src/gallium/drivers/virgl/virgl_tgsi.c
index af19401ebdb..f14583a3464 100644
--- a/src/gallium/drivers/virgl/virgl_tgsi.c
+++ b/src/gallium/drivers/virgl/virgl_tgsi.c
@@ -70,6 +70,8 @@ struct virgl_transform_context {
unsigned num_writemask_fixups;
struct virgl_input_temp input_temp[INPUT_TEMP_COUNT];
+
+ uint32_t *precise_flags;
};
static void
@@ -245,6 +247,8 @@ virgl_tgsi_transform_prolog(struct tgsi_transform_context * ctx)
}
virgl_mov_input_temp_uint(ctx, &vtctx->input_temp[INPUT_TEMP_HELPER_INVOCATION]);
+
+ vtctx->precise_flags = calloc((vtctx->next_temp + 7)/8, sizeof(uint32_t));
}
static void
@@ -271,6 +275,45 @@ virgl_tgsi_transform_instruction(struct tgsi_transform_context *ctx,
if (!vtctx->has_precise && inst->Instruction.Precise)
inst->Instruction.Precise = 0;
+ /* For outputs NTT adds a final mov op but NIR doesn't propagate precise with moves,
+ * so that we don't see whether the assignment is from a precise instruction, but
+ * we need to know this to set the output decoration correctly, so propagate the
+ * precise flag with TGSI */
+ for (int i = 0; i < inst->Instruction.NumDstRegs; ++i) {
+ if (inst->Dst[i].Register.File == TGSI_FILE_TEMPORARY) {
+ uint32_t index = inst->Dst[i].Register.Index / 8;
+ uint32_t bits = inst->Dst[i].Register.WriteMask << (inst->Dst[i].Register.Index % 8);
+
+ /* Since we re-use temps set and clear the precise flag according to the last use
+ * for the register index and written components. Since moves are not marked
+ * as precise originally, and we may end up with an if/else clause that assignes
+ * a precise result in the if branche, but does a simple move from a constant
+ * on the else branche, we don't clear the flag when we hit a mov.
+ * We do the conservatiove approach here, because virglrenderer emits different temp
+ * ranges, and we don't want to mark all temps as precise only because we have
+ * one precise output */
+ if (inst->Instruction.Precise)
+ vtctx->precise_flags[index] |= bits;
+ else if (inst->Instruction.Opcode != TGSI_OPCODE_MOV)
+ vtctx->precise_flags[index] &= ~bits;
+ } else if (inst->Instruction.Opcode == TGSI_OPCODE_MOV) {
+ for (int i = 0; i < inst->Instruction.NumSrcRegs; ++i) {
+ if (inst->Src[i].Register.File == TGSI_FILE_TEMPORARY) {
+ uint32_t index = inst->Src[i].Register.Index / 8;
+ uint32_t read_mask = (1 << inst->Src[i].Register.SwizzleX) |
+ (1 << inst->Src[i].Register.SwizzleY) |
+ (1 << inst->Src[i].Register.SwizzleZ) |
+ (1 << inst->Src[i].Register.SwizzleW);
+ uint32_t bits = read_mask << (inst->Dst[i].Register.Index % 8);
+ if (vtctx->precise_flags[index] & bits) {
+ inst->Instruction.Precise = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+
/* virglrenderer can run out of space in internal buffers for immediates as
* tex operands. Move the first immediate tex arg to a temp to save space in
* the buffer.
@@ -377,5 +420,8 @@ struct tgsi_token *virgl_tgsi_transform(struct virgl_screen *vscreen, const stru
tgsi_scan_shader(tokens_in, &transform.info);
- return tgsi_transform_shader(tokens_in, newLen, &transform.base);
+ struct tgsi_token *new_tokens = tgsi_transform_shader(tokens_in, newLen, &transform.base);
+ free(transform.precise_flags);
+ return new_tokens;
+
}
More information about the mesa-commit
mailing list