16

これは、この質問のフォローアップです。私は現在、簡単なゲームを書いていますが、ちらつきやその他のアーティファクトなしに、RGBデータの配列をWin32ウィンドウに(繰り返し)表示するための最速の方法を探しています。

前の質問への回答では、いくつかの異なるアプローチが推奨されましたが、どれが最速であるかについてのコンセンサスはありませんでした。そこで、テストプログラムをまとめました。このコードは、フレームバッファを画面にできるだけ速く繰り返し表示するだけです。

これらは、32ビットビデオモードで実行されている32ビットデータについて私が得た結果です-一部の人々を驚かせるかもしれません:

- Direct3D (1):             500 fps
- Direct3D (2):             650 fps
- DirectDraw (3):          1100 fps
- DirectDraw (4):           800 fps
- GDI (SetDIBitsToDevice): 2000 fps

これらの数字を考えると:

  • なぜ多くの人がGDIがこの操作には遅すぎると固執しているのですか?
  • SetDIBitsToDeviceよりもDirectDrawまたはDirect3Dを好む理由はありますか?

これは、各Direct*コードパスによって行われた呼び出しの簡単な要約です。DirectDraw / Direct3Dをより効率的に使用する方法を知っている人がいる場合は、コメントしてください。

1. CreateTexture(D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT);
       LockRect(); memcpy(); UnlockRect(); DrawPrimitive()

2. CreateTexture(0, D3DPOOL_SYSTEMMEM); CreateTexture(0, D3DPOOL_DEFAULT);
       LockRect(); memcpy(); UnlockRect(); UpdateTexture(); DrawPrimitive()

3. CreateSurface(); SetSurfaceDesc(lpSurface = &frameBuffer[0]);
       memcpy(); primarySurface->Blt();

4. CreateSurface();
       Lock(); memcpy(); Unlock(); primarySurface->Blt();
4

3 に答える 3

7

ここで覚えておくべきことがいくつかあります。まず第一に、多くの「常識」は、もはや実際には当てはまらないいくつかの事実に基づいています。

AGPの時代、CPUがGPUと直接通信するとき、CPUは常にベースPCIプロトコルを使用していましたが、これは「1倍」の速度で(常にそして必然的に)発生しました。AGX 2x / 4x / 8xは、GPUがメモリコントローラーに直接接続している場合にのみ適用されます。言い換えると、いつ見ているかにもよりますが、GPUがメモリからテクスチャをロードするのは、CPUが同じデータをGPUに直接送信する場合の最大8倍の速さでした。もちろん、CPUには、サポートされているPCIバスよりもはるかに多くのメモリ帯域幅がありました。

しかし、PCI-Eに切り替えると、それは完全に変わりました。パスによって帯域幅に違いが生じる可能性がありますが、メモリ->GPUがCPU->GPUよりも高速になるという一般的な規則はありません。(ほとんど)安全な一般化の1つは、専用のグラフィックカードを使用している場合、GPUはほとんどの場合、マザーボードのメインメモリよりもグラフィックカードのメモリに対してより多くの帯域幅を使用できるということです。

あなたの場合、それはそれほど重要ではありません-あなたはCPUスペースからGPUスペースにデータを移動することについて話しているのです。DirectX(またはOpenGL)を使用する場合の主な速度の違いは、すべて(またはほとんど)の計算をGPUで保持し、CPU(またはメインメモリ)をまったく使用しない場合に発生します。それらは(AGPが歴史であるため)メモリ->表示帯域幅の実質的な改善を提供しません。

于 2010-11-08T22:25:49.910 に答える
3

ジェリー・コフィンはいくつかの良い点を述べています。覚えておくべきことは、DIがSetDIBitsToDeviceで何を表すかです。DeviceIndependentの略です。つまり、あなたは常にドライバーに翻弄されていたということです。一部のドライバーは完全にゴミであり、パフォーマンスに大きな影響を与えていました。DirectDrawにも同様の問題がありましたが、ハードウェアブリッターにもアクセスできたため、一般的にはより便利でした。また、IHVは、ゲームとの関連性があるため、DirectDraw用の適切なドライバーの作成により多くの時間を費やす傾向がありました。ハードウェアが非常に優れたパフォーマンスを発揮できるときに、パフォーマンスの山の底になりたいのは誰ですか?

最近では、多くのグラフィックカードがビットデータを直接受け入れることができるため、変換は行われません。それがスウィズルする必要がある場合、これもこの時代では信じられないほど速いです。

比較すると、Direct3Dのパフォーマンスが非常にひどい理由は、Direct3Dは、GPUの内部で完全に使用されることを意図しており、キャッシュパフォーマンスなどを改善するために奇妙で複雑な形式を使用するためです。

テクスチャ/サーフェスを作成し、それをロックし、コピーし、ロックを解除してから、(さまざまな方法で)バックバッファを描画することにより、(DDrawおよびD3Dを使用して)同じようにテストしていないという事実と組み合わせます。最高のパフォーマンスを得るには、DISCARDロックを使用してバックバッファーを直接ロックしてから、ロックを解除する前に、返されたバッファーに直接memcpyするのが最善です。これにより、パフォーマンスがSetDIBitsToDeviceにはるかに近くなります。ただし、上記の理由により、D3DはDDrawよりも遅いと思います。

于 2010-11-09T11:38:29.250 に答える
1

人々がGDIを踏みにじるのを聞く理由は、それが以前は古いWindowsAPI呼び出しであったためです。新しいバージョン(私が最後にemを見たときにGDI +と呼ばれていました)は、実際にはDirectX呼び出しの上に配置されたAPIにすぎません。したがって、GDIを使用することは、プログラミングに関してはかなり単純に見える場合がありますが、物事の間にレイヤーを追加すると、常に物事が遅くなります。Jerry Coffinからの応答で述べたように、あなたの例はデータの移動に関するものであり、それは遅い時間です。DirectXの方がはるかに遅いことに少し驚いていますが、DirectXのドキュメントを掘り下げることでこれ以上の手助けはできません(これはかなり長い間本当に素晴らしいものでした。www.codesampler.comをチェックしたいかもしれません。 。私はいつも彼から良い出発点を見つけました、そして実際、私はこれを言うのは正気ではないかもしれませんが、

DirectDrawとDirect3D(GDI呼び出しではない)の議論について。Direct3Dに行くと思います。DirectDrawは8.0かそこらから非推奨になり、9.0はかなり長い間使用されてきたと思います。そして、結局のところ、DirectXはすべて3Dであり、周りにある便利な2D APIのレベルによって異なりますが、実際に3D空間を使用している場合、2D環境で非常に興味深いことができる場合があります。(私は、スペースインベーダーのクローン用にランダムに生成されたかなりきちんとした稲妻武器を一度に持っていました:))

誰でも、これが役に立てば幸いです!

PS:DirectXが常に最速であるとは限らないことに注意してください。キーボード入力の場合(これが10または11で変更されていない限り)、ほとんどの場合、Windowsイベントを使用することをお勧めします。DirectInputは実際にはそのシステムの単なるラッパーでした!..XInputは-awesome- !!

于 2010-11-09T06:59:04.013 に答える