上一篇文章中,我们解析了Shader解析后的代码。我们在这篇文章中来看怎么实现Shader指令优化
在DirectX平台,常数运算是不占指令数的。但是,稳妥起见我们最好自己计算好常数计算的结果。防止其他平台认为常数运算需要占指令。
fixed4 frag (v2f i) : SV_Target
{
//常数基本计算
return 2 * 3;
}
ps_4_0
dcl_output o0.xyzw
0: mov o0.xyzw, l(6.000000,6.000000,6.000000,6.000000)
1: ret
定义临时存储变量,也是不消耗指令数的,对性能没有影响
fixed4 frag (v2f i) : SV_Target
{
//常数基本计算
fixed4 c = 0.2 * 3 / sin(4);
fixed4 c1 = c;
return c1;
}
ps_4_0
dcl_output o0.xyzw
0: mov o0.xyzw, l(-0.792809,-0.792809,-0.792809,-0.792809)
1: ret
变量的基本运算,是会使用GPU计算指令的。因为变量在计算前是未知的,会预留计算指令
_Value(“Value”,Vector) = (0,0,0,0)
fixed4 frag (v2f i) : SV_Target
{
//2、变量基本运算
float a = _Value.x;
float b = _Value.y;
float c = _Value.z;
float d = _Value.w;
float e = 1 + a;
return e;
}
ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
0: add o0.xyzw, cb0[2].xxxx, l(1.000000, 1.000000, 1.000000, 1.000000)
1: ret
e = 1 - a;
ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
0: add o0.xyzw, -cb0[2].xxxx, l(1.000000, 1.000000, 1.000000, 1.000000)
1: ret
e = 3 * a
ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
0: mul o0.xyzw, cb0[2].xxxx, l(3.000000, 3.000000, 3.000000, 3.000000)
1: ret
e = 3 / a
ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
0: div o0.xyzw, l(3.000000, 3.000000, 3.000000, 3.000000), cb0[2].xxxx
1: ret
e = 3 * a * b;
ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
dcl_temps 1
0: mul r0.x, cb0[2].x, cb0[2].y
1: mul o0.xyzw, r0.xxxx, l(3.000000, 3.000000, 3.000000, 3.000000)
2: ret
e = 3 * a + b;
ps_4_0
dcl_constantbuffer CB0[3], immediateIndexed
dcl_output o0.xyzw
0: mad o0.xyzw, cb0[2].xxxx, l(3.000000, 3.000000, 3.000000, 3.000000), cb0[2].yyyy
1: ret
if(i.uv.x < 0.5)
{
i.uv.x = 1;
}
else
{
i.uv.x = 0;
}
return i.uv.x;
这里我们可以使用 step 函数来替代 该 条件语句
替代后,虽然编译结果一样的。但是,这是因为 条件语句 的程序体太简单
如果遇到比较复杂的 条件语句,我们可以使用 结合 step 和 算法的方法 把条件语句剔除
使用 step 函数后:
return step(0.5,i.uv.x);
float e = 0;
for(int i = 0;i < 5;i++)
{
e += 0.1;
}
return e;
优化前:
float e = (a + b) * (a - b);
return e;
float e = a * a * (-b * b);
return e;
一维向量(常数):
float e = normalize(a);
return e;
float e = normalize(_Value);
return e;
传入式子:
float e = abs(a * b);
return e;
float e = abs(a) * abs(b);
return e;
移动前:
float e = -dot(a,a);
return e;
移动后:
float e = dot(-a,a);
return e;
结合前:
float3 e = _Value.xyz * a * b * _Value.yzw * c * d;
return fixed4(e,1);
结合后:
float3 e = (_Value.xyz * _Value.yzw) * (a * b * c * d);
return fixed4(e,1);
float e = asin(a);
return e;