? diff ? full.diff ? i915-tex-swizzle.diff ? render.diff Index: i915_context.h =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/i915/i915_context.h,v retrieving revision 1.7 diff -u -r1.7 i915_context.h --- i915_context.h 18 Aug 2006 09:04:48 -0000 1.7 +++ i915_context.h 20 Sep 2006 10:37:51 -0000 @@ -29,6 +29,7 @@ #define I915CONTEXT_INC #include "intel_context.h" +#include "i915_reg.h" #define I915_FALLBACK_TEXTURE 0x1000 #define I915_FALLBACK_COLORMASK 0x2000 @@ -103,6 +104,8 @@ #define I915_PROGRAM_SIZE 192 +#define I915_MAX_INSN (I915_MAX_TEX_INSN+I915_MAX_ALU_INSN) + /* Hardware version of a parsed fragment program. "Derived" from the * mesa fragment_program struct. @@ -152,7 +155,10 @@ * use. */ - + /* Track which R registers are "live" for each instruction. + * A register is live between the time it's written to and the last time + * it's read. */ + GLuint usedRegs[I915_MAX_INSN]; /* Helpers for i915_fragprog.c: */ Index: i915_fragprog.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/i915/i915_fragprog.c,v retrieving revision 1.18 diff -u -r1.18 i915_fragprog.c --- i915_fragprog.c 20 Jul 2006 16:49:57 -0000 1.18 +++ i915_fragprog.c 20 Sep 2006 10:37:51 -0000 @@ -53,6 +53,11 @@ 1.0/(4*3*2*1), -1.0/(6*5*4*3*2*1) }; + + + + + /** * Retrieve a ureg for the given source register. Will emit * constants, apply swizzling and negation as needed. @@ -207,7 +212,7 @@ GLuint coord = src_vector( p, &inst->SrcReg[0], program); \ /* Texel lookup */ \ \ - i915_emit_texld( p, \ + i915_emit_texld( p, get_live_regs(p, inst), \ get_result_vector( p, inst ), \ get_result_flags( inst ), \ sampler, \ @@ -230,6 +235,42 @@ #define EMIT_2ARG_ARITH( OP ) EMIT_ARITH( OP, 2 ) #define EMIT_3ARG_ARITH( OP ) EMIT_ARITH( OP, 3 ) +/* + * TODO: consider moving this into core + */ +static void calc_live_regs( struct i915_fragment_program *p ) +{ + const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current; + GLuint regsUsed = 0xffff0000; + GLint i; + + for (i = program->Base.NumInstructions - 1; i >= 0; i--) { + struct prog_instruction *inst = &program->Base.Instructions[i]; + int opArgs = _mesa_num_inst_src_regs(inst->Opcode); + 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); + + 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) + regsUsed |= 1 << inst->SrcReg[a].Index; + } + + p->usedRegs[i] = regsUsed; + } +} + +static GLuint get_live_regs( struct i915_fragment_program *p, + const struct prog_instruction *inst ) +{ + const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current; + GLuint nr = inst - program->Base.Instructions; + + return p->usedRegs[nr]; +} /* Possible concerns: * @@ -263,6 +304,17 @@ return; } + if (program->Base.NumInstructions > I915_MAX_INSN) + { + i915_program_error( p, "Exceeded max instructions" ); + return; + } + + /* Not always needed: + */ + calc_live_regs(p); + + while (1) { GLuint src0, src1, src2, flags; GLuint tmp = 0; @@ -410,7 +462,7 @@ src0 = src_vector( p, &inst->SrcReg[0], program); tmp = i915_get_utemp( p ); - i915_emit_texld( p, + i915_emit_texld( p, get_live_regs(p, inst), tmp, A0_DEST_CHANNEL_ALL, /* use a dummy dest reg */ 0, src0, Index: i915_program.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/i915/i915_program.c,v retrieving revision 1.6 diff -u -r1.6 i915_program.c --- i915_program.c 18 Aug 2006 09:04:48 -0000 1.6 +++ i915_program.c 20 Sep 2006 10:37:51 -0000 @@ -38,6 +38,7 @@ #include "i915_context.h" #include "i915_program.h" +#include "program_instruction.h" #define A0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT) #define D0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT) @@ -194,7 +195,19 @@ return dest; } +static GLuint get_free_rreg (struct i915_fragment_program *p, + GLuint live_regs) +{ + int bit = ffs(~live_regs); + if (!bit) { + i915_program_error(p, "Can't find free R reg"); + return UREG_BAD; + } + return UREG(REG_TYPE_R, bit - 1); +} + GLuint i915_emit_texld( struct i915_fragment_program *p, + GLuint live_regs, GLuint dest, GLuint destmask, GLuint sampler, @@ -202,19 +215,23 @@ GLuint op ) { if (coord != UREG(GET_UREG_TYPE(coord), GET_UREG_NR(coord))) { - /* No real way to work around this in the general case - need to - * allocate and declare a new temporary register (a utemp won't - * do). Will fallback for now. - */ - i915_program_error(p, "Can't (yet) swizzle TEX arguments"); - return 0; + /* With the help of the "needed registers" table created earlier, pick + * a register we can MOV the swizzled TC to (since TEX doesn't support + * swizzled sources) */ + GLuint swizCoord = get_free_rreg(p, live_regs); + if (swizCoord == UREG_BAD) + return 0; + + i915_emit_arith( p, A0_MOV, swizCoord, A0_DEST_CHANNEL_ALL, 0, coord, 0, 0 ); + coord = swizCoord; } - /* Don't worry about saturate as we only support + /* Don't worry about saturate as we only support texture formats + * that are always in the 0..1 range. */ if (destmask != A0_DEST_CHANNEL_ALL) { GLuint tmp = i915_get_utemp(p); - i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, sampler, coord, op ); + i915_emit_texld( p, 0, tmp, A0_DEST_CHANNEL_ALL, sampler, coord, op ); i915_emit_arith( p, A0_MOV, dest, destmask, 0, tmp, 0, 0 ); return dest; } Index: i915_program.h =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/i915/i915_program.h,v retrieving revision 1.3 diff -u -r1.3 i915_program.h --- i915_program.h 1 Sep 2005 03:32:48 -0000 1.3 +++ i915_program.h 20 Sep 2006 10:37:51 -0000 @@ -110,6 +110,7 @@ extern GLuint i915_emit_texld( struct i915_fragment_program *p, + GLuint live_regs, GLuint dest, GLuint destmask, GLuint sampler, Index: i915_texprog.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/i915/i915_texprog.c,v retrieving revision 1.6 diff -u -r1.6 i915_texprog.c --- i915_texprog.c 11 Apr 2006 11:41:11 -0000 1.6 +++ i915_texprog.c 20 Sep 2006 10:37:51 -0000 @@ -69,7 +69,7 @@ if (p->VB->TexCoordPtr[unit]->size == 4) op = T0_TEXLDP; - p->src_texture = i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, + p->src_texture = i915_emit_texld( p, 0, tmp, A0_DEST_CHANNEL_ALL, sampler, texcoord, op ); }