From fa4fd67f7824727d92e52c816543b0233eacd932 Mon Sep 17 00:00:00 2001 From: Emma Anholt Date: Thu, 30 Sep 2021 21:12:00 -0700 Subject: [PATCH] i915g: Make sure we consider negates/swizzles on bias/shadow coords. Caught by imirkin while debugging #4986. Part-of: --- src/gallium/drivers/i915/i915_fpc.h | 4 +- src/gallium/drivers/i915/i915_fpc_emit.c | 31 +++++---------- src/gallium/drivers/i915/i915_fpc_optimize.c | 33 +--------------- src/gallium/drivers/i915/i915_fpc_translate.c | 38 ++++++++++++------- 4 files changed, 38 insertions(+), 68 deletions(-) diff --git a/src/gallium/drivers/i915/i915_fpc.h b/src/gallium/drivers/i915/i915_fpc.h index c223599400c..a8426f7b88b 100644 --- a/src/gallium/drivers/i915/i915_fpc.h +++ b/src/gallium/drivers/i915/i915_fpc.h @@ -185,7 +185,7 @@ extern void i915_release_utemps(struct i915_fp_compile *p); extern uint32_t i915_emit_texld(struct i915_fp_compile *p, uint32_t dest, uint32_t destmask, uint32_t sampler, uint32_t coord, uint32_t op, - uint32_t num_coord); + uint32_t coord_mask); extern uint32_t i915_emit_arith(struct i915_fp_compile *p, uint32_t op, uint32_t dest, uint32_t mask, uint32_t saturate, @@ -285,7 +285,7 @@ extern struct i915_token_list *i915_optimize(const struct tgsi_token *tokens); extern void i915_optimize_free(struct i915_token_list *tokens); -extern uint32_t i915_num_coords(uint32_t tex); +extern uint32_t i915_coord_mask(enum tgsi_opcode opcode, enum tgsi_texture_type tex); extern bool i915_nir_lower_sincos(struct nir_shader *s); diff --git a/src/gallium/drivers/i915/i915_fpc_emit.c b/src/gallium/drivers/i915/i915_fpc_emit.c index 9d4e17d713c..9c7e55b477a 100644 --- a/src/gallium/drivers/i915/i915_fpc_emit.c +++ b/src/gallium/drivers/i915/i915_fpc_emit.c @@ -176,32 +176,21 @@ i915_emit_arith(struct i915_fp_compile *p, uint32_t op, uint32_t dest, uint32_t i915_emit_texld(struct i915_fp_compile *p, uint32_t dest, uint32_t destmask, uint32_t sampler, uint32_t coord, uint32_t opcode, - uint32_t num_coord) + uint32_t coord_mask) { const uint32_t k = UREG(GET_UREG_TYPE(coord), GET_UREG_NR(coord)); int temp = -1; - uint32_t ignore = 0; - /* Eliminate the useless texture coordinates. Otherwise we end up generating - * a swizzle for no reason below. */ - switch (num_coord) { - case 1: - /* For 1D textures, make sure that the Y coordinate is actually - * initialized. It seems that if the channel is never written during the - * program, texturing returns undefined results (even if the Y wrap is - * REPEAT). - */ - coord = swizzle(coord, X, X, Z, W); - FALLTHROUGH; - case 2: - ignore |= (0xf << UREG_CHANNEL_Z_SHIFT); - FALLTHROUGH; - case 3: - ignore |= (0xf << UREG_CHANNEL_W_SHIFT); - } + uint32_t coord_used = 0xf << UREG_CHANNEL_X_SHIFT; + if (coord_mask & TGSI_WRITEMASK_Y) + coord_used |= 0xf << UREG_CHANNEL_Y_SHIFT; + if (coord_mask & TGSI_WRITEMASK_Z) + coord_used |= 0xf << UREG_CHANNEL_Z_SHIFT; + if (coord_mask & TGSI_WRITEMASK_W) + coord_used |= 0xf << UREG_CHANNEL_W_SHIFT; - if ((coord & ~ignore) != (k & ~ignore) || + if ((coord & coord_used) != (k & coord_used) || GET_UREG_TYPE(coord) == REG_TYPE_CONST) { /* texcoord is swizzled or negated. Need to allocate a new temporary * register (a utemp / unpreserved temp) won't do. @@ -226,7 +215,7 @@ i915_emit_texld(struct i915_fp_compile *p, uint32_t dest, uint32_t destmask, /* if not writing to XYZW... */ uint32_t tmp = i915_get_utemp(p); i915_emit_texld(p, tmp, A0_DEST_CHANNEL_ALL, sampler, coord, opcode, - num_coord); + coord_mask); i915_emit_arith(p, A0_MOV, dest, destmask, 0, tmp, 0, 0); /* XXX release utemp here? */ } else { diff --git a/src/gallium/drivers/i915/i915_fpc_optimize.c b/src/gallium/drivers/i915/i915_fpc_optimize.c index 9dd7bdfb5a9..85b6cfaf822 100644 --- a/src/gallium/drivers/i915/i915_fpc_optimize.c +++ b/src/gallium/drivers/i915/i915_fpc_optimize.c @@ -148,26 +148,6 @@ op_commutes(unsigned opcode) return op_table[opcode].commutes; } -static unsigned -mask_for_unswizzled(int num_components) -{ - unsigned mask = 0; - switch (num_components) { - case 4: - mask |= TGSI_WRITEMASK_W; - FALLTHROUGH; - case 3: - mask |= TGSI_WRITEMASK_Z; - FALLTHROUGH; - case 2: - mask |= TGSI_WRITEMASK_Y; - FALLTHROUGH; - case 1: - mask |= TGSI_WRITEMASK_X; - } - return mask; -} - static bool is_unswizzled(struct i915_full_src_register *r, unsigned write_mask) { @@ -385,17 +365,8 @@ unused_from(struct i915_optimize_context *ctx, static unsigned i915_tex_mask(union i915_full_token *instr) { - unsigned mask; - - /* Get the number of coords */ - mask = mask_for_unswizzled( - i915_num_coords(instr->FullInstruction.Texture.Texture)); - - /* Add the W component if projective */ - if (instr->FullInstruction.Instruction.Opcode == TGSI_OPCODE_TXP) - mask |= TGSI_WRITEMASK_W; - - return mask; + return i915_coord_mask(instr->FullInstruction.Instruction.Opcode, + instr->FullInstruction.Texture.Texture); } static bool diff --git a/src/gallium/drivers/i915/i915_fpc_translate.c b/src/gallium/drivers/i915/i915_fpc_translate.c index 93e95c16ac0..345f8609805 100644 --- a/src/gallium/drivers/i915/i915_fpc_translate.c +++ b/src/gallium/drivers/i915/i915_fpc_translate.c @@ -326,26 +326,28 @@ translate_tex_src_target(struct i915_fp_compile *p, uint32_t tex) * Return the number of coords needed to access a given TGSI_TEXTURE_* */ uint32_t -i915_num_coords(uint32_t tex) +i915_coord_mask(enum tgsi_opcode opcode, enum tgsi_texture_type tex) { + uint32_t coord_mask = 0; + + if (opcode == TGSI_OPCODE_TXP || opcode == TGSI_OPCODE_TXB) + coord_mask |= TGSI_WRITEMASK_W; + switch (tex) { - case TGSI_TEXTURE_SHADOW1D: - case TGSI_TEXTURE_1D: - return 1; - - case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_1D: /* See the 1D coord swizzle below. */ case TGSI_TEXTURE_2D: - case TGSI_TEXTURE_SHADOWRECT: case TGSI_TEXTURE_RECT: - return 2; + return coord_mask | TGSI_WRITEMASK_XY; + case TGSI_TEXTURE_SHADOW1D: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: case TGSI_TEXTURE_3D: case TGSI_TEXTURE_CUBE: - return 3; + return coord_mask | TGSI_WRITEMASK_XYZ; default: - debug_printf("Unknown texture target for num coords"); - return 2; + unreachable("bad texture target"); } } @@ -362,9 +364,17 @@ emit_tex(struct i915_fp_compile *p, const struct i915_full_instruction *inst, uint32_t sampler = i915_emit_decl(p, REG_TYPE_S, unit, tex); uint32_t coord = src_vector(p, &inst->Src[0], fs); + /* For 1D textures, make sure that the Y coordinate is actually + * initialized. It seems that if the channel is never written during the + * program, texturing returns undefined results (even if the Y wrap is + * REPEAT). + */ + if (texture == TGSI_TEXTURE_1D || texture == TGSI_TEXTURE_SHADOW1D) + coord = swizzle(coord, X, X, Z, W); + i915_emit_texld(p, get_result_vector(p, &inst->Dst[0]), get_result_flags(inst), sampler, coord, opcode, - i915_num_coords(texture)); + i915_coord_mask(inst->Instruction.Opcode, texture)); } /** @@ -521,7 +531,7 @@ i915_translate_instruction(struct i915_fp_compile *p, 0, /* sampler */ src0, /* coord*/ T0_TEXKILL, /* opcode */ - 4); /* num_coord */ + TGSI_WRITEMASK_XYZW);/* coord_mask */ break; case TGSI_OPCODE_KILL: @@ -534,7 +544,7 @@ i915_translate_instruction(struct i915_fp_compile *p, negate(swizzle(UREG(REG_TYPE_R, 0), ONE, ONE, ONE, ONE), 1, 1, 1, 1), /* coord */ T0_TEXKILL, /* opcode */ - 1); /* num_coord */ + TGSI_WRITEMASK_X); /* coord_mask */ break; case TGSI_OPCODE_LG2: