2

私は最近、すべてのc#SlimDX DX11レンダリングコードをフォーム(はい、私は怠惰な開発者です)から特注のクラスに移動してから少し遅れています。私は自分のプログラムをEQATECProfilerに打ち込み、これを私のラグの主な原因として手に入れました。

EQATECプロファイラーの結果は、関数postRender()に障害があることを示しています

ここで、postRender()にあるものが本当に貴重なミリ秒を占有していることは明らかです。実際、私がそこに持っているクレイジーで複雑なコードが何であれ、それ自体でフレームレートを実質的に最大15FPSに下げることができます。

では、postRender()には何が含まれていますか?たった1行のコード:

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は、4つのレンダーターゲットを使用して、拡散反射光、法線、位置、および色をピクセルごとにキャプチャします。CompositeSceneは、それらをすべてまとめます。これには、 GPUは、続行する前に前のステップを計算しました。このプロセス全体が続行され、DoFはPostProcessの結果などを要求します。したがって、Swapchain.Present()を保持している可能性がある唯一のシェーダーは、で実行されるシェーダーである必要があります。関数DoFは、他のすべてのシェーダーが終了するまでCPUをロックするためです。正しいですか?

4

1 に答える 1

1

Present()がフレーム内でこれほど多くの時間を費やしていることに気付く理由はいくつかあります。現在の呼び出しは、CPUとGPU間の同期の主要な方法です。CPUがGPUが処理できるよりもはるかに高速にフレームを生成している場合、それらはキューに入れられます。バッファがいっぱいになると、Present()は、バッファが空になるのを待つ間、栄光のSleep()呼び出しに変わります。

もちろん、ここで提供したわずかな情報で言うことはほとんど不可能です。マシンがCrysisを実行しているからといって、カードに好きなものを投げることで逃げることができるわけではありません。クレイジーな量のジオメトリをレンダリングすることを期待していないこと、およびシェーダーが異常に長く複雑でないことを再確認してください。

また、利用可能なGPUプロファイラーの1つを使用してアプリを確認してください。PIXはベースポイントとして適していますが、NVIDIAとAMDはそれぞれ、独自の製品に対して独自のより具体的な製品を提供しています。最後に、ドライバーが更新されていることを確認してください。ドライバーにバグがある場合、問題について推論する機会があれば、ウィンドウの外に出てしまいます。

于 2012-05-01T15:34:50.247 に答える