闲来无事狂写blog,最近的生活就是如此。
这里先对nVIDIA 253一把。2大消费型显卡厂商中,nVIDIA对开发者的支持显然要比ATi要做的更到位些,不管是现在要说的这个性能分析工具还是GPU Gems系列丛书,它为我们这些缺乏技术支持和资金的开发者提供了不少的帮助。
现在讲一下NVPerfHUD是什么。最早接触它是在2004年的上海Perfect Kitchen(中文名是“十全十美厨艺大会” -_-b)的讲座中,那时还是2.0(2.1?)版本,不过演讲者对它的介绍还是让在场所有开发者都感到兴奋。利用这个工具我们可以清楚的得知一些由d3d runtime和driver管理的数据如AGP显存的占用和显卡显存的占用、每帧DP/DIP的调用次数;并提供功能可以很方便的hook应用程序中的一些重要资源。比如说你怀疑是大量的纹理造成了总线带宽不足,那你可以利用NVPerfHUD把所有的纹理都换成2×2的大小。如果这时fps有显著提升,那么很可能在这里就是一个瓶颈。还有其他功能诸如忽略DP/DIP调用、启用/关闭 VS/PS等。
前不久nVIDIA发布了NVPerfHUD的新版本,这次版本号定为3确实可以说名副其实。不仅保留了原先2.1的所有功能,还提供另外2个控制台。一个称为Debug Console Mode,可以观察OutputDebugString的信息(这样就可以部分省去了attach debugger);另一个称为Frame Analysis Mode,在这个控制台下,我们可以把程序渲染整个一帧的动作全截获下来,然后可以随心所欲指定d3d画到哪里。这样可以清楚的看到每一个DP/DIP都在画些什么了,而且当前使用的纹理也显示在左上角。这样非常利于分析引擎中的底层api代码是怎样工作的,同时也大大方便了优化。Frame Analysis Mode的高级界面中,可以提供vertex/pixel shader的分析(是不是把NVShaderPerf的东西整合了进来?),同样可以知道vs/ps对整个渲染效率的影响。不过因为高级着色语言(HLSL)不是d3d runtime的一部分(但是是DirectX的一部分,它一般在载入时进行即时编译),所以我们看到的shader代码都是assembly shader,这一点没办法,让我们这些熟悉高级语言的家伙会有些不知所措。不过assembly shader的东西还算简单,花点时间上去就没问题的。
性能分析工具就只说到这里。关于性能分析的方法学可以参考nVIDIA的白皮书和一些presentation,也是在nVIDIA网站上提供下载。我用过NVPerfHUD和PIX,应该说NVPerfHUD和PIX并不是同一类的产品,但一般情况下我会先用NVPerfHUD试试,PIX可能更靠近d3d的api调用分析吧。以上纯属是自己的想法,持不同见解还望不吝赐教。
Reference:
1. NVPerfHUD 3 Review. Reviewer: Bryan Mau, available at http://www.gamedev.net/features/reviews/productreview.asp?productid=547
2. NVPerfHUD 3. Available at http://developer.nvidia.com/object/nvperfhud_home.html

表误会,说的不是毒品。我说的是一种现象,这种现象在grid-based的pathfinder中相当常见。
是怎样的情况,且由我慢慢说来:pathfinder通常找到的是一条最优路径(如果你的实现是A*的话)。但是最优路径的“最优”二字定义是指两点间“代价”的最小化。这给我们想要的现实表现带来了困扰:最优路径不一定是我们想要的!举最明显的例子,grid-based pathfinder在绕开障碍物时,通常会生成一条曲折的(zigzag)路径。从而你的人物沿着这条路径走,就会不停的改换朝向以适应路径。即使你使用了平滑插值,你还是会看到你的人物不停的摇头,“挤”向该走的方向。
以上的解决方法可以通过一种小技巧来避免。A*算法中,next node和current node之间有一个代价值。这个值可由一个估值函数提供。如果我们在估值函数中加上了对“曲折蛇行”路径的一点小惩罚,也就是说,对每一次A*迭代比较上一次为止产生的路径,如果这个节点所产生的新路径和上一次为止产生的路径方向一致(或小于一个threshold),那么什么事都没有发生;如果这个方向和上一此为止产生的路径方向不一致(或大于一个threshold),那么我们对这个估值函数的返回值上加上一个很小的惩罚值,比如说0.0001f,这个“很小的值”取值应该小于两个节点间的最小距离。这样的话,虽然说这点惩罚值对最终形成“最优路径”的结果没有影响,但是会使A*避免去选择方向改变较多的路径,而选择方向较为稳定的路径。这也正是我们这样做的目的——消灭zigzag。
同样的效果可以通过对生成的路径做post processing达到。处理的基本思想跟上面一致。而我个人比较倾向于上面这种做法,简单易行。
现代3D游戏中真正在runtime时使用A*的似乎越来越少了,因为可以通过节点数据结构的优化进行预处理,直接存储所有的路径信息。比grid-based时代的东西要精致优雅得多。这个以后再讲。
Reference:
1. Game Programming Gems. The Basics of A* for Path Planning, by Bryan Stout
2. Game Programming Gems. A* Aesthetic Optimizations, by Steve Rabin
