i915g: Make sure we consider negates/swizzles on bias/shadow coords.

Caught by imirkin while debugging #4986.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13133>
This commit is contained in:
Emma Anholt
2021-09-30 21:12:00 -07:00
committed by Marge Bot
parent ebe5626de6
commit fa4fd67f78
4 changed files with 38 additions and 68 deletions

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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

View File

@@ -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: