<div dir="ltr">Hi all,<div><br></div><div>I've been looking at some shaders from Portal recently.</div><div>A lot of them seem to hand-roll a pow-function with </div><div>log2, multiply, and exp2, like this:</div><div>
<div><br></div><div>r3.x = log2( r3.x );</div><div>r3.y = log2( r3.y );</div><div>r3.z = log2( r3.z );</div><div>r3.xyz = r3.xyz * vd2.zzz;</div><div>r3.x = exp2( r3.x );</div><div>r3.y = exp2( r3.y );</div><div>r3.z = exp2( r3.z );</div>
</div><div><br></div><div>The corresponding output from the shader-db run shows:</div><div><br></div><div><div> (assign (xyz) (var_ref r3) (expression vec3 log2 (swiz xyz (var_ref r3) )) ) </div><div>0x000003c8: math log(8) g27<1>.xyzF g27<4,4,1>.xyzzF null { align16 WE_normal 1Q compacted };</div>
<div> (assign (xz) (var_ref r6) (swiz yy (array_ref (var_ref vc) (constant int (0)) ) )) </div><div>0x000003d0: mov(8) g25<1>.xzF g1<0,4,1>.yF { align16 WE_normal 1Q };</div>
<div> (assign (w) (var_ref r0) (expression float + (expression float dot (swiz xyz (array_ref (var_ref vc) (constant int (28)) ) )(expression vec3 neg (swiz xyz (var_ref r5) )) ) (expression float neg (swiz z (array_ref (var_ref vc) (constant int (30)) ) )) ) ) </div>
<div>0x000003e0: dp3(8) g105<1>.xF g5.4<0,4,1>.xyzzF -g26<4,4,1>.xyzzF { align16 WE_normal 1Q };</div><div> (assign (xyz) (var_ref r0) (expression vec3 + (expression vec3 * (swiz xyz (var_ref r0) )(expression vec3 neg (swiz xxx (var_ref inversesqrt_retval) )) ) (expression vec3 neg (swiz xyz (array_ref (var_ref vc) (constant int (28)) ) )) ) ) </div>
<div>0x000003f0: mad(8) g30<1>.xyzF g108<4,4,1>F.xyzz g30<4,4,1>F.xyzz -g97<4,4,1>F.x { align16 WE_normal 1Q };</div><div> (assign (xyz) (var_ref r6) (expression vec3 * (swiz yxx (var_ref r7) )(swiz xyz (var_ref r6) )) ) </div>
<div>0x00000400: mul(8) g25<1>.xyzF g24<4,4,1>.yxxxF g25<4,4,1>.xyzzF { align16 WE_normal 1Q };</div><div> (assign (xyz) (var_ref r3) (expression vec3 * (swiz xyz (var_ref r3) )(constant vec3 (2.200000 2.200000 2.200000)) ) ) </div>
<div>0x00000410: mul(8) g27<1>.xyzF g27<4,4,1>.xyzzF 2.2F { align16 WE_normal 1Q };</div><div> (assign (w) (var_ref r0) (expression float + (expression float dot (swiz xyz (array_ref (var_ref vc) (constant int (28)) ) )(expression vec3 neg (swiz xyz (var_ref r5) )) ) (expression float neg (swiz z (array_ref (var_ref vc) (constant int (30)) ) )) ) ) </div>
<div>0x00000420: add(8) g107<1>.xF g105<4,4,1>.xF -g6.4<0,4,1>.zF { align16 WE_normal 1Q };</div><div> (assign (xyz) (var_ref r0) (expression vec3 + (expression vec3 * (swiz www (array_ref (var_ref vc) (constant int (27)) ) )(swiz xyz (var_ref r0) )) (swiz xyz (var_ref r5) )) ) </div>
<div>0x00000430: mad(8) g30<1>.xyzF g26<4,4,1>F.xyzz g5.3<0,1,0>F.w g30<4,4,1>F.xyzz { align16 WE_normal 1Q };</div><div> (assign (x) (var_ref dot_retval) (expression float dot (swiz xyz (array_ref (var_ref vc) (constant int (31)) ) )(swiz xyz (var_ref r6) )) ) </div>
<div>0x00000440: dp3(8) g18<1>.xF g7<0,4,1>.xyzzF g25<4,4,1>.xyzzF { align16 WE_normal 1Q compacted };</div><div> (assign (xyz) (var_ref r3) (expression vec3 exp2 (swiz xyz (var_ref r3) )) ) </div>
<div>0x00000448: math exp(8) g27<1>.xyzF g27<4,4,1>.xyzzF null { align16 WE_normal 1Q compacted };</div></div><div><br></div><div><br></div><div>As far as I've been able to understand, the i965 hardware</div>
<div>has a pow() instruction, how is this with other hardware?</div><div><br></div><div>I've considered writing an algebraic optimization to convert</div><div>this into an ir_binop_pow. If my understanding is correct the backend</div>
<div>will then implement this in a similar fashion as above if it does not</div><div>have a native pow() instruction.</div><div><br></div><div>If, on the other hand, we have a pow() instruction, my guess is</div><div>we'd see reduced instruction-counts.</div>
<div><br></div><div>Is my understanding correct? Is this something that's worth doing?</div><div><br></div><div>regards,</div><div>Thomas Helland</div></div>