2

自从我将我的所有 c# SlimDX DX11 渲染代码从我的表单(是的,我是一个懒惰的开发人员)移动到定制类后,我最近有点滞后。我将我的程序打进了 EQATEC Profiler 并把它作为我滞后的主要贡献者:

EQATEC Profiler 结果显示函数 postRender() 有问题

现在很清楚, postRender() 中的任何内容都真正占用了宝贵的毫秒数。事实上,无论我在其中有什么疯狂、复杂的代码,它本身都会有效地将我的帧速率降低到 ~15 FPS。

那么 postRender() 中有什么?只需一行代码:

swapChain.Present(0, PresentFlags.None);

我只是不知道是什么导致它这么慢,我根本没有对交换链代码进行任何更改。我所更改的只是屏幕分辨率(1680x1050),但这绝对没问题(作为参考,这台机器可以在该分辨率下以最大设置运行 crysis2 而不会出汗)。

有没有人知道什么可能导致交换链需要这么长时间才能呈现或者我应该在哪里寻找问题?

编辑:

查看我的代码结构,我的 RenderFrame() 函数如下:

preRender();
DeferredRender(preShader);
//Composite scene to output image
CompositeScene(compositeShader);
//Post Process
PostProcess(postProcShader);
//Depth of Field
DoF(dofShader);
//Present the swapchain
postRender();

其中一些函数的结果基于之前的函数(例如,DeferredRender 使用四个渲染目标以逐像素的方式捕获漫反射光照、法线、位置和颜色。然后 CompositeScene 将它们放在一起。这将需要GPU 在继续之前已经计算了上一步。整个过程继续进行,DoF 需要 PostProcess 的结果等。因此,唯一可能保持 Swapchain.Present() 的着色器必须是运行在功能DoF,因为所有其他着色器都会导致CPU锁定直到它们完成。对吗?

4

1 回答 1

1

有几个原因可能会导致 Present() 在框架中占用这么多时间。Present调用是CPU和GPU之间同步的主要方法;如果 CPU 生成帧的速度比 GPU 处理它们的速度快得多,它们就会排队。一旦缓冲区满了,Present() 就会变成一个美化的 Sleep() 调用,等待它清空。

当然,您在这里提供的信息很少,几乎不可能说出来。仅仅因为一台机器运行《孤岛危机》并不意味着你可以随意向卡片扔任何你想要的东西。仔细检查您是否期望渲染大量几何图形,并且您的着色器没有异常长和复杂。

还可以使用其中一种可用的 GPU 分析器查看您的应用程序;PIX 是一个很好的基点,而 NVIDIA 和 AMD 各自为自己的产品提供了更具体的产品。最后,确保您的驱动程序已更新。如果驱动程序中存在错误,那么您对问题进行推理的任何机会都会消失。

于 2012-05-01T15:34:50.247 回答