Saturday, February 17, 2007
我遭遇的nVidia和ATI driver的硬伤
nVidia和ATI无疑是优秀的,他们的芯片技术各展所长,各擅胜场。
我做Splinter Cell: Double Agent的图形优化的时候,遭遇了这两家各一个硬伤。有趣的是,两者都是Driver里的bug,而且表现也有几分相似。
先说nVidia的:场景中的某些位置,会突然“卡”(lag)一下;用NVPerfHUD“侦查”发现导致“卡”的瓶颈是pixel shader。而罪魁祸首,是nVidia显卡Driver中的一个小动作(据nVidia的专家说现在的Driver已经X掉这个bug了)。nVidia的专家说:vertex shader must be correctly setup in order to have the pixel shader not being re-optimized. This sounds weird but this is the way our driver works (for obscure reasons). 让我解释一下细节:在某些情况下,nVidia的driver可能会重新编译microcode来优化系统,因此即使你已经对所有能想到的事物做了cache,仍旧可能出现上述的“卡”的现象,因为driver在编译microcode。因此nVidia专家才会说你必须谨慎对待vertex shader的设置以便他们的driver不再做重新编译microcode来优化系统。那么你应该怎么处理vertex shader呢?专家如是说:To sum-up what can cause the Optimizer to recompile the microcode for optimization, here is a list of things that will trigger opmization if ever changed :
- whether fog is enabled or not- the exact fog mode (linear, exp, exp2)
- whether specular is enabled (tblend or TSS only)- whether sRGB writes are enabled
- the src/dst alpha blend modes (if alpha test and alpha blend are enabled)
- whether alpha test is enabled and the exact alpha test mode when using MRT
- whether you mix different formats when using MRT rendering
- whether the render target is floating point or not
- whether alpha is written (i.e, do we have an X8 buffer or an RGB-only writemask)
- whether RGB is written (is the writemask null or alpha-only?)
- whether projective textures are enabled (for TSS and PS <=1.3 only)
- whether a texture lookup references an FP32, FP16, or other format texture
- whether a texture lookup uses sRGB or not- whether a texture is 2D, 3D, or a cube map
- whether a texture is a shadow map or not
-whether a texture is any of several "special" formats (R32F, G16R16F, G32R32F, A16B16G16R16)- the 16 boolean constants
- the vertex shader
这会让人抓狂,按照我的经验,如果你妄图通过谨慎处理这些情况来避免Driver重新编译microcode,确实会让你抓狂!尤其当你的时间很紧,系统又很大。我的办法是:让pixel shader中的所有动态分支情况都运行一遍;换句话说,就是让程序模拟玩家在场景中跑上一遍。结论是:效果显著。
再说ATI的:场景的某些位置,转动camera,FPS会变得很低;停止转动,一段时间后FPS会突然跳高,恢复到正常水平。很显然,这不是cache的问题,极可能是Driver又做了不欲为人知的事情。
先描述我的经历:
那个时候ATI还没有类似nVidia的NVPerfHUD的工具。我用土方法,将问题定位到了pixel shader,是Global Illumination导致的问题。具体来说就是,我们使用了RGBe格式来做GI Light Map,然后运行时在pixel shader中做解压的工作。ATI的朋友曾经很肯定地跟我说:“我们的显卡运算能力比Nvidia要强,所以建议你们少用texture,多用计算。”那么为什么nVidia行,ATI却不行呢?那个解压缩的程序,并不复杂啊?这还不是最绝的,绝的是我们解决这个问题的方法:将pixel shader中调用的函数中的某条语句移出到函数外面。我能想到的是这种方法改变了编译器编译出的代码,因此性能表现上不同也就不足为奇了。可比较改动前后assembly代码发现并没有什么不同。还有更绝的,将那个被调用到的函数中的一个static flow control去掉,竟然会导致问题的再次出现。
因此我有理由做出猜测:ATI pixel shader的计算能力,是毋庸置疑的。我们所遇到的问题,并不是计算能力不行,因为问题解决前后所得到的assembly是相同的。因此问题的症结应该是Driver试图做的某些优化,反而使得芯片性能下降。辩证法啊!!!
后记:我在ATI的朋友后来证明了我的猜测,他们已经修掉了这个bug。
Subscribe to:
Posts (Atom)