DirectX应用程序每3秒"打嗝"一次

Tim*_*man 9 c++ directx frame-rate directx-11 lag

我已经在我的DirectX 11 C++应用程序中调查了一个多星期的问题,所以我转向StackOverflow上的优秀人员,以获得可以帮助我跟踪这个问题的任何见解.

我的应用程序将主要以每秒60-90帧的速度运行,但是每隔几秒我就会得到一个大约需要三分之一秒才完成的帧.经过大量调查,调试和使用各种代码分析器后,我将其缩小到调用DirectX API.但是,从一个慢帧到另一个慢帧,并不总是导致减速的相同API调用.在我最近的运行中,停止的呼叫(总是大约五分之一秒)是

  • ID3D11DeviceContext:UpdateSubresource
  • ID3D11DeviceContext:DrawIndexed
  • IDXGISwapChain:现状

它不仅与停止的功能不同,而且这些功能中的每一个(主要是前两个)慢速调用可能来自我的代码中从一个到另一个的不同位置.

根据多个分析工具和我自己的高分辨率计时器,我放入我的代码来帮助测量事物,我发现这个"打嗝"会以不到3秒(~2.95)的一致间隔发生.

此应用程序从外部硬件收集数据,并使用DirectX实时显示该数据.在应用程序运行时,硬件可能处于空闲状态或以各种速度运行.硬件越快,收集的数据越多,必须可视化.我指出这一点,因为在考虑这个bug的一些特征时它可能是有用的:

  • 硬件空闲时不会出现长帧.这对我来说很有意义,因为软件只需要重绘已有的数据,而不必将新数据传输到GPU.
  • 但是,无论硬件运行的速度如何,长帧都以这些一致的3秒间隔发生.因此,即使我的应用程序每秒收集两倍的数据量,长帧的频率也不会改变.
  • 这些长帧的持续时间非常一致.总是在0.25到0.3秒之间(我相信这是对DirectX API的缓慢调用是一致的,因此整个帧持续时间的任何变化都是该调用的外部).
  • 在上周进行现场测试时(当我第一次发现这个问题时),我注意到在几次运行的应用程序中,经过很长时间(可能是20分钟或更长时间)的连续测试,除了观看之外没有与程序交互太多,打嗝会消失.如果我们与应用程序的某些功能进行交互或重新启动程序,则会出现打嗝.对我来说没有意义,但几乎就像GPU"想通"并修复了问题,但当我们改变了以前做过的工作模式时又回来了.不幸的是,我们硬件的性质使我很难在实验室环境中复制它.

这个错误在具有非常相似硬件的两台不同机器上持续发生(双GTX580卡).但是,在最新版本的应用程序中,没有发生此问题.不幸的是,代码自那时起经历了许多变化,因此很难确定导致问题的具体变化.

我考虑过图形驱动程序,因此更新到最新版本,但这并没有什么区别.我还考虑过对两台计算机进行了一些其他更改的可能性,或者可能对这两台计算机上运行的软件的更新都可能导致GPU出现问题.但是,除了在应用程序运行时在两台机器上运行的Microsoft Security Essentials之外,我无法想到任何其他内容,而且我已经尝试禁用它的实时保护功能无济于事.

虽然我很乐意将原因作为一个我可以关闭的外部程序,但最终我担心我必须使用DirectX API做错误/不正确的事情导致GPU必须每隔几秒进行一次调整.也许我在更新GPU上的数据的方式上做错了(因为滞后只发生在我收集要显示的数据时).然后GPU每隔几秒就会停止一次,在停顿期间碰巧调用的任何API函数都无法像通常那样快速返回?

任何建议将不胜感激!

蒂姆,谢谢

更新(2013.01.21):

我终于放弃了,然后回顾了我的应用程序的先前版本,直到找到了这个错误未发生的点.然后我通过修订进行了修订,直到找到错误发生的确切时间,并设法找出问题的根源.在我向顶点类型添加"无符号整数"字段后,问题就开始了,我为其分配了一个大的顶点缓冲区.由于顶点缓冲区的大小,此更改将大小增加184.65 MB(1107.87 MB到1292.52).因为我确实在我的顶点结构中需要这个额外的字段,我找到了其他方法来削减整个顶点缓冲区大小,并将其降低到704.26 MB.

我最好的猜测是,添加该字段和所需的额外内存会导致我超过GPU上的某个阈值/限制.我不确定它是否超出了总内存分配,或者是单个顶点缓冲区的超出限制.无论哪种方式,似乎这种过剩导致GPU每隔几秒就必须每隔几秒钟做一些额外的工作(可能与CPU通信),所以我对API的调用必须等待.如果有人有任何信息可以澄清大顶点缓冲区的含义,我很乐意听到它!

感谢所有给我时间和建议的人.

bob*_*obo 1

1)尝试打开VSYNC

2)您是否分配/释放大块内存?尝试在程序开始时分配内存并且不要释放它,只需覆盖它(这可能就是您对 updatesubresource 所做的事情)

3)将与硬件设备的交互放在单独的线程上。设备完全完成向应用程序传递数据后,将其加载到 GPU 中。不要让设备控制主线程。我怀疑设备经常阻塞主线程,我完全是猜测,但如果您直接将数据从设备复制到 GPU,设备偶尔会阻塞,这会导致速度减慢。