2014-10-19 29 views
0

我有一个非常复杂的HLSL着色器,它使用Direct3D9中的着色器模型3来执行吨纹理读取。复杂的代码仅用于某些像素,因此我在该代码块周围放置了一条if语句。令我惊讶的是,这并没有带来性能上的好处。如果我使用clip(-1),我确实看到了巨大的性能提升,所以这个着色器确实是我的程序的瓶颈。为什么没有剪辑(-1)行,分支不会提高我的性能?如何仅通过对某些像素执行复杂代码来优化SM3 HLSL像素着色器?

我找到了这个话题:How much performance do conditionals and unused samplers/textures add to SM2/3 pixel shaders?该主题指出,在着色器模型3中可以优化分支,但性能是每批像素中最差的。在很多情况下,慢分支主要在屏幕的边缘,而快分支主要在屏幕的中心。我认为这意味着批量像素通常会采用同一个分支,所以我期望通过这种方式获得性能提升。

在伪代码的像素着色器看起来是这样的:

float4 colour = tex2D(texture, uv); 
if (colour.a < 0.5f) 
{ 
    //I only get a performance boost if I replace this line with clip(-1); 
    oColour = colour; 
} 
else 
{ 
    complexSlowCodeWithTonsOfTextureReadsGoesHere; 
    oColour = result; 
} 
oColour *= 2; 

这给了我完全一样的性能,当我删除分支和经常使用的代码在缓慢其他分支。如果我用clip(-1)替换第五行,我会看到巨大的性能提升(以及大部分黑屏),因此if语句实际上正在运行。

我在这里做错了什么,或者是不可能在着色器模型3中优化像这样的着色器?

+0

您的着色器是否仅在全屏传球中运行一次?或者它用来绘制多个对象。在使用模板的第一种情况下,可以为您提供相当不错的性能提升。 – catflier 2014-10-20 14:34:00

+0

这是一个全屏幕后效果。为此使用模板缓冲区将非常复杂但可能。但Gnietschow的回复已经很好地回答了我的问题。 :)(我只是刚刚发现我可以点击V标志来表示我的问题已被回答......) – Oogst 2014-10-20 18:12:16

回答

1

问题是,如果您的if将被展平(两者都被执行,错误分支的结果被丢弃),因为您在其中一个分支(doc)中使用了像tex2D这样的渐变函数。如果您从分支中删除这些函数或将其替换为非梯度函数(如tex2Dlod或tex2Dgrad),您应该会看到性能提升。如果在if之前添加[branch],编译器将帮助查找有问题的行。这会提示编译器你想要一个真正的分支,如果你使用梯度函数,编译时会失败。

据我的经验,gpu用2x2碎片计算输出。这需要计算用于纹理查找的正确小平面,因此需要邻居的信息。这可以防止tex2D功能分离,因为它们是相邻操作所需的。如果通过传递miplevel来给gpu提供所需的信息,则不再需要其他碎片,因此该分支可以被实际跳过。

+0

感谢您的非常明确的解释!我转向使用tex2Dlod,现在我确实看到了预期的性能增益! :) 顺便说一句,我清楚地看到在我的framerate中,剪辑(-1)与tex2D一起使用,这让我感到惊讶,因为这也会干扰从邻居那里获取miplevel信息。 – Oogst 2014-10-19 19:38:57

+0

这一点已经让我困惑,不幸的是,我对此没有任何解释。唯一我能想象的是,这种剪辑片段带来了特殊的价值。我希望其他人能够照亮我们:) – Gnietschow 2014-10-19 20:57:53

相关问题