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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user