Reciprocal, RSqrt, and SqrtΒΆ

On the PowerVR Rogue and Volcanic architectures, the reciprocal operation is directly supported by an instruction (RCP):

fragColor.x = 1.0 / t.x; // one cycle
{frcp}

// Instructions on Volcanic:
fragColor.x = 1.0 / t.x;
{rcp}

The same is true with the inversesqrt() function (RSQ):

fragColor.x = inversesqrt(t.x); // one cycle
{frsq}

// Instructions on Volcanic:
fragColor.x = 1.0 / t.x;
{rsq}

However, sqrt() is implemented as: 1 / (1/sqrt(x)).

This results in a two cycle cost:

fragColor.x = sqrt(t.x); // two cycles
{frsq}
{frcp}

// Instructions on Volcanic:
fragColor.x = sqrt(t.x);
{rsq}
{rcp}

A commonly used alternative: x * 1/sqrt(x) gives the same two cycle results.

fragColor.x = t.x * inversesqrt(t.x); // two cycles
{frsq}
{sop, sop}

// Instructions on Volcanic:
fragColor.x = t.x * inversesqrt(t.x);
{rsq}
{mul}

The only case when it is better to use the above alternative is if the result is tested. In this case, the test instructions can fit into the second instruction.

fragColor.x = sqrt(t.x) > 0.5 ? 0.5 : 1.0; // three cycles
{frsq}
{frcp}
{mov, mov, pck, tstg, mov}
-->
fragColor.x = (t.x * inversesqrt(t.x)) > 0.5 ? 0.5 : 1.0; // two cycles
{frsq}
{fmul, pck, tstg, mov}

// Instructions on Volcanic:
fragColor.x = sqrt(t.x) > 0.5 ? 0.5 : 1.0;
{rsq}
{rcp}
p0 = r0 > 0.5f (sc42)
{movc}
-->
fragColor.x = (t.x * inversesqrt(t.x)) > 0.5 ? 0.5 : 1.0;
{rsq}
{mul}
p0 = i0 > 0.5f (sc42)
{movc}