On Wed, Jan 07, 2009 at 01:49:42AM -0800, Eric Anholt wrote: > Bug #18074
Looks good to me. Reviewed-by: Ian Romanick <ian.d.roman...@intel.com> > --- > src/mesa/drivers/dri/i915/i915_context.c | 3 +- > src/mesa/drivers/dri/i915/i915_context.h | 1 + > src/mesa/drivers/dri/i915/i915_fragprog.c | 82 > +++++++++++++++++++++++++---- > src/mesa/drivers/dri/i915/i915_reg.h | 4 +- > 4 files changed, 76 insertions(+), 14 deletions(-) > > diff --git a/src/mesa/drivers/dri/i915/i915_context.c > b/src/mesa/drivers/dri/i915/i915_context.c > index 9bff742..010cf0c 100644 > --- a/src/mesa/drivers/dri/i915/i915_context.c > +++ b/src/mesa/drivers/dri/i915/i915_context.c > @@ -159,7 +159,8 @@ i915CreateContext(const __GLcontextModes * mesaVis, > * instruction can translate to more than one HW instruction, so > * we'll still have to check and fallback each time. > */ > - ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY; > + ctx->Const.FragmentProgram.MaxTemps = I915_MAX_TEMPS; > + ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_NATIVE_TEMPS; > ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* 8 tex, 2 color, > fog */ > ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT; > ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN; > diff --git a/src/mesa/drivers/dri/i915/i915_context.h > b/src/mesa/drivers/dri/i915/i915_context.h > index 87bbf5f..a5df3fa 100644 > --- a/src/mesa/drivers/dri/i915/i915_context.h > +++ b/src/mesa/drivers/dri/i915/i915_context.h > @@ -177,6 +177,7 @@ struct i915_fragment_program > * it's read. */ > GLuint usedRegs[I915_MAX_INSN]; > > + GLuint temp_reg_mapping[I915_MAX_TEMPS]; > /* Helpers for i915_fragprog.c: > */ > GLuint wpos_tex; > diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c > b/src/mesa/drivers/dri/i915/i915_fragprog.c > index 46f1740..ef22beb 100644 > --- a/src/mesa/drivers/dri/i915/i915_fragprog.c > +++ b/src/mesa/drivers/dri/i915/i915_fragprog.c > @@ -87,11 +87,7 @@ src_vector(struct i915_fragment_program *p, > /* Registers: > */ > case PROGRAM_TEMPORARY: > - if (source->Index >= I915_MAX_TEMPORARY) { > - i915_program_error(p, "Exceeded max temporary reg"); > - return 0; > - } > - src = UREG(REG_TYPE_R, source->Index); > + src = UREG(REG_TYPE_R, p->temp_reg_mapping[source->Index]); > break; > case PROGRAM_INPUT: > switch (source->Index) { > @@ -272,15 +268,17 @@ do { > \ > static void calc_live_regs( struct i915_fragment_program *p ) > { > const struct gl_fragment_program *program = > p->ctx->FragmentProgram._Current; > - GLuint regsUsed = 0xffff0000; > + GLuint regsUsed = 0; > GLint i; > > /* Work from the front marking regs as live when they're written to. */ > for (i = 0; i < program->Base.NumInstructions; i++) { > struct prog_instruction *inst = &program->Base.Instructions[i]; > > - if (inst->DstReg.File == PROGRAM_TEMPORARY) > + if (inst->DstReg.File == PROGRAM_TEMPORARY) { > + assert(inst->DstReg.Index < I915_MAX_TEMPS); > regsUsed |= 1 << inst->DstReg.Index; > + } > p->usedRegs[i] = regsUsed; > } > > @@ -292,20 +290,83 @@ static void calc_live_regs( struct > i915_fragment_program *p ) > int a; > > for (a = 0; a < opArgs; a++) { > - if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) > + if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) { > + assert(inst->SrcReg[a].Index < I915_MAX_TEMPS); > regsUsed |= 1 << inst->SrcReg[a].Index; > + } > } > p->usedRegs[i] &= regsUsed; > } > } > > +/* Returns the set of live hw registers at the moment, by working from > + * the set of live sw temporaries. > + */ > 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; > + GLuint live_sw_regs = p->usedRegs[nr]; > + GLuint live_hw_regs = 0; > + > + while (live_sw_regs != 0) { > + int sw_reg = ffs(live_sw_regs) - 1; > + > + live_sw_regs &= ~(1 << sw_reg); > + live_hw_regs |= 1 << p->temp_reg_mapping[sw_reg]; > + } > > - return p->usedRegs[nr]; > + /* Return invalid hw regs as live, as the consumer looking for a > + * temporary will use ffs on the inverse. > + */ > + return 0xffff0000 | live_hw_regs; > +} > + > +/** > + * Creates the mapping from ARB program temporary indices to native indices. > + * > + * This lets us run some programs which would otherwise exceed our limits on > + * number of temporaries. Note that this code relies on calc_live_regs > + * marking live from first write through last read, as otherwise we might > + * assign it two different hw regs and end up stomping on live stuff. > + */ > +static void > +create_temp_mapping(struct i915_fragment_program *p) > +{ > + const struct gl_fragment_program *program = > p->ctx->FragmentProgram._Current; > + GLuint avail_hw_regs = 0xffff; /* 1 << I915_MAX_NATIVE_TEMPS - 1 */ > + GLuint assigned_sw_indices = 0; > + int i; > + > + for (i = 0; i < program->Base.NumInstructions; i++) { > + int sw_to_assign; > + > + /* Get a hardware index for any newly-live registers. */ > + while ((sw_to_assign = ffs(p->usedRegs[i] & > + ~assigned_sw_indices) - 1) != -1) { > + int hw_reg = ffs(avail_hw_regs) - 1; > + if (hw_reg == -1) { > + i915_program_error(p, "Exceeded max native temporaries"); > + return; > + } > + > + avail_hw_regs &= ~(1 << hw_reg); > + assigned_sw_indices |= 1 << sw_to_assign; > + p->temp_reg_mapping[sw_to_assign] = hw_reg; > + } > + > + /* Restore availability for newly-dead registers */ > + if (i > 0) { > + int sw_new_dead = p->usedRegs[i - 1] & ~p->usedRegs[i]; > + int sw_to_restore; > + > + while ((sw_to_restore = ffs(sw_new_dead) - 1) != -1) { > + avail_hw_regs |= 1 << p->temp_reg_mapping[sw_to_restore]; > + sw_new_dead &= ~(1 << sw_to_restore); > + } > + } > + } > } > > /* Possible concerns: > @@ -347,9 +408,8 @@ upload_program(struct i915_fragment_program *p) > return; > } > > - /* Not always needed: > - */ > calc_live_regs(p); > + create_temp_mapping(p); > > while (1) { > GLuint src0, src1, src2, flags; > diff --git a/src/mesa/drivers/dri/i915/i915_reg.h > b/src/mesa/drivers/dri/i915/i915_reg.h > index 8891e11..b4117eb 100644 > --- a/src/mesa/drivers/dri/i915/i915_reg.h > +++ b/src/mesa/drivers/dri/i915/i915_reg.h > @@ -374,8 +374,8 @@ > #define I915_MAX_TEX_INSN 32 > #define I915_MAX_ALU_INSN 64 > #define I915_MAX_DECL_INSN 27 > -#define I915_MAX_TEMPORARY 16 > - > +#define I915_MAX_NATIVE_TEMPS 16 > +#define I915_MAX_TEMPS 32 > > /* Each instruction is 3 dwords long, though most don't require all > * this space. Maximum of 123 instructions. Smaller maxes per insn > -- > 1.5.6.5
pgpSSh1ahv4Rr.pgp
Description: PGP signature
------------------------------------------------------------------------------ Check out the new SourceForge.net Marketplace. It is the best place to buy or sell services for just about anything Open Source. http://p.sf.net/sfu/Xq1LFB
_______________________________________________ Mesa3d-dev mailing list Mesa3d-dev@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mesa3d-dev