Пример #1
0
/***********************************************************************
 * Expand various instructions here to simpler forms.  
 */
static void precalc_dst( struct brw_wm_compile *c,
			       const struct prog_instruction *inst )
{
   struct prog_src_register src0 = inst->SrcReg[0];
   struct prog_src_register src1 = inst->SrcReg[1];
   struct prog_dst_register dst = inst->DstReg;
   
   if (dst.WriteMask & WRITEMASK_Y) {      
      /* dst.y = mul src0.y, src1.y
       */
      emit_op(c,
	      OPCODE_MUL,
	      dst_mask(dst, WRITEMASK_Y),
	      inst->SaturateMode,
	      src0,
	      src1,
	      src_undef());
   }

   if (dst.WriteMask & WRITEMASK_XZ) {
      struct prog_instruction *swz;
      GLuint z = GET_SWZ(src0.Swizzle, Z);

      /* dst.xz = swz src0.1zzz
       */
      swz = emit_op(c,
		    OPCODE_SWZ,
		    dst_mask(dst, WRITEMASK_XZ),
		    inst->SaturateMode,
		    src_swizzle(src0, SWIZZLE_ONE, z, z, z),
		    src_undef(),
		    src_undef());
      /* Avoid letting negation flag of src0 affect our 1 constant. */
      swz->SrcReg[0].Negate &= ~NEGATE_X;
   }
   if (dst.WriteMask & WRITEMASK_W) {
      /* dst.w = mov src1.w
       */
      emit_op(c,
	      OPCODE_MOV,
	      dst_mask(dst, WRITEMASK_W),
	      inst->SaturateMode,
	      src1,
	      src_undef(),
	      src_undef());
   }
}
Пример #2
0
/* Internally generated immediates: overkill...
 */
static struct brw_fp_src src_imm( struct brw_wm_compile *c, 
				  const GLfloat *v, 
				  unsigned nr)
{
   unsigned i, j;
   unsigned swizzle;

   /* Could do a first pass where we examine all existing immediates
    * without expanding.
    */

   for (i = 0; i < c->nr_immediates; i++) {
      if (match_or_expand_immediate( v, 
                                     nr,
                                     c->immediate[i].v,
                                     &c->immediate[i].nr, 
                                     &swizzle ))
         goto out;
   }

   if (c->nr_immediates < Elements(c->immediate)) {
      i = c->nr_immediates++;
      if (match_or_expand_immediate( v,
                                     nr,
                                     c->immediate[i].v,
                                     &c->immediate[i].nr, 
                                     &swizzle ))
         goto out;
   }

   c->error = 1;
   return src_undef();

out:
   /* Make sure that all referenced elements are from this immediate.
    * Has the effect of making size-one immediates into scalars.
    */
   for (j = nr; j < 4; j++)
      swizzle |= (swizzle & 0x3) << (j * 2);

   return src_swizzle( src_reg( TGSI_FILE_IMMEDIATE, i ),
		       BRW_GET_SWZ(swizzle, X),
		       BRW_GET_SWZ(swizzle, Y),
		       BRW_GET_SWZ(swizzle, Z),
		       BRW_GET_SWZ(swizzle, W) );
}
Пример #3
0
static struct brw_fp_src src_scalar( struct brw_fp_src reg, int x )
{
   return src_swizzle(reg, x, x, x, x);
}
Пример #4
0
/**
 * Some TEX instructions require extra code, cube map coordinate
 * normalization, or coordinate scaling for RECT textures, etc.
 * This function emits those extra instructions and the TEX
 * instruction itself.
 */
static void precalc_tex( struct brw_wm_compile *c,
			 struct brw_fp_dst dst,
			 unsigned target,
			 unsigned unit,
			 struct brw_fp_src src0,
			 struct brw_fp_src sampler )
{
   struct brw_fp_src coord;
   struct brw_fp_dst tmp = dst_undef();

   assert(unit < BRW_MAX_TEX_UNIT);

   /* Cubemap: find longest component of coord vector and normalize
    * it.
    */
   if (target == TGSI_TEXTURE_CUBE) {
      struct brw_fp_src tmpsrc;

      tmp = get_temp(c);
      tmpsrc = src_reg_from_dst(tmp);

      /* tmp = abs(src0) */
      emit_op1(c, 
	       TGSI_OPCODE_MOV,
	       tmp,
	       src_abs(src0));

      /* tmp.X = MAX(tmp.X, tmp.Y) */
      emit_op2(c, TGSI_OPCODE_MAX,
	       dst_mask(tmp, BRW_WRITEMASK_X),
	       src_scalar(tmpsrc, X),
	       src_scalar(tmpsrc, Y));

      /* tmp.X = MAX(tmp.X, tmp.Z) */
      emit_op2(c, TGSI_OPCODE_MAX,
	       dst_mask(tmp, BRW_WRITEMASK_X),
	       tmpsrc,
	       src_scalar(tmpsrc, Z));

      /* tmp.X = 1 / tmp.X */
      emit_op1(c, TGSI_OPCODE_RCP,
	      dst_mask(tmp, BRW_WRITEMASK_X),
	      tmpsrc);

      /* tmp = src0 * tmp.xxxx */
      emit_op2(c, TGSI_OPCODE_MUL,
	       tmp,
	       src0,
	       src_scalar(tmpsrc, X));

      coord = tmpsrc;
   }
   else if (target == TGSI_TEXTURE_RECT ||
	    target == TGSI_TEXTURE_SHADOWRECT) {
      /* XXX: need a mechanism for internally generated constants.
       */
      coord = src0;
   }
   else {
      coord = src0;
   }

   /* Need to emit YUV texture conversions by hand.  Probably need to
    * do this here - the alternative is in brw_wm_emit.c, but the
    * conversion requires allocating a temporary variable which we
    * don't have the facility to do that late in the compilation.
    */
   if (c->key.yuvtex_mask & (1 << unit)) {
      /* convert ycbcr to RGBA */
      GLboolean  swap_uv = c->key.yuvtex_swap_mask & (1<<unit);
      struct brw_fp_dst tmp = get_temp(c);
      struct brw_fp_src tmpsrc = src_reg_from_dst(tmp);
      struct brw_fp_src C0 = src_imm4f( c,  -.5, -.0625, -.5, 1.164 );
      struct brw_fp_src C1 = src_imm4f( c, 1.596, -0.813, 2.018, -.391 );
     
      /* tmp     = TEX ...
       */
      emit_tex_op(c, 
                  TGSI_OPCODE_TEX,
                  dst_saturate(tmp, dst.saturate),
                  unit,
                  target,
                  sampler.index,
                  coord,
                  src_undef(),
                  src_undef());

      /* tmp.xyz =  ADD TMP, C0
       */
      emit_op2(c, TGSI_OPCODE_ADD,
	       dst_mask(tmp, BRW_WRITEMASK_XYZ),
	       tmpsrc,
	       C0);

      /* YUV.y   = MUL YUV.y, C0.w
       */
      emit_op2(c, TGSI_OPCODE_MUL,
	       dst_mask(tmp, BRW_WRITEMASK_Y),
	       tmpsrc,
	       src_scalar(C0, W));

      /* 
       * if (UV swaped)
       *     RGB.xyz = MAD YUV.zzx, C1, YUV.y
       * else
       *     RGB.xyz = MAD YUV.xxz, C1, YUV.y
       */

      emit_op3(c, TGSI_OPCODE_MAD,
	       dst_mask(dst, BRW_WRITEMASK_XYZ),
	       ( swap_uv ? 
		 src_swizzle(tmpsrc, Z,Z,X,X) : 
		 src_swizzle(tmpsrc, X,X,Z,Z)),
	       C1,
	       src_scalar(tmpsrc, Y));

      /*  RGB.y   = MAD YUV.z, C1.w, RGB.y
       */
      emit_op3(c,
	       TGSI_OPCODE_MAD,
	       dst_mask(dst, BRW_WRITEMASK_Y),
	       src_scalar(tmpsrc, Z),
	       src_scalar(C1, W),
	       src_scalar(src_reg_from_dst(dst), Y));

      release_temp(c, tmp);
   }
   else {
      /* ordinary RGBA tex instruction */
      emit_tex_op(c, 
                  TGSI_OPCODE_TEX,
                  dst,
                  unit,
                  target,
                  sampler.index,
                  coord,
                  src_undef(),
                  src_undef());
   }

   /* XXX: add GL_EXT_texture_swizzle support to gallium -- by
    * generating shader variants in mesa state tracker.
    */

   /* Release this temp if we ended up allocating it:
    */
   if (!dst_is_undef(tmp))
      release_temp(c, tmp);
}
Пример #5
0
/**
 * Some TEX instructions require extra code, cube map coordinate
 * normalization, or coordinate scaling for RECT textures, etc.
 * This function emits those extra instructions and the TEX
 * instruction itself.
 */
static void precalc_tex( struct brw_wm_compile *c,
			 const struct prog_instruction *inst )
{
   struct prog_src_register coord;
   struct prog_dst_register tmpcoord;
   const GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];

   assert(unit < BRW_MAX_TEX_UNIT);

   if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) {
       struct prog_instruction *out;
       struct prog_dst_register tmp0 = get_temp(c);
       struct prog_src_register tmp0src = src_reg_from_dst(tmp0);
       struct prog_dst_register tmp1 = get_temp(c);
       struct prog_src_register tmp1src = src_reg_from_dst(tmp1);
       struct prog_src_register src0 = inst->SrcReg[0];

       /* find longest component of coord vector and normalize it */
       tmpcoord = get_temp(c);
       coord = src_reg_from_dst(tmpcoord);

       /* tmpcoord = src0 (i.e.: coord = src0) */
       out = emit_op(c, OPCODE_MOV,
                     tmpcoord,
                     0,
                     src0,
                     src_undef(),
                     src_undef());
       out->SrcReg[0].Negate = NEGATE_NONE;
       out->SrcReg[0].Abs = 1;

       /* tmp0 = MAX(coord.X, coord.Y) */
       emit_op(c, OPCODE_MAX,
               tmp0,
               0,
               src_swizzle1(coord, X),
               src_swizzle1(coord, Y),
               src_undef());

       /* tmp1 = MAX(tmp0, coord.Z) */
       emit_op(c, OPCODE_MAX,
               tmp1,
               0,
               tmp0src,
               src_swizzle1(coord, Z),
               src_undef());

       /* tmp0 = 1 / tmp1 */
       emit_op(c, OPCODE_RCP,
               dst_mask(tmp0, WRITEMASK_X),
               0,
               tmp1src,
               src_undef(),
               src_undef());

       /* tmpCoord = src0 * tmp0 */
       emit_op(c, OPCODE_MUL,
               tmpcoord,
               0,
               src0,
               src_swizzle1(tmp0src, SWIZZLE_X),
               src_undef());

       release_temp(c, tmp0);
       release_temp(c, tmp1);
   }
   else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) {
      struct prog_src_register scale = 
	 search_or_add_param5( c, 
			       STATE_INTERNAL, 
			       STATE_TEXRECT_SCALE,
			       unit,
			       0,0 );

      tmpcoord = get_temp(c);

      /* coord.xy   = MUL inst->SrcReg[0], { 1/width, 1/height }
       */
      emit_op(c,
	      OPCODE_MUL,
	      tmpcoord,
	      0,
	      inst->SrcReg[0],
	      src_swizzle(scale,
			  SWIZZLE_X,
			  SWIZZLE_Y,
			  SWIZZLE_ONE,
			  SWIZZLE_ONE),
	      src_undef());

      coord = src_reg_from_dst(tmpcoord);
   }
   else {
      coord = inst->SrcReg[0];
   }

   /* Need to emit YUV texture conversions by hand.  Probably need to
    * do this here - the alternative is in brw_wm_emit.c, but the
    * conversion requires allocating a temporary variable which we
    * don't have the facility to do that late in the compilation.
    */
   if (c->key.yuvtex_mask & (1 << unit)) {
      /* convert ycbcr to RGBA */
      GLboolean  swap_uv = c->key.yuvtex_swap_mask & (1<<unit);

      /* 
	 CONST C0 = { -.5, -.0625,  -.5, 1.164 }
	 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
	 UYV     = TEX ...
	 UYV.xyz = ADD UYV,     C0
	 UYV.y   = MUL UYV.y,   C0.w
 	 if (UV swaped)
	    RGB.xyz = MAD UYV.zzx, C1,   UYV.y
	 else
	    RGB.xyz = MAD UYV.xxz, C1,   UYV.y 
	 RGB.y   = MAD UYV.z,   C1.w, RGB.y
      */
      struct prog_dst_register dst = inst->DstReg;
      struct prog_dst_register tmp = get_temp(c);
      struct prog_src_register tmpsrc = src_reg_from_dst(tmp);
      struct prog_src_register C0 = search_or_add_const4f( c,  -.5, -.0625, -.5, 1.164 );
      struct prog_src_register C1 = search_or_add_const4f( c, 1.596, -0.813, 2.018, -.391 );
     
      /* tmp     = TEX ...
       */
      emit_tex_op(c, 
                  OPCODE_TEX,
                  tmp,
                  inst->SaturateMode,
                  unit,
                  inst->TexSrcTarget,
                  inst->TexShadow,
                  coord,
                  src_undef(),
                  src_undef());

      /* tmp.xyz =  ADD TMP, C0
       */
      emit_op(c,
	      OPCODE_ADD,
	      dst_mask(tmp, WRITEMASK_XYZ),
	      0,
	      tmpsrc,
	      C0,
	      src_undef());

      /* YUV.y   = MUL YUV.y, C0.w
       */

      emit_op(c,
	      OPCODE_MUL,
	      dst_mask(tmp, WRITEMASK_Y),
	      0,
	      tmpsrc,
	      src_swizzle1(C0, W),
	      src_undef());

      /* 
       * if (UV swaped)
       *     RGB.xyz = MAD YUV.zzx, C1, YUV.y
       * else
       *     RGB.xyz = MAD YUV.xxz, C1, YUV.y
       */

      emit_op(c,
	      OPCODE_MAD,
	      dst_mask(dst, WRITEMASK_XYZ),
	      0,
	      swap_uv?src_swizzle(tmpsrc, Z,Z,X,X):src_swizzle(tmpsrc, X,X,Z,Z),
	      C1,
	      src_swizzle1(tmpsrc, Y));

      /*  RGB.y   = MAD YUV.z, C1.w, RGB.y
       */
      emit_op(c,
	      OPCODE_MAD,
	      dst_mask(dst, WRITEMASK_Y),
	      0,
	      src_swizzle1(tmpsrc, Z),
	      src_swizzle1(C1, W),
	      src_swizzle1(src_reg_from_dst(dst), Y));

      release_temp(c, tmp);
   }
   else {
      /* ordinary RGBA tex instruction */
      emit_tex_op(c, 
                  OPCODE_TEX,
                  inst->DstReg,
                  inst->SaturateMode,
                  unit,
                  inst->TexSrcTarget,
                  inst->TexShadow,
                  coord,
                  src_undef(),
                  src_undef());
   }

   /* For GL_EXT_texture_swizzle: */
   if (c->key.tex_swizzles[unit] != SWIZZLE_NOOP) {
      /* swizzle the result of the TEX instruction */
      struct prog_src_register tmpsrc = src_reg_from_dst(inst->DstReg);
      emit_op(c, OPCODE_SWZ,
              inst->DstReg,
              SATURATE_OFF, /* saturate already done above */
              src_swizzle4(tmpsrc, c->key.tex_swizzles[unit]),
              src_undef(),
              src_undef());
   }

   if ((inst->TexSrcTarget == TEXTURE_RECT_INDEX) ||
       (inst->TexSrcTarget == TEXTURE_CUBE_INDEX))
      release_temp(c, tmpcoord);
}
Пример #6
0
static void emit_interp( struct brw_wm_compile *c,
			 GLuint idx )
{
   struct prog_dst_register dst = dst_reg(PROGRAM_INPUT, idx);
   struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
   struct prog_src_register deltas = get_delta_xy(c);

   /* Need to use PINTERP on attributes which have been
    * multiplied by 1/W in the SF program, and LINTERP on those
    * which have not:
    */
   switch (idx) {
   case FRAG_ATTRIB_WPOS:
      /* Have to treat wpos.xy specially:
       */
      emit_op(c,
	      WM_WPOSXY,
	      dst_mask(dst, WRITEMASK_XY),
	      0,
	      get_pixel_xy(c),
	      src_undef(),
	      src_undef());
      
      dst = dst_mask(dst, WRITEMASK_ZW);

      /* PROGRAM_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw
       */
      emit_op(c,
	      WM_LINTERP,
	      dst,
	      0,
	      interp,
	      deltas,
	      src_undef());
      break;
   case FRAG_ATTRIB_COL0:
   case FRAG_ATTRIB_COL1:
      if (c->key.flat_shade) {
	 emit_op(c,
		 WM_CINTERP,
		 dst,
		 0,
		 interp,
		 src_undef(),
		 src_undef());
      }
      else {
         if (c->key.linear_color) {
            emit_op(c,
                    WM_LINTERP,
                    dst,
                    0,
                    interp,
                    deltas,
                    src_undef());
         }
         else {
            /* perspective-corrected color interpolation */
            emit_op(c,
                    WM_PINTERP,
                    dst,
                    0,
                    interp,
                    deltas,
                    get_pixel_w(c));
         }
      }
      break;
   case FRAG_ATTRIB_FOGC:
      /* Interpolate the fog coordinate */
      emit_op(c,
	      WM_PINTERP,
	      dst_mask(dst, WRITEMASK_X),
	      0,
	      interp,
	      deltas,
	      get_pixel_w(c));

      emit_op(c,
	      OPCODE_MOV,
	      dst_mask(dst, WRITEMASK_YZW),
	      0,
	      src_swizzle(interp,
			  SWIZZLE_ZERO,
			  SWIZZLE_ZERO,
			  SWIZZLE_ZERO,
			  SWIZZLE_ONE),
	      src_undef(),
	      src_undef());
      break;

   case FRAG_ATTRIB_FACE:
      emit_op(c,
              WM_FRONTFACING,
              dst_mask(dst, WRITEMASK_X),
              0,
              src_undef(),
              src_undef(),
              src_undef());
      break;

   case FRAG_ATTRIB_PNTC:
      /* XXX review/test this case */
      emit_op(c,
	      WM_PINTERP,
	      dst_mask(dst, WRITEMASK_XY),
	      0,
	      interp,
	      deltas,
	      get_pixel_w(c));

      emit_op(c,
	      OPCODE_MOV,
	      dst_mask(dst, WRITEMASK_ZW),
	      0,
	      src_swizzle(interp,
			  SWIZZLE_ZERO,
			  SWIZZLE_ZERO,
			  SWIZZLE_ZERO,
			  SWIZZLE_ONE),
	      src_undef(),
	      src_undef());
      break;

   default:
      emit_op(c,
	      WM_PINTERP,
	      dst,
	      0,
	      interp,
	      deltas,
	      get_pixel_w(c));
      break;
   }

   c->fp_interp_emitted |= 1<<idx;
}
Пример #7
0
static struct prog_src_register src_swizzle1( struct prog_src_register reg, int x )
{
   return src_swizzle(reg, x, x, x, x);
}
Пример #8
0
static void precalc_tex( struct brw_wm_compile *c,
			 const struct prog_instruction *inst )
{
   struct prog_src_register coord;
   struct prog_dst_register tmpcoord;

   if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) {
      struct prog_src_register scale = 
	 search_or_add_param5( c, 
			       STATE_INTERNAL, 
			       STATE_TEXRECT_SCALE,
			       inst->TexSrcUnit,
			       0,0 );

      tmpcoord = get_temp(c);

      /* coord.xy   = MUL inst->SrcReg[0], { 1/width, 1/height }
       */
      emit_op(c,
	      OPCODE_MUL,
	      tmpcoord,
	      0, 0, 0,
	      inst->SrcReg[0],
	      scale,
	      src_undef());

      coord = src_reg_from_dst(tmpcoord);
   }
   else {
      coord = inst->SrcReg[0];
   }

   /* Need to emit YUV texture conversions by hand.  Probably need to
    * do this here - the alternative is in brw_wm_emit.c, but the
    * conversion requires allocating a temporary variable which we
    * don't have the facility to do that late in the compilation.
    */
   if (!(c->key.yuvtex_mask & (1<<inst->TexSrcUnit))) {
      emit_op(c, 
	      OPCODE_TEX,
	      inst->DstReg,
	      inst->SaturateMode,
	      inst->TexSrcUnit,
	      inst->TexSrcTarget,
	      coord,
	      src_undef(),
	      src_undef());
   }
   else {
      /* 
	 CONST C0 = { -.5, -.0625,  -.5, 1.164 }
	 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
	 UYV     = TEX ...
	 UYV.xyz = ADD UYV,     C0
	 UYV.y   = MUL UYV.y,   C0.w
	 RGB.xyz = MAD UYV.xxz, C1,   UYV.y
	 RGB.y   = MAD UYV.z,   C1.w, RGB.y
      */
      struct prog_dst_register dst = inst->DstReg;
      struct prog_src_register src0 = inst->SrcReg[0];
      struct prog_dst_register tmp = get_temp(c);
      struct prog_src_register tmpsrc = src_reg_from_dst(tmp);
      struct prog_src_register C0 = search_or_add_const4f( c,  -.5, -.0625, -.5, 1.164 );
      struct prog_src_register C1 = search_or_add_const4f( c, 1.596, -0.813, 2.018, -.391 );
     
      /* tmp     = TEX ...
       */
      emit_op(c, 
	      OPCODE_TEX,
	      tmp,
	      inst->SaturateMode,
	      inst->TexSrcUnit,
	      inst->TexSrcTarget,
	      src0,
	      src_undef(),
	      src_undef());

      /* tmp.xyz =  ADD TMP, C0
       */
      emit_op(c,
	      OPCODE_ADD,
	      dst_mask(tmp, WRITEMASK_XYZ),
	      0, 0, 0,
	      tmpsrc,
	      C0,
	      src_undef());

      /* YUV.y   = MUL YUV.y, C0.w
       */
      emit_op(c,
	      OPCODE_MUL,
	      dst_mask(tmp, WRITEMASK_Y),
	      0, 0, 0,
	      tmpsrc,
	      src_swizzle1(C0, W),
	      src_undef());

      /* RGB.xyz = MAD YUV.xxz, C1, YUV.y
       */
      emit_op(c,
	      OPCODE_MAD,
	      dst_mask(dst, WRITEMASK_XYZ),
	      0, 0, 0,
	      src_swizzle(tmpsrc, X,X,Z,Z),
	      C1,
	      src_swizzle1(tmpsrc, Y));

      /*  RGB.y   = MAD YUV.z, C1.w, RGB.y
       */
      emit_op(c,
	      OPCODE_MAD,
	      dst_mask(dst, WRITEMASK_Y),
	      0, 0, 0,
	      src_swizzle1(tmpsrc, Z),
	      src_swizzle1(C1, W),
	      src_swizzle1(src_reg_from_dst(dst), Y));

      release_temp(c, tmp);
   }

   if (inst->TexSrcTarget == GL_TEXTURE_RECTANGLE_NV) 
      release_temp(c, tmpcoord);
}