i915: Only mark a register as available if all components are written

Previously a register would be marked as available if any component
was written.  This caused shaders such as this:

  0: TEX TEMP[0].xyz, INPUT[14].xyyy, texture[0], 2D;
  1: MUL TEMP[1], UNIFORM[0], TEMP[0].xxxx;
  2: MAD TEMP[2], UNIFORM[1], TEMP[0].yyyy, TEMP[1];
  3: MAD TEMP[1], UNIFORM[2], TEMP[0].zzzz, TEMP[2];
  4: ADD TEMP[0].xyz, TEMP[1].xyzx, UNIFORM[3].xyzx;
  5: TEX TEMP[1].w, INPUT[14].xyyy, texture[0], 2D;
  6: MOV TEMP[0].w, TEMP[1].wwww;
  7: MOV OUTPUT[2], TEMP[0];
  8: END

to produce incorrect code such as this:

  BEGIN
  DCL S[0]
  DCL T_TEX0
  R[0] = MOV T_TEX0.xyyy
  U[0] = TEXLD S[0],R[0]
  R[0].xyz = MOV U[0]
  R[1] = MUL CONST[0], R[0].xxxx
  R[2] = MAD CONST[1], R[0].yyyy, R[1]
  R[1] = MAD CONST[2], R[0].zzzz, R[2]
  R[0].xyz = ADD R[1].xyzx, CONST[3].xyzx
  R[0] = MOV T_TEX0.xyyy
  U[0] = TEXLD S[0],R[0]
  R[1].w = MOV U[0]
  R[0].w = MOV R[1].wwww
  oC = MOV R[0]
  END

Note that T_TEX0 is copied to R[0], but the xyz components of R[0] are
still expected to hold a calculated value.

Fixes piglit tests draw-elements-vs-inputs, fp-kill, and
glsl-fs-color-matrix.  It also fixes Meego bugzilla #13005.

NOTE: This is a candidate for the 7.9 and 7.10 branches.
This commit is contained in:
Ian Romanick 2011-02-01 13:35:36 -08:00
parent 20d278a7ff
commit a04582739e
1 changed files with 17 additions and 3 deletions

View File

@ -306,6 +306,7 @@ static void calc_live_regs( struct i915_fragment_program *p )
{
const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current;
GLuint regsUsed = 0xffff0000;
uint8_t live_components[16] = { 0, };
GLint i;
for (i = program->Base.NumInstructions - 1; i >= 0; i--) {
@ -314,13 +315,26 @@ static void calc_live_regs( struct i915_fragment_program *p )
int a;
/* Register is written to: unmark as live for this and preceeding ops */
if (inst->DstReg.File == PROGRAM_TEMPORARY)
regsUsed &= ~(1 << inst->DstReg.Index);
if (inst->DstReg.File == PROGRAM_TEMPORARY) {
live_components[inst->DstReg.Index] &= ~inst->DstReg.WriteMask;
if (live_components[inst->DstReg.Index] == 0)
regsUsed &= ~(1 << inst->DstReg.Index);
}
for (a = 0; a < opArgs; a++) {
/* Register is read from: mark as live for this and preceeding ops */
if (inst->SrcReg[a].File == PROGRAM_TEMPORARY)
if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) {
unsigned c;
regsUsed |= 1 << inst->SrcReg[a].Index;
for (c = 0; c < 4; c++) {
const unsigned field = GET_SWZ(inst->SrcReg[a].Swizzle, c);
if (field <= SWIZZLE_W)
live_components[inst->SrcReg[a].Index] |= (1U << field);
}
}
}
p->usedRegs[i] = regsUsed;