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

Attachment: 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

Reply via email to