当我使用pow(foo, 6)
或pow(foo, 8)
编译HLSL着色器时,编译器会创建比使用pow(foo, 9)
或{{1}创建相同着色器多10个指令的程序集}或pow(foo,10)
。
为什么?
答案 0 :(得分:5)
说明或说明插槽?
pow
指令需要三个3个插槽,而mul
指令只需要1个。
(参考:指令集:vs_2_0,ps_2_0,vs_3_0,ps_3_0)
在编写着色器时,您通常希望保持指令槽倒计时,因为着色器模型定义的指令槽数量有限。它也是估算着色器计算复杂度的合理方法(即:它的运行速度)。
1的幂显然是无操作。 2的幂需要一条mul
指令。使用两个mul
指令可以完成3和4的幂。 5,6和8的权力可以用三个mul
指令完成。
(我想这个优化背后的数学是由Jim Lewis发布的link解释的。)
编译器在单个mul
指令上选择三个pow
指令(两者都使用相同数量的指令槽)的可能原因是具有常量指数的pow
指令将还需要分配一个常量寄存器来存储该指数。显然,使用三个指令槽并且没有常数寄存器比使用三个槽和一个常量寄存器更好。
(为什么你得到 10 更多的指令?我不确定,它将取决于你的着色器代码.HLSL编译器在优化的名义下做了许多奇怪而美妙的事情。)
如果您使用选项fxc
在DirectX SDK中使用着色器编译器(/Cc /Fc output.html
),它将为您提供一个可以检查的精美汇编读数,包括指令槽数的计数使用
答案 1 :(得分:1)
它可能正在进行某种exponentiation by squaring优化,其中操作的数量取决于指数中设置为1的位数及其位置。 (但这与你所描述的内容并不完全相符:在纯方形和乘法实现中,你期望2的幂比设置更多位的指数更有效。)