修复PhysX Visual Debugger复杂场景闪退
最近忙于各种优化,有遇到PxScene::simulate()
耗时很长的情况——这时的第一反应就是掏出PVD,想看下是不是场景里是不是又被摆了一堆奇怪的玩意儿。
结果在游戏里Connect Debugger后、PVD直接原地crash,令人尴尬。尝试了下直接在游戏里保存出pvd文件倒是没问题,只不过打开时依然闪退。
感觉就像某些场景里有脏东西,一碰就炸;而另一些场景则是可以正常使用PVD查看。
鉴于PVD本身是没有源代码的,先找找有无平替:
- OmniPVD号称是PVD的替代品
The PhysX Omniverse Visual Debugger (OmniPVD), is the next iteration of PhysX Visual Debugger (PVD), and it consists of a library that is used to both record PhysX simulations as well as to read them back.
- OpenPVD来自毅哥的推荐,作者开坑之初也是因为PVD不开源+N久没更新了,不过看上去项目不火有点心虚…
找雨桐帮忙快速试了手: OmniPVD和PhysX不兼容; OpenPVD虽然没有图形界面,却有意外之喜——使用filter处理pvd文件之后,就可以用PVD打开了!
这样虽然不知道脏东西是什么,但是好歹能看到一些数据了,同时也说明pvd文件本身是合法的。
一时陷入僵局,只能回头看下PVD的crash堆栈有无线索——emmm看上去是准备绘制的时候出幺蛾子:
============================================================================== |
而且为啥这个堆栈解析的这么清晰?翻了下PVD安装文件夹,看到了PVDNext.pdb
之后,不禁产生了一个想法: 要不试试分析下具体原因看看能不能盲修一发?
先用procdump抓个full dump,快速验证了一下确实是memcmp的第一个参数越界了
接下来看OpenGLWidget::addGeometry(std::vector<physx::PxVec3>&, std::vector<unsigned short>&, int)
ps. 看这个函数声明,盲猜传入的应该是position
、indices
和count
a1
相当于是OpenGLWidget
的this
指针v21=a1+808
应该是OpenGLWidget
的某个成员变量,应该是类似偏移量- 闪退堆栈对应
memmove(dst, src, num)
里出现write access violation,就是a1+768
(类似buffer)加偏移量2*v21
到非法地址了
结合后面的glBindBuffer
和glBufferSubData
调用,继续猜测
- 这儿应该是在更新position和indices数据到GL里
a1+796
和a1+804
是两个GL Targeta1+800
和a1+808
是两个size- 盲猜前者是position、后者是indices,正好对上
sizeof(vec3f)=12
,sizeof(short)=2
- 盲猜前者是position、后者是indices,正好对上
到目前为止感觉都能自圆其说,而且让我写也估计就是类似写法来着。索性整理下变量名+盲猜一手成员变量:
越看越觉得靠谱hhh 索性看下对应的构造函数,这个=nullptr
看上去也没问题,那就还得找找到底哪里初始化了这俩buffer来着
最后在OpenGLWidget::initializeGeometryBuffers
里看到默认size给了0x80000
,之后使用的时候也完全没考虑扩容…
搞了半天是只要场景足够复杂,PVD就会爆炸orz
来都来了…直接把这俩buffer的初始大小常量左移一发
尝试了下前面保存的pvd文件,完美打开! 有种感受到出题者思路的快乐(划走)嘿嘿嘿