mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-30 19:24:23 +01:00
Replace length()/normalize() with inversesqrt() pattern for better
performance on mobile GPUs. The inversesqrt instruction is a single
hardware operation, while length() requires sqrt(dot()) and normalize()
requires inversesqrt internally plus a multiply.
Changes:
1. Light distance calculation:
Before: distance = length(toLight); toLight /= distance;
After: distSq = dot(toLight, toLight);
invDist = inversesqrt(distSq);
distance = distSq * invDist;
toLight *= invDist;
2. Specular half-vector normalization:
Before: ldot = dot(normalize(toLight + vec3(0,0,1)), worldnormal);
After: halfVec = toLight + vec3(0,0,1);
halfInvLen = inversesqrt(dot(halfVec, halfVec));
ldot = dot(halfVec, worldnormal) * halfInvLen;
Also reuses distSq in attenuation calculation to avoid recomputing
distance*distance.
Offline shader compiler results (vertex shader with 4-light ubershader):
Mali (malioc):
G31 (Bifrost): 44.90 -> 40.50 cycles (-9.8%)
G52 (Bifrost): 14.97 -> 13.50 cycles (-9.8%)
G310 (Valhall): 13.88 -> 12.88 cycles (-7.2%)
G57 (Valhall): 7.60 -> 6.97 cycles (-8.3%)
PowerVR (Profiling Compilers):
Series 8 GE8300: 322 -> 302 ALU cycles (-6.2%)
Series 9 GM9445: 296 -> 280 ALU cycles (-5.4%)
Series B BXM: 560 -> 540 instructions (-3.6%)
Signed-off-by: Chris Healy <cphealy@gmail.com>