我有一个顶点着色器
void main (){
vec4 wPos = modelMatrix * vec4( position , 1. );
vWorldPosition = wPos.xyz;
float mask = step(
0.,
dot(
cameraDir,
normalize(normalMatrix * aNormal)
)
);
gl_PointSize = mask * uPointSize;
gl_Position = projectionMatrix * viewMatrix * wPos;
}
我不完全确定如何测试着色器的性能,并排除其他因素,如过度绘制。我想象一个大小为1的点,在屏幕空间中排列成网格,没有任何重叠会起作用吗?
否则我对这些调整感到好奇:
(删除step
,删除乘法,介绍if
else
)
void main (){
if(dot(
cameraDir,
normalize(normalMatrix * aNormal) //remove step
) < 0.) {
gl_Position = vec4(0.,.0,-2.,.1);
gl_PointSize = 0.;
} else {
gl_PointSize = uPointSize; //remove a multiplication
vec4 wPos = modelMatrix * vec4( position , 1. );
vWorldPosition = wPos.xyz;
gl_Position = projectionMatrix * viewMatrix * wPos;
}
}
对比这样的事情:
void main (){
if(dot(
cameraDir,
normalize(normalMatrix * aNormal)
) < 0.) {
gl_Position = vec4(0.,.0,-2.,.1);
return;
}
gl_PointSize = uPointSize;
vec4 wPos = modelMatrix * vec4( position , 1. );
vWorldPosition = wPos.xyz;
gl_Position = projectionMatrix * viewMatrix * wPos;
}
这些着色器的行为会不同,为什么/如何?
我感兴趣的是,有什么东西可以量化性能上的差异。
floor
代替step
也可能吗?):
float condition = clamp(floor(myDot + 1.),0.,1.); //is it slower?
答案 0 :(得分:1)
有条件分支在GPU上很昂贵 - 通常比乘法更昂贵,因此修改后的着色器可能会更慢。
答案 1 :(得分:1)
有太多变量,所以答案是“它取决于”。一些GPU可以处理分支。有些不能和代码被编译器扩展,因此没有分支,只有数学乘以0而其他数学不是。然后有一些事情,比如平铺GPU,试图积极避免透支。我确定还有其他因素。
理论上,您可以运行着色器的百万或几百万次迭代并使用
计时gl.readPixels(one pixel);
const start = performance.now();
...draw a bunch..
gl.readPixels(one pixel);
const end = performance.now();
const elapsedTime = end - start;
gl.readPixels
是一个同步操作,因此它会停止GPU管道。
elapsedTime
本身并不是实际的时间,因为它包括启动GPU并将其停止等等,但似乎您可以将一个着色器中的elapsedTime
与另一个着色器进行比较以查看哪个更快。
换句话说,如果elapsedTime
为10秒,则并不意味着您的着色器需要十秒钟。这意味着启动gpu,运行着色器并停止GPU需要10秒钟。这些秒数中有多少是开始的,有多少是停止的,有多少是你的着色器不可用。但是,如果一个着色器的elaspedTime
为10秒而另一个着色器为11,那么可以说一个着色器比另一个着色器快。请注意,您可能希望让测试时间足够长,以便获得几秒钟的差异而不是微秒的差异。您还需要在多个GPU上进行测试,以确定速度差异是否始终为真。
请注意,在顶点着色器中调用return
不会阻止生成顶点。事实上,gl_Position
在这种情况下是未定义的。