<p></p>
<p>Sending from a mobile, pardon my terseness. ~ C.</p>
<div class="gmail_quote">On Aug 23, 2011 2:42 PM, &quot;Tom Stellard&quot; &lt;<a href="mailto:tstellar@gmail.com">tstellar@gmail.com</a>&gt; wrote:<br type="attribution">&gt; According to the GLSL spec, the implementor can decide which way to round<br>
&gt; when the fraction is .5.  The r300 compiler will round down, so we can use<br>&gt; CND and save an instruction.<br>&gt; ---<br>&gt; <br>&gt; MLAA should work on r300g (r500 only) with this patch.  I&#39;ve tested<br>
&gt; with the kasanen-post-process-v2 branch and it looks OK to me, but it<br>&gt; would be nice to have a second opinion.<br>&gt; <br>&gt; I was testing with: pp_jimenezmlaa=8 glxgears<br>&gt; <br>&gt; src/gallium/drivers/r300/compiler/radeon_opcodes.c |    7 +++<br>
&gt;  src/gallium/drivers/r300/compiler/radeon_opcodes.h |    3 +<br>&gt;  .../drivers/r300/compiler/radeon_program_alu.c     |   54 ++++++++++++++++++++<br>&gt;  src/gallium/drivers/r300/r300_tgsi_to_rc.c         |    2 +-<br>
&gt;  4 files changed, 65 insertions(+), 1 deletions(-)<br>&gt; <br>&gt; diff --git a/src/gallium/drivers/r300/compiler/radeon_opcodes.c b/src/gallium/drivers/r300/compiler/radeon_opcodes.c<br>&gt; index afd78ad..527db9a 100644<br>
&gt; --- a/src/gallium/drivers/r300/compiler/radeon_opcodes.c<br>&gt; +++ b/src/gallium/drivers/r300/compiler/radeon_opcodes.c<br>&gt; @@ -246,6 +246,13 @@ struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = {<br>&gt;                  .IsStandardScalar = 1<br>
&gt;          },<br>&gt;          {<br>&gt; +                .Opcode = RC_OPCODE_ROUND,<br>&gt; +                .Name = &quot;ROUND&quot;,<br>&gt; +                .NumSrcRegs = 1,<br>&gt; +                .HasDstReg = 1,<br>&gt; +                .IsComponentwise = 1<br>&gt; +        },<br>&gt; +        {<br>&gt;                  .Opcode = RC_OPCODE_RSQ,<br>
&gt;                  .Name = &quot;RSQ&quot;,<br>&gt;                  .NumSrcRegs = 1,<br>&gt; diff --git a/src/gallium/drivers/r300/compiler/radeon_opcodes.h b/src/gallium/drivers/r300/compiler/radeon_opcodes.h<br>&gt; index b586882..968dc7b 100644<br>
&gt; --- a/src/gallium/drivers/r300/compiler/radeon_opcodes.h<br>&gt; +++ b/src/gallium/drivers/r300/compiler/radeon_opcodes.h<br>&gt; @@ -133,6 +133,9 @@ typedef enum {<br>&gt;          /** scalar instruction: dst = 1 / src0.x */<br>
&gt;          RC_OPCODE_RCP,<br>&gt;  <br>&gt; +        /** vec4 instruction: dst.c = frc(src0.c) &gt; 0.5 ? ceil(src0.c) : floor(src0.c) */<br>&gt; +        RC_OPCODE_ROUND,<br>&gt; +<br>&gt;          /** scalar instruction: dst = 1 / sqrt(src0.x) */<br>
&gt;          RC_OPCODE_RSQ,<br>&gt;  <br>&gt; diff --git a/src/gallium/drivers/r300/compiler/radeon_program_alu.c b/src/gallium/drivers/r300/compiler/radeon_program_alu.c<br>&gt; index e273bc4..0bfd2dc 100644<br>&gt; --- a/src/gallium/drivers/r300/compiler/radeon_program_alu.c<br>
&gt; +++ b/src/gallium/drivers/r300/compiler/radeon_program_alu.c<br>&gt; @@ -104,6 +104,13 @@ static const struct rc_src_register builtin_one = {<br>&gt;          .Index = 0,<br>&gt;          .Swizzle = RC_SWIZZLE_1111<br>&gt;  };<br>
&gt; +<br>&gt; +static const struct rc_src_register builtin_half = {<br>&gt; +        .File = RC_FILE_NONE,<br>&gt; +        .Index = 0,<br>&gt; +        .Swizzle = RC_SWIZZLE_HHHH<br>&gt; +};<br>&gt; +<br>&gt;  static const struct rc_src_register srcreg_undefined = {<br>
&gt;          .File = RC_FILE_NONE,<br>&gt;          .Index = 0,<br>&gt; @@ -416,6 +423,52 @@ static void transform_POW(struct radeon_compiler* c,<br>&gt;          rc_remove_instruction(inst);<br>&gt;  }<br>&gt;  <br>&gt; +/* dst = ROUND(src) :<br>
&gt; + *   frac = FRC(src)<br>&gt; + *   low = src - frac<br>&gt; + *   high = low + 1<br>&gt; + *   dst = CND high, low, frac<br>&gt; + *<br>&gt; + * According to the GLSL spec, the implementor can decide which way to round<br>
&gt; + * when the fraction is .5.  In this case we round down, so we can use<br>&gt; + * CND and save an instruction.<br>&gt; + *<br>&gt; + * The optimizer should reduce this sequence to 3 instructions using<br>&gt; + * presubtract.<br>
&gt; + */<br>&gt; +static void transform_ROUND(struct radeon_compiler* c,<br>&gt; +        struct rc_instruction* inst)<br>&gt; +{<br>&gt; +        unsigned int mask = inst-&gt;U.I.DstReg.WriteMask;<br>&gt; +        unsigned int frac_index, low_index, high_index;<br>
&gt; +        struct rc_dst_register frac_dst, low_dst, high_dst;<br>&gt; +        struct rc_src_register frac_src, low_src, high_src;<br>&gt; +<br>&gt; +        /* frac = FRC(src) */<br>&gt; +        frac_index = rc_find_free_temporary(c);<br>&gt; +        frac_dst = dstregtmpmask(frac_index, mask);<br>
&gt; +        emit1(c, inst-&gt;Prev, RC_OPCODE_FRC, 0, frac_dst, inst-&gt;U.I.SrcReg[0]);<br>&gt; +        frac_src = srcreg(RC_FILE_TEMPORARY, frac_dst.Index);<br>&gt; +<br>&gt; +        /* low = src - frc */<br>&gt; +        low_index = rc_find_free_temporary(c);<br>
&gt; +        low_dst = dstregtmpmask(low_index, mask);<br>&gt; +        emit2(c, inst-&gt;Prev, RC_OPCODE_ADD, 0, low_dst,<br>&gt; +                                        negate(inst-&gt;U.I.SrcReg[0]), frac_src);<br>&gt; +        low_src = srcreg(RC_FILE_TEMPORARY, low_dst.Index);<br>
&gt; +<br>&gt; +        /* high = low + 1 */<br>&gt; +        high_index = rc_find_free_temporary(c);<br>&gt; +        high_dst = dstregtmpmask(high_index, mask);<br>&gt; +        emit2(c, inst-&gt;Prev, RC_OPCODE_ADD, 0, high_dst, low_src, builtin_one);<br>
&gt; +        high_src = srcreg(RC_FILE_TEMPORARY, high_dst.Index);<br>&gt; +<br>&gt; +        /* dst = CND high, low, frac */<br>&gt; +        emit3(c, inst-&gt;Prev, RC_OPCODE_CND, 0, inst-&gt;U.I.DstReg,<br>&gt; +                                                high_src, low_src, frac_src);<br>
&gt; +        rc_remove_instruction(inst);<br>&gt; +}<br>&gt; +<br>&gt;  static void transform_RSQ(struct radeon_compiler* c,<br>&gt;          struct rc_instruction* inst)<br>&gt;  {<br>&gt; @@ -599,6 +652,7 @@ int radeonTransformALU(<br>
&gt;          case RC_OPCODE_LIT: transform_LIT(c, inst); return 1;<br>&gt;          case RC_OPCODE_LRP: transform_LRP(c, inst); return 1;<br>&gt;          case RC_OPCODE_POW: transform_POW(c, inst); return 1;<br>&gt; +        case RC_OPCODE_ROUND: transform_ROUND(c, inst); return 1;<br>
&gt;          case RC_OPCODE_RSQ: transform_RSQ(c, inst); return 1;<br>&gt;          case RC_OPCODE_SEQ: transform_SEQ(c, inst); return 1;<br>&gt;          case RC_OPCODE_SFL: transform_SFL(c, inst); return 1;<br>&gt; diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c<br>
&gt; index 07a3f3c..4cb08b5 100644<br>&gt; --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c<br>&gt; +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c<br>&gt; @@ -57,7 +57,7 @@ static unsigned translate_opcode(unsigned opcode)<br>
&gt;          case TGSI_OPCODE_FRC: return RC_OPCODE_FRC;<br>&gt;          case TGSI_OPCODE_CLAMP: return RC_OPCODE_CLAMP;<br>&gt;          case TGSI_OPCODE_FLR: return RC_OPCODE_FLR;<br>&gt; -     /* case TGSI_OPCODE_ROUND: return RC_OPCODE_ROUND; */<br>
&gt; +        case TGSI_OPCODE_ROUND: return RC_OPCODE_ROUND;<br>&gt;          case TGSI_OPCODE_EX2: return RC_OPCODE_EX2;<br>&gt;          case TGSI_OPCODE_LG2: return RC_OPCODE_LG2;<br>&gt;          case TGSI_OPCODE_POW: return RC_OPCODE_POW;<br>
&gt; -- <br>&gt; 1.7.3.4<br>&gt; <br>&gt; _______________________________________________<br>&gt; mesa-dev mailing list<br>&gt; <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>&gt; <a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</div>