summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2011-02-01 13:35:36 -0800
committerIan Romanick <[email protected]>2011-02-01 13:43:36 -0800
commita04582739e77b58cea9e2aa523109e878bf90b6a (patch)
treed0cc6557117c21a1637581d917c363df782aaee4
parent20d278a7ff0ce66e5c4ac437e1fbe52c31a1ecb3 (diff)
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.
-rw-r--r--src/mesa/drivers/dri/i915/i915_fragprog.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c
index 1c6e9845172..624f18d6710 100644
--- a/src/mesa/drivers/dri/i915/i915_fragprog.c
+++ b/src/mesa/drivers/dri/i915/i915_fragprog.c
@@ -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;