GLSL IF速度与乘法因子

时间:2015-08-31 07:24:35

标签: android ios windows opengl glsl

我知道这个问题已被普遍提出,但答案是“依赖”,所以我正在创建一个具体的问题,希望得到一个具体的答案。

我知道IF在GLSL上的邪恶,它们可能非常昂贵,甚至在某些硬件中执行所有代码。

所以,我有一个示例的碎片着色器(双抛物面阴影贴图),它使用if来确定使用哪个贴图并计算深度,但我知道用乘数替换那些是非常容易的,问题在片段着色器中是否有纹理采样,使用if或使用乘数来过滤未使用的数据会更快?

这些是建议的代码:

IF版本:

//Alpha is a variable computed on the fly, cannot be replaced

float depth = 0;
float mydepth = 0;

if(alpha >= 0.5f)
{
    depth = texture2D(ShadowFrontS, P0.xy).x;
    mydepth = P0.z;
}
else
{
    depth = texture2D(ShadowBackS, P1.xy).x;
    mydepth = P1.z;
}

过滤版本:

float mlt = ceiling(alpha - 0.5f);

float depth = 0;
float mydepth = 0;

depth = texture2D(ShadowFrontS, P0.xy).x * mlt;
mydepth = P0.z * mlt;
mlt = 1.0f - mlt;
depth = depth + (texture2D(ShadowFrontS, P1.xy).x * mlt);
mydepth = P1.z * mlt;

P.D。:我的目标是桌面和移动设备,因此必须在低端硬件上实现性能。

1 个答案:

答案 0 :(得分:7)

分支在大规模SIMD架构上并非“邪恶”。如果“束”中的所有线程(NVidia称它们为Warps)遵循相同的代码路径,即采用所有相同的分支,一切都很好。

只有部分分支(在该分支内)而另一部分不分支,必须执行两个分支,然后在计算和数据提取中丢弃与当前线程无关的分支。

现在,在您的情况下,需要仔细分析才能看到,哪种变体有利于您的GPU。但我的直觉告诉我,它实际上是分支版本。为什么?因为:通常您决定分支的值取决于屏幕空间位置,并且通常大的连续片段区域共享相同的代码路径和分支;因此,性能惩罚只发生在那些覆盖边界地区的“束”中。这些束通常只有几个像素大小(8×8或16×16)。

你在那里使用的着色器不受GPU限制(即受GPU的计算能力限制),但是内存带宽受限,即GPU的内存链接提供的吞吐量;这是因为texture2D获取操作。在这种情况下,减少实际的读取次数,从而减少所需的内存带宽,可能会使计划受益,而不是减少计算次数。

着色器的无分支mix-multiplex变体将始终获取两个纹理,分支将仅在边界区域内执行。所以,从那个启发式算法我猜,你的分支变体实际上是更好的选择。

但是要确保你必须个人资料它。